Re: [PATCH 22/25] KVM: TDX: Use guest physical address to configure EPT level and GPAW

Xiaoyao Li
2024-10-10T09:13:48Z

On 8/13/2024 6:48 AM, Rick Edgecombe wrote:
> From: Xiaoyao Li <xiaoyao.li@intel.com>
>
> KVM reports guest physical address in CPUID.0x800000008.EAX[23:16],
> which is similar to TDX's GPAW. Use this field as the interface for
> userspace to configure the GPAW and EPT level for TDs.
>
> Note,
>
> 1. only value 48 and 52 are supported. 52 means GPAW-52 and EPT level
> 5, and 48 means GPAW-48 and EPT level 4.
> 2. value 48, i.e., GPAW-48 is always supported. value 52 is only
> supported when the platform supports 5 level EPT.
>
> Current TDX module doesn't support max_gpa configuration. However
> current implementation relies on max_gpa to configure EPT level and
> GPAW. Hack KVM to make it work.

This patch needs to be squashed into patch 14.

> Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> ---
> uAPI breakout v1:
> - New patch
> ---
> arch/x86/kvm/vmx/tdx.c | 32 +++++++++++++++++++-------------
> 1 file changed, 19 insertions(+), 13 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index fe2bbc2ced41..c6bfeb0b3cc9 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -514,23 +514,22 @@ static int setup_tdparams_eptp_controls(struct kvm_cpuid2 *cpuid,
> struct td_params *td_params)
> {
> const struct kvm_cpuid_entry2 *entry;
> - int max_pa = 36;
> + int guest_pa;
>
> entry = kvm_find_cpuid_entry2(cpuid->entries, cpuid->nent, 0x80000008, 0);
> - if (entry)
> - max_pa = entry->eax & 0xff;
> + if (!entry)
> + return -EINVAL;
> +
> + guest_pa = (entry->eax >> 16) & 0xff;
> +
> + if (guest_pa != 48 && guest_pa != 52)
> + return -EINVAL;
> +
> + if (guest_pa == 52 && !cpu_has_vmx_ept_5levels())
> + return -EINVAL;
>
> td_params->eptp_controls = VMX_EPTP_MT_WB;
> - /*
> - * No CPU supports 4-level && max_pa > 48.
> - * "5-level paging and 5-level EPT" section 4.1 4-level EPT
> - * "4-level EPT is limited to translating 48-bit guest-physical
> - * addresses."
> - * cpu_has_vmx_ept_5levels() check is just in case.
> - */
> - if (!cpu_has_vmx_ept_5levels() && max_pa > 48)
> - return -EINVAL;
> - if (cpu_has_vmx_ept_5levels() && max_pa > 48) {
> + if (guest_pa == 52) {
> td_params->eptp_controls |= VMX_EPTP_PWL_5;
> td_params->exec_controls |= TDX_EXEC_CONTROL_MAX_GPAW;
> } else {
> @@ -576,6 +575,9 @@ static int setup_tdparams_cpuids(struct kvm_cpuid2 *cpuid,
> value->ebx = entry->ebx;
> value->ecx = entry->ecx;
> value->edx = entry->edx;
> +
> + if (c->leaf == 0x80000008)
> + value->eax &= 0xff00ffff;
> }
>
> return 0;
> @@ -1277,6 +1279,10 @@ static int __init setup_kvm_tdx_caps(void)
> memcpy(dest, &source, sizeof(struct kvm_tdx_cpuid_config));
> if (dest->sub_leaf == KVM_TDX_CPUID_NO_SUBLEAF)
> dest->sub_leaf = 0;
> +
> + /* Work around missing support on old TDX modules */
> + if (dest->leaf == 0x80000008)
> + dest->eax |= 0x00ff0000;
> }
>
> return 0;