tpm_svsm.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
  4. *
  5. * Driver for the vTPM defined by the AMD SVSM spec [1].
  6. *
  7. * The specification defines a protocol that a SEV-SNP guest OS can use to
  8. * discover and talk to a vTPM emulated by the Secure VM Service Module (SVSM)
  9. * in the guest context, but at a more privileged level (usually VMPL0).
  10. *
  11. * [1] "Secure VM Service Module for SEV-SNP Guests"
  12. * Publication # 58019 Revision: 1.00
  13. */
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/tpm_svsm.h>
  18. #include <asm/sev.h>
  19. #include "tpm.h"
  20. struct tpm_svsm_priv {
  21. void *buffer;
  22. };
  23. static int tpm_svsm_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
  24. size_t cmd_len)
  25. {
  26. struct tpm_svsm_priv *priv = dev_get_drvdata(&chip->dev);
  27. int ret;
  28. ret = svsm_vtpm_cmd_request_fill(priv->buffer, 0, buf, cmd_len);
  29. if (ret)
  30. return ret;
  31. /*
  32. * The SVSM call uses the same buffer for the command and for the
  33. * response, so after this call, the buffer will contain the response.
  34. *
  35. * Note: we have to use an internal buffer because the device in SVSM
  36. * expects the svsm_vtpm header + data to be physically contiguous.
  37. */
  38. ret = snp_svsm_vtpm_send_command(priv->buffer);
  39. if (ret)
  40. return ret;
  41. return svsm_vtpm_cmd_response_parse(priv->buffer, buf, bufsiz);
  42. }
  43. static struct tpm_class_ops tpm_chip_ops = {
  44. .flags = TPM_OPS_AUTO_STARTUP,
  45. .send = tpm_svsm_send,
  46. };
  47. static int __init tpm_svsm_probe(struct platform_device *pdev)
  48. {
  49. struct device *dev = &pdev->dev;
  50. struct tpm_svsm_priv *priv;
  51. struct tpm_chip *chip;
  52. int err;
  53. priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
  54. if (!priv)
  55. return -ENOMEM;
  56. /*
  57. * The maximum buffer supported is one page (see SVSM_VTPM_MAX_BUFFER
  58. * in tpm_svsm.h).
  59. */
  60. priv->buffer = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0);
  61. if (!priv->buffer)
  62. return -ENOMEM;
  63. chip = tpmm_chip_alloc(dev, &tpm_chip_ops);
  64. if (IS_ERR(chip))
  65. return PTR_ERR(chip);
  66. dev_set_drvdata(&chip->dev, priv);
  67. chip->flags |= TPM_CHIP_FLAG_SYNC;
  68. err = tpm2_probe(chip);
  69. if (err)
  70. return err;
  71. err = tpm_chip_register(chip);
  72. if (err)
  73. return err;
  74. dev_info(dev, "SNP SVSM vTPM %s device\n",
  75. (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2");
  76. return 0;
  77. }
  78. static void __exit tpm_svsm_remove(struct platform_device *pdev)
  79. {
  80. struct tpm_chip *chip = platform_get_drvdata(pdev);
  81. tpm_chip_unregister(chip);
  82. }
  83. /*
  84. * tpm_svsm_remove() lives in .exit.text. For drivers registered via
  85. * module_platform_driver_probe() this is ok because they cannot get unbound
  86. * at runtime. So mark the driver struct with __refdata to prevent modpost
  87. * triggering a section mismatch warning.
  88. */
  89. static struct platform_driver tpm_svsm_driver __refdata = {
  90. .remove = __exit_p(tpm_svsm_remove),
  91. .driver = {
  92. .name = "tpm-svsm",
  93. },
  94. };
  95. module_platform_driver_probe(tpm_svsm_driver, tpm_svsm_probe);
  96. MODULE_DESCRIPTION("SNP SVSM vTPM Driver");
  97. MODULE_LICENSE("GPL");
  98. MODULE_ALIAS("platform:tpm-svsm");