diff mbox series

[v3,1/4] x86/sev: add SVSM vTPM probe/send_command functions

Message ID 20250311094225.35129-2-sgarzare@redhat.com (mailing list archive)
State New
Headers show
Series Enlightened vTPM support for SVSM on SEV-SNP | expand

Commit Message

Stefano Garzarella March 11, 2025, 9:42 a.m. UTC
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 these functions to be used by other modules such as a tpm
driver.

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

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>
---
v3:
- removed link to the spec because those URLs are unstable [Borislav]
- squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
  in this one [Borislav]
- slimmed down snp_svsm_vtpm_probe() [Borislav]
- removed features check and any print related [Tom]
---
 arch/x86/include/asm/sev.h |  7 +++++++
 arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

Comments

Jarkko Sakkinen March 11, 2025, 9:56 a.m. UTC | #1
On Tue, Mar 11, 2025 at 10:42:22AM +0100, Stefano Garzarella wrote:
> 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 these functions to be used by other modules such as a tpm
> driver.
> 
> [1] "Secure VM Service Module for SEV-SNP Guests"
>     Publication # 58019 Revision: 1.00
> 
> 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>
> ---
> v3:
> - removed link to the spec because those URLs are unstable [Borislav]
> - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
>   in this one [Borislav]
> - slimmed down snp_svsm_vtpm_probe() [Borislav]
> - removed features check and any print related [Tom]
> ---
>  arch/x86/include/asm/sev.h |  7 +++++++
>  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> index ba7999f66abe..09471d058ce5 100644
> --- a/arch/x86/include/asm/sev.h
> +++ b/arch/x86/include/asm/sev.h
> @@ -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,9 @@ 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);
>  
> +bool snp_svsm_vtpm_probe(void);
> +int snp_svsm_vtpm_send_command(u8 *buffer);
> +
>  void __init snp_secure_tsc_prepare(void);
>  void __init snp_secure_tsc_init(void);
>  
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 96c7bc698e6b..2166bdff88b7 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
>  	return ret;
>  }
>  

Since this is an exported symbol, it'd be a good practice document
snp_svsm_vtpm_probe().

> +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);

I supposed CAA is some kind of shared memory area for host and VM?

> +
> +	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)) == BIT_ULL(8);
> +}
> +EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe);
> +

Ditto.

> +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,
> -- 
> 2.48.1
> 

That said, these are rather self-documenting (i.e, nice and clean).

BR, Jarkko
Stefano Garzarella March 12, 2025, 10:56 a.m. UTC | #2
On Tue, Mar 11, 2025 at 11:56:23AM +0200, Jarkko Sakkinen wrote:
>On Tue, Mar 11, 2025 at 10:42:22AM +0100, Stefano Garzarella wrote:
>> 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 these functions to be used by other modules such as a tpm
>> driver.
>>
>> [1] "Secure VM Service Module for SEV-SNP Guests"
>>     Publication # 58019 Revision: 1.00
>>
>> 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>
>> ---
>> v3:
>> - removed link to the spec because those URLs are unstable [Borislav]
>> - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
>>   in this one [Borislav]
>> - slimmed down snp_svsm_vtpm_probe() [Borislav]
>> - removed features check and any print related [Tom]
>> ---
>>  arch/x86/include/asm/sev.h |  7 +++++++
>>  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
>>  2 files changed, 38 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
>> index ba7999f66abe..09471d058ce5 100644
>> --- a/arch/x86/include/asm/sev.h
>> +++ b/arch/x86/include/asm/sev.h
>> @@ -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,9 @@ 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);
>>
>> +bool snp_svsm_vtpm_probe(void);
>> +int snp_svsm_vtpm_send_command(u8 *buffer);
>> +
>>  void __init snp_secure_tsc_prepare(void);
>>  void __init snp_secure_tsc_init(void);
>>
>> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
>> index 96c7bc698e6b..2166bdff88b7 100644
>> --- a/arch/x86/coco/sev/core.c
>> +++ b/arch/x86/coco/sev/core.c
>> @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
>>  	return ret;
>>  }
>>
>
>Since this is an exported symbol, it'd be a good practice document
>snp_svsm_vtpm_probe().

Yes, you are right, since the others were not documented, I had not 
added it, but I agree with you, I'll do in v4.

>
>> +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);
>
>I supposed CAA is some kind of shared memory area for host and VM?

Not with the host, but with SVSM, which is the firmware running in the 
guest, but at a higher privilege level (VMPL) than the kernel, where, 
for example, the vTPM is emulated.

BTW, yep it is a shared memory defined by the SVSM calling convention.
 From AMD SVSM specification:

   5 Calling Convention

     Each call to the SVSM conveys data through a combination of the
     SVSM Calling Area (whose address was first configured through the
     SVSM_CAA field of the secrets page) and registers. Use of the
     Calling Area is necessary for the SVSM to detect the difference
     between a call that was issued by the guest and a spurious
     invocation by a poorly behaved host. Registers are used for all
     other parameters.
     The initially configured SVSM Calling Area is a page of memory that
     lies outside the initial SVSM memory range and has not had its VMPL
     permissions restricted in any way. The address is guaranteed to be
     aligned to a 4 KB boundary, so the remainder of the page may be used
     by the guest for memory-based parameter passing if desired.
     The contents of the Calling Area are described in the following
     table:

     Table 2: Calling Area
     Byte      Size     Name                Description
     Offset

     0x000     1 byte   SVSM_CALL_PENDING   Indicates whether a call has
                                            been requested by the guest
                                            (0=no call requested, 1=call
                                            requested).
     0x001     1 byte   SVSM_MEM_AVAILABLE  Free memory is available to
                                            be withdrawn.
     0x002     6 byte                       Reserved. The SVSM is not
                                            required to verify that
                                            these bytes are 0.

>
>> +
>> +	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)) == BIT_ULL(8);
>> +}
>> +EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe);
>> +
>
>Ditto.

Ack.

>
>> +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,
>> --
>> 2.48.1
>>
>
>That said, these are rather self-documenting (i.e, nice and clean).

Thanks for the review!
Stefano
Jarkko Sakkinen March 14, 2025, 3:04 p.m. UTC | #3
On Wed, Mar 12, 2025 at 11:56:06AM +0100, Stefano Garzarella wrote:
> On Tue, Mar 11, 2025 at 11:56:23AM +0200, Jarkko Sakkinen wrote:
> > On Tue, Mar 11, 2025 at 10:42:22AM +0100, Stefano Garzarella wrote:
> > > 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 these functions to be used by other modules such as a tpm
> > > driver.
> > > 
> > > [1] "Secure VM Service Module for SEV-SNP Guests"
> > >     Publication # 58019 Revision: 1.00
> > > 
> > > 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>
> > > ---
> > > v3:
> > > - removed link to the spec because those URLs are unstable [Borislav]
> > > - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
> > >   in this one [Borislav]
> > > - slimmed down snp_svsm_vtpm_probe() [Borislav]
> > > - removed features check and any print related [Tom]
> > > ---
> > >  arch/x86/include/asm/sev.h |  7 +++++++
> > >  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
> > >  2 files changed, 38 insertions(+)
> > > 
> > > diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> > > index ba7999f66abe..09471d058ce5 100644
> > > --- a/arch/x86/include/asm/sev.h
> > > +++ b/arch/x86/include/asm/sev.h
> > > @@ -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,9 @@ 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);
> > > 
> > > +bool snp_svsm_vtpm_probe(void);
> > > +int snp_svsm_vtpm_send_command(u8 *buffer);
> > > +
> > >  void __init snp_secure_tsc_prepare(void);
> > >  void __init snp_secure_tsc_init(void);
> > > 
> > > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> > > index 96c7bc698e6b..2166bdff88b7 100644
> > > --- a/arch/x86/coco/sev/core.c
> > > +++ b/arch/x86/coco/sev/core.c
> > > @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
> > >  	return ret;
> > >  }
> > > 
> > 
> > Since this is an exported symbol, it'd be a good practice document
> > snp_svsm_vtpm_probe().
> 
> Yes, you are right, since the others were not documented, I had not added
> it, but I agree with you, I'll do in v4.
> 
> > 
> > > +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);
> > 
> > I supposed CAA is some kind of shared memory area for host and VM?
> 
> Not with the host, but with SVSM, which is the firmware running in the
> guest, but at a higher privilege level (VMPL) than the kernel, where, for
> example, the vTPM is emulated.
> 
> BTW, yep it is a shared memory defined by the SVSM calling convention.
> From AMD SVSM specification:
> 
>   5 Calling Convention
> 
>     Each call to the SVSM conveys data through a combination of the
>     SVSM Calling Area (whose address was first configured through the
>     SVSM_CAA field of the secrets page) and registers. Use of the
>     Calling Area is necessary for the SVSM to detect the difference
>     between a call that was issued by the guest and a spurious
>     invocation by a poorly behaved host. Registers are used for all
>     other parameters.
>     The initially configured SVSM Calling Area is a page of memory that
>     lies outside the initial SVSM memory range and has not had its VMPL
>     permissions restricted in any way. The address is guaranteed to be
>     aligned to a 4 KB boundary, so the remainder of the page may be used
>     by the guest for memory-based parameter passing if desired.
>     The contents of the Calling Area are described in the following
>     table:
> 
>     Table 2: Calling Area
>     Byte      Size     Name                Description
>     Offset
> 
>     0x000     1 byte   SVSM_CALL_PENDING   Indicates whether a call has
>                                            been requested by the guest
>                                            (0=no call requested, 1=call
>                                            requested).
>     0x001     1 byte   SVSM_MEM_AVAILABLE  Free memory is available to
>                                            be withdrawn.
>     0x002     6 byte                       Reserved. The SVSM is not
>                                            required to verify that
>                                            these bytes are 0.
> 
> > 
> > > +
> > > +	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)) == BIT_ULL(8);
> > > +}
> > > +EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe);
> > > +
> > 
> > Ditto.
> 
> Ack.
> 
> > 
> > > +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,
> > > --
> > > 2.48.1
> > > 
> > 
> > That said, these are rather self-documenting (i.e, nice and clean).
> 
> Thanks for the review!

Sure, don't worry about it! Let's just cycle this enough rounds that
it fits well...

> Stefano

BR, Jarkko
Tom Lendacky March 14, 2025, 3:27 p.m. UTC | #4
On 3/11/25 04:42, Stefano Garzarella wrote:
> 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 these functions to be used by other modules such as a tpm
> driver.
> 
> [1] "Secure VM Service Module for SEV-SNP Guests"
>     Publication # 58019 Revision: 1.00
> 
> 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>

One minor nit below, otherwise:

Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>

> ---
> v3:
> - removed link to the spec because those URLs are unstable [Borislav]
> - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
>   in this one [Borislav]
> - slimmed down snp_svsm_vtpm_probe() [Borislav]
> - removed features check and any print related [Tom]
> ---
>  arch/x86/include/asm/sev.h |  7 +++++++
>  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> index ba7999f66abe..09471d058ce5 100644
> --- a/arch/x86/include/asm/sev.h
> +++ b/arch/x86/include/asm/sev.h
> @@ -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,9 @@ 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);
>  
> +bool snp_svsm_vtpm_probe(void);
> +int snp_svsm_vtpm_send_command(u8 *buffer);
> +
>  void __init snp_secure_tsc_prepare(void);
>  void __init snp_secure_tsc_init(void);
>  
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 96c7bc698e6b..2166bdff88b7 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
>  	return ret;
>  }
>  
> +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)) == BIT_ULL(8);

It's a bool function, so this could simplified to just:

	return call.rcx_out & BIT_ULL(8);

Thanks,
Tom

> +}
> +EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe);
> +
> +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,
Jarkko Sakkinen March 17, 2025, 1:36 p.m. UTC | #5
On Fri, Mar 14, 2025 at 10:27:07AM -0500, Tom Lendacky wrote:
> On 3/11/25 04:42, Stefano Garzarella wrote:
> > 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 these functions to be used by other modules such as a tpm
> > driver.
> > 
> > [1] "Secure VM Service Module for SEV-SNP Guests"
> >     Publication # 58019 Revision: 1.00
> > 
> > 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>
> 
> One minor nit below, otherwise:
> 
> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> > ---
> > v3:
> > - removed link to the spec because those URLs are unstable [Borislav]
> > - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
> >   in this one [Borislav]
> > - slimmed down snp_svsm_vtpm_probe() [Borislav]
> > - removed features check and any print related [Tom]
> > ---
> >  arch/x86/include/asm/sev.h |  7 +++++++
> >  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
> >  2 files changed, 38 insertions(+)
> > 
> > diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> > index ba7999f66abe..09471d058ce5 100644
> > --- a/arch/x86/include/asm/sev.h
> > +++ b/arch/x86/include/asm/sev.h
> > @@ -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,9 @@ 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);
> >  
> > +bool snp_svsm_vtpm_probe(void);
> > +int snp_svsm_vtpm_send_command(u8 *buffer);
> > +
> >  void __init snp_secure_tsc_prepare(void);
> >  void __init snp_secure_tsc_init(void);
> >  
> > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> > index 96c7bc698e6b..2166bdff88b7 100644
> > --- a/arch/x86/coco/sev/core.c
> > +++ b/arch/x86/coco/sev/core.c
> > @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
> >  	return ret;
> >  }
> >  
> > +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)) == BIT_ULL(8);
> 
> It's a bool function, so this could simplified to just:
> 
> 	return call.rcx_out & BIT_ULL(8);

Or perhaps even just "call.rcx_out & 0x100". I don't think BIT_ULL()
here brings much additional clarity or anything useful...


> 
> Thanks,
> Tom

BR, Jarkko
Stefano Garzarella March 18, 2025, 10:07 a.m. UTC | #6
On Mon, Mar 17, 2025 at 03:36:26PM +0200, Jarkko Sakkinen wrote:
>On Fri, Mar 14, 2025 at 10:27:07AM -0500, Tom Lendacky wrote:
>> On 3/11/25 04:42, Stefano Garzarella wrote:
>> > 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 these functions to be used by other modules such as a tpm
>> > driver.
>> >
>> > [1] "Secure VM Service Module for SEV-SNP Guests"
>> >     Publication # 58019 Revision: 1.00
>> >
>> > 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>
>>
>> One minor nit below, otherwise:
>>
>> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>

Thanks!

>>
>> > ---
>> > v3:
>> > - removed link to the spec because those URLs are unstable [Borislav]
>> > - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
>> >   in this one [Borislav]
>> > - slimmed down snp_svsm_vtpm_probe() [Borislav]
>> > - removed features check and any print related [Tom]
>> > ---
>> >  arch/x86/include/asm/sev.h |  7 +++++++
>> >  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
>> >  2 files changed, 38 insertions(+)
>> >
>> > diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
>> > index ba7999f66abe..09471d058ce5 100644
>> > --- a/arch/x86/include/asm/sev.h
>> > +++ b/arch/x86/include/asm/sev.h
>> > @@ -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,9 @@ 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);
>> >
>> > +bool snp_svsm_vtpm_probe(void);
>> > +int snp_svsm_vtpm_send_command(u8 *buffer);
>> > +
>> >  void __init snp_secure_tsc_prepare(void);
>> >  void __init snp_secure_tsc_init(void);
>> >
>> > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
>> > index 96c7bc698e6b..2166bdff88b7 100644
>> > --- a/arch/x86/coco/sev/core.c
>> > +++ b/arch/x86/coco/sev/core.c
>> > @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
>> >  	return ret;
>> >  }
>> >
>> > +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)) == BIT_ULL(8);
>>
>> It's a bool function, so this could simplified to just:
>>
>> 	return call.rcx_out & BIT_ULL(8);

Sure.

>
>Or perhaps even just "call.rcx_out & 0x100". I don't think BIT_ULL()
>here brings much additional clarity or anything useful...

I can do that, I slightly prefer BIT_ULL() macro, but I don't have a 
strong opinion on my side.
@Borislav since you suggested it, WDYT?

Thanks,
Stefano
Jarkko Sakkinen March 20, 2025, 3:03 p.m. UTC | #7
On Tue, Mar 18, 2025 at 11:07:57AM +0100, Stefano Garzarella wrote:
> On Mon, Mar 17, 2025 at 03:36:26PM +0200, Jarkko Sakkinen wrote:
> > On Fri, Mar 14, 2025 at 10:27:07AM -0500, Tom Lendacky wrote:
> > > On 3/11/25 04:42, Stefano Garzarella wrote:
> > > > 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 these functions to be used by other modules such as a tpm
> > > > driver.
> > > >
> > > > [1] "Secure VM Service Module for SEV-SNP Guests"
> > > >     Publication # 58019 Revision: 1.00
> > > >
> > > > 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>
> > > 
> > > One minor nit below, otherwise:
> > > 
> > > Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Thanks!
> 
> > > 
> > > > ---
> > > > v3:
> > > > - removed link to the spec because those URLs are unstable [Borislav]
> > > > - squashed "x86/sev: add SVSM call macros for the vTPM protocol" patch
> > > >   in this one [Borislav]
> > > > - slimmed down snp_svsm_vtpm_probe() [Borislav]
> > > > - removed features check and any print related [Tom]
> > > > ---
> > > >  arch/x86/include/asm/sev.h |  7 +++++++
> > > >  arch/x86/coco/sev/core.c   | 31 +++++++++++++++++++++++++++++++
> > > >  2 files changed, 38 insertions(+)
> > > >
> > > > diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> > > > index ba7999f66abe..09471d058ce5 100644
> > > > --- a/arch/x86/include/asm/sev.h
> > > > +++ b/arch/x86/include/asm/sev.h
> > > > @@ -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,9 @@ 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);
> > > >
> > > > +bool snp_svsm_vtpm_probe(void);
> > > > +int snp_svsm_vtpm_send_command(u8 *buffer);
> > > > +
> > > >  void __init snp_secure_tsc_prepare(void);
> > > >  void __init snp_secure_tsc_init(void);
> > > >
> > > > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> > > > index 96c7bc698e6b..2166bdff88b7 100644
> > > > --- a/arch/x86/coco/sev/core.c
> > > > +++ b/arch/x86/coco/sev/core.c
> > > > @@ -2628,6 +2628,37 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
> > > >  	return ret;
> > > >  }
> > > >
> > > > +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)) == BIT_ULL(8);
> > > 
> > > It's a bool function, so this could simplified to just:
> > > 
> > > 	return call.rcx_out & BIT_ULL(8);
> 
> Sure.
> 
> > 
> > Or perhaps even just "call.rcx_out & 0x100". I don't think BIT_ULL()
> > here brings much additional clarity or anything useful...
> 
> I can do that, I slightly prefer BIT_ULL() macro, but I don't have a strong
> opinion on my side.
> @Borislav since you suggested it, WDYT?

Either goes for me. Sorry for nitpicking that :-) The first comment
stil applies.

> 
> Thanks,
> Stefano
> 

BR, Jarkko
Borislav Petkov March 20, 2025, 5:16 p.m. UTC | #8
On Thu, Mar 20, 2025 at 05:03:09PM +0200, Jarkko Sakkinen wrote:
> > I can do that, I slightly prefer BIT_ULL() macro, but I don't have a strong
> > opinion on my side.
> > @Borislav since you suggested it, WDYT?
> 
> Either goes for me. Sorry for nitpicking that :-) The first comment
> stil applies.

Bit 8 is a lot better than 0x100.

Let's give a better example:

0x0000000008000000

or

BIT_ULL(27)

:-)

While I'm here: I'm guessing I'll route patches 1 and 4 through tip once
they're ready to go and give Jarkko an immutable branch he can base the other
two ontop.

Agreed?

Thx.
Jarkko Sakkinen March 20, 2025, 5:30 p.m. UTC | #9
On Thu, Mar 20, 2025 at 06:16:19PM +0100, Borislav Petkov wrote:
> On Thu, Mar 20, 2025 at 05:03:09PM +0200, Jarkko Sakkinen wrote:
> > > I can do that, I slightly prefer BIT_ULL() macro, but I don't have a strong
> > > opinion on my side.
> > > @Borislav since you suggested it, WDYT?
> > 
> > Either goes for me. Sorry for nitpicking that :-) The first comment
> > stil applies.
> 
> Bit 8 is a lot better than 0x100.
> 
> Let's give a better example:
> 
> 0x0000000008000000
> 
> or
> 
> BIT_ULL(27)
> 
> :-)

Sure, I'm fine with using BIT_ULL() :-)

> 
> While I'm here: I'm guessing I'll route patches 1 and 4 through tip once
> they're ready to go and give Jarkko an immutable branch he can base the other
> two ontop.
> 
> Agreed?

Works for me.

> 
> Thx.
> 
> -- 
> Regards/Gruss,
>     Boris.
> 
> https://people.kernel.org/tglx/notes-about-netiquette

BR, Jarkko
Stefano Garzarella March 21, 2025, 9:01 a.m. UTC | #10
On Thu, Mar 20, 2025 at 07:30:43PM +0200, Jarkko Sakkinen wrote:
>On Thu, Mar 20, 2025 at 06:16:19PM +0100, Borislav Petkov wrote:
>> On Thu, Mar 20, 2025 at 05:03:09PM +0200, Jarkko Sakkinen wrote:
>> > > I can do that, I slightly prefer BIT_ULL() macro, but I don't have a strong
>> > > opinion on my side.
>> > > @Borislav since you suggested it, WDYT?
>> >
>> > Either goes for me. Sorry for nitpicking that :-) The first comment
>> > stil applies.
>>
>> Bit 8 is a lot better than 0x100.
>>
>> Let's give a better example:
>>
>> 0x0000000008000000
>>
>> or
>>
>> BIT_ULL(27)
>>
>> :-)
>
>Sure, I'm fine with using BIT_ULL() :-)

Yeah, we all agree :-)

>
>>
>> While I'm here: I'm guessing I'll route patches 1 and 4 through tip once
>> they're ready to go and give Jarkko an immutable branch he can base the other
>> two ontop.
>>
>> Agreed?
>
>Works for me.

Just a note, patch 2 adds `include/linux/svsm_vtpm.h`, that file is 
basically a translation of the AMD SVSM specification into structures 
and functions used to communicate with SVSM in the way it is defined by 
the specification.

I realized that the file does not fall under any section of MAINTAINERS.
How do you suggest we proceed?

Should we create an SVSM section to maintain it, including the TPM 
driver and future other drivers,etc.?

Or include it in other sections? Which one in this case?

I'm willing to help both as a sub-maintainer and reviewer of course, but 
I would like your advice.

Thanks,
Stefano
Borislav Petkov March 21, 2025, 10:05 p.m. UTC | #11
On Fri, Mar 21, 2025 at 10:01:17AM +0100, Stefano Garzarella wrote:
> Just a note, patch 2 adds `include/linux/svsm_vtpm.h`, that file is
> basically a translation of the AMD SVSM specification into structures and
> functions used to communicate with SVSM in the way it is defined by the
> specification.
> 
> I realized that the file does not fall under any section of MAINTAINERS.
> How do you suggest we proceed?
> 
> Should we create an SVSM section to maintain it, including the TPM driver
> and future other drivers,etc.?

This all belongs to the TPM drivers, right?

I.e., drivers/char/tpm/

So I guess add that header to the TPM DEVICE DRIVER section if the gents there
are fine with it...
Jarkko Sakkinen March 22, 2025, 8:17 p.m. UTC | #12
On Fri, Mar 21, 2025 at 11:05:20PM +0100, Borislav Petkov wrote:
> On Fri, Mar 21, 2025 at 10:01:17AM +0100, Stefano Garzarella wrote:
> > Just a note, patch 2 adds `include/linux/svsm_vtpm.h`, that file is
> > basically a translation of the AMD SVSM specification into structures and
> > functions used to communicate with SVSM in the way it is defined by the
> > specification.
> > 
> > I realized that the file does not fall under any section of MAINTAINERS.
> > How do you suggest we proceed?
> > 
> > Should we create an SVSM section to maintain it, including the TPM driver
> > and future other drivers,etc.?
> 
> This all belongs to the TPM drivers, right?
> 
> I.e., drivers/char/tpm/
> 
> So I guess add that header to the TPM DEVICE DRIVER section if the gents there
> are fine with it...

It's fine for me but I'd suggest to rename the header as "tpm_svsm.h".
Then this will already provide coverage:

https://web.git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git/commit/?id=a2fbcecc7027944a2ce447d4dd72725c5822321f


> 
> -- 
> Regards/Gruss,
>     Boris.
> 
> https://people.kernel.org/tglx/notes-about-netiquette
> 

BR, Jarkko
Stefano Garzarella March 24, 2025, 9 a.m. UTC | #13
On Sat, Mar 22, 2025 at 10:17:03PM +0200, Jarkko Sakkinen wrote:
>On Fri, Mar 21, 2025 at 11:05:20PM +0100, Borislav Petkov wrote:
>> On Fri, Mar 21, 2025 at 10:01:17AM +0100, Stefano Garzarella wrote:
>> > Just a note, patch 2 adds `include/linux/svsm_vtpm.h`, that file is
>> > basically a translation of the AMD SVSM specification into structures and
>> > functions used to communicate with SVSM in the way it is defined by the
>> > specification.
>> >
>> > I realized that the file does not fall under any section of MAINTAINERS.
>> > How do you suggest we proceed?
>> >
>> > Should we create an SVSM section to maintain it, including the TPM driver
>> > and future other drivers,etc.?
>>
>> This all belongs to the TPM drivers, right?

For now yes, we may have other devices in the future, but we can think
about that later.

>>
>> I.e., drivers/char/tpm/
>>
>> So I guess add that header to the TPM DEVICE DRIVER section if the gents there
>> are fine with it...
>
>It's fine for me but I'd suggest to rename the header as "tpm_svsm.h".
>Then this will already provide coverage:
>
>https://web.git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git/commit/?id=a2fbcecc7027944a2ce447d4dd72725c5822321f
>

Great, I'll rename it and send v4.

Thanks,
Stefano
diff mbox series

Patch

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index ba7999f66abe..09471d058ce5 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -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,9 @@  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);
 
+bool snp_svsm_vtpm_probe(void);
+int snp_svsm_vtpm_send_command(u8 *buffer);
+
 void __init snp_secure_tsc_prepare(void);
 void __init snp_secure_tsc_init(void);
 
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 96c7bc698e6b..2166bdff88b7 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -2628,6 +2628,37 @@  static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
 	return ret;
 }
 
+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)) == BIT_ULL(8);
+}
+EXPORT_SYMBOL_GPL(snp_svsm_vtpm_probe);
+
+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,