RE: [PATCH] KVM: x86/cpuid: Exclude unpermitted xfeatures sizes at KVM_GET_SUPPORTED_CPUID

From: Tian, Kevin
Date: Mon Jan 24 2022 - 22:15:53 EST


> From: Paolo Bonzini <pbonzini@xxxxxxxxxx>
> Sent: Monday, January 24, 2022 10:00 PM
>
> On 1/24/22 09:02, Like Xu wrote:
> > case 0xd: {
> > - u64 guest_perm = xstate_get_guest_group_perm();
> > + u64 supported_xcr0 = supported_xcr0 &
> xstate_get_guest_group_perm();
> >
> > - entry->eax &= supported_xcr0 & guest_perm;
> > + entry->eax &= supported_xcr0;
> > entry->ebx = xstate_required_size(supported_xcr0, false);
> > entry->ecx = entry->ebx;
> > - entry->edx &= (supported_xcr0 & guest_perm) >> 32;
> > + entry->edx &= supported_xcr0 >> 32;
> > if (!supported_xcr0)
> > break;
> >
>
> No, please don't use this kind of shadowing. I'm not even sure it
> works, and one would have to read the C standard or look at the
> disassembly to be sure. Perhaps this instead could be an idea:
>
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index 3dcd58a138a9..03deb51d8d18 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -887,13 +887,14 @@ static inline int __do_cpuid_func(struct
> kvm_cpuid_array *array, u32 function)
> }
> break;
> case 0xd: {
> - u64 supported_xcr0 = supported_xcr0 &
> xstate_get_guest_group_perm();
> + u64 permitted_xcr0 = supported_xcr0 &
> xstate_get_guest_group_perm();
>
> - entry->eax &= supported_xcr0;
> - entry->ebx = xstate_required_size(supported_xcr0, false);
> +#define supported_xcr0 DO_NOT_USE_ME
> + entry->eax &= permitted_xcr0;
> + entry->ebx = xstate_required_size(permitted_xcr0, false);
> entry->ecx = entry->ebx;
> - entry->edx &= supported_xcr0 >> 32;
> - if (!supported_xcr0)
> + entry->edx &= permitted_xcr0 >> 32;
> + if (!permitted_xcr0)
> break;
>
> entry = do_host_cpuid(array, function, 1);
> @@ -902,7 +903,7 @@ static inline int __do_cpuid_func(struct
> kvm_cpuid_array *array, u32 function)
>
> cpuid_entry_override(entry, CPUID_D_1_EAX);
> if (entry->eax & (F(XSAVES)|F(XSAVEC)))
> - entry->ebx = xstate_required_size(supported_xcr0 |
> supported_xss,
> + entry->ebx = xstate_required_size(permitted_xcr0 |
> supported_xss,
> true);
> else {
> WARN_ON_ONCE(supported_xss != 0);
> @@ -913,7 +914,7 @@ static inline int __do_cpuid_func(struct
> kvm_cpuid_array *array, u32 function)
>
> for (i = 2; i < 64; ++i) {
> bool s_state;
> - if (supported_xcr0 & BIT_ULL(i))
> + if (permitted_xcr0 & BIT_ULL(i))
> s_state = false;
> else if (supported_xss & BIT_ULL(i))
> s_state = true;
> @@ -942,6 +943,7 @@ static inline int __do_cpuid_func(struct
> kvm_cpuid_array *array, u32 function)
> entry->edx = 0;
> }
> break;
> +#undef supported_xcr0
> }
> case 0x12:
> /* Intel SGX */
>
> or alternatively add
>
> u64 permitted_xss = supported_xss;
>
> so that you use "permitted" consistently. Anybody can vote on what they
> prefer (including "permitted_xcr0" and no #define/#undef).
>

I prefer to permitted_xcr0 and permitted_xss. no #define/#undef.

'permitted' implies 'supported' plus certain permissions for this task. Once
both xcr0 and xss are defined consistently in this way, it's not necessary to
further guard supported_xcr0 with #define/#undef.

Thanks
Kevin