... | ... | ||
---|---|---|---|
34 | - a recent version of Coconut SVSM [4] containing an ephemeral vTPM | 34 | - a recent version of Coconut SVSM [4] containing an ephemeral vTPM |
35 | - a PoC [5] containing a stateful vTPM used for sealing/unsealing a LUKS key | 35 | - a PoC [5] containing a stateful vTPM used for sealing/unsealing a LUKS key |
36 | 36 | ||
37 | Changelog: | 37 | Changelog: |
38 | 38 | ||
39 | v5 -> v6 | 39 | v6 -> v7: |
40 | - Moved snp_svsm_vtpm_probe() call from the driver to sev/core.c to register | ||
41 | the device only when it's really available [Borislav] | ||
42 | - s/device/devices in pr_info [Tom] | ||
43 | - Added Jarkko's R-b on patches 3 and 4 | ||
44 | - Updated some commit descriptions to reflect the current implementation | ||
45 | |||
46 | v5 -> v6: https://lore.kernel.org/linux-integrity/20250403100943.120738-1-sgarzare@redhat.com/ | ||
40 | - Removed the `locality` field (set to 0) and the FIXME comment [Jarkko] | 47 | - Removed the `locality` field (set to 0) and the FIXME comment [Jarkko] |
41 | - Added Tom's R-b on patch 4 | 48 | - Added Tom's R-b on patch 4 |
42 | 49 | ||
43 | v4 -> v5: https://lore.kernel.org/linux-integrity/20250331103900.92701-1-sgarzare@redhat.com/ | 50 | v4 -> v5: https://lore.kernel.org/linux-integrity/20250331103900.92701-1-sgarzare@redhat.com/ |
44 | - Added stubs when !CONFIG_AMD_MEM_ENCRYPT [Dionna] | 51 | - Added stubs when !CONFIG_AMD_MEM_ENCRYPT [Dionna] |
... | ... | ||
106 | x86/sev: add SVSM vTPM probe/send_command functions | 113 | x86/sev: add SVSM vTPM probe/send_command functions |
107 | svsm: add header with SVSM_VTPM_CMD helpers | 114 | svsm: add header with SVSM_VTPM_CMD helpers |
108 | tpm: add SNP SVSM vTPM driver | 115 | tpm: add SNP SVSM vTPM driver |
109 | x86/sev: register tpm-svsm platform device | 116 | x86/sev: register tpm-svsm platform device |
110 | 117 | ||
111 | arch/x86/include/asm/sev.h | 9 +++ | 118 | arch/x86/include/asm/sev.h | 7 ++ |
112 | include/linux/tpm_svsm.h | 149 ++++++++++++++++++++++++++++++++++++ | 119 | include/linux/tpm_svsm.h | 149 ++++++++++++++++++++++++++++++++++++ |
113 | arch/x86/coco/sev/core.c | 67 ++++++++++++++++ | 120 | arch/x86/coco/sev/core.c | 69 ++++++++++++++++- |
114 | drivers/char/tpm/tpm_svsm.c | 128 +++++++++++++++++++++++++++++++ | 121 | drivers/char/tpm/tpm_svsm.c | 125 ++++++++++++++++++++++++++++++ |
115 | drivers/char/tpm/Kconfig | 10 +++ | 122 | drivers/char/tpm/Kconfig | 10 +++ |
116 | drivers/char/tpm/Makefile | 1 + | 123 | drivers/char/tpm/Makefile | 1 + |
117 | 6 files changed, 364 insertions(+) | 124 | 6 files changed, 360 insertions(+), 1 deletion(-) |
118 | create mode 100644 include/linux/tpm_svsm.h | 125 | create mode 100644 include/linux/tpm_svsm.h |
119 | create mode 100644 drivers/char/tpm/tpm_svsm.c | 126 | create mode 100644 drivers/char/tpm/tpm_svsm.c |
120 | 127 | ||
121 | -- | 128 | -- |
122 | 2.49.0 | 129 | 2.49.0 | diff view generated by jsdifflib |
1 | From: Stefano Garzarella <sgarzare@redhat.com> | 1 | From: Stefano Garzarella <sgarzare@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Add two new functions to probe and send commands to the SVSM vTPM. | 3 | Add two new functions to probe and send commands to the SVSM vTPM. |
4 | They leverage the two calls defined by the AMD SVSM specification [1] | 4 | They leverage the two calls defined by the AMD SVSM specification [1] |
5 | for the vTPM protocol: SVSM_VTPM_QUERY and SVSM_VTPM_CMD. | 5 | for the vTPM protocol: SVSM_VTPM_QUERY and SVSM_VTPM_CMD. |
6 | 6 | ||
7 | Expose these functions to be used by other modules such as a tpm | 7 | Expose snp_svsm_vtpm_send_command() to be used by a tpm driver. |
8 | driver. | ||
9 | 8 | ||
10 | [1] "Secure VM Service Module for SEV-SNP Guests" | 9 | [1] "Secure VM Service Module for SEV-SNP Guests" |
11 | Publication # 58019 Revision: 1.00 | 10 | Publication # 58019 Revision: 1.00 |
12 | 11 | ||
13 | Co-developed-by: James Bottomley <James.Bottomley@HansenPartnership.com> | 12 | Co-developed-by: James Bottomley <James.Bottomley@HansenPartnership.com> |
... | ... | ||
16 | Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com> | 15 | Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com> |
17 | Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> | 16 | Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> |
18 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> | 17 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> |
19 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | 18 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> |
20 | --- | 19 | --- |
20 | v7: | ||
21 | - avoided exporting snp_svsm_vtpm_probe() because we will only use it | ||
22 | internally | ||
21 | v5: | 23 | v5: |
22 | - added stubs when !CONFIG_AMD_MEM_ENCRYPT [Dionna] | 24 | - added stubs when !CONFIG_AMD_MEM_ENCRYPT [Dionna] |
23 | - added Jarkko's R-b | 25 | - added Jarkko's R-b |
24 | v4: | 26 | v4: |
25 | - added Tom's R-b | 27 | - added Tom's R-b |
... | ... | ||
30 | - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch | 32 | - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch |
31 | in this one [Borislav] | 33 | in this one [Borislav] |
32 | - slimmed down snp_svsm_vtpm_probe() [Borislav] | 34 | - slimmed down snp_svsm_vtpm_probe() [Borislav] |
33 | - removed features check and any print related [Tom] | 35 | - removed features check and any print related [Tom] |
34 | --- | 36 | --- |
35 | arch/x86/include/asm/sev.h | 9 ++++++ | 37 | arch/x86/include/asm/sev.h | 7 +++++ |
36 | arch/x86/coco/sev/core.c | 59 ++++++++++++++++++++++++++++++++++++++ | 38 | arch/x86/coco/sev/core.c | 58 ++++++++++++++++++++++++++++++++++++++ |
37 | 2 files changed, 68 insertions(+) | 39 | 2 files changed, 65 insertions(+) |
38 | 40 | ||
39 | diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h | 41 | diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h |
40 | index XXXXXXX..XXXXXXX 100644 | 42 | index XXXXXXX..XXXXXXX 100644 |
41 | --- a/arch/x86/include/asm/sev.h | 43 | --- a/arch/x86/include/asm/sev.h |
42 | +++ b/arch/x86/include/asm/sev.h | 44 | +++ b/arch/x86/include/asm/sev.h |
... | ... | ||
53 | extern u8 snp_vmpl; | 55 | extern u8 snp_vmpl; |
54 | @@ -XXX,XX +XXX,XX @@ void snp_msg_free(struct snp_msg_desc *mdesc); | 56 | @@ -XXX,XX +XXX,XX @@ void snp_msg_free(struct snp_msg_desc *mdesc); |
55 | int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, | 57 | int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, |
56 | struct snp_guest_request_ioctl *rio); | 58 | struct snp_guest_request_ioctl *rio); |
57 | 59 | ||
58 | +bool snp_svsm_vtpm_probe(void); | ||
59 | +int snp_svsm_vtpm_send_command(u8 *buffer); | 60 | +int snp_svsm_vtpm_send_command(u8 *buffer); |
60 | + | 61 | + |
61 | void __init snp_secure_tsc_prepare(void); | 62 | void __init snp_secure_tsc_prepare(void); |
62 | void __init snp_secure_tsc_init(void); | 63 | void __init snp_secure_tsc_init(void); |
63 | 64 | ||
64 | @@ -XXX,XX +XXX,XX @@ static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; } | 65 | @@ -XXX,XX +XXX,XX @@ static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; } |
65 | static inline void snp_msg_free(struct snp_msg_desc *mdesc) { } | 66 | static inline void snp_msg_free(struct snp_msg_desc *mdesc) { } |
66 | static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, | 67 | static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, |
67 | struct snp_guest_request_ioctl *rio) { return -ENODEV; } | 68 | struct snp_guest_request_ioctl *rio) { return -ENODEV; } |
68 | +static inline bool snp_svsm_vtpm_probe(void) { return false; } | ||
69 | +static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; } | 69 | +static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; } |
70 | static inline void __init snp_secure_tsc_prepare(void) { } | 70 | static inline void __init snp_secure_tsc_prepare(void) { } |
71 | static inline void __init snp_secure_tsc_init(void) { } | 71 | static inline void __init snp_secure_tsc_init(void) { } |
72 | 72 | ||
73 | diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c | 73 | diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c |
... | ... | ||
84 | + * This function checks that there is SVSM and that it supports at least | 84 | + * This function checks that there is SVSM and that it supports at least |
85 | + * TPM_SEND_COMMAND which is the only request we use so far. | 85 | + * TPM_SEND_COMMAND which is the only request we use so far. |
86 | + * | 86 | + * |
87 | + * Return: true if the platform provides a vTPM SVSM device, false otherwise. | 87 | + * Return: true if the platform provides a vTPM SVSM device, false otherwise. |
88 | + */ | 88 | + */ |
89 | +bool snp_svsm_vtpm_probe(void) | 89 | +static bool snp_svsm_vtpm_probe(void) |
90 | +{ | 90 | +{ |
91 | + struct svsm_call call = {}; | 91 | + struct svsm_call call = {}; |
92 | + | 92 | + |
93 | + /* The vTPM device is available only if a SVSM is present */ | 93 | + /* The vTPM device is available only if a SVSM is present */ |
94 | + if (!snp_vmpl) | 94 | + if (!snp_vmpl) |
... | ... | ||
101 | + return false; | 101 | + return false; |
102 | + | 102 | + |
103 | + /* Check platform commands contains TPM_SEND_COMMAND - platform command 8 */ | 103 | + /* Check platform commands contains TPM_SEND_COMMAND - platform command 8 */ |
104 | + return call.rcx_out & BIT_ULL(8); | 104 | + return call.rcx_out & BIT_ULL(8); |
105 | +} | 105 | +} |
106 | +EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe); | ||
107 | + | 106 | + |
108 | +/** | 107 | +/** |
109 | + * snp_svsm_vtpm_send_command() - execute a vTPM operation on SVSM | 108 | + * snp_svsm_vtpm_send_command() - execute a vTPM operation on SVSM |
110 | + * @buffer: A buffer used to both send the command and receive the response. | 109 | + * @buffer: A buffer used to both send the command and receive the response. |
111 | + * | 110 | + * |
... | ... | diff view generated by jsdifflib |
1 | From: Stefano Garzarella <sgarzare@redhat.com> | 1 | From: Stefano Garzarella <sgarzare@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Helpers for the SVSM_VTPM_CMD calls used by the vTPM protocol defined by | 3 | Helpers for the SVSM_VTPM_CMD calls used by the vTPM protocol defined by |
4 | the AMD SVSM spec [1]. | 4 | the AMD SVSM spec [1]. |
5 | 5 | ||
6 | The vTPM protocol follows the Official TPM 2.0 Reference Implementation | 6 | The vTPM protocol follows the Official TPM 2.0 Reference Implementation |
7 | (originally by Microsoft, now part of the TCG) simulator protocol. | 7 | (originally by Microsoft, now part of the TCG) simulator protocol. |
8 | 8 | ||
9 | [1] "Secure VM Service Module for SEV-SNP Guests" | 9 | [1] "Secure VM Service Module for SEV-SNP Guests" |
10 | Publication # 58019 Revision: 1.00 | 10 | Publication # 58019 Revision: 1.00 |
11 | 11 | ||
12 | Co-developed-by: James Bottomley <James.Bottomley@HansenPartnership.com> | 12 | Co-developed-by: James Bottomley <James.Bottomley@HansenPartnership.com> |
13 | Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> | 13 | Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> |
14 | Co-developed-by: Claudio Carvalho <cclaudio@linux.ibm.com> | 14 | Co-developed-by: Claudio Carvalho <cclaudio@linux.ibm.com> |
15 | Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com> | 15 | Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com> |
16 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> | 16 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> |
17 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | 17 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> |
18 | --- | 18 | --- |
19 | v5: | 19 | v5: |
20 | - added Jarkko's R-b | 20 | - added Jarkko's R-b |
21 | v4: | 21 | v4: |
22 | - used svsm_vtpm_ prefix consistently [Jarkko] | 22 | - used svsm_vtpm_ prefix consistently [Jarkko] |
23 | - removed __packed where not needed [Jarkko] | 23 | - removed __packed where not needed [Jarkko] |
24 | - expanded headers to avoid obfuscation [Jarkko] | 24 | - expanded headers to avoid obfuscation [Jarkko] |
25 | - used `buf` instead of `inbuf`/`outbuf` [Jarkko] | 25 | - used `buf` instead of `inbuf`/`outbuf` [Jarkko] |
26 | - added more documentation quoting the specification | 26 | - added more documentation quoting the specification |
27 | - removed TPM_* macros since we only use TPM_SEND_COMMAND in one place | 27 | - removed TPM_* macros since we only use TPM_SEND_COMMAND in one place |
28 | and don't want dependencies on external headers, but put the value | 28 | and don't want dependencies on external headers, but put the value |
29 | directly as specified in the AMD SVSM specification | 29 | directly as specified in the AMD SVSM specification |
30 | - header renamed in tpm_svsm.h so it will fall under TPM DEVICE DRIVER | 30 | - header renamed in tpm_svsm.h so it will fall under TPM DEVICE DRIVER |
31 | section [Borislav, Jarkko] | 31 | section [Borislav, Jarkko] |
32 | v3: | 32 | v3: |
33 | - renamed header and prefix to make clear it's related to the SVSM vTPM | 33 | - renamed header and prefix to make clear it's related to the SVSM vTPM |
34 | protocol | 34 | protocol |
35 | - renamed fill/parse functions [Tom] | 35 | - renamed fill/parse functions [Tom] |
36 | - removed link to the spec because those URLs are unstable [Borislav] | 36 | - removed link to the spec because those URLs are unstable [Borislav] |
37 | --- | 37 | --- |
38 | include/linux/tpm_svsm.h | 149 +++++++++++++++++++++++++++++++++++++++ | 38 | include/linux/tpm_svsm.h | 149 +++++++++++++++++++++++++++++++++++++++ |
39 | 1 file changed, 149 insertions(+) | 39 | 1 file changed, 149 insertions(+) |
40 | create mode 100644 include/linux/tpm_svsm.h | 40 | create mode 100644 include/linux/tpm_svsm.h |
41 | 41 | ||
42 | diff --git a/include/linux/tpm_svsm.h b/include/linux/tpm_svsm.h | 42 | diff --git a/include/linux/tpm_svsm.h b/include/linux/tpm_svsm.h |
43 | new file mode 100644 | 43 | new file mode 100644 |
44 | index XXXXXXX..XXXXXXX | 44 | index XXXXXXX..XXXXXXX |
45 | --- /dev/null | 45 | --- /dev/null |
46 | +++ b/include/linux/tpm_svsm.h | 46 | +++ b/include/linux/tpm_svsm.h |
47 | @@ -XXX,XX +XXX,XX @@ | 47 | @@ -XXX,XX +XXX,XX @@ |
48 | +/* SPDX-License-Identifier: GPL-2.0-only */ | 48 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
49 | +/* | 49 | +/* |
50 | + * Copyright (C) 2023 James.Bottomley@HansenPartnership.com | 50 | + * Copyright (C) 2023 James.Bottomley@HansenPartnership.com |
51 | + * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. | 51 | + * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. |
52 | + * | 52 | + * |
53 | + * Helpers for the SVSM_VTPM_CMD calls used by the vTPM protocol defined by the | 53 | + * Helpers for the SVSM_VTPM_CMD calls used by the vTPM protocol defined by the |
54 | + * AMD SVSM spec [1]. | 54 | + * AMD SVSM spec [1]. |
55 | + * | 55 | + * |
56 | + * The vTPM protocol follows the Official TPM 2.0 Reference Implementation | 56 | + * The vTPM protocol follows the Official TPM 2.0 Reference Implementation |
57 | + * (originally by Microsoft, now part of the TCG) simulator protocol. | 57 | + * (originally by Microsoft, now part of the TCG) simulator protocol. |
58 | + * | 58 | + * |
59 | + * [1] "Secure VM Service Module for SEV-SNP Guests" | 59 | + * [1] "Secure VM Service Module for SEV-SNP Guests" |
60 | + * Publication # 58019 Revision: 1.00 | 60 | + * Publication # 58019 Revision: 1.00 |
61 | + */ | 61 | + */ |
62 | +#ifndef _TPM_SVSM_H_ | 62 | +#ifndef _TPM_SVSM_H_ |
63 | +#define _TPM_SVSM_H_ | 63 | +#define _TPM_SVSM_H_ |
64 | + | 64 | + |
65 | +#include <linux/errno.h> | 65 | +#include <linux/errno.h> |
66 | +#include <linux/string.h> | 66 | +#include <linux/string.h> |
67 | +#include <linux/types.h> | 67 | +#include <linux/types.h> |
68 | + | 68 | + |
69 | +#define SVSM_VTPM_MAX_BUFFER 4096 /* max req/resp buffer size */ | 69 | +#define SVSM_VTPM_MAX_BUFFER 4096 /* max req/resp buffer size */ |
70 | + | 70 | + |
71 | +/** | 71 | +/** |
72 | + * struct svsm_vtpm_request - Generic request for single word command | 72 | + * struct svsm_vtpm_request - Generic request for single word command |
73 | + * @cmd: The command to send | 73 | + * @cmd: The command to send |
74 | + * | 74 | + * |
75 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - | 75 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - |
76 | + * Table 15: vTPM Common Request/Response Structure | 76 | + * Table 15: vTPM Common Request/Response Structure |
77 | + * Byte Size In/Out Description | 77 | + * Byte Size In/Out Description |
78 | + * Offset (Bytes) | 78 | + * Offset (Bytes) |
79 | + * 0x000 4 In Platform command | 79 | + * 0x000 4 In Platform command |
80 | + * Out Platform command response size | 80 | + * Out Platform command response size |
81 | + */ | 81 | + */ |
82 | +struct svsm_vtpm_request { | 82 | +struct svsm_vtpm_request { |
83 | + u32 cmd; | 83 | + u32 cmd; |
84 | +}; | 84 | +}; |
85 | + | 85 | + |
86 | +/** | 86 | +/** |
87 | + * struct svsm_vtpm_response - Generic response | 87 | + * struct svsm_vtpm_response - Generic response |
88 | + * @size: The response size (zero if nothing follows) | 88 | + * @size: The response size (zero if nothing follows) |
89 | + * | 89 | + * |
90 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - | 90 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - |
91 | + * Table 15: vTPM Common Request/Response Structure | 91 | + * Table 15: vTPM Common Request/Response Structure |
92 | + * Byte Size In/Out Description | 92 | + * Byte Size In/Out Description |
93 | + * Offset (Bytes) | 93 | + * Offset (Bytes) |
94 | + * 0x000 4 In Platform command | 94 | + * 0x000 4 In Platform command |
95 | + * Out Platform command response size | 95 | + * Out Platform command response size |
96 | + * | 96 | + * |
97 | + * Note: most TCG Simulator commands simply return zero here with no indication | 97 | + * Note: most TCG Simulator commands simply return zero here with no indication |
98 | + * of success or failure. | 98 | + * of success or failure. |
99 | + */ | 99 | + */ |
100 | +struct svsm_vtpm_response { | 100 | +struct svsm_vtpm_response { |
101 | + u32 size; | 101 | + u32 size; |
102 | +}; | 102 | +}; |
103 | + | 103 | + |
104 | +/** | 104 | +/** |
105 | + * struct svsm_vtpm_cmd_request - Structure for a TPM_SEND_COMMAND request | 105 | + * struct svsm_vtpm_cmd_request - Structure for a TPM_SEND_COMMAND request |
106 | + * @cmd: The command to send (must be TPM_SEND_COMMAND) | 106 | + * @cmd: The command to send (must be TPM_SEND_COMMAND) |
107 | + * @locality: The locality | 107 | + * @locality: The locality |
108 | + * @buf_size: The size of the input buffer following | 108 | + * @buf_size: The size of the input buffer following |
109 | + * @buf: A buffer of size buf_size | 109 | + * @buf: A buffer of size buf_size |
110 | + * | 110 | + * |
111 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - | 111 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - |
112 | + * Table 16: TPM_SEND_COMMAND Request Structure | 112 | + * Table 16: TPM_SEND_COMMAND Request Structure |
113 | + * Byte Size Meaning | 113 | + * Byte Size Meaning |
114 | + * Offset (Bytes) | 114 | + * Offset (Bytes) |
115 | + * 0x000 4 Platform command (8) | 115 | + * 0x000 4 Platform command (8) |
116 | + * 0x004 1 Locality (must-be-0) | 116 | + * 0x004 1 Locality (must-be-0) |
117 | + * 0x005 4 TPM Command size (in bytes) | 117 | + * 0x005 4 TPM Command size (in bytes) |
118 | + * 0x009 Variable TPM Command | 118 | + * 0x009 Variable TPM Command |
119 | + * | 119 | + * |
120 | + * Note: the TCG Simulator expects @buf_size to be equal to the size of the | 120 | + * Note: the TCG Simulator expects @buf_size to be equal to the size of the |
121 | + * specific TPM command, otherwise an TPM_RC_COMMAND_SIZE error is returned. | 121 | + * specific TPM command, otherwise an TPM_RC_COMMAND_SIZE error is returned. |
122 | + */ | 122 | + */ |
123 | +struct svsm_vtpm_cmd_request { | 123 | +struct svsm_vtpm_cmd_request { |
124 | + u32 cmd; | 124 | + u32 cmd; |
125 | + u8 locality; | 125 | + u8 locality; |
126 | + u32 buf_size; | 126 | + u32 buf_size; |
127 | + u8 buf[]; | 127 | + u8 buf[]; |
128 | +} __packed; | 128 | +} __packed; |
129 | + | 129 | + |
130 | +/** | 130 | +/** |
131 | + * struct svsm_vtpm_cmd_response - Structure for a TPM_SEND_COMMAND response | 131 | + * struct svsm_vtpm_cmd_response - Structure for a TPM_SEND_COMMAND response |
132 | + * @buf_size: The size of the output buffer following | 132 | + * @buf_size: The size of the output buffer following |
133 | + * @buf: A buffer of size buf_size | 133 | + * @buf: A buffer of size buf_size |
134 | + * | 134 | + * |
135 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - | 135 | + * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" - |
136 | + * Table 17: TPM_SEND_COMMAND Response Structure | 136 | + * Table 17: TPM_SEND_COMMAND Response Structure |
137 | + * Byte Size Meaning | 137 | + * Byte Size Meaning |
138 | + * Offset (Bytes) | 138 | + * Offset (Bytes) |
139 | + * 0x000 4 Response size (in bytes) | 139 | + * 0x000 4 Response size (in bytes) |
140 | + * 0x004 Variable Response | 140 | + * 0x004 Variable Response |
141 | + */ | 141 | + */ |
142 | +struct svsm_vtpm_cmd_response { | 142 | +struct svsm_vtpm_cmd_response { |
143 | + u32 buf_size; | 143 | + u32 buf_size; |
144 | + u8 buf[]; | 144 | + u8 buf[]; |
145 | +}; | 145 | +}; |
146 | + | 146 | + |
147 | +/** | 147 | +/** |
148 | + * svsm_vtpm_cmd_request_fill() - Fill a TPM_SEND_COMMAND request to be sent to SVSM | 148 | + * svsm_vtpm_cmd_request_fill() - Fill a TPM_SEND_COMMAND request to be sent to SVSM |
149 | + * @req: The struct svsm_vtpm_cmd_request to fill | 149 | + * @req: The struct svsm_vtpm_cmd_request to fill |
150 | + * @locality: The locality | 150 | + * @locality: The locality |
151 | + * @buf: The buffer from where to copy the payload of the command | 151 | + * @buf: The buffer from where to copy the payload of the command |
152 | + * @len: The size of the buffer | 152 | + * @len: The size of the buffer |
153 | + * | 153 | + * |
154 | + * Return: 0 on success, negative error code on failure. | 154 | + * Return: 0 on success, negative error code on failure. |
155 | + */ | 155 | + */ |
156 | +static inline int | 156 | +static inline int |
157 | +svsm_vtpm_cmd_request_fill(struct svsm_vtpm_cmd_request *req, u8 locality, | 157 | +svsm_vtpm_cmd_request_fill(struct svsm_vtpm_cmd_request *req, u8 locality, |
158 | + const u8 *buf, size_t len) | 158 | + const u8 *buf, size_t len) |
159 | +{ | 159 | +{ |
160 | + if (len > SVSM_VTPM_MAX_BUFFER - sizeof(*req)) | 160 | + if (len > SVSM_VTPM_MAX_BUFFER - sizeof(*req)) |
161 | + return -EINVAL; | 161 | + return -EINVAL; |
162 | + | 162 | + |
163 | + req->cmd = 8; /* TPM_SEND_COMMAND */ | 163 | + req->cmd = 8; /* TPM_SEND_COMMAND */ |
164 | + req->locality = locality; | 164 | + req->locality = locality; |
165 | + req->buf_size = len; | 165 | + req->buf_size = len; |
166 | + | 166 | + |
167 | + memcpy(req->buf, buf, len); | 167 | + memcpy(req->buf, buf, len); |
168 | + | 168 | + |
169 | + return 0; | 169 | + return 0; |
170 | +} | 170 | +} |
171 | + | 171 | + |
172 | +/** | 172 | +/** |
173 | + * svsm_vtpm_cmd_response_parse() - Parse a TPM_SEND_COMMAND response received from SVSM | 173 | + * svsm_vtpm_cmd_response_parse() - Parse a TPM_SEND_COMMAND response received from SVSM |
174 | + * @resp: The struct svsm_vtpm_cmd_response to parse | 174 | + * @resp: The struct svsm_vtpm_cmd_response to parse |
175 | + * @buf: The buffer where to copy the response | 175 | + * @buf: The buffer where to copy the response |
176 | + * @len: The size of the buffer | 176 | + * @len: The size of the buffer |
177 | + * | 177 | + * |
178 | + * Return: buffer size filled with the response on success, negative error | 178 | + * Return: buffer size filled with the response on success, negative error |
179 | + * code on failure. | 179 | + * code on failure. |
180 | + */ | 180 | + */ |
181 | +static inline int | 181 | +static inline int |
182 | +svsm_vtpm_cmd_response_parse(const struct svsm_vtpm_cmd_response *resp, u8 *buf, | 182 | +svsm_vtpm_cmd_response_parse(const struct svsm_vtpm_cmd_response *resp, u8 *buf, |
183 | + size_t len) | 183 | + size_t len) |
184 | +{ | 184 | +{ |
185 | + if (len < resp->buf_size) | 185 | + if (len < resp->buf_size) |
186 | + return -E2BIG; | 186 | + return -E2BIG; |
187 | + | 187 | + |
188 | + if (resp->buf_size > SVSM_VTPM_MAX_BUFFER - sizeof(*resp)) | 188 | + if (resp->buf_size > SVSM_VTPM_MAX_BUFFER - sizeof(*resp)) |
189 | + return -EINVAL; // Invalid response from the platform TPM | 189 | + return -EINVAL; // Invalid response from the platform TPM |
190 | + | 190 | + |
191 | + memcpy(buf, resp->buf, resp->buf_size); | 191 | + memcpy(buf, resp->buf, resp->buf_size); |
192 | + | 192 | + |
193 | + return resp->buf_size; | 193 | + return resp->buf_size; |
194 | +} | 194 | +} |
195 | + | 195 | + |
196 | +#endif /* _TPM_SVSM_H_ */ | 196 | +#endif /* _TPM_SVSM_H_ */ |
197 | -- | 197 | -- |
198 | 2.49.0 | 198 | 2.49.0 |
199 | 199 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
4 | 4 | ||
5 | The specification defines a protocol that a SEV-SNP guest OS can use to | 5 | The specification defines a protocol that a SEV-SNP guest OS can use to |
6 | discover and talk to a vTPM emulated by the Secure VM Service Module (SVSM) | 6 | discover and talk to a vTPM emulated by the Secure VM Service Module (SVSM) |
7 | in the guest context, but at a more privileged level (VMPL0). | 7 | in the guest context, but at a more privileged level (VMPL0). |
8 | 8 | ||
9 | The new tpm-svsm platform driver uses two functions exposed by x86/sev | 9 | The new tpm-svsm platform driver uses API exposed by x86/sev to send |
10 | to verify that the device is actually emulated by the platform and to | 10 | commands and receive responses. |
11 | send commands and receive responses. | ||
12 | 11 | ||
13 | The device cannot be hot-plugged/unplugged as it is emulated by the | 12 | The device cannot be hot-plugged/unplugged as it is emulated by the |
14 | platform, so we can use module_platform_driver_probe(). The probe | 13 | platform, so we can use module_platform_driver_probe(). The device will |
15 | function will only check whether in the current runtime configuration, | 14 | be registered by the platform only when it's available, so the probe |
16 | SVSM is present and provides a vTPM. | 15 | function just needs to setup the tpm_chip. |
17 | 16 | ||
18 | This device does not support interrupts and sends responses to commands | 17 | This device does not support interrupts and sends responses to commands |
19 | synchronously. In order to have .recv() called just after .send() in | 18 | synchronously. |
20 | tpm_try_transmit(), the .status() callback returns 0, and both | 19 | In order to have .recv() called just after .send() in tpm_try_transmit(), |
21 | .req_complete_mask and .req_complete_val are set to 0. | 20 | the .status() callback is not implemented as recently supported by |
21 | commit 980a573621ea ("tpm: Make chip->{status,cancel,req_canceled} opt"). | ||
22 | 22 | ||
23 | [1] "Secure VM Service Module for SEV-SNP Guests" | 23 | [1] "Secure VM Service Module for SEV-SNP Guests" |
24 | Publication # 58019 Revision: 1.00 | 24 | Publication # 58019 Revision: 1.00 |
25 | 25 | ||
26 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> | ||
26 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | 27 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> |
27 | --- | 28 | --- |
29 | v7: | ||
30 | - added Jarkko's R-b | ||
31 | - avoided to call snp_svsm_vtpm_probe() since the device will be | ||
32 | registered by SEV core only if the device is detected [Borislav] | ||
33 | - updated commit description | ||
28 | v6: | 34 | v6: |
29 | - removed the `locality` field (set to 0) and the FIXME comment [Jarkko] | 35 | - removed the `locality` field (set to 0) and the FIXME comment [Jarkko] |
30 | v5: | 36 | v5: |
31 | - removed cancel/status/req_* ops after rebase on master that cotains | 37 | - removed cancel/status/req_* ops after rebase on master that cotains |
32 | commit 980a573621ea ("tpm: Make chip->{status,cancel,req_canceled} opt") | 38 | commit 980a573621ea ("tpm: Make chip->{status,cancel,req_canceled} opt") |
... | ... | ||
36 | v3: | 42 | v3: |
37 | - removed send_recv() ops and followed the ftpm driver implementing .status, | 43 | - removed send_recv() ops and followed the ftpm driver implementing .status, |
38 | .req_complete_mask, .req_complete_val, etc. [Jarkko] | 44 | .req_complete_mask, .req_complete_val, etc. [Jarkko] |
39 | - removed link to the spec because those URLs are unstable [Borislav] | 45 | - removed link to the spec because those URLs are unstable [Borislav] |
40 | --- | 46 | --- |
41 | drivers/char/tpm/tpm_svsm.c | 128 ++++++++++++++++++++++++++++++++++++ | 47 | drivers/char/tpm/tpm_svsm.c | 125 ++++++++++++++++++++++++++++++++++++ |
42 | drivers/char/tpm/Kconfig | 10 +++ | 48 | drivers/char/tpm/Kconfig | 10 +++ |
43 | drivers/char/tpm/Makefile | 1 + | 49 | drivers/char/tpm/Makefile | 1 + |
44 | 3 files changed, 139 insertions(+) | 50 | 3 files changed, 136 insertions(+) |
45 | create mode 100644 drivers/char/tpm/tpm_svsm.c | 51 | create mode 100644 drivers/char/tpm/tpm_svsm.c |
46 | 52 | ||
47 | diff --git a/drivers/char/tpm/tpm_svsm.c b/drivers/char/tpm/tpm_svsm.c | 53 | diff --git a/drivers/char/tpm/tpm_svsm.c b/drivers/char/tpm/tpm_svsm.c |
48 | new file mode 100644 | 54 | new file mode 100644 |
49 | index XXXXXXX..XXXXXXX | 55 | index XXXXXXX..XXXXXXX |
... | ... | ||
116 | + struct device *dev = &pdev->dev; | 122 | + struct device *dev = &pdev->dev; |
117 | + struct tpm_svsm_priv *priv; | 123 | + struct tpm_svsm_priv *priv; |
118 | + struct tpm_chip *chip; | 124 | + struct tpm_chip *chip; |
119 | + int err; | 125 | + int err; |
120 | + | 126 | + |
121 | + if (!snp_svsm_vtpm_probe()) | ||
122 | + return -ENODEV; | ||
123 | + | ||
124 | + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); | 127 | + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); |
125 | + if (!priv) | 128 | + if (!priv) |
126 | + return -ENOMEM; | 129 | + return -ENOMEM; |
127 | + | 130 | + |
128 | + /* | 131 | + /* |
... | ... | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
3 | SNP platform can provide a vTPM device emulated by SVSM. | 3 | SNP platform can provide a vTPM device emulated by SVSM. |
4 | 4 | ||
5 | The "tpm-svsm" device can be handled by the platform driver added | 5 | The "tpm-svsm" device can be handled by the platform driver added |
6 | by the previous commit in drivers/char/tpm/tpm_svsm.c | 6 | by the previous commit in drivers/char/tpm/tpm_svsm.c |
7 | 7 | ||
8 | Register the device unconditionally. The support check (e.g. SVSM, cmd) | 8 | Register the platform device only when SVSM is available and it |
9 | is in snp_svsm_vtpm_probe(), keeping all logic in one place. | 9 | supports vTPM commands as checked by snp_svsm_vtpm_probe(). |
10 | This function is called during the driver's probe along with other | ||
11 | setup tasks like memory allocation. | ||
12 | 10 | ||
13 | Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> | 11 | Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> |
12 | Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> | ||
14 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | 13 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> |
15 | --- | 14 | --- |
15 | v7: | ||
16 | - added Jarkko's R-b | ||
17 | - call snp_svsm_vtpm_probe() before registering the device [Borislav] | ||
18 | - s/device/devices in pr_info [Tom] | ||
19 | - updated commit description | ||
16 | v6: | 20 | v6: |
17 | - added Tom's R-b | 21 | - added Tom's R-b |
18 | v4: | 22 | v4: |
19 | - explained better why we register it anyway in the commit message | 23 | - explained better why we register it anyway in the commit message |
20 | --- | 24 | --- |
21 | arch/x86/coco/sev/core.c | 8 ++++++++ | 25 | arch/x86/coco/sev/core.c | 11 ++++++++++- |
22 | 1 file changed, 8 insertions(+) | 26 | 1 file changed, 10 insertions(+), 1 deletion(-) |
23 | 27 | ||
24 | diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c | 28 | diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c |
25 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/arch/x86/coco/sev/core.c | 30 | --- a/arch/x86/coco/sev/core.c |
27 | +++ b/arch/x86/coco/sev/core.c | 31 | +++ b/arch/x86/coco/sev/core.c |
... | ... | ||
39 | if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) | 43 | if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) |
40 | @@ -XXX,XX +XXX,XX @@ static int __init snp_init_platform_device(void) | 44 | @@ -XXX,XX +XXX,XX @@ static int __init snp_init_platform_device(void) |
41 | if (platform_device_register(&sev_guest_device)) | 45 | if (platform_device_register(&sev_guest_device)) |
42 | return -ENODEV; | 46 | return -ENODEV; |
43 | 47 | ||
44 | + if (platform_device_register(&tpm_svsm_device)) | 48 | - pr_info("SNP guest platform device initialized.\n"); |
49 | + if (snp_svsm_vtpm_probe() && | ||
50 | + platform_device_register(&tpm_svsm_device)) | ||
45 | + return -ENODEV; | 51 | + return -ENODEV; |
46 | + | 52 | + |
47 | pr_info("SNP guest platform device initialized.\n"); | 53 | + pr_info("SNP guest platform devices initialized.\n"); |
48 | return 0; | 54 | return 0; |
49 | } | 55 | } |
56 | device_initcall(snp_init_platform_device); | ||
50 | -- | 57 | -- |
51 | 2.49.0 | 58 | 2.49.0 | diff view generated by jsdifflib |