]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/sev: Add SVSM vTPM probe/send_command functions
authorStefano Garzarella <sgarzare@redhat.com>
Thu, 3 Apr 2025 10:09:39 +0000 (12:09 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Thu, 10 Apr 2025 14:15:41 +0000 (16:15 +0200)
Add two new functions to probe and send commands to the SVSM vTPM. They
leverage the two calls defined by the AMD SVSM specification [1] for the vTPM
protocol: SVSM_VTPM_QUERY and SVSM_VTPM_CMD.

Expose snp_svsm_vtpm_send_command() to be used by a TPM driver.

  [1] "Secure VM Service Module for SEV-SNP Guests"
      Publication # 58019 Revision: 1.00

  [ bp: Some doc touchups. ]

Co-developed-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Co-developed-by: Claudio Carvalho <cclaudio@linux.ibm.com>
Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20250403100943.120738-2-sgarzare@redhat.com
arch/x86/coco/sev/core.c
arch/x86/include/asm/sev.h

index b0c1a7a574974a297b3078a9c9de942e1dc3434b..ecd09dad87f244c4bfb47347f88ed4138a57ce2b 100644 (file)
@@ -2625,6 +2625,64 @@ e_restore_irq:
        return ret;
 }
 
+/**
+ * snp_svsm_vtpm_probe() - Probe if SVSM provides a vTPM device
+ *
+ * Check that there is SVSM and that it supports at least TPM_SEND_COMMAND
+ * which is the only request used so far.
+ *
+ * Return: true if the platform provides a vTPM SVSM device, false otherwise.
+ */
+static bool snp_svsm_vtpm_probe(void)
+{
+       struct svsm_call call = {};
+
+       /* The vTPM device is available only if a SVSM is present */
+       if (!snp_vmpl)
+               return false;
+
+       call.caa = svsm_get_caa();
+       call.rax = SVSM_VTPM_CALL(SVSM_VTPM_QUERY);
+
+       if (svsm_perform_call_protocol(&call))
+               return false;
+
+       /* Check platform commands contains TPM_SEND_COMMAND - platform command 8 */
+       return call.rcx_out & BIT_ULL(8);
+}
+
+/**
+ * snp_svsm_vtpm_send_command() - Execute a vTPM operation on SVSM
+ * @buffer: A buffer used to both send the command and receive the response.
+ *
+ * Execute a SVSM_VTPM_CMD call as defined by
+ * "Secure VM Service Module for SEV-SNP Guests" Publication # 58019 Revision: 1.00
+ *
+ * All command request/response buffers have a common structure as specified by
+ * the following table:
+ *     Byte      Size       In/Out    Description
+ *     Offset    (Bytes)
+ *     0x000     4          In        Platform command
+ *                          Out       Platform command response size
+ *
+ * Each command can build upon this common request/response structure to create
+ * a structure specific to the command. See include/linux/tpm_svsm.h for more
+ * details.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int snp_svsm_vtpm_send_command(u8 *buffer)
+{
+       struct svsm_call call = {};
+
+       call.caa = svsm_get_caa();
+       call.rax = SVSM_VTPM_CALL(SVSM_VTPM_CMD);
+       call.rcx = __pa(buffer);
+
+       return svsm_perform_call_protocol(&call);
+}
+EXPORT_SYMBOL_GPL(snp_svsm_vtpm_send_command);
+
 static struct platform_device sev_guest_device = {
        .name           = "sev-guest",
        .id             = -1,
index ba7999f66abe6de599b3e5bc19fcf8ca2dd9131d..d9ba035d8609ca3c932a758d7f50c5c704c4ee04 100644 (file)
@@ -384,6 +384,10 @@ struct svsm_call {
 #define SVSM_ATTEST_SERVICES           0
 #define SVSM_ATTEST_SINGLE_SERVICE     1
 
+#define SVSM_VTPM_CALL(x)              ((2ULL << 32) | (x))
+#define SVSM_VTPM_QUERY                        0
+#define SVSM_VTPM_CMD                  1
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern u8 snp_vmpl;
@@ -481,6 +485,8 @@ void snp_msg_free(struct snp_msg_desc *mdesc);
 int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
                           struct snp_guest_request_ioctl *rio);
 
+int snp_svsm_vtpm_send_command(u8 *buffer);
+
 void __init snp_secure_tsc_prepare(void);
 void __init snp_secure_tsc_init(void);
 
@@ -524,6 +530,7 @@ static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; }
 static inline void snp_msg_free(struct snp_msg_desc *mdesc) { }
 static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
                                         struct snp_guest_request_ioctl *rio) { return -ENODEV; }
+static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; }
 static inline void __init snp_secure_tsc_prepare(void) { }
 static inline void __init snp_secure_tsc_init(void) { }