diff mbox

[v4,18/26] x86/domctl: Update PV domain cpumasks when setting cpuid policy

Message ID 1458750989-28967-19-git-send-email-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Cooper March 23, 2016, 4:36 p.m. UTC
This allows PV domains with different featuresets to observe different values
from a native cpuid instruction, on supporting hardware.

It is important to leak the host view of HTT and CMP_LEGACY through to guests,
even though they could be hidden.  These flags affect how to interpret other
cpuid leaves which are not maskable.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>

v2:
 * Use switch() rather than if/elseif chain
 * Clamp to static PV featuremask
v3:
 * Only set a shadow cpumask if it is available in hardware.  This causes
   fewer branches in the context switch.
 * Fix interaction between fastforward bits and override MSR.
 * Fix up the cross-vendor case.
 * Fix the host view of HTT/CMP_LEGACY.
v4:
 * More comments explaining the masking MSRs behaviour.
 * s/CPU/CPUID/
 * Leak host X2APIC.
---
 xen/arch/x86/domctl.c            | 138 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/cpufeature.h |   1 +
 2 files changed, 139 insertions(+)

Comments

Jan Beulich March 24, 2016, 5:04 p.m. UTC | #1
>>> On 23.03.16 at 17:36, <andrew.cooper3@citrix.com> wrote:
> This allows PV domains with different featuresets to observe different values
> from a native cpuid instruction, on supporting hardware.
> 
> It is important to leak the host view of HTT and CMP_LEGACY through to 
> guests,
> even though they could be hidden.  These flags affect how to interpret other
> cpuid leaves which are not maskable.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> 
> v2:
>  * Use switch() rather than if/elseif chain
>  * Clamp to static PV featuremask
> v3:
>  * Only set a shadow cpumask if it is available in hardware.  This causes
>    fewer branches in the context switch.
>  * Fix interaction between fastforward bits and override MSR.
>  * Fix up the cross-vendor case.
>  * Fix the host view of HTT/CMP_LEGACY.
> v4:
>  * More comments explaining the masking MSRs behaviour.
>  * s/CPU/CPUID/
>  * Leak host X2APIC.

Did you perhaps mean to also mention this one in the commit message
then? Anyway,
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Andrew Cooper March 24, 2016, 5:05 p.m. UTC | #2
On 24/03/16 17:04, Jan Beulich wrote:
>>>> On 23.03.16 at 17:36, <andrew.cooper3@citrix.com> wrote:
>> This allows PV domains with different featuresets to observe different values
>> from a native cpuid instruction, on supporting hardware.
>>
>> It is important to leak the host view of HTT and CMP_LEGACY through to 
>> guests,
>> even though they could be hidden.  These flags affect how to interpret other
>> cpuid leaves which are not maskable.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> ---
>> CC: Jan Beulich <JBeulich@suse.com>
>>
>> v2:
>>  * Use switch() rather than if/elseif chain
>>  * Clamp to static PV featuremask
>> v3:
>>  * Only set a shadow cpumask if it is available in hardware.  This causes
>>    fewer branches in the context switch.
>>  * Fix interaction between fastforward bits and override MSR.
>>  * Fix up the cross-vendor case.
>>  * Fix the host view of HTT/CMP_LEGACY.
>> v4:
>>  * More comments explaining the masking MSRs behaviour.
>>  * s/CPU/CPUID/
>>  * Leak host X2APIC.
> Did you perhaps mean to also mention this one in the commit message
> then? Anyway,
> Reviewed-by: Jan Beulich <jbeulich@suse.com>

Yes, I did.  I will fix up the message.

~Andrew
Konrad Rzeszutek Wilk March 28, 2016, 7:51 p.m. UTC | #3
On Wed, Mar 23, 2016 at 04:36:21PM +0000, Andrew Cooper wrote:
> This allows PV domains with different featuresets to observe different values
> from a native cpuid instruction, on supporting hardware.
> 
> It is important to leak the host view of HTT and CMP_LEGACY through to guests,
> even though they could be hidden.  These flags affect how to interpret other
> cpuid leaves which are not maskable.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
diff mbox

Patch

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index b7c7f42..403bae8 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -36,6 +36,7 @@ 
 #include <asm/xstate.h>
 #include <asm/debugger.h>
 #include <asm/psr.h>
+#include <asm/cpuid.h>
 
 static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
 {
@@ -87,6 +88,143 @@  static void update_domain_cpuid_info(struct domain *d,
         d->arch.x86_model = (ctl->eax >> 4) & 0xf;
         if ( d->arch.x86 >= 0x6 )
             d->arch.x86_model |= (ctl->eax >> 12) & 0xf0;
+
+        if ( is_pv_domain(d) && ((levelling_caps & LCAP_1cd) == LCAP_1cd) )
+        {
+            uint64_t mask = cpuidmask_defaults._1cd;
+            uint32_t ecx = ctl->ecx & pv_featureset[FEATURESET_1c];
+            uint32_t edx = ctl->edx & pv_featureset[FEATURESET_1d];
+
+            /*
+             * Must expose hosts HTT and X2APIC value so a guest using native
+             * CPUID can correctly interpret other leaves which cannot be
+             * masked.
+             */
+            if ( cpu_has_x2apic )
+                ecx |= cpufeat_mask(X86_FEATURE_X2APIC);
+            if ( cpu_has_htt )
+                edx |= cpufeat_mask(X86_FEATURE_HTT);
+
+            switch ( boot_cpu_data.x86_vendor )
+            {
+            case X86_VENDOR_INTEL:
+                /*
+                 * Intel masking MSRs are documented as AND masks.
+                 * Experimentally, they are applied before OSXSAVE and APIC
+                 * are fast-forwarded from real hardware state.
+                 */
+                mask &= ((uint64_t)edx << 32) | ecx;
+                break;
+
+            case X86_VENDOR_AMD:
+                mask &= ((uint64_t)ecx << 32) | edx;
+
+                /*
+                 * AMD masking MSRs are documented as overrides.
+                 * Experimentally, fast-forwarding of the OSXSAVE and APIC
+                 * bits from real hardware state only occurs if the MSR has
+                 * the respective bits set.
+                 */
+                if ( ecx & cpufeat_mask(X86_FEATURE_XSAVE) )
+                    ecx = cpufeat_mask(X86_FEATURE_OSXSAVE);
+                else
+                    ecx = 0;
+                edx = cpufeat_mask(X86_FEATURE_APIC);
+
+                mask |= ((uint64_t)ecx << 32) | edx;
+                break;
+            }
+
+            d->arch.pv_domain.cpuidmasks->_1cd = mask;
+        }
+        break;
+
+    case 6:
+        if ( is_pv_domain(d) && ((levelling_caps & LCAP_6c) == LCAP_6c) )
+        {
+            uint64_t mask = cpuidmask_defaults._6c;
+
+            if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+                mask &= (~0ULL << 32) | ctl->ecx;
+
+            d->arch.pv_domain.cpuidmasks->_6c = mask;
+        }
+        break;
+
+    case 7:
+        if ( ctl->input[1] != 0 )
+            break;
+
+        if ( is_pv_domain(d) && ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) )
+        {
+            uint64_t mask = cpuidmask_defaults._7ab0;
+            uint32_t eax = ctl->eax;
+            uint32_t ebx = ctl->ebx & pv_featureset[FEATURESET_7b0];
+
+            if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+                mask &= ((uint64_t)eax << 32) | ebx;
+
+            d->arch.pv_domain.cpuidmasks->_7ab0 = mask;
+        }
+        break;
+
+    case 0xd:
+        if ( ctl->input[1] != 1 )
+            break;
+
+        if ( is_pv_domain(d) && ((levelling_caps & LCAP_Da1) == LCAP_Da1) )
+        {
+            uint64_t mask = cpuidmask_defaults.Da1;
+            uint32_t eax = ctl->eax & pv_featureset[FEATURESET_Da1];
+
+            if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+                mask &= (~0ULL << 32) | eax;
+
+            d->arch.pv_domain.cpuidmasks->Da1 = mask;
+        }
+        break;
+
+    case 0x80000001:
+        if ( is_pv_domain(d) && ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) )
+        {
+            uint64_t mask = cpuidmask_defaults.e1cd;
+            uint32_t ecx = ctl->ecx & pv_featureset[FEATURESET_e1c];
+            uint32_t edx = ctl->edx & pv_featureset[FEATURESET_e1d];
+
+            /*
+             * Must expose hosts CMP_LEGACY value so a guest using native
+             * CPUID can correctly interpret other leaves which cannot be
+             * masked.
+             */
+            if ( cpu_has_cmp_legacy )
+                ecx |= cpufeat_mask(X86_FEATURE_CMP_LEGACY);
+
+            /* If not emulating AMD, clear the duplicated features in e1d. */
+            if ( d->arch.x86_vendor != X86_VENDOR_AMD )
+                edx &= ~CPUID_COMMON_1D_FEATURES;
+
+            switch ( boot_cpu_data.x86_vendor )
+            {
+            case X86_VENDOR_INTEL:
+                mask &= ((uint64_t)edx << 32) | ecx;
+                break;
+
+            case X86_VENDOR_AMD:
+                mask &= ((uint64_t)ecx << 32) | edx;
+
+                /*
+                 * Fast-forward bits - Must be set in the masking MSR for
+                 * fast-forwarding to occur in hardware.
+                 */
+                ecx = 0;
+                edx = cpufeat_mask(X86_FEATURE_APIC);
+
+                mask |= ((uint64_t)ecx << 32) | edx;
+                break;
+            }
+
+            d->arch.pv_domain.cpuidmasks->e1cd = mask;
+        }
         break;
     }
 }
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 84d3220..ae7b47b 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -81,6 +81,7 @@ 
 #define cpu_has_xsavec		boot_cpu_has(X86_FEATURE_XSAVEC)
 #define cpu_has_xgetbv1		boot_cpu_has(X86_FEATURE_XGETBV1)
 #define cpu_has_xsaves		boot_cpu_has(X86_FEATURE_XSAVES)
+#define cpu_has_cmp_legacy	boot_cpu_has(X86_FEATURE_CMP_LEGACY)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 
 enum _cache_type {