All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/25] xen/x86: Per-domain CPUID policies
@ 2017-01-09 11:03 Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
                   ` (24 more replies)
  0 siblings, 25 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Presented herewith is v2 of the first part of improvement work to support full
per-domain CPUID policies.  More work is pending on top of this series.

This series is available in git form from:

  http://xenbits.xen.org/gitweb/?p=people/andrewcoop/xen.git;a=shortlog;h=refs/heads/xen-cpuid-v2

Testing wise, this series has been bisected, checking at each stage that the
guest-visibile CPUID information is identical (other than reported-frequency
values) for different VMs in a number of configurations.

All review comment from v1 have been addressed.  Headline changes are the
dynamic generation of bitfield names, and recalculation of policy in more
places.

Andrew Cooper (25):
  x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  x86/cpuid: Introduce struct cpuid_policy
  x86/cpuid: Move featuresets into struct cpuid_policy
  x86/cpuid: Allocate a CPUID policy for every domain
  x86/cpuid: Recalculate a domains CPUID policy when appropriate
  x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid()
  x86/cpuid: Dispatch cpuid_hypervisor_leaves() from guest_cpuid()
  x86/cpuid: Introduce named feature bitfields
  x86/hvm: Improve hvm_efer_valid() using named features
  x86/hvm: Improve CR4 verification using named features
  x86/vvmx: Use hvm_cr4_guest_valid_bits() to calculate MSR_IA32_VMX_CR4_FIXED1
  x86/pv: Improve pv_cpuid() using named features
  x86/hvm: Improve CPUID and MSR handling using named features
  x86/svm: Improvements using named features
  x86/pv: Use per-domain policy information when calculating the cpumasks
  x86/pv: Use per-domain policy information in pv_cpuid()
  x86/hvm: Use per-domain policy information in hvm_cpuid()
  x86/cpuid: Drop the temporary linear feature bitmap from struct cpuid_policy
  x86/cpuid: Calculate appropriate max_leaf values for the global policies
  x86/cpuid: Perform max_leaf calculations in guest_cpuid()
  x86/cpuid: Move all leaf 7 handling into guest_cpuid()
  x86/hvm: Use guest_cpuid() rather than hvm_cpuid()
  x86/svm: Use guest_cpuid() rather than hvm_cpuid()
  x86/cpuid: Effectively remove pv_cpuid() and hvm_cpuid()
  x86/cpuid: Alter the legacy-path prototypes to match guest_cpuid()

 tools/tests/x86_emulator/x86_emulate.c |  15 +-
 tools/tests/x86_emulator/x86_emulate.h |  60 ++-
 xen/arch/arm/domctl.c                  |   5 +
 xen/arch/x86/cpuid.c                   | 860 ++++++++++++++++++++++++++++++---
 xen/arch/x86/domain.c                  |  11 +-
 xen/arch/x86/domctl.c                  |  41 +-
 xen/arch/x86/hvm/emulate.c             |  10 +-
 xen/arch/x86/hvm/hvm.c                 | 518 +++-----------------
 xen/arch/x86/hvm/mtrr.c                |  13 +-
 xen/arch/x86/hvm/nestedhvm.c           |   6 +-
 xen/arch/x86/hvm/svm/svm.c             |  63 +--
 xen/arch/x86/hvm/viridian.c            |  65 ++-
 xen/arch/x86/hvm/vmx/vmx.c             |  35 +-
 xen/arch/x86/hvm/vmx/vvmx.c            |  58 +--
 xen/arch/x86/setup.c                   |   4 +-
 xen/arch/x86/sysctl.c                  |  21 +-
 xen/arch/x86/time.c                    |   2 +
 xen/arch/x86/traps.c                   | 472 ++----------------
 xen/arch/x86/x86_emulate/x86_emulate.c |  34 +-
 xen/arch/x86/x86_emulate/x86_emulate.h |  12 +-
 xen/common/domctl.c                    |   4 -
 xen/include/asm-x86/cpufeature.h       |   1 +
 xen/include/asm-x86/cpuid.h            | 194 +++++++-
 xen/include/asm-x86/domain.h           |   5 +-
 xen/include/asm-x86/hvm/emulate.h      |   8 +-
 xen/include/asm-x86/hvm/hvm.h          |   4 +-
 xen/include/asm-x86/hvm/nestedhvm.h    |   2 +-
 xen/include/asm-x86/hvm/vcpu.h         |  10 +-
 xen/include/asm-x86/hvm/viridian.h     |   9 +-
 xen/include/asm-x86/mm.h               |   4 +-
 xen/include/asm-x86/processor.h        |   6 +-
 xen/tools/gen-cpuid.py                 |  32 ++
 32 files changed, 1357 insertions(+), 1227 deletions(-)

-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:38   ` Paul Durrant
                     ` (3 more replies)
  2017-01-09 11:03 ` [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy Andrew Cooper
                   ` (23 subsequent siblings)
  24 siblings, 4 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel
  Cc: Kevin Tian, Jan Beulich, Andrew Cooper, Paul Durrant,
	Jun Nakajima, Boris Ostrovsky, Suravee Suthikulpanit

Longterm, pv_cpuid() and hvm_cpuid() will be merged into a single
guest_cpuid(), which is also capable of working outside of current context.

To aid this transtion, introduce guest_cpuid() with the intended API, which
simply defers back to pv_cpuid() or hvm_cpuid() as appropriate.

Introduce struct cpuid_leaf which is used to represent the results of a CPUID
query in a more efficient mannor than passing four pointers through the
calltree.

Update all codepaths which should use the new guest_cpuid() API.  These are
the codepaths which have variable inputs, and (other than some specific
x86_emulate() cases) all pertain to servicing a CPUID instruction from a
guest.

The other codepaths using {pv,hvm}_cpuid() with fixed inputs will later be
adjusted to read their data straight from the policy block.

No intended functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Paul Durrant <paul.durrant@citrix.com>
CC: Jun Nakajima <jun.nakajima@intel.com>
CC: Kevin Tian <kevin.tian@intel.com>
CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
v2:
 * Rename res to cpuid_leaf in x86_emulate(), and make common to functions.
 * Return lost const and newline in pv_emul_cpuid().
 * Extra brackets around EMPTY_LEAF.
 * Consistently use uint32_t.
 * Tweak {hvm,pv}_cpuid() dispatch logic for a reduced delta later in the series.
---
 tools/tests/x86_emulator/x86_emulate.c | 15 ++++-----
 tools/tests/x86_emulator/x86_emulate.h | 60 ++++++++++++++++------------------
 xen/arch/x86/cpuid.c                   | 36 ++++++++++++++++++++
 xen/arch/x86/hvm/emulate.c             | 10 ++----
 xen/arch/x86/hvm/svm/svm.c             | 23 ++++++-------
 xen/arch/x86/hvm/vmx/vmx.c             | 35 ++++++--------------
 xen/arch/x86/traps.c                   | 25 +++++++-------
 xen/arch/x86/x86_emulate/x86_emulate.c | 34 +++++++++----------
 xen/arch/x86/x86_emulate/x86_emulate.h | 12 ++++---
 xen/include/asm-x86/cpuid.h            |  4 +++
 xen/include/asm-x86/hvm/emulate.h      |  8 ++---
 xen/include/asm-x86/mm.h               |  4 +--
 12 files changed, 137 insertions(+), 129 deletions(-)

diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
index d48f78a..2e8dfbf 100644
--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -41,22 +41,21 @@ bool emul_test_make_stack_executable(void)
 }
 
 int emul_test_cpuid(
-    unsigned int *eax,
-    unsigned int *ebx,
-    unsigned int *ecx,
-    unsigned int *edx,
+    uint32_t leaf,
+    uint32_t subleaf,
+    struct cpuid_leaf *res,
     struct x86_emulate_ctxt *ctxt)
 {
-    unsigned int leaf = *eax;
-
-    asm ("cpuid" : "+a" (*eax), "+c" (*ecx), "=d" (*edx), "=b" (*ebx));
+    asm ("cpuid"
+         : "=a" (res->a), "=b" (res->b), "=c" (res->c), "=d" (res->d)
+         : "a" (leaf), "c" (subleaf));
 
     /*
      * The emulator doesn't itself use MOVBE, so we can always run the
      * respective tests.
      */
     if ( leaf == 1 )
-        *ecx |= 1U << 22;
+        res->c |= 1U << 22;
 
     return X86EMUL_OKAY;
 }
diff --git a/tools/tests/x86_emulator/x86_emulate.h b/tools/tests/x86_emulator/x86_emulate.h
index c14c613..8bc2e43 100644
--- a/tools/tests/x86_emulator/x86_emulate.h
+++ b/tools/tests/x86_emulator/x86_emulate.h
@@ -58,61 +58,59 @@ static inline uint64_t xgetbv(uint32_t xcr)
 }
 
 #define cache_line_size() ({		     \
-    unsigned int eax = 1, ebx, ecx = 0, edx; \
-    emul_test_cpuid(&eax, &ebx, &ecx, &edx, NULL); \
-    edx & (1U << 19) ? (ebx >> 5) & 0x7f8 : 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    res.d & (1U << 19) ? (res.b >> 5) & 0x7f8 : 0; \
 })
 
 #define cpu_has_mmx ({ \
-    unsigned int eax = 1, ecx = 0, edx; \
-    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
-    (edx & (1U << 23)) != 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    (res.d & (1U << 23)) != 0; \
 })
 
 #define cpu_has_sse ({ \
-    unsigned int eax = 1, ecx = 0, edx; \
-    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
-    (edx & (1U << 25)) != 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    (res.d & (1U << 25)) != 0; \
 })
 
 #define cpu_has_sse2 ({ \
-    unsigned int eax = 1, ecx = 0, edx; \
-    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
-    (edx & (1U << 26)) != 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    (res.d & (1U << 26)) != 0; \
 })
 
 #define cpu_has_xsave ({ \
-    unsigned int eax = 1, ecx = 0; \
-    emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
     /* Intentionally checking OSXSAVE here. */ \
-    (ecx & (1U << 27)) != 0; \
+    (res.c & (1U << 27)) != 0; \
 })
 
 #define cpu_has_avx ({ \
-    unsigned int eax = 1, ecx = 0; \
-    emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
-    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
-        ecx = 0; \
-    (ecx & (1U << 28)) != 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
+        res.c = 0; \
+    (res.c & (1U << 28)) != 0; \
 })
 
 #define cpu_has_avx2 ({ \
-    unsigned int eax = 1, ebx, ecx = 0; \
-    emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
-    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
-        ebx = 0; \
+    struct cpuid_leaf res; \
+    emul_test_cpuid(1, 0, &res, NULL); \
+    if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
+        res.b = 0; \
     else { \
-        eax = 7, ecx = 0; \
-        emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
+        emul_test_cpuid(7, 0, &res, NULL); \
     } \
-    (ebx & (1U << 5)) != 0; \
+    (res.b & (1U << 5)) != 0; \
 })
 
 int emul_test_cpuid(
-    unsigned int *eax,
-    unsigned int *ebx,
-    unsigned int *ecx,
-    unsigned int *edx,
+    uint32_t leaf,
+    uint32_t subleaf,
+    struct cpuid_leaf *res,
     struct x86_emulate_ctxt *ctxt);
 
 int emul_test_read_cr(
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 3e85a63..f3491ed 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -1,5 +1,6 @@
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/sched.h>
 #include <asm/cpuid.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/vmx/vmcs.h>
@@ -17,6 +18,8 @@ uint32_t __read_mostly raw_featureset[FSCAPINTS];
 uint32_t __read_mostly pv_featureset[FSCAPINTS];
 uint32_t __read_mostly hvm_featureset[FSCAPINTS];
 
+#define EMPTY_LEAF ((struct cpuid_leaf){})
+
 static void __init sanitise_featureset(uint32_t *fs)
 {
     /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
@@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
     return NULL;
 }
 
+void guest_cpuid(const struct vcpu *v, uint32_t leaf,
+                 uint32_t subleaf, struct cpuid_leaf *res)
+{
+    const struct vcpu *curr = current;
+    const struct domain *d = v->domain;
+
+    *res = EMPTY_LEAF;
+
+    /* {hvm,pv}_cpuid() have this expectation. */
+    ASSERT(v == curr);
+
+    if ( is_hvm_domain(d) )
+    {
+        res->c = subleaf;
+
+        hvm_cpuid(leaf, &res->a, &res->b, &res->c, &res->d);
+    }
+    else
+    {
+        struct cpu_user_regs regs = *guest_cpu_user_regs();
+
+        regs._eax = leaf;
+        regs._ecx = subleaf;
+
+        pv_cpuid(&regs);
+
+        res->a = regs._eax;
+        res->b = regs._ebx;
+        res->c = regs._ecx;
+        res->d = regs._edx;
+    }
+}
+
 static void __init __maybe_unused build_assertions(void)
 {
     BUILD_BUG_ON(ARRAY_SIZE(known_features) != FSCAPINTS);
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 41bd4f5..ecbac4b 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -1552,12 +1552,8 @@ static int hvmemul_wbinvd(
     return X86EMUL_OKAY;
 }
 
-int hvmemul_cpuid(
-    unsigned int *eax,
-    unsigned int *ebx,
-    unsigned int *ecx,
-    unsigned int *edx,
-    struct x86_emulate_ctxt *ctxt)
+int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
+                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
 {
     /*
      * x86_emulate uses this function to query CPU features for its own internal
@@ -1568,7 +1564,7 @@ int hvmemul_cpuid(
          hvm_check_cpuid_faulting(current) )
         return X86EMUL_EXCEPTION;
 
-    hvm_cpuid(*eax, eax, ebx, ecx, edx);
+    guest_cpuid(current, leaf, subleaf, res);
     return X86EMUL_OKAY;
 }
 
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 04a7b60..6fb1cbc 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1572,23 +1572,20 @@ static void svm_fpu_dirty_intercept(void)
 
 static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
 {
-    unsigned int eax, ebx, ecx, edx, inst_len;
+    struct vcpu *curr = current;
+    unsigned int inst_len;
+    struct cpuid_leaf res;
 
-    if ( (inst_len = __get_instruction_length(current, INSTR_CPUID)) == 0 )
+    if ( (inst_len = __get_instruction_length(curr, INSTR_CPUID)) == 0 )
         return;
 
-    eax = regs->_eax;
-    ebx = regs->_ebx;
-    ecx = regs->_ecx;
-    edx = regs->_edx;
-
-    hvm_cpuid(regs->_eax, &eax, &ebx, &ecx, &edx);
-    HVMTRACE_5D(CPUID, regs->_eax, eax, ebx, ecx, edx);
+    guest_cpuid(curr, regs->_eax, regs->_ecx, &res);
+    HVMTRACE_5D(CPUID, regs->_eax, res.a, res.b, res.c, res.d);
 
-    regs->rax = eax;
-    regs->rbx = ebx;
-    regs->rcx = ecx;
-    regs->rdx = edx;
+    regs->rax = res.a;
+    regs->rbx = res.b;
+    regs->rcx = res.c;
+    regs->rdx = res.d;
 
     __update_guest_eip(regs, inst_len);
 }
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index e75b190..01c225f 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2361,8 +2361,9 @@ static void vmx_fpu_dirty_intercept(void)
 
 static int vmx_do_cpuid(struct cpu_user_regs *regs)
 {
-    unsigned int eax, ebx, ecx, edx;
-    unsigned int leaf, subleaf;
+    struct vcpu *curr = current;
+    unsigned int leaf = regs->_eax, subleaf = regs->_ecx;
+    struct cpuid_leaf res;
 
     if ( hvm_check_cpuid_faulting(current) )
     {
@@ -2370,21 +2371,13 @@ static int vmx_do_cpuid(struct cpu_user_regs *regs)
         return 1;  /* Don't advance the guest IP! */
     }
 
-    eax = regs->_eax;
-    ebx = regs->_ebx;
-    ecx = regs->_ecx;
-    edx = regs->_edx;
-
-    leaf = regs->_eax;
-    subleaf = regs->_ecx;
+    guest_cpuid(curr, leaf, subleaf, &res);
+    HVMTRACE_5D(CPUID, leaf, res.a, res.b, res.c, res.d);
 
-    hvm_cpuid(leaf, &eax, &ebx, &ecx, &edx);
-    HVMTRACE_5D(CPUID, leaf, eax, ebx, ecx, edx);
-
-    regs->rax = eax;
-    regs->rbx = ebx;
-    regs->rcx = ecx;
-    regs->rdx = edx;
+    regs->rax = res.a;
+    regs->rbx = res.b;
+    regs->rcx = res.c;
+    regs->rdx = res.d;
 
     return hvm_monitor_cpuid(get_instruction_length(), leaf, subleaf);
 }
@@ -3559,15 +3552,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
     }
     case EXIT_REASON_CPUID:
     {
-        int rc;
-
-        if ( is_pvh_vcpu(v) )
-        {
-            pv_cpuid(regs);
-            rc = 0;
-        }
-        else
-            rc = vmx_do_cpuid(regs);
+        int rc = vmx_do_cpuid(regs);
 
         /*
          * rc < 0 error in monitor/vm_event, crash
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index e45ff71..3acc244 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1412,6 +1412,7 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
 {
     char sig[5], instr[2];
     unsigned long eip, rc;
+    struct cpuid_leaf res;
 
     eip = regs->rip;
 
@@ -1444,7 +1445,12 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
 
     eip += sizeof(instr);
 
-    pv_cpuid(regs);
+    guest_cpuid(current, regs->_eax, regs->_ecx, &res);
+
+    regs->rax = res.a;
+    regs->rbx = res.b;
+    regs->rcx = res.c;
+    regs->rdx = res.d;
 
     instruction_done(regs, eip);
 
@@ -3254,10 +3260,10 @@ static int priv_op_wbinvd(struct x86_emulate_ctxt *ctxt)
     return X86EMUL_OKAY;
 }
 
-int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
-                  unsigned int *edx, struct x86_emulate_ctxt *ctxt)
+int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
+                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
 {
-    struct cpu_user_regs regs = *ctxt->regs;
+    const struct vcpu *curr = current;
 
     /*
      * x86_emulate uses this function to query CPU features for its own
@@ -3266,7 +3272,6 @@ int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
      */
     if ( ctxt->opcode == X86EMUL_OPC(0x0f, 0xa2) )
     {
-        const struct vcpu *curr = current;
 
         /* If cpuid faulting is enabled and CPL>0 leave the #GP untouched. */
         if ( curr->arch.cpuid_faulting &&
@@ -3274,15 +3279,7 @@ int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
             return X86EMUL_EXCEPTION;
     }
 
-    regs._eax = *eax;
-    regs._ecx = *ecx;
-
-    pv_cpuid(&regs);
-
-    *eax = regs._eax;
-    *ebx = regs._ebx;
-    *ecx = regs._ecx;
-    *edx = regs._edx;
+    guest_cpuid(curr, leaf, subleaf, res);
 
     return X86EMUL_OKAY;
 }
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index 98ba7c5..3dbc3ce 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1265,19 +1265,19 @@ static bool vcpu_has(
     struct x86_emulate_ctxt *ctxt,
     const struct x86_emulate_ops *ops)
 {
-    unsigned int ebx = 0, ecx = 0, edx = 0;
+    struct cpuid_leaf res;
     int rc = X86EMUL_OKAY;
 
     fail_if(!ops->cpuid);
-    rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
+    rc = ops->cpuid(eax, 0, &res, ctxt);
     if ( rc == X86EMUL_OKAY )
     {
         switch ( reg )
         {
-        case EAX: reg = eax; break;
-        case EBX: reg = ebx; break;
-        case ECX: reg = ecx; break;
-        case EDX: reg = edx; break;
+        case EAX: reg = res.a; break;
+        case EBX: reg = res.b; break;
+        case ECX: reg = res.c; break;
+        case EDX: reg = res.d; break;
         default: BUG();
         }
         if ( !(reg & (1U << bit)) )
@@ -2722,6 +2722,7 @@ x86_emulate(
     {
         enum x86_segment seg;
         struct segment_register cs, sreg;
+        struct cpuid_leaf cpuid_leaf;
 
     case 0x00 ... 0x05: add: /* add */
         emulate_2op_SrcV("add", src, dst, _regs._eflags);
@@ -4525,15 +4526,14 @@ x86_emulate(
 
         case 0xfc: /* clzero */
         {
-            unsigned int eax = 1, ebx = 0, dummy = 0;
             unsigned long zero = 0;
 
             base = ad_bytes == 8 ? _regs.r(ax) :
                    ad_bytes == 4 ? _regs._eax : _regs.ax;
             limit = 0;
             if ( vcpu_has_clflush() &&
-                 ops->cpuid(&eax, &ebx, &dummy, &dummy, ctxt) == X86EMUL_OKAY )
-                limit = ((ebx >> 8) & 0xff) * 8;
+                 ops->cpuid(1, 0, &cpuid_leaf, ctxt) == X86EMUL_OKAY )
+                limit = ((cpuid_leaf.b >> 8) & 0xff) * 8;
             generate_exception_if(limit < sizeof(long) ||
                                   (limit & (limit - 1)), EXC_UD);
             base &= ~(limit - 1);
@@ -5265,22 +5265,18 @@ x86_emulate(
         dst.val = test_cc(b, _regs._eflags);
         break;
 
-    case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */ {
-        unsigned int eax = _regs._eax, ebx = _regs._ebx;
-        unsigned int ecx = _regs._ecx, edx = _regs._edx;
-
+    case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */
         fail_if(ops->cpuid == NULL);
-        rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
+        rc = ops->cpuid(_regs._eax, _regs._ecx, &cpuid_leaf, ctxt);
         generate_exception_if(rc == X86EMUL_EXCEPTION,
                               EXC_GP, 0); /* CPUID Faulting? */
         if ( rc != X86EMUL_OKAY )
             goto done;
-        _regs.r(ax) = eax;
-        _regs.r(bx) = ebx;
-        _regs.r(cx) = ecx;
-        _regs.r(dx) = edx;
+        _regs.r(ax) = cpuid_leaf.a;
+        _regs.r(bx) = cpuid_leaf.b;
+        _regs.r(cx) = cpuid_leaf.c;
+        _regs.r(dx) = cpuid_leaf.d;
         break;
-    }
 
     case X86EMUL_OPC(0x0f, 0xa3): bt: /* bt */
         emulate_2op_SrcV_nobyte("bt", src, dst, _regs._eflags);
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
index 43c0c5e..57ebfde 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -164,6 +164,11 @@ enum x86_emulate_fpu_type {
     X86EMUL_FPU_ymm  /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
 };
 
+struct cpuid_leaf
+{
+    uint32_t a, b, c, d;
+};
+
 struct x86_emulate_state;
 
 /*
@@ -415,10 +420,9 @@ struct x86_emulate_ops
      * #GP[0].  Used to implement CPUID faulting.
      */
     int (*cpuid)(
-        unsigned int *eax,
-        unsigned int *ebx,
-        unsigned int *ecx,
-        unsigned int *edx,
+        uint32_t leaf,
+        uint32_t subleaf,
+        struct cpuid_leaf *res,
         struct x86_emulate_ctxt *ctxt);
 
     /*
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 05f2c9a..4586c7d 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -17,6 +17,7 @@
 
 #ifndef __ASSEMBLY__
 #include <xen/types.h>
+#include <asm/x86_emulate.h>
 #include <public/sysctl.h>
 
 extern const uint32_t known_features[FSCAPINTS];
@@ -64,6 +65,9 @@ extern struct cpuidmasks cpuidmask_defaults;
 /* Whether or not cpuid faulting is available for the current domain. */
 DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
 
+void guest_cpuid(const struct vcpu *v, uint32_t leaf,
+                 uint32_t subleaf, struct cpuid_leaf *res);
+
 #endif /* __ASSEMBLY__ */
 #endif /* !__X86_CPUID_H__ */
 
diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
index 68a95e4..83266bb 100644
--- a/xen/include/asm-x86/hvm/emulate.h
+++ b/xen/include/asm-x86/hvm/emulate.h
@@ -57,12 +57,8 @@ void hvm_emulate_init_per_insn(
     unsigned int insn_bytes);
 void hvm_emulate_writeback(
     struct hvm_emulate_ctxt *hvmemul_ctxt);
-int hvmemul_cpuid(
-    unsigned int *eax,
-    unsigned int *ebx,
-    unsigned int *ecx,
-    unsigned int *edx,
-    struct x86_emulate_ctxt *ctxt);
+int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
+                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
 struct segment_register *hvmemul_get_seg_reg(
     enum x86_segment seg,
     struct hvm_emulate_ctxt *hvmemul_ctxt);
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index a15029c..93a073d 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -504,8 +504,8 @@ extern int mmcfg_intercept_write(enum x86_segment seg,
                                  void *p_data,
                                  unsigned int bytes,
                                  struct x86_emulate_ctxt *ctxt);
-int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
-                  unsigned int *edx, struct x86_emulate_ctxt *ctxt);
+int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
+                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
 
 int  ptwr_do_page_fault(struct vcpu *, unsigned long,
                         struct cpu_user_regs *);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 15:15   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 03/25] x86/cpuid: Move featuresets into " Andrew Cooper
                   ` (22 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

struct cpuid_policy will eventually be a complete replacement for the cpuids[]
array, with a fixed layout and named fields to allow O(1) access to specific
information.

For now, the CPUID content is capped at the 0xd and 0x8000001c leaves, which
matches the maximum policy that the toolstack will generate for a domain.  The
xstate leaves extend up to LWP, and the structured features leaf is
implemented with subleaf properties (in anticipation of subleaf 1 appearing
soon), although only subleaf 0 is currently implemented.

Introduce calculate_raw_policy() which fills raw_policy with information,
making use of the new helpers, cpuid_{,count_}leaf().

Finally, rename calculate_featuresets() to init_guest_cpuid(), as it is going
to perform rather more work.

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

v2:
 * Defer leaves 2 and 4 for now.  More per-vcpu policy logic is required
   before they can work sensibly.
 * Fix collection of xstate leaves beyond subleaf 31.
 * Consistently use uint32_t.
 * Drop the double structs.
---
 xen/arch/x86/cpuid.c        | 81 ++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/setup.c        |  2 +-
 xen/include/asm-x86/cpuid.h | 69 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index f3491ed..1bfa7d7 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -20,6 +20,19 @@ uint32_t __read_mostly hvm_featureset[FSCAPINTS];
 
 #define EMPTY_LEAF ((struct cpuid_leaf){})
 
+static struct cpuid_policy __read_mostly raw_policy;
+
+static void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *data)
+{
+    cpuid(leaf, &data->a, &data->b, &data->c, &data->d);
+}
+
+static void cpuid_count_leaf(uint32_t leaf, uint32_t subleaf,
+                             struct cpuid_leaf *data)
+{
+    cpuid_count(leaf, subleaf, &data->a, &data->b, &data->c, &data->d);
+}
+
 static void __init sanitise_featureset(uint32_t *fs)
 {
     /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
@@ -67,6 +80,58 @@ static void __init sanitise_featureset(uint32_t *fs)
                           (fs[FEATURESET_e1d] & ~CPUID_COMMON_1D_FEATURES));
 }
 
+static void __init calculate_raw_policy(void)
+{
+    struct cpuid_policy *p = &raw_policy;
+    unsigned int i;
+
+    cpuid_leaf(0, &p->basic.raw[0]);
+    for ( i = 1; i < min(ARRAY_SIZE(p->basic.raw),
+                         p->basic.max_leaf + 1ul); ++i )
+    {
+        switch ( i )
+        {
+        case 0x2: case 0x4: case 0x7: case 0xd:
+            /* Multi-invocation leaves.  Deferred. */
+            continue;
+        }
+
+        cpuid_leaf(i, &p->basic.raw[i]);
+    }
+
+    if ( p->basic.max_leaf >= 7 )
+    {
+        cpuid_count_leaf(7, 0, &p->feat.raw[0]);
+
+        for ( i = 1; i < min(ARRAY_SIZE(p->feat.raw),
+                             p->feat.max_subleaf + 1ul); ++i )
+            cpuid_count_leaf(7, i, &p->feat.raw[i]);
+    }
+
+    if ( p->basic.max_leaf >= 0xd )
+    {
+        uint64_t xstates;
+
+        cpuid_count_leaf(0xd, 0, &p->xstate.raw[0]);
+        cpuid_count_leaf(0xd, 1, &p->xstate.raw[1]);
+
+        xstates = ((uint64_t)(p->xstate.xcr0_high | p->xstate.xss_high) << 32) |
+            (p->xstate.xcr0_low | p->xstate.xss_low);
+
+        for ( i = 2; i < 63; ++i )
+        {
+            if ( xstates & (1ul << i) )
+                cpuid_count_leaf(0xd, i, &p->xstate.raw[i]);
+        }
+    }
+
+    /* Extended leaves. */
+    cpuid_leaf(0x80000000, &p->extd.raw[0]);
+    for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
+                         p->extd.max_leaf + 1 - 0x80000000ul); ++i )
+        cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
+}
+
 static void __init calculate_raw_featureset(void)
 {
     unsigned int max, tmp;
@@ -181,8 +246,10 @@ static void __init calculate_hvm_featureset(void)
     sanitise_featureset(hvm_featureset);
 }
 
-void __init calculate_featuresets(void)
+void __init init_guest_cpuid(void)
 {
+    calculate_raw_policy();
+
     calculate_raw_featureset();
     calculate_pv_featureset();
     calculate_hvm_featureset();
@@ -259,6 +326,18 @@ static void __init __maybe_unused build_assertions(void)
     BUILD_BUG_ON(ARRAY_SIZE(hvm_shadow_featuremask) != FSCAPINTS);
     BUILD_BUG_ON(ARRAY_SIZE(hvm_hap_featuremask) != FSCAPINTS);
     BUILD_BUG_ON(ARRAY_SIZE(deep_features) != FSCAPINTS);
+
+    /* Find some more clever allocation scheme if this trips. */
+    BUILD_BUG_ON(sizeof(struct cpuid_policy) > PAGE_SIZE);
+
+    BUILD_BUG_ON(sizeof(raw_policy.basic) !=
+                 sizeof(raw_policy.basic.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.feat) !=
+                 sizeof(raw_policy.feat.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.xstate) !=
+                 sizeof(raw_policy.xstate.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.extd) !=
+                 sizeof(raw_policy.extd.raw));
 }
 
 /*
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index d473ac8..94db514 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1590,7 +1590,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                "Multiple initrd candidates, picking module #%u\n",
                initrdidx);
 
-    calculate_featuresets();
+    init_guest_cpuid();
 
     /*
      * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0().
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 4586c7d..6176da7 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -17,6 +17,7 @@
 
 #ifndef __ASSEMBLY__
 #include <xen/types.h>
+#include <xen/kernel.h>
 #include <asm/x86_emulate.h>
 #include <public/sysctl.h>
 
@@ -28,7 +29,7 @@ extern uint32_t raw_featureset[FSCAPINTS];
 extern uint32_t pv_featureset[FSCAPINTS];
 extern uint32_t hvm_featureset[FSCAPINTS];
 
-void calculate_featuresets(void);
+void init_guest_cpuid(void);
 
 const uint32_t *lookup_deep_deps(uint32_t feature);
 
@@ -65,6 +66,72 @@ extern struct cpuidmasks cpuidmask_defaults;
 /* Whether or not cpuid faulting is available for the current domain. */
 DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
 
+#define CPUID_GUEST_NR_BASIC      (0xdu + 1)
+#define CPUID_GUEST_NR_FEAT       (0u + 1)
+#define CPUID_GUEST_NR_XSTATE     (62u + 1)
+#define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
+#define CPUID_GUEST_NR_EXTD_AMD   (0x1cu + 1)
+#define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
+                                      CPUID_GUEST_NR_EXTD_AMD)
+
+struct cpuid_policy
+{
+    /*
+     * WARNING: During the CPUID transition period, not all information here
+     * is accurate.  The following items are accurate, and can be relied upon.
+     *
+     * Global *_policy objects:
+     *
+     * - Host accurate:
+     *   - max_{,sub}leaf
+     *   - {xcr0,xss}_{high,low}
+     *
+     * - Guest accurate:
+     *   - Nothing
+     *
+     * Everything else should be considered inaccurate, and not necesserily 0.
+     */
+
+    /* Basic leaves: 0x000000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC];
+        struct {
+            /* Leaf 0x0 - Max and vendor. */
+            uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } basic;
+
+    /* Structured feature leaf: 0x00000007[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
+        struct {
+            /* Subleaf 0. */
+            uint32_t max_subleaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } feat;
+
+    /* Xstate feature leaf: 0x0000000D[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_XSTATE];
+        struct {
+            /* Subleaf 0. */
+            uint32_t xcr0_low, /* b */:32, /* c */:32, xcr0_high;
+
+            /* Subleaf 1. */
+            uint32_t /* a */:32, /* b */:32, xss_low, xss_high;
+        };
+    } xstate;
+
+    /* Extended leaves: 0x800000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
+        struct {
+            /* Leaf 0x80000000 - Max and vendor. */
+            uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } extd;
+};
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 03/25] x86/cpuid: Move featuresets into struct cpuid_policy
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 04/25] x86/cpuid: Allocate a CPUID policy for every domain Andrew Cooper
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Featuresets will eventually live only once in a struct cpuid_policy, but lots
of code currently uses the global featuresets as a linear bitmap.  Remove the
existing global *_featureset bitmaps, replacing them with *_policy objects
containing named featureset words and a fs[] linear bitmap.

Two new helpers are introduced to scatter/gather a linear featureset bitmap
to/from the fixed word locations in struct cpuid_policy.

The existing calculate_raw_policy() already obtains the scattered raw
featureset.  Gather the raw featureset into raw_policy.fs in
calculate_raw_policy() and drop calculate_raw_featureset() entirely.

Now that host_featureset can't be a straight define of
boot_cpu_data.x86_capability, introduce calculate_host_policy() to suitably
fill in host_policy from boot_cpu_data.x86_capability.  (Future changes will
have additional sanitization logic in this function.)

The PV and HVM policy objects and calculation functions have max introduced to
their names, as there will eventually be a distinction between max and default
policies for each domain type.  The existing logic works in terms of linear
bitmaps, so scatter the result back into the policy objects.

Leave some compatibility defines providing the old *_featureset API.  This
results in no observed change in the *_featureset values, which are still used
at the hypercall and guest_cpuid() interfaces.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
 * Avoid double structs.
---
 xen/arch/x86/cpuid.c        | 64 +++++++++++++--------------------------
 xen/include/asm-x86/cpuid.h | 73 ++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 85 insertions(+), 52 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 1bfa7d7..b31eda7 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -14,13 +14,12 @@ static const uint32_t __initconst hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEA
 static const uint32_t __initconst hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES;
 static const uint32_t __initconst deep_features[] = INIT_DEEP_FEATURES;
 
-uint32_t __read_mostly raw_featureset[FSCAPINTS];
-uint32_t __read_mostly pv_featureset[FSCAPINTS];
-uint32_t __read_mostly hvm_featureset[FSCAPINTS];
-
 #define EMPTY_LEAF ((struct cpuid_leaf){})
 
-static struct cpuid_policy __read_mostly raw_policy;
+struct cpuid_policy __read_mostly raw_policy,
+    __read_mostly host_policy,
+    __read_mostly pv_max_policy,
+    __read_mostly hvm_max_policy;
 
 static void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *data)
 {
@@ -130,47 +129,22 @@ static void __init calculate_raw_policy(void)
     for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
                          p->extd.max_leaf + 1 - 0x80000000ul); ++i )
         cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
+
+    cpuid_policy_to_featureset(p, p->fs);
 }
 
-static void __init calculate_raw_featureset(void)
+static void __init calculate_host_policy(void)
 {
-    unsigned int max, tmp;
-
-    max = cpuid_eax(0);
-
-    if ( max >= 1 )
-        cpuid(0x1, &tmp, &tmp,
-              &raw_featureset[FEATURESET_1c],
-              &raw_featureset[FEATURESET_1d]);
-    if ( max >= 7 )
-        cpuid_count(0x7, 0, &tmp,
-                    &raw_featureset[FEATURESET_7b0],
-                    &raw_featureset[FEATURESET_7c0],
-                    &raw_featureset[FEATURESET_7d0]);
-    if ( max >= 0xd )
-        cpuid_count(0xd, 1,
-                    &raw_featureset[FEATURESET_Da1],
-                    &tmp, &tmp, &tmp);
-
-    max = cpuid_eax(0x80000000);
-    if ( (max >> 16) != 0x8000 )
-        return;
+    struct cpuid_policy *p = &host_policy;
 
-    if ( max >= 0x80000001 )
-        cpuid(0x80000001, &tmp, &tmp,
-              &raw_featureset[FEATURESET_e1c],
-              &raw_featureset[FEATURESET_e1d]);
-    if ( max >= 0x80000007 )
-        cpuid(0x80000007, &tmp, &tmp, &tmp,
-              &raw_featureset[FEATURESET_e7d]);
-    if ( max >= 0x80000008 )
-        cpuid(0x80000008, &tmp,
-              &raw_featureset[FEATURESET_e8b],
-              &tmp, &tmp);
+    memcpy(p->fs, boot_cpu_data.x86_capability, sizeof(p->fs));
+
+    cpuid_featureset_to_policy(host_featureset, p);
 }
 
-static void __init calculate_pv_featureset(void)
+static void __init calculate_pv_max_policy(void)
 {
+    struct cpuid_policy *p = &pv_max_policy;
     unsigned int i;
 
     for ( i = 0; i < FSCAPINTS; ++i )
@@ -188,10 +162,12 @@ static void __init calculate_pv_featureset(void)
     __set_bit(X86_FEATURE_CMP_LEGACY, pv_featureset);
 
     sanitise_featureset(pv_featureset);
+    cpuid_featureset_to_policy(pv_featureset, p);
 }
 
-static void __init calculate_hvm_featureset(void)
+static void __init calculate_hvm_max_policy(void)
 {
+    struct cpuid_policy *p = &hvm_max_policy;
     unsigned int i;
     const uint32_t *hvm_featuremask;
 
@@ -244,15 +220,15 @@ static void __init calculate_hvm_featureset(void)
     }
 
     sanitise_featureset(hvm_featureset);
+    cpuid_featureset_to_policy(hvm_featureset, p);
 }
 
 void __init init_guest_cpuid(void)
 {
     calculate_raw_policy();
-
-    calculate_raw_featureset();
-    calculate_pv_featureset();
-    calculate_hvm_featureset();
+    calculate_host_policy();
+    calculate_pv_max_policy();
+    calculate_hvm_max_policy();
 }
 
 const uint32_t * __init lookup_deep_deps(uint32_t feature)
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 6176da7..0d0ac52 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -24,11 +24,6 @@
 extern const uint32_t known_features[FSCAPINTS];
 extern const uint32_t special_features[FSCAPINTS];
 
-extern uint32_t raw_featureset[FSCAPINTS];
-#define host_featureset boot_cpu_data.x86_capability
-extern uint32_t pv_featureset[FSCAPINTS];
-extern uint32_t hvm_featureset[FSCAPINTS];
-
 void init_guest_cpuid(void);
 
 const uint32_t *lookup_deep_deps(uint32_t feature);
@@ -87,7 +82,7 @@ struct cpuid_policy
      *   - {xcr0,xss}_{high,low}
      *
      * - Guest accurate:
-     *   - Nothing
+     *   - All FEATURESET_* words
      *
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
@@ -98,6 +93,9 @@ struct cpuid_policy
         struct {
             /* Leaf 0x0 - Max and vendor. */
             uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+
+            /* Leaf 0x1 - Family/model/stepping and features. */
+            uint32_t /* a */:32, /* b */:32, _1c, _1d;
         };
     } basic;
 
@@ -106,7 +104,7 @@ struct cpuid_policy
         struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
         struct {
             /* Subleaf 0. */
-            uint32_t max_subleaf, /* b */:32, /* c */:32, /* d */:32;
+            uint32_t max_subleaf, _7b0, _7c0, _7d0;
         };
     } feat;
 
@@ -118,7 +116,7 @@ struct cpuid_policy
             uint32_t xcr0_low, /* b */:32, /* c */:32, xcr0_high;
 
             /* Subleaf 1. */
-            uint32_t /* a */:32, /* b */:32, xss_low, xss_high;
+            uint32_t Da1, /* b */:32, xss_low, xss_high;
         };
     } xstate;
 
@@ -128,10 +126,69 @@ struct cpuid_policy
         struct {
             /* Leaf 0x80000000 - Max and vendor. */
             uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+
+            /* Leaf 0x80000001 - Family/model/stepping and features. */
+            uint32_t /* a */:32, /* b */:32, e1c, e1d;
+
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* L1 cache/TLB. */
+            uint64_t :64, :64; /* L2/3 cache/TLB. */
+
+            /* Leaf 0x80000007 - Advanced Power Management. */
+            uint32_t /* a */:32, /* b */:32, /* c */:32, e7d;
+
+            /* Leaf 0x80000008 - Misc addr/feature info. */
+            uint32_t /* a */:32, e8b, /* c */:32, /* d */:32;
         };
     } extd;
+
+    /* Temporary featureset bitmap. */
+    uint32_t fs[FSCAPINTS];
 };
 
+/* Fill in a featureset bitmap from a CPUID policy. */
+static inline void cpuid_policy_to_featureset(
+    const struct cpuid_policy *p, uint32_t fs[FSCAPINTS])
+{
+    fs[FEATURESET_1d]  = p->basic._1d;
+    fs[FEATURESET_1c]  = p->basic._1c;
+    fs[FEATURESET_e1d] = p->extd.e1d;
+    fs[FEATURESET_e1c] = p->extd.e1c;
+    fs[FEATURESET_Da1] = p->xstate.Da1;
+    fs[FEATURESET_7b0] = p->feat._7b0;
+    fs[FEATURESET_7c0] = p->feat._7c0;
+    fs[FEATURESET_e7d] = p->extd.e7d;
+    fs[FEATURESET_e8b] = p->extd.e8b;
+    fs[FEATURESET_7d0] = p->feat._7d0;
+}
+
+/* Fill in a CPUID policy from a featureset bitmap. */
+static inline void cpuid_featureset_to_policy(
+    const uint32_t fs[FSCAPINTS], struct cpuid_policy *p)
+{
+    p->basic._1d  = fs[FEATURESET_1d];
+    p->basic._1c  = fs[FEATURESET_1c];
+    p->extd.e1d   = fs[FEATURESET_e1d];
+    p->extd.e1c   = fs[FEATURESET_e1c];
+    p->xstate.Da1 = fs[FEATURESET_Da1];
+    p->feat._7b0  = fs[FEATURESET_7b0];
+    p->feat._7c0  = fs[FEATURESET_7c0];
+    p->extd.e7d   = fs[FEATURESET_e7d];
+    p->extd.e8b   = fs[FEATURESET_e8b];
+    p->feat._7d0  = fs[FEATURESET_7d0];
+}
+
+extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
+    hvm_max_policy;
+
+/* Temporary compatibility defines. */
+#define raw_featureset raw_policy.fs
+#define host_featureset host_policy.fs
+#define pv_featureset pv_max_policy.fs
+#define hvm_featureset hvm_max_policy.fs
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 04/25] x86/cpuid: Allocate a CPUID policy for every domain
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (2 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 03/25] x86/cpuid: Move featuresets into " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate Andrew Cooper
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Introduce init_domain_cpuid_policy() to allocate an appropriate cpuid policy
for the domain (currently the domains maximum applicable policy), and call it
during domain construction.

init_guest_cpuid() now needs calling before dom0 is constructed.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
 * Move cpuid_policy * in arch_domain to avoid extra holes
---
 xen/arch/x86/cpuid.c         | 12 ++++++++++++
 xen/arch/x86/domain.c        |  6 ++++++
 xen/arch/x86/setup.c         |  4 ++--
 xen/include/asm-x86/cpuid.h  | 13 +++++++++++++
 xen/include/asm-x86/domain.h |  3 +++
 5 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index b31eda7..6c95b7f 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -261,6 +261,18 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
     return NULL;
 }
 
+int init_domain_cpuid_policy(struct domain *d)
+{
+    d->arch.cpuid = xmalloc(struct cpuid_policy);
+
+    if ( !d->arch.cpuid )
+        return -ENOMEM;
+
+    *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
+
+    return 0;
+}
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res)
 {
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 9393187..c1f95cc 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -532,6 +532,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( is_idle_domain(d) )
     {
         d->arch.emulation_flags = 0;
+        d->arch.cpuid = ZERO_BLOCK_PTR; /* Catch stray misuses. */
     }
     else
     {
@@ -601,6 +602,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
             goto fail;
         paging_initialised = 1;
 
+        if ( (rc = init_domain_cpuid_policy(d)) )
+            goto fail;
+
         d->arch.cpuids = xmalloc_array(cpuid_input_t, MAX_CPUID_INPUT);
         rc = -ENOMEM;
         if ( d->arch.cpuids == NULL )
@@ -674,6 +678,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     cleanup_domain_irq_mapping(d);
     free_xenheap_page(d->shared_info);
     xfree(d->arch.cpuids);
+    xfree(d->arch.cpuid);
     if ( paging_initialised )
         paging_final_teardown(d);
     free_perdomain_mappings(d);
@@ -692,6 +697,7 @@ void arch_domain_destroy(struct domain *d)
 
     xfree(d->arch.e820);
     xfree(d->arch.cpuids);
+    xfree(d->arch.cpuid);
 
     free_domain_pirqs(d);
     if ( !is_idle_domain(d) )
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 94db514..0ccef1d 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1540,6 +1540,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( !tboot_protect_mem_regions() )
         panic("Could not protect TXT memory regions");
 
+    init_guest_cpuid();
+
     if ( opt_dom0pvh )
         domcr_flags |= DOMCRF_pvh | DOMCRF_hap;
 
@@ -1590,8 +1592,6 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                "Multiple initrd candidates, picking module #%u\n",
                initrdidx);
 
-    init_guest_cpuid();
-
     /*
      * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0().
      * This saves a large number of corner cases interactions with
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 0d0ac52..77a467a 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -84,6 +84,16 @@ struct cpuid_policy
      * - Guest accurate:
      *   - All FEATURESET_* words
      *
+     * Per-domain objects:
+     *
+     * - Host accurate:
+     *   - max_{,sub}leaf
+     *   - {xcr0,xss}_{high,low}
+     *   - All FEATURESET_* words
+     *
+     * - Guest accurate:
+     *   - Nothing
+     *
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
 
@@ -189,6 +199,9 @@ extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
 #define pv_featureset pv_max_policy.fs
 #define hvm_featureset hvm_max_policy.fs
 
+/* Allocate and initialise a CPUID policy suitable for the domain. */
+int init_domain_cpuid_policy(struct domain *d);
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 95762cf..780f311 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -362,6 +362,9 @@ struct arch_domain
 
     cpuid_input_t *cpuids;
 
+    /* CPUID Policy. */
+    struct cpuid_policy *cpuid;
+
     struct PITState vpit;
 
     /* TSC management (emulation, pv, scaling, stats) */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (3 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 04/25] x86/cpuid: Allocate a CPUID policy for every domain Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:35   ` Andrew Cooper
  2017-01-09 15:22   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid() Andrew Cooper
                   ` (19 subsequent siblings)
  24 siblings, 2 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, Jan Beulich

Introduce recalculate_cpuid_policy() which clamps a CPUID policy based on the
domains current restrictions.

Each adjustment introduced here mirrors what currently happens in
{pv,hvm}_cpuid(), although some logic is expressed differently.

 * The clearing X86_FEATURE_LM for 32bit PV guests, sanitise_featureset()
   takes out all 64bit-dependent features in one go.

 * The toolstacks choice of X86_FEATURE_ITSC in (by default) clobbered in
   domain_cpuid(), but {pv,hvm}_cpuid() needed to account for the host ITSC
   value when masking the toolstack value.

This now requires that sanitise_featureset(), lookup_deep_deps() and
associated data needs to be available at runtime, so moves out of __init.

Recalculate the cpuid policy when:

 * The domain is first created
 * Switching a PV guest to being compat
 * Setting disable_migrate or vTSC modes
 * The toolstack sets new policy data

The disable_migrate code was previously common.  To compensate, move the code
to each archs arch_do_domctl(), as the implementations now differ.

From this point on, domains have full and correct feature-leaf information in
their CPUID policies, allowing for substantial cleanup and improvements.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

v2:
 * Rewrite the commit message
 * Recalculate on disable_migrate/vTSC changes
 * Reorder and comment the logic better in recalculate_cpuid_policy()
---
 xen/arch/arm/domctl.c            |  5 +++
 xen/arch/x86/cpuid.c             | 70 ++++++++++++++++++++++++++++++++++++----
 xen/arch/x86/domain.c            |  1 +
 xen/arch/x86/domctl.c            | 29 +++++++++++++++++
 xen/arch/x86/time.c              |  2 ++
 xen/common/domctl.c              |  4 ---
 xen/include/asm-x86/cpufeature.h |  1 +
 xen/include/asm-x86/cpuid.h      | 10 +++---
 8 files changed, 105 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 09d9959..fee4b17 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -115,6 +115,11 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
 
         return 0;
     }
+
+    case XEN_DOMCTL_disable_migrate:
+        d->disable_migrate = domctl->u.disable_migrate.disable;
+        break;
+
     default:
     {
         int rc;
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 6c95b7f..0d54465 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -9,10 +9,10 @@
 const uint32_t known_features[] = INIT_KNOWN_FEATURES;
 const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
 
-static const uint32_t __initconst pv_featuremask[] = INIT_PV_FEATURES;
-static const uint32_t __initconst hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES;
-static const uint32_t __initconst hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES;
-static const uint32_t __initconst deep_features[] = INIT_DEEP_FEATURES;
+static const uint32_t pv_featuremask[] = INIT_PV_FEATURES;
+static const uint32_t hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES;
+static const uint32_t hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES;
+static const uint32_t deep_features[] = INIT_DEEP_FEATURES;
 
 #define EMPTY_LEAF ((struct cpuid_leaf){})
 
@@ -32,7 +32,7 @@ static void cpuid_count_leaf(uint32_t leaf, uint32_t subleaf,
     cpuid_count(leaf, subleaf, &data->a, &data->b, &data->c, &data->d);
 }
 
-static void __init sanitise_featureset(uint32_t *fs)
+static void sanitise_featureset(uint32_t *fs)
 {
     /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
     uint32_t disabled_features[
@@ -231,12 +231,12 @@ void __init init_guest_cpuid(void)
     calculate_hvm_max_policy();
 }
 
-const uint32_t * __init lookup_deep_deps(uint32_t feature)
+const uint32_t *lookup_deep_deps(uint32_t feature)
 {
     static const struct {
         uint32_t feature;
         uint32_t fs[FSCAPINTS];
-    } deep_deps[] __initconst = INIT_DEEP_DEPS;
+    } deep_deps[] = INIT_DEEP_DEPS;
     unsigned int start = 0, end = ARRAY_SIZE(deep_deps);
 
     BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS);
@@ -261,6 +261,60 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
     return NULL;
 }
 
+void recalculate_cpuid_policy(struct domain *d)
+{
+    struct cpuid_policy *p = d->arch.cpuid;
+    const struct cpuid_policy *max =
+        is_pv_domain(d) ? &pv_max_policy : &hvm_max_policy;
+    uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS];
+    unsigned int i;
+
+    cpuid_policy_to_featureset(p, fs);
+    memcpy(max_fs, max->fs, sizeof(max_fs));
+
+    /*
+     * HVM domains using Shadow paging have further restrictions on their
+     * available paging features.
+     */
+    if ( is_hvm_domain(d) && !hap_enabled(d) )
+    {
+        for ( i = 0; i < ARRAY_SIZE(max_fs); i++ )
+            max_fs[i] &= hvm_shadow_featuremask[i];
+    }
+
+    /*
+     * 32bit PV domains can't use any Long Mode features, and cannot use
+     * SYSCALL on non-AMD hardware.
+     */
+    if ( is_pv_32bit_domain(d) )
+    {
+        __clear_bit(X86_FEATURE_LM, max_fs);
+        if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+            __clear_bit(X86_FEATURE_SYSCALL, max_fs);
+    }
+
+    /*
+     * ITSC is masked by default (so domains are safe to migrate), but a
+     * toolstack which has configured disable_migrate or vTSC for a domain may
+     * safely select it, and needs a way of doing so.
+     */
+    if ( cpu_has_itsc && (d->disable_migrate || d->arch.vtsc) )
+        __set_bit(X86_FEATURE_ITSC, max_fs);
+
+    /* Clamp the toolstacks choices to reality. */
+    for ( i = 0; i < ARRAY_SIZE(fs); i++ )
+        fs[i] &= max_fs[i];
+
+    sanitise_featureset(fs);
+
+    /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
+    fs[FEATURESET_7b0] &= ~special_features[FEATURESET_7b0];
+    fs[FEATURESET_7b0] |= (host_featureset[FEATURESET_7b0] &
+                           special_features[FEATURESET_7b0]);
+
+    cpuid_featureset_to_policy(fs, p);
+}
+
 int init_domain_cpuid_policy(struct domain *d)
 {
     d->arch.cpuid = xmalloc(struct cpuid_policy);
@@ -270,6 +324,8 @@ int init_domain_cpuid_policy(struct domain *d)
 
     *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
 
+    recalculate_cpuid_policy(d);
+
     return 0;
 }
 
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c1f95cc..7d33c41 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -352,6 +352,7 @@ int switch_compat(struct domain *d)
     }
 
     domain_set_alloc_bitsize(d);
+    recalculate_cpuid_policy(d);
 
     d->arch.x87_fip_width = 4;
 
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index ab141b1..a3b2b72 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -51,6 +51,30 @@ static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
 static void update_domain_cpuid_info(struct domain *d,
                                      const xen_domctl_cpuid_t *ctl)
 {
+    struct cpuid_policy *p = d->arch.cpuid;
+    const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
+
+    /* Insert ctl data into cpuid_policy. */
+    if ( ctl->input[0] < ARRAY_SIZE(p->basic.raw) )
+    {
+        if ( ctl->input[0] == 7 )
+        {
+            if ( ctl->input[1] < ARRAY_SIZE(p->feat.raw) )
+                p->feat.raw[ctl->input[1]] = leaf;
+        }
+        else if ( ctl->input[0] == 0xd )
+        {
+            if ( ctl->input[1] < ARRAY_SIZE(p->xstate.raw) )
+                p->xstate.raw[ctl->input[1]] = leaf;
+        }
+        else
+            p->basic.raw[ctl->input[0]] = leaf;
+    }
+    else if ( (ctl->input[0] - 0x80000000) < ARRAY_SIZE(p->extd.raw) )
+        p->extd.raw[ctl->input[0] - 0x80000000] = leaf;
+
+    recalculate_cpuid_policy(d);
+
     switch ( ctl->input[0] )
     {
     case 0: {
@@ -1409,6 +1433,11 @@ long arch_do_domctl(
         }
         break;
 
+    case XEN_DOMCTL_disable_migrate:
+        d->disable_migrate = domctl->u.disable_migrate.disable;
+        recalculate_cpuid_policy(d);
+        break;
+
     default:
         ret = iommu_do_domctl(domctl, d, u_domctl);
         break;
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index b89fa13..e17da1b 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -2106,6 +2106,8 @@ void tsc_set_info(struct domain *d,
                                      d->arch.hvm_domain.sync_tsc);
         }
     }
+
+    recalculate_cpuid_policy(d);
 }
 
 /* vtsc may incur measurable performance degradation, diagnose with this */
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index b0ee961..12cf4a9 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -1103,10 +1103,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
         copyback = 1;
         break;
 
-    case XEN_DOMCTL_disable_migrate:
-        d->disable_migrate = op->u.disable_migrate.disable;
-        break;
-
 #ifdef CONFIG_HAS_MEM_ACCESS
     case XEN_DOMCTL_set_access_required:
         if ( unlikely(current->domain == d) ) /* no domain_pause() */
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 9326616..f34d01c 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -71,6 +71,7 @@
 #define cpu_has_eist		boot_cpu_has(X86_FEATURE_EIST)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_cmp_legacy	boot_cpu_has(X86_FEATURE_CMP_LEGACY)
+#define cpu_has_itsc		boot_cpu_has(X86_FEATURE_ITSC)
 
 enum _cache_type {
     CACHE_TYPE_NULL = 0,
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 77a467a..0592b38 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -86,13 +86,8 @@ struct cpuid_policy
      *
      * Per-domain objects:
      *
-     * - Host accurate:
-     *   - max_{,sub}leaf
-     *   - {xcr0,xss}_{high,low}
-     *   - All FEATURESET_* words
-     *
      * - Guest accurate:
-     *   - Nothing
+     *   - All FEATURESET_* words
      *
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
@@ -202,6 +197,9 @@ extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
 /* Allocate and initialise a CPUID policy suitable for the domain. */
 int init_domain_cpuid_policy(struct domain *d);
 
+/* Clamp the CPUID policy to reality. */
+void recalculate_cpuid_policy(struct domain *d);
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (4 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:36   ` Paul Durrant
  2017-01-09 15:29   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() " Andrew Cooper
                   ` (18 subsequent siblings)
  24 siblings, 2 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Paul Durrant, Jan Beulich

... rather than from the legacy path.  Update the API to match guest_cpuid(),
and remove its dependence on current.

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

v2:
 * Introduce a break statement into guest_cpuid().
 * Retain the explicit zeroing of SP and Service branch.
 * Drop the EFER/SVM adjustment and leave the code as it was.
 * Consistently use uint32_t.
---
 xen/arch/x86/cpuid.c               | 12 +++++++
 xen/arch/x86/hvm/hvm.c             |  3 --
 xen/arch/x86/hvm/viridian.c        | 65 +++++++++++++++++++-------------------
 xen/include/asm-x86/hvm/viridian.h |  9 ++----
 4 files changed, 46 insertions(+), 43 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 0d54465..69a4f1b 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -337,6 +337,18 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
 
     *res = EMPTY_LEAF;
 
+    /*
+     * First pass:
+     * - Dispatch the virtualised leaves to their respective handlers.
+     */
+    switch ( leaf )
+    {
+    case 0x40000000 ... 0x400000ff:
+        if ( is_viridian_domain(d) )
+            return cpuid_viridian_leaves(v, leaf, subleaf, res);
+        break;
+    }
+
     /* {hvm,pv}_cpuid() have this expectation. */
     ASSERT(v == curr);
 
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 4c0f561..9ff5f92 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3353,9 +3353,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     if ( !edx )
         edx = &dummy;
 
-    if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
-        return;
-
     if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
         return;
 
diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c
index f6abdd2..37c8f68 100644
--- a/xen/arch/x86/hvm/viridian.c
+++ b/xen/arch/x86/hvm/viridian.c
@@ -66,77 +66,76 @@
 #define CPUID6A_MSR_BITMAPS     (1 << 1)
 #define CPUID6A_NESTED_PAGING   (1 << 3)
 
-int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax,
-                          unsigned int *ebx, unsigned int *ecx,
-                          unsigned int *edx)
+void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
+                           uint32_t subleaf, struct cpuid_leaf *res)
 {
-    struct domain *d = current->domain;
+    const struct domain *d = v->domain;
 
-    if ( !is_viridian_domain(d) )
-        return 0;
+    ASSERT(is_viridian_domain(d));
+    ASSERT(leaf >= 0x40000000 && leaf < 0x40000100);
 
     leaf -= 0x40000000;
-    if ( leaf > 6 )
-        return 0;
 
-    *eax = *ebx = *ecx = *edx = 0;
     switch ( leaf )
     {
     case 0:
-        *eax = 0x40000006; /* Maximum leaf */
-        *ebx = 0x7263694d; /* Magic numbers  */
-        *ecx = 0x666F736F;
-        *edx = 0x76482074;
+        res->a = 0x40000006; /* Maximum leaf */
+        res->b = 0x7263694d; /* Magic numbers  */
+        res->c = 0x666F736F;
+        res->d = 0x76482074;
         break;
+
     case 1:
-        *eax = 0x31237648; /* Version number */
+        res->a = 0x31237648; /* Version number */
         break;
+
     case 2:
         /* Hypervisor information, but only if the guest has set its
            own version number. */
         if ( d->arch.hvm_domain.viridian.guest_os_id.raw == 0 )
             break;
-        *eax = 1; /* Build number */
-        *ebx = (xen_major_version() << 16) | xen_minor_version();
-        *ecx = 0; /* SP */
-        *edx = 0; /* Service branch and number */
+        res->a = 1; /* Build number */
+        res->b = (xen_major_version() << 16) | xen_minor_version();
+        res->c = 0; /* SP */
+        res->d = 0; /* Service branch and number */
         break;
+
     case 3:
         /* Which hypervisor MSRs are available to the guest */
-        *eax = (CPUID3A_MSR_APIC_ACCESS |
-                CPUID3A_MSR_HYPERCALL   |
-                CPUID3A_MSR_VP_INDEX);
+        res->a = (CPUID3A_MSR_APIC_ACCESS |
+                  CPUID3A_MSR_HYPERCALL   |
+                  CPUID3A_MSR_VP_INDEX);
         if ( !(viridian_feature_mask(d) & HVMPV_no_freq) )
-            *eax |= CPUID3A_MSR_FREQ;
+            res->a |= CPUID3A_MSR_FREQ;
         if ( viridian_feature_mask(d) & HVMPV_time_ref_count )
-            *eax |= CPUID3A_MSR_TIME_REF_COUNT;
+            res->a |= CPUID3A_MSR_TIME_REF_COUNT;
         if ( viridian_feature_mask(d) & HVMPV_reference_tsc )
-            *eax |= CPUID3A_MSR_REFERENCE_TSC;
+            res->a |= CPUID3A_MSR_REFERENCE_TSC;
         break;
+
     case 4:
         /* Recommended hypercall usage. */
         if ( (d->arch.hvm_domain.viridian.guest_os_id.raw == 0) ||
              (d->arch.hvm_domain.viridian.guest_os_id.fields.os < 4) )
             break;
-        *eax = CPUID4A_RELAX_TIMER_INT;
+        res->a = CPUID4A_RELAX_TIMER_INT;
         if ( viridian_feature_mask(d) & HVMPV_hcall_remote_tlb_flush )
-            *eax |= CPUID4A_HCALL_REMOTE_TLB_FLUSH;
+            res->a |= CPUID4A_HCALL_REMOTE_TLB_FLUSH;
         if ( !cpu_has_vmx_apic_reg_virt )
-            *eax |= CPUID4A_MSR_BASED_APIC;
-        *ebx = 2047; /* long spin count */
+            res->a |= CPUID4A_MSR_BASED_APIC;
+        res->b = 2047; /* long spin count */
         break;
+
     case 6:
         /* Detected and in use hardware features. */
         if ( cpu_has_vmx_virtualize_apic_accesses )
-            *eax |= CPUID6A_APIC_OVERLAY;
+            res->a |= CPUID6A_APIC_OVERLAY;
         if ( cpu_has_vmx_msr_bitmap || (read_efer() & EFER_SVME) )
-            *eax |= CPUID6A_MSR_BITMAPS;
+            res->a |= CPUID6A_MSR_BITMAPS;
         if ( hap_enabled(d) )
-            *eax |= CPUID6A_NESTED_PAGING;
+            res->a |= CPUID6A_NESTED_PAGING;
         break;
     }
-
-    return 1;
 }
 
 static void dump_guest_os_id(const struct domain *d)
diff --git a/xen/include/asm-x86/hvm/viridian.h b/xen/include/asm-x86/hvm/viridian.h
index bdbccd5..8c45d0f 100644
--- a/xen/include/asm-x86/hvm/viridian.h
+++ b/xen/include/asm-x86/hvm/viridian.h
@@ -97,13 +97,8 @@ struct viridian_domain
     union viridian_reference_tsc reference_tsc;
 };
 
-int
-cpuid_viridian_leaves(
-    unsigned int leaf,
-    unsigned int *eax,
-    unsigned int *ebx,
-    unsigned int *ecx,
-    unsigned int *edx);
+void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
+                           uint32_t subleaf, struct cpuid_leaf *res);
 
 int
 wrmsr_viridian_regs(
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() from guest_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (5 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 16:21   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields Andrew Cooper
                   ` (17 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

... rather than from the legacy path.  Update the API to match guest_cpuid(),
and remove its dependence on current.

Make use of guest_cpuid() unconditionally zeroing res to avoid repeated
re-zeroing.  To use a const struct domain, domain_cpuid() needs to be
const-corrected.

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

v2:
 * Don't expose Xen leaves through two windows.
 * Drop unnecessary !! and casts.
---
 xen/arch/x86/cpuid.c            |  5 ++-
 xen/arch/x86/domain.c           |  2 +-
 xen/arch/x86/hvm/hvm.c          |  3 --
 xen/arch/x86/traps.c            | 99 ++++++++++++++++-------------------------
 xen/include/asm-x86/domain.h    |  2 +-
 xen/include/asm-x86/processor.h |  4 +-
 6 files changed, 47 insertions(+), 68 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 69a4f1b..37203eb 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -346,7 +346,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
     case 0x40000000 ... 0x400000ff:
         if ( is_viridian_domain(d) )
             return cpuid_viridian_leaves(v, leaf, subleaf, res);
-        break;
+
+        /* Fallthrough. */
+    case 0x40000100 ... 0x4fffffff:
+        return cpuid_hypervisor_leaves(v, leaf, subleaf, res);
     }
 
     /* {hvm,pv}_cpuid() have this expectation. */
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 7d33c41..b554a9c 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -2623,7 +2623,7 @@ void arch_dump_vcpu_info(struct vcpu *v)
 }
 
 void domain_cpuid(
-    struct domain *d,
+    const struct domain *d,
     unsigned int  input,
     unsigned int  sub_input,
     unsigned int  *eax,
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 9ff5f92..ebddefc 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3353,9 +3353,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     if ( !edx )
         edx = &dummy;
 
-    if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
-        return;
-
     if ( input & 0x7fffffff )
     {
         /*
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 3acc244..5ce8936 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -902,20 +902,18 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
     return 0;
 }
 
-int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
-               uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf,
+                             uint32_t subleaf, struct cpuid_leaf *res)
 {
-    struct vcpu *curr = current;
-    struct domain *currd = curr->domain;
-    /* Optionally shift out of the way of Viridian architectural leaves. */
-    uint32_t base = is_viridian_domain(currd) ? 0x40000100 : 0x40000000;
+    const struct domain *d = v->domain;
+    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
+    uint32_t idx  = leaf - base;
     uint32_t limit, dummy;
 
-    idx -= base;
     if ( idx > XEN_CPUID_MAX_NUM_LEAVES )
-        return 0; /* Avoid unnecessary pass through domain_cpuid() */
+        return; /* Avoid unnecessary pass through domain_cpuid() */
 
-    domain_cpuid(currd, base, 0, &limit, &dummy, &dummy, &dummy);
+    domain_cpuid(d, base, 0, &limit, &dummy, &dummy, &dummy);
     if ( limit == 0 )
         /* Default number of leaves */
         limit = XEN_CPUID_MAX_NUM_LEAVES;
@@ -929,83 +927,70 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
             limit = XEN_CPUID_MAX_NUM_LEAVES;
     }
 
-    if ( idx > limit ) 
-        return 0;
+    if ( idx > limit )
+        return;
 
     switch ( idx )
     {
     case 0:
-        *eax = base + limit; /* Largest leaf */
-        *ebx = XEN_CPUID_SIGNATURE_EBX;
-        *ecx = XEN_CPUID_SIGNATURE_ECX;
-        *edx = XEN_CPUID_SIGNATURE_EDX;
+        res->a = base + limit; /* Largest leaf */
+        res->b = XEN_CPUID_SIGNATURE_EBX;
+        res->c = XEN_CPUID_SIGNATURE_ECX;
+        res->d = XEN_CPUID_SIGNATURE_EDX;
         break;
 
     case 1:
-        *eax = (xen_major_version() << 16) | xen_minor_version();
-        *ebx = 0;          /* Reserved */
-        *ecx = 0;          /* Reserved */
-        *edx = 0;          /* Reserved */
+        res->a = (xen_major_version() << 16) | xen_minor_version();
         break;
 
     case 2:
-        *eax = 1;          /* Number of hypercall-transfer pages */
-        *ebx = 0x40000000; /* MSR base address */
-        if ( is_viridian_domain(currd) )
-            *ebx = 0x40000200;
-        *ecx = 0;          /* Features 1 */
-        *edx = 0;          /* Features 2 */
-        if ( is_pv_domain(currd) )
-            *ecx |= XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD;
+        res->a = 1;            /* Number of hypercall-transfer pages */
+                               /* MSR base address */
+        res->b = is_viridian_domain(d) ? 0x40000200 : 0x40000000;
+        if ( is_pv_domain(d) ) /* Features */
+            res->c |= XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD;
         break;
 
     case 3: /* Time leaf. */
-        switch ( sub_idx )
+        switch ( subleaf )
         {
         case 0: /* features */
-            *eax = ((!!currd->arch.vtsc << 0) |
-                    (!!host_tsc_is_safe() << 1) |
-                    (!!boot_cpu_has(X86_FEATURE_RDTSCP) << 2));
-            *ebx = currd->arch.tsc_mode;
-            *ecx = currd->arch.tsc_khz;
-            *edx = currd->arch.incarnation;
+            res->a = ((d->arch.vtsc << 0) |
+                      (!!host_tsc_is_safe() << 1) |
+                      (!!boot_cpu_has(X86_FEATURE_RDTSCP) << 2));
+            res->b = d->arch.tsc_mode;
+            res->c = d->arch.tsc_khz;
+            res->d = d->arch.incarnation;
             break;
 
         case 1: /* scale and offset */
         {
             uint64_t offset;
 
-            if ( !currd->arch.vtsc )
-                offset = currd->arch.vtsc_offset;
+            if ( !d->arch.vtsc )
+                offset = d->arch.vtsc_offset;
             else
                 /* offset already applied to value returned by virtual rdtscp */
                 offset = 0;
-            *eax = (uint32_t)offset;
-            *ebx = (uint32_t)(offset >> 32);
-            *ecx = currd->arch.vtsc_to_ns.mul_frac;
-            *edx = (s8)currd->arch.vtsc_to_ns.shift;
+            res->a = offset;
+            res->b = offset >> 32;
+            res->c = d->arch.vtsc_to_ns.mul_frac;
+            res->d = (s8)d->arch.vtsc_to_ns.shift;
             break;
         }
 
         case 2: /* physical cpu_khz */
-            *eax = cpu_khz;
-            *ebx = *ecx = *edx = 0;
-            break;
-
-        default:
-            *eax = *ebx = *ecx = *edx = 0;
+            res->a = cpu_khz;
             break;
         }
         break;
 
     case 4: /* HVM hypervisor leaf. */
-        *eax = *ebx = *ecx = *edx = 0;
-
-        if ( !has_hvm_container_domain(currd) || sub_idx != 0 )
+        if ( !has_hvm_container_domain(d) || subleaf != 0 )
             break;
 
         if ( cpu_has_vmx_apic_reg_virt )
-            *eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
+            res->a |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
 
         /*
          * We want to claim that x2APIC is virtualized if APIC MSR accesses
@@ -1016,24 +1001,22 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
         if ( cpu_has_vmx_virtualize_x2apic_mode &&
              cpu_has_vmx_apic_reg_virt &&
              cpu_has_vmx_virtual_intr_delivery )
-            *eax |= XEN_HVM_CPUID_X2APIC_VIRT;
+            res->a |= XEN_HVM_CPUID_X2APIC_VIRT;
 
         /*
          * Indicate that memory mapped from other domains (either grants or
          * foreign pages) has valid IOMMU entries.
          */
-        *eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
+        res->a |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
 
         /* Indicate presence of vcpu id and set it in ebx */
-        *eax |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
-        *ebx = curr->vcpu_id;
+        res->a |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
+        res->b = v->vcpu_id;
         break;
 
     default:
         BUG();
     }
-
-    return 1;
 }
 
 void pv_cpuid(struct cpu_user_regs *regs)
@@ -1047,9 +1030,6 @@ void pv_cpuid(struct cpu_user_regs *regs)
     subleaf = c = regs->_ecx;
     d = regs->_edx;
 
-    if ( cpuid_hypervisor_leaves(leaf, subleaf, &a, &b, &c, &d) )
-        goto out;
-
     if ( leaf & 0x7fffffff )
     {
         /*
@@ -1381,7 +1361,6 @@ void pv_cpuid(struct cpu_user_regs *regs)
         break;
     }
 
- out:
     regs->rax = a;
     regs->rbx = b;
     regs->rcx = c;
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 780f311..896e78d 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -617,7 +617,7 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *, unsigned long guest_cr4);
              X86_CR4_OSXSAVE | X86_CR4_SMEP |               \
              X86_CR4_FSGSBASE | X86_CR4_SMAP))
 
-void domain_cpuid(struct domain *d,
+void domain_cpuid(const struct domain *d,
                   unsigned int  input,
                   unsigned int  sub_input,
                   unsigned int  *eax,
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index aff115b..3e84164 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -610,8 +610,8 @@ struct stubs {
 DECLARE_PER_CPU(struct stubs, stubs);
 unsigned long alloc_stub_page(unsigned int cpu, unsigned long *mfn);
 
-int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
-          uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf,
+                             uint32_t subleaf, struct cpuid_leaf *res);
 int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val);
 int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val);
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (6 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 16:31   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 09/25] x86/hvm: Improve hvm_efer_valid() using named features Andrew Cooper
                   ` (16 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

It greatly aids the readibility of code to express feature checks with their
direct name (e.g. p->basic.mtrr or p->extd.lm), rarther that by a field and a
bitmask.  gen-cpuid.py is augmented to calculate a suitable declaration to
live in a union with the underlying feature word.

gen-cpuid.py doesn't know Xen's choice of naming for the feature word indicies
(and arguably shouldn't care), so provides the declarations in terms of their
numeric feature word index.  The DECL_BITFIELD() macro (local to cpuid_policy)
takes a feature word index name and chooses the right declaration, to aid
clarity.

All X86_FEATURE_*'s are included in the naming, other than the features
fast-forwarded from other state (APIC, OSXSAVE, OSPKE), whose value cannot be
read out of the feature word.

No functional change.

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

v2:
 * Dynamically generate the names
---
 xen/include/asm-x86/cpuid.h | 61 ++++++++++++++++++++++++++++++++++++++++-----
 xen/tools/gen-cpuid.py      | 32 ++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 0592b38..924e5d4 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -92,6 +92,10 @@ struct cpuid_policy
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
 
+#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
+#define _DECL_BITFIELD(x)   __DECL_BITFIELD(x)
+#define __DECL_BITFIELD(x)  NAMED_BITFIELD_ ## x
+
     /* Basic leaves: 0x000000xx */
     union {
         struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC];
@@ -100,7 +104,15 @@ struct cpuid_policy
             uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
 
             /* Leaf 0x1 - Family/model/stepping and features. */
-            uint32_t /* a */:32, /* b */:32, _1c, _1d;
+            uint32_t /* a */:32, /* b */:32;
+            union {
+                uint32_t _1c;
+                struct { DECL_BITFIELD(1c); };
+            };
+            union {
+                uint32_t _1d;
+                struct { DECL_BITFIELD(1d); };
+            };
         };
     } basic;
 
@@ -109,7 +121,19 @@ struct cpuid_policy
         struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
         struct {
             /* Subleaf 0. */
-            uint32_t max_subleaf, _7b0, _7c0, _7d0;
+            uint32_t max_subleaf;
+            union {
+                uint32_t _7b0;
+                struct { DECL_BITFIELD(7b0); };
+            };
+            union {
+                uint32_t _7c0;
+                struct { DECL_BITFIELD(7c0); };
+            };
+            union {
+                uint32_t _7d0;
+                struct { DECL_BITFIELD(7d0); };
+            };
         };
     } feat;
 
@@ -121,7 +145,11 @@ struct cpuid_policy
             uint32_t xcr0_low, /* b */:32, /* c */:32, xcr0_high;
 
             /* Subleaf 1. */
-            uint32_t Da1, /* b */:32, xss_low, xss_high;
+            union {
+                uint32_t Da1;
+                struct { DECL_BITFIELD(Da1); };
+            };
+            uint32_t /* b */:32, xss_low, xss_high;
         };
     } xstate;
 
@@ -133,7 +161,15 @@ struct cpuid_policy
             uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
 
             /* Leaf 0x80000001 - Family/model/stepping and features. */
-            uint32_t /* a */:32, /* b */:32, e1c, e1d;
+            uint32_t /* a */:32, /* b */:32;
+            union {
+                uint32_t e1c;
+                struct { DECL_BITFIELD(e1c); };
+            };
+            union {
+                uint32_t e1d;
+                struct { DECL_BITFIELD(e1d); };
+            };
 
             uint64_t :64, :64; /* Brand string. */
             uint64_t :64, :64; /* Brand string. */
@@ -142,13 +178,26 @@ struct cpuid_policy
             uint64_t :64, :64; /* L2/3 cache/TLB. */
 
             /* Leaf 0x80000007 - Advanced Power Management. */
-            uint32_t /* a */:32, /* b */:32, /* c */:32, e7d;
+            uint32_t /* a */:32, /* b */:32, /* c */:32;
+            union {
+                uint32_t e7d;
+                struct { DECL_BITFIELD(e7d); };
+            };
 
             /* Leaf 0x80000008 - Misc addr/feature info. */
-            uint32_t /* a */:32, e8b, /* c */:32, /* d */:32;
+            uint32_t /* a */:32;
+            union {
+                uint32_t e8b;
+                struct { DECL_BITFIELD(e8b); };
+            };
+            uint32_t /* c */:32, /* d */:32;
         };
     } extd;
 
+#undef __DECL_BITFIELD
+#undef _DECL_BITFIELD
+#undef DECL_BITFIELD
+
     /* Temporary featureset bitmap. */
     uint32_t fs[FSCAPINTS];
 };
diff --git a/xen/tools/gen-cpuid.py b/xen/tools/gen-cpuid.py
index 420a5cc..b9da06c 100755
--- a/xen/tools/gen-cpuid.py
+++ b/xen/tools/gen-cpuid.py
@@ -29,6 +29,7 @@ class State(object):
         self.pv = []
         self.hvm_shadow = []
         self.hvm_hap = []
+        self.bitfields = [] # Text to declare named bitfields in C
 
 def parse_definitions(state):
     """
@@ -291,6 +292,28 @@ def crunch_numbers(state):
     for k, v in state.deep_deps.iteritems():
         state.deep_deps[k] = featureset_to_uint32s(v, nr_entries)
 
+    # Calculate the bitfield name declarations
+    for word in xrange(nr_entries):
+
+        names = []
+        for bit in xrange(32):
+
+            name = state.names.get(word * 32 + bit, "")
+
+            # Prepend an underscore if the name starts with a digit.
+            if name and name[0] in "0123456789":
+                name = "_" + name
+
+            # Don't generate names for the duplicate features, or ones
+            # fast-forwarded from other state
+            if (name.startswith("E1D_") or
+                name in ("APIC", "OSXSAVE", "OSPKE")):
+                name = ""
+
+            names.append(name.lower())
+
+        state.bitfields.append("bool " + ":1, ".join(names) + ":1")
+
 
 def write_results(state):
     state.output.write(
@@ -344,6 +367,15 @@ def write_results(state):
     state.output.write(
 """}
 
+""")
+
+    for idx, text in enumerate(state.bitfields):
+        state.output.write(
+            "#define NAMED_BITFIELD_%d \\\n    %s\n\n"
+            % (idx, text))
+
+    state.output.write(
+"""
 #endif /* __XEN_X86__FEATURESET_DATA__ */
 """)
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 09/25] x86/hvm: Improve hvm_efer_valid() using named features
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (7 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 10/25] x86/hvm: Improve CR4 verification " Andrew Cooper
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Pick the appropriate cpuid_policy object rather than using hvm_cpuid() or
boot_cpu_data.  This breaks the dependency on current.

As data is read straight out of cpuid_policy, there is no need to work around
the fact that X86_FEATURE_SYSCALL might be clear because of the dynamic
adjustment in hvm_cpuid().  This simplifies the SCE handling, as EFER.SCE can
be set in isolation in 32bit mode on Intel hardware.

Alter nestedhvm_enabled() to be const-correct, allowing hvm_efer_valid() to be
properly const-correct.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
 * Retain explicit signed
---
 xen/arch/x86/hvm/hvm.c              | 40 ++++++++++---------------------------
 xen/arch/x86/hvm/nestedhvm.c        |  6 ++----
 xen/include/asm-x86/hvm/nestedhvm.h |  2 +-
 3 files changed, 13 insertions(+), 35 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ebddefc..a9daf40 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -917,53 +917,33 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
 const char *hvm_efer_valid(const struct vcpu *v, uint64_t value,
                            signed int cr0_pg)
 {
-    unsigned int ext1_ecx = 0, ext1_edx = 0;
+    const struct domain *d = v->domain;
+    const struct cpuid_policy *p;
 
-    if ( cr0_pg < 0 && !is_hardware_domain(v->domain) )
-    {
-        unsigned int level;
-
-        ASSERT(v->domain == current->domain);
-        hvm_cpuid(0x80000000, &level, NULL, NULL, NULL);
-        if ( (level >> 16) == 0x8000 && level > 0x80000000 )
-            hvm_cpuid(0x80000001, NULL, NULL, &ext1_ecx, &ext1_edx);
-    }
+    if ( cr0_pg < 0 && !is_hardware_domain(d) )
+        p = d->arch.cpuid;
     else
-    {
-        ext1_edx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_LM)];
-        ext1_ecx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_SVM)];
-    }
+        p = &host_policy;
 
-    /*
-     * Guests may want to set EFER.SCE and EFER.LME at the same time, so we
-     * can't make the check depend on only X86_FEATURE_SYSCALL (which on VMX
-     * will be clear without the guest having entered 64-bit mode).
-     */
-    if ( (value & EFER_SCE) &&
-         !(ext1_edx & cpufeat_mask(X86_FEATURE_SYSCALL)) &&
-         (cr0_pg >= 0 || !(value & EFER_LME)) )
+    if ( (value & EFER_SCE) && !p->extd.syscall )
         return "SCE without feature";
 
-    if ( (value & (EFER_LME | EFER_LMA)) &&
-         !(ext1_edx & cpufeat_mask(X86_FEATURE_LM)) )
+    if ( (value & (EFER_LME | EFER_LMA)) && !p->extd.lm )
         return "LME/LMA without feature";
 
     if ( (value & EFER_LMA) && (!(value & EFER_LME) || !cr0_pg) )
         return "LMA/LME/CR0.PG inconsistency";
 
-    if ( (value & EFER_NX) && !(ext1_edx & cpufeat_mask(X86_FEATURE_NX)) )
+    if ( (value & EFER_NX) && !p->extd.nx )
         return "NX without feature";
 
-    if ( (value & EFER_SVME) &&
-         (!(ext1_ecx & cpufeat_mask(X86_FEATURE_SVM)) ||
-          !nestedhvm_enabled(v->domain)) )
+    if ( (value & EFER_SVME) && (!p->extd.svm || !nestedhvm_enabled(d)) )
         return "SVME without nested virt";
 
     if ( (value & EFER_LMSLE) && !cpu_has_lmsl )
         return "LMSLE without support";
 
-    if ( (value & EFER_FFXSE) &&
-         !(ext1_edx & cpufeat_mask(X86_FEATURE_FFXSR)) )
+    if ( (value & EFER_FFXSE) && !p->extd.ffxsr )
         return "FFXSE without feature";
 
     return NULL;
diff --git a/xen/arch/x86/hvm/nestedhvm.c b/xen/arch/x86/hvm/nestedhvm.c
index c09c5b2..a400d55 100644
--- a/xen/arch/x86/hvm/nestedhvm.c
+++ b/xen/arch/x86/hvm/nestedhvm.c
@@ -27,11 +27,9 @@
 static unsigned long *shadow_io_bitmap[3];
 
 /* Nested HVM on/off per domain */
-bool_t
-nestedhvm_enabled(struct domain *d)
+bool nestedhvm_enabled(const struct domain *d)
 {
-    return is_hvm_domain(d) &&
-           d->arch.hvm_domain.params[HVM_PARAM_NESTEDHVM];
+    return is_hvm_domain(d) && d->arch.hvm_domain.params[HVM_PARAM_NESTEDHVM];
 }
 
 /* Nested VCPU */
diff --git a/xen/include/asm-x86/hvm/nestedhvm.h b/xen/include/asm-x86/hvm/nestedhvm.h
index bc82425..47165fc 100644
--- a/xen/include/asm-x86/hvm/nestedhvm.h
+++ b/xen/include/asm-x86/hvm/nestedhvm.h
@@ -33,7 +33,7 @@ enum nestedhvm_vmexits {
 };
 
 /* Nested HVM on/off per domain */
-bool_t nestedhvm_enabled(struct domain *d);
+bool nestedhvm_enabled(const struct domain *d);
 
 /* Nested VCPU */
 int nestedhvm_vcpu_initialise(struct vcpu *v);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 10/25] x86/hvm: Improve CR4 verification using named features
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (8 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 09/25] x86/hvm: Improve hvm_efer_valid() using named features Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 11/25] x86/vvmx: Use hvm_cr4_guest_valid_bits() to calculate MSR_IA32_VMX_CR4_FIXED1 Andrew Cooper
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Alter the function to return the valid CR4 bits, rather than the invalid CR4
bits.  This will allow reuse in other areas of code.

Pick the appropriate cpuid_policy object rather than using hvm_cpuid() or
boot_cpu_data.  This breaks the dependency on current.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/domain.c         |  2 +-
 xen/arch/x86/hvm/hvm.c        | 92 +++++++++++++++----------------------------
 xen/include/asm-x86/hvm/hvm.h |  2 +-
 3 files changed, 34 insertions(+), 62 deletions(-)

diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index b554a9c..319cc8a 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1512,7 +1512,7 @@ int arch_set_info_hvm_guest(struct vcpu *v, const vcpu_hvm_context_t *ctx)
     if ( v->arch.hvm_vcpu.guest_efer & EFER_LME )
         v->arch.hvm_vcpu.guest_efer |= EFER_LMA;
 
-    if ( v->arch.hvm_vcpu.guest_cr[4] & hvm_cr4_guest_reserved_bits(v, 0) )
+    if ( v->arch.hvm_vcpu.guest_cr[4] & ~hvm_cr4_guest_valid_bits(v, 0) )
     {
         gprintk(XENLOG_ERR, "Bad CR4 value: %#016lx\n",
                 v->arch.hvm_vcpu.guest_cr[4]);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index a9daf40..4ecdb35 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -957,67 +957,39 @@ const char *hvm_efer_valid(const struct vcpu *v, uint64_t value,
         X86_CR0_WP | X86_CR0_AM | X86_CR0_NW |  \
         X86_CR0_CD | X86_CR0_PG)))
 
-/* These bits in CR4 cannot be set by the guest. */
-unsigned long hvm_cr4_guest_reserved_bits(const struct vcpu *v,bool_t restore)
+/* These bits in CR4 can be set by the guest. */
+unsigned long hvm_cr4_guest_valid_bits(const struct vcpu *v, bool restore)
 {
-    unsigned int leaf1_ecx = 0, leaf1_edx = 0;
-    unsigned int leaf7_0_ebx = 0, leaf7_0_ecx = 0;
-
-    if ( !restore && !is_hardware_domain(v->domain) )
-    {
-        unsigned int level;
+    const struct domain *d = v->domain;
+    const struct cpuid_policy *p;
+    bool mce, vmxe;
 
-        ASSERT(v->domain == current->domain);
-        hvm_cpuid(0, &level, NULL, NULL, NULL);
-        if ( level >= 1 )
-            hvm_cpuid(1, NULL, NULL, &leaf1_ecx, &leaf1_edx);
-        if ( level >= 7 )
-            hvm_cpuid(7, NULL, &leaf7_0_ebx, &leaf7_0_ecx, NULL);
-    }
+    if ( !restore && !is_hardware_domain(d) )
+        p = d->arch.cpuid;
     else
-    {
-        leaf1_edx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_VME)];
-        leaf1_ecx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_PCID)];
-        leaf7_0_ebx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_FSGSBASE)];
-        leaf7_0_ecx = boot_cpu_data.x86_capability[cpufeat_word(X86_FEATURE_PKU)];
-    }
-
-    return ~(unsigned long)
-            ((leaf1_edx & cpufeat_mask(X86_FEATURE_VME) ?
-              X86_CR4_VME | X86_CR4_PVI : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_TSC) ?
-              X86_CR4_TSD : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_DE) ?
-              X86_CR4_DE : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_PSE) ?
-              X86_CR4_PSE : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_PAE) ?
-              X86_CR4_PAE : 0) |
-             (leaf1_edx & (cpufeat_mask(X86_FEATURE_MCE) |
-                           cpufeat_mask(X86_FEATURE_MCA)) ?
-              X86_CR4_MCE : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_PGE) ?
-              X86_CR4_PGE : 0) |
-             X86_CR4_PCE |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_FXSR) ?
-              X86_CR4_OSFXSR : 0) |
-             (leaf1_edx & cpufeat_mask(X86_FEATURE_SSE) ?
-              X86_CR4_OSXMMEXCPT : 0) |
-             ((restore || nestedhvm_enabled(v->domain)) &&
-              (leaf1_ecx & cpufeat_mask(X86_FEATURE_VMX)) ?
-              X86_CR4_VMXE : 0) |
-             (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_FSGSBASE) ?
-              X86_CR4_FSGSBASE : 0) |
-             (leaf1_ecx & cpufeat_mask(X86_FEATURE_PCID) ?
-              X86_CR4_PCIDE : 0) |
-             (leaf1_ecx & cpufeat_mask(X86_FEATURE_XSAVE) ?
-              X86_CR4_OSXSAVE : 0) |
-             (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_SMEP) ?
-              X86_CR4_SMEP : 0) |
-             (leaf7_0_ebx & cpufeat_mask(X86_FEATURE_SMAP) ?
-              X86_CR4_SMAP : 0) |
-              (leaf7_0_ecx & cpufeat_mask(X86_FEATURE_PKU) ?
-              X86_CR4_PKE : 0));
+        p = &host_policy;
+
+    /* Logic broken out simply to aid readability below. */
+    mce  = p->basic.mce || p->basic.mca;
+    vmxe = p->basic.vmx && (restore || nestedhvm_enabled(d));
+
+    return ((p->basic.vme     ? X86_CR4_VME | X86_CR4_PVI : 0) |
+            (p->basic.tsc     ? X86_CR4_TSD               : 0) |
+            (p->basic.de      ? X86_CR4_DE                : 0) |
+            (p->basic.pse     ? X86_CR4_PSE               : 0) |
+            (p->basic.pae     ? X86_CR4_PAE               : 0) |
+            (mce              ? X86_CR4_MCE               : 0) |
+            (p->basic.pge     ? X86_CR4_PGE               : 0) |
+                                X86_CR4_PCE                    |
+            (p->basic.fxsr    ? X86_CR4_OSFXSR            : 0) |
+            (p->basic.sse     ? X86_CR4_OSXMMEXCPT        : 0) |
+            (vmxe             ? X86_CR4_VMXE              : 0) |
+            (p->feat.fsgsbase ? X86_CR4_FSGSBASE          : 0) |
+            (p->basic.pcid    ? X86_CR4_PCIDE             : 0) |
+            (p->basic.xsave   ? X86_CR4_OSXSAVE           : 0) |
+            (p->feat.smep     ? X86_CR4_SMEP              : 0) |
+            (p->feat.smap     ? X86_CR4_SMAP              : 0) |
+            (p->feat.pku      ? X86_CR4_PKE               : 0));
 }
 
 static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
@@ -1054,7 +1026,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
         return -EINVAL;
     }
 
-    if ( ctxt.cr4 & hvm_cr4_guest_reserved_bits(v, 1) )
+    if ( ctxt.cr4 & ~hvm_cr4_guest_valid_bits(v, 1) )
     {
         printk(XENLOG_G_ERR "HVM%d restore: bad CR4 %#" PRIx64 "\n",
                d->domain_id, ctxt.cr4);
@@ -2390,7 +2362,7 @@ int hvm_set_cr4(unsigned long value, bool_t may_defer)
     struct vcpu *v = current;
     unsigned long old_cr;
 
-    if ( value & hvm_cr4_guest_reserved_bits(v, 0) )
+    if ( value & ~hvm_cr4_guest_valid_bits(v, 0) )
     {
         HVM_DBG_LOG(DBG_LEVEL_1,
                     "Guest attempts to set reserved bit in CR4: %lx",
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 8c95c08..14b765e 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -615,7 +615,7 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
 /* Check CR4/EFER values */
 const char *hvm_efer_valid(const struct vcpu *v, uint64_t value,
                            signed int cr0_pg);
-unsigned long hvm_cr4_guest_reserved_bits(const struct vcpu *v, bool_t restore);
+unsigned long hvm_cr4_guest_valid_bits(const struct vcpu *v, bool restore);
 
 /*
  * This must be defined as a macro instead of an inline function,
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 11/25] x86/vvmx: Use hvm_cr4_guest_valid_bits() to calculate MSR_IA32_VMX_CR4_FIXED1
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (9 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 10/25] x86/hvm: Improve CR4 verification " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 12/25] x86/pv: Improve pv_cpuid() using named features Andrew Cooper
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Reuse the logic in hvm_cr4_guest_valid_bits() instead of duplicating it.

This fixes a bug to do with the handling of X86_CR4_PCE.  The RDPMC
instruction predate the architectural performance feature, and has been around
since the P6.  X86_CR4_PCE is like X86_CR4_TSD and only controls whether RDPMC
is available at cpl!=0, not whether RDPMC is generally unavailable.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 58 +++------------------------------------------
 1 file changed, 3 insertions(+), 55 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index cfc9a88..9caebe5 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1840,16 +1840,12 @@ int nvmx_handle_invvpid(struct cpu_user_regs *regs)
 int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content)
 {
     struct vcpu *v = current;
-    unsigned int eax, ebx, ecx, edx;
+    struct domain *d = v->domain;
     u64 data = 0, host_data = 0;
     int r = 1;
 
-    if ( !nestedhvm_enabled(v->domain) )
-        return 0;
-
     /* VMX capablity MSRs are available only when guest supports VMX. */
-    hvm_cpuid(0x1, NULL, NULL, &ecx, &edx);
-    if ( !(ecx & cpufeat_mask(X86_FEATURE_VMX)) )
+    if ( !nestedhvm_enabled(d) || !d->arch.cpuid->basic.vmx )
         return 0;
 
     /*
@@ -1995,55 +1991,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content)
         data = X86_CR4_VMXE;
         break;
     case MSR_IA32_VMX_CR4_FIXED1:
-        if ( edx & cpufeat_mask(X86_FEATURE_VME) )
-            data |= X86_CR4_VME | X86_CR4_PVI;
-        if ( edx & cpufeat_mask(X86_FEATURE_TSC) )
-            data |= X86_CR4_TSD;
-        if ( edx & cpufeat_mask(X86_FEATURE_DE) )
-            data |= X86_CR4_DE;
-        if ( edx & cpufeat_mask(X86_FEATURE_PSE) )
-            data |= X86_CR4_PSE;
-        if ( edx & cpufeat_mask(X86_FEATURE_PAE) )
-            data |= X86_CR4_PAE;
-        if ( edx & cpufeat_mask(X86_FEATURE_MCE) )
-            data |= X86_CR4_MCE;
-        if ( edx & cpufeat_mask(X86_FEATURE_PGE) )
-            data |= X86_CR4_PGE;
-        if ( edx & cpufeat_mask(X86_FEATURE_FXSR) )
-            data |= X86_CR4_OSFXSR;
-        if ( edx & cpufeat_mask(X86_FEATURE_SSE) )
-            data |= X86_CR4_OSXMMEXCPT;
-        if ( ecx & cpufeat_mask(X86_FEATURE_VMX) )
-            data |= X86_CR4_VMXE;
-        if ( ecx & cpufeat_mask(X86_FEATURE_SMX) )
-            data |= X86_CR4_SMXE;
-        if ( ecx & cpufeat_mask(X86_FEATURE_PCID) )
-            data |= X86_CR4_PCIDE;
-        if ( ecx & cpufeat_mask(X86_FEATURE_XSAVE) )
-            data |= X86_CR4_OSXSAVE;
-
-        hvm_cpuid(0x0, &eax, NULL, NULL, NULL);
-        switch ( eax )
-        {
-        default:
-            hvm_cpuid(0xa, &eax, NULL, NULL, NULL);
-            /* Check whether guest has the perf monitor feature. */
-            if ( (eax & 0xff) && (eax & 0xff00) )
-                data |= X86_CR4_PCE;
-            /* fall through */
-        case 0x7 ... 0x9:
-            ecx = 0;
-            hvm_cpuid(0x7, NULL, &ebx, &ecx, NULL);
-            if ( ebx & cpufeat_mask(X86_FEATURE_FSGSBASE) )
-                data |= X86_CR4_FSGSBASE;
-            if ( ebx & cpufeat_mask(X86_FEATURE_SMEP) )
-                data |= X86_CR4_SMEP;
-            if ( ebx & cpufeat_mask(X86_FEATURE_SMAP) )
-                data |= X86_CR4_SMAP;
-            /* fall through */
-        case 0x0 ... 0x6:
-            break;
-        }
+        data = hvm_cr4_guest_valid_bits(v, 0);
         break;
     case MSR_IA32_VMX_MISC:
         /* Do not support CR3-target feature now */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 12/25] x86/pv: Improve pv_cpuid() using named features
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (10 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 11/25] x86/vvmx: Use hvm_cr4_guest_valid_bits() to calculate MSR_IA32_VMX_CR4_FIXED1 Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 13/25] x86/hvm: Improve CPUID and MSR handling " Andrew Cooper
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

This avoids refering back to domain_cpuid() or native CPUID to obtain
information which is directly available.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/traps.c | 22 +++++-----------------
 1 file changed, 5 insertions(+), 17 deletions(-)

diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 5ce8936..47c7ce7 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1024,6 +1024,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
     uint32_t leaf, subleaf, a, b, c, d;
     struct vcpu *curr = current;
     struct domain *currd = curr->domain;
+    const struct cpuid_policy *p = currd->arch.cpuid;
 
     leaf = a = regs->_eax;
     b = regs->_ebx;
@@ -1060,7 +1061,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
 
     switch ( leaf )
     {
-        uint32_t tmp, _ecx, _ebx;
+        uint32_t tmp;
 
     case 0x00000001:
         c &= pv_featureset[FEATURESET_1c];
@@ -1246,14 +1247,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
         break;
 
     case XSTATE_CPUID:
-
-        if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
-            domain_cpuid(currd, 1, 0, &tmp, &tmp, &_ecx, &tmp);
-        else
-            _ecx = cpuid_ecx(1);
-        _ecx &= pv_featureset[FEATURESET_1c];
-
-        if ( !(_ecx & cpufeat_mask(X86_FEATURE_XSAVE)) || subleaf >= 63 )
+        if ( !p->basic.xsave || subleaf >= 63 )
             goto unsupported;
         switch ( subleaf )
         {
@@ -1262,20 +1256,14 @@ void pv_cpuid(struct cpu_user_regs *regs)
             uint64_t xfeature_mask = XSTATE_FP_SSE;
             uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
 
-            if ( _ecx & cpufeat_mask(X86_FEATURE_AVX) )
+            if ( p->basic.avx )
             {
                 xfeature_mask |= XSTATE_YMM;
                 xstate_size = (xstate_offsets[_XSTATE_YMM] +
                                xstate_sizes[_XSTATE_YMM]);
             }
 
-            if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
-                domain_cpuid(currd, 7, 0, &tmp, &_ebx, &tmp, &tmp);
-            else
-                cpuid_count(7, 0, &tmp, &_ebx, &tmp, &tmp);
-            _ebx &= pv_featureset[FEATURESET_7b0];
-
-            if ( _ebx & cpufeat_mask(X86_FEATURE_AVX512F) )
+            if ( p->feat.avx512f )
             {
                 xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
                 xstate_size = max(xstate_size,
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 13/25] x86/hvm: Improve CPUID and MSR handling using named features
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (11 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 12/25] x86/pv: Improve pv_cpuid() using named features Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 14/25] x86/svm: Improvements " Andrew Cooper
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

This avoids hvm_cpuid() recursing into itself, and the MSR paths using
hvm_cpuid() to obtain information which is directly available.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/hvm.c | 95 +++++++++++++++-----------------------------------
 1 file changed, 29 insertions(+), 66 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 4ecdb35..a7fcb84 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3293,6 +3293,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
+    const struct cpuid_policy *p = d->arch.cpuid;
     unsigned int count, dummy = 0;
 
     if ( !eax )
@@ -3330,8 +3331,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
 
     switch ( input )
     {
-        unsigned int _ebx, _ecx, _edx;
-
     case 0x1:
         /* Fix up VLAPIC details. */
         *ebx &= 0x00FFFFFFu;
@@ -3414,8 +3413,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         break;
 
     case XSTATE_CPUID:
-        hvm_cpuid(1, NULL, NULL, &_ecx, NULL);
-        if ( !(_ecx & cpufeat_mask(X86_FEATURE_XSAVE)) || count >= 63 )
+        if ( !p->basic.xsave || count >= 63 )
         {
             *eax = *ebx = *ecx = *edx = 0;
             break;
@@ -3427,7 +3425,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
             uint64_t xfeature_mask = XSTATE_FP_SSE;
             uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
 
-            if ( _ecx & cpufeat_mask(X86_FEATURE_AVX) )
+            if ( p->basic.avx )
             {
                 xfeature_mask |= XSTATE_YMM;
                 xstate_size = max(xstate_size,
@@ -3435,10 +3433,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                   xstate_sizes[_XSTATE_YMM]);
             }
 
-            _ecx = 0;
-            hvm_cpuid(7, NULL, &_ebx, &_ecx, NULL);
-
-            if ( _ebx & cpufeat_mask(X86_FEATURE_MPX) )
+            if ( p->feat.mpx )
             {
                 xfeature_mask |= XSTATE_BNDREGS | XSTATE_BNDCSR;
                 xstate_size = max(xstate_size,
@@ -3446,7 +3441,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                   xstate_sizes[_XSTATE_BNDCSR]);
             }
 
-            if ( _ebx & cpufeat_mask(X86_FEATURE_AVX512F) )
+            if ( p->feat.avx512f )
             {
                 xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
                 xstate_size = max(xstate_size,
@@ -3460,7 +3455,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                   xstate_sizes[_XSTATE_HI_ZMM]);
             }
 
-            if ( _ecx & cpufeat_mask(X86_FEATURE_PKU) )
+            if ( p->feat.pku )
             {
                 xfeature_mask |= XSTATE_PKRU;
                 xstate_size = max(xstate_size,
@@ -3468,9 +3463,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                   xstate_sizes[_XSTATE_PKRU]);
             }
 
-            hvm_cpuid(0x80000001, NULL, NULL, &_ecx, NULL);
-
-            if ( _ecx & cpufeat_mask(X86_FEATURE_LWP) )
+            if ( p->extd.lwp )
             {
                 xfeature_mask |= XSTATE_LWP;
                 xstate_size = max(xstate_size,
@@ -3494,7 +3487,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         case 1:
             *eax &= hvm_featureset[FEATURESET_Da1];
 
-            if ( *eax & cpufeat_mask(X86_FEATURE_XSAVES) )
+            if ( p->xstate.xsaves )
             {
                 /*
                  * Always read CPUID[0xD,1].EBX from hardware, rather than
@@ -3575,14 +3568,11 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         if ( *eax > count )
             *eax = count;
 
-        hvm_cpuid(1, NULL, NULL, NULL, &_edx);
-        count = _edx & (cpufeat_mask(X86_FEATURE_PAE) |
-                        cpufeat_mask(X86_FEATURE_PSE36)) ? 36 : 32;
+        count = (p->basic.pae || p->basic.pse36) ? 36 : 32;
         if ( *eax < count )
             *eax = count;
 
-        hvm_cpuid(0x80000001, NULL, NULL, NULL, &_edx);
-        *eax |= (_edx & cpufeat_mask(X86_FEATURE_LM) ? vaddr_bits : 32) << 8;
+        *eax |= (p->extd.lm ? vaddr_bits : 32) << 8;
 
         *ebx &= hvm_featureset[FEATURESET_e8b];
         break;
@@ -3649,26 +3639,16 @@ void hvm_rdtsc_intercept(struct cpu_user_regs *regs)
 int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
 {
     struct vcpu *v = current;
+    struct domain *d = v->domain;
     uint64_t *var_range_base, *fixed_range_base;
-    bool mtrr = false;
     int ret = X86EMUL_OKAY;
 
     var_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.var_ranges;
     fixed_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.fixed_ranges;
 
-    if ( msr == MSR_MTRRcap ||
-         (msr >= MSR_IA32_MTRR_PHYSBASE(0) && msr <= MSR_MTRRdefType) )
-    {
-        unsigned int edx;
-
-        hvm_cpuid(1, NULL, NULL, NULL, &edx);
-        if ( edx & cpufeat_mask(X86_FEATURE_MTRR) )
-            mtrr = true;
-    }
-
     switch ( msr )
     {
-        unsigned int eax, ebx, ecx, index;
+        unsigned int index;
 
     case MSR_EFER:
         *msr_content = v->arch.hvm_vcpu.guest_efer;
@@ -3704,53 +3684,49 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
         break;
 
     case MSR_MTRRcap:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         *msr_content = v->arch.hvm_vcpu.mtrr.mtrr_cap;
         break;
     case MSR_MTRRdefType:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         *msr_content = v->arch.hvm_vcpu.mtrr.def_type
                         | (v->arch.hvm_vcpu.mtrr.enabled << 10);
         break;
     case MSR_MTRRfix64K_00000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         *msr_content = fixed_range_base[0];
         break;
     case MSR_MTRRfix16K_80000:
     case MSR_MTRRfix16K_A0000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         index = msr - MSR_MTRRfix16K_80000;
         *msr_content = fixed_range_base[index + 1];
         break;
     case MSR_MTRRfix4K_C0000...MSR_MTRRfix4K_F8000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         index = msr - MSR_MTRRfix4K_C0000;
         *msr_content = fixed_range_base[index + 3];
         break;
     case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1):
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         index = msr - MSR_IA32_MTRR_PHYSBASE(0);
         *msr_content = var_range_base[index];
         break;
 
     case MSR_IA32_XSS:
-        ecx = 1;
-        hvm_cpuid(XSTATE_CPUID, &eax, NULL, &ecx, NULL);
-        if ( !(eax & cpufeat_mask(X86_FEATURE_XSAVES)) )
+        if ( !d->arch.cpuid->xstate.xsaves )
             goto gp_fault;
         *msr_content = v->arch.hvm_vcpu.msr_xss;
         break;
 
     case MSR_IA32_BNDCFGS:
-        ecx = 0;
-        hvm_cpuid(7, NULL, &ebx, &ecx, NULL);
-        if ( !(ebx & cpufeat_mask(X86_FEATURE_MPX)) ||
+        if ( !d->arch.cpuid->feat.mpx ||
              !hvm_get_guest_bndcfgs(v, msr_content) )
             goto gp_fault;
         break;
@@ -3791,21 +3767,12 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
                             bool_t may_defer)
 {
     struct vcpu *v = current;
-    bool mtrr = false;
+    struct domain *d = v->domain;
     int ret = X86EMUL_OKAY;
 
     HVMTRACE_3D(MSR_WRITE, msr,
                (uint32_t)msr_content, (uint32_t)(msr_content >> 32));
 
-    if ( msr >= MSR_IA32_MTRR_PHYSBASE(0) && msr <= MSR_MTRRdefType )
-    {
-        unsigned int edx;
-
-        hvm_cpuid(1, NULL, NULL, NULL, &edx);
-        if ( edx & cpufeat_mask(X86_FEATURE_MTRR) )
-            mtrr = true;
-    }
-
     if ( may_defer && unlikely(monitored_msr(v->domain, msr)) )
     {
         ASSERT(v->arch.vm_event);
@@ -3821,7 +3788,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
 
     switch ( msr )
     {
-        unsigned int eax, ebx, ecx, index;
+        unsigned int index;
 
     case MSR_EFER:
         if ( hvm_set_efer(msr_content) )
@@ -3867,14 +3834,14 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
         goto gp_fault;
 
     case MSR_MTRRdefType:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         if ( !mtrr_def_type_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
                                     msr_content) )
            goto gp_fault;
         break;
     case MSR_MTRRfix64K_00000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr, 0,
                                      msr_content) )
@@ -3882,7 +3849,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
         break;
     case MSR_MTRRfix16K_80000:
     case MSR_MTRRfix16K_A0000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         index = msr - MSR_MTRRfix16K_80000 + 1;
         if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
@@ -3890,7 +3857,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
             goto gp_fault;
         break;
     case MSR_MTRRfix4K_C0000...MSR_MTRRfix4K_F8000:
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         index = msr - MSR_MTRRfix4K_C0000 + 3;
         if ( !mtrr_fix_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
@@ -3898,7 +3865,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
             goto gp_fault;
         break;
     case MSR_IA32_MTRR_PHYSBASE(0)...MSR_IA32_MTRR_PHYSMASK(MTRR_VCNT-1):
-        if ( !mtrr )
+        if ( !d->arch.cpuid->basic.mtrr )
             goto gp_fault;
         if ( !mtrr_var_range_msr_set(v->domain, &v->arch.hvm_vcpu.mtrr,
                                      msr, msr_content) )
@@ -3906,18 +3873,14 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
         break;
 
     case MSR_IA32_XSS:
-        ecx = 1;
-        hvm_cpuid(XSTATE_CPUID, &eax, NULL, &ecx, NULL);
         /* No XSS features currently supported for guests. */
-        if ( !(eax & cpufeat_mask(X86_FEATURE_XSAVES)) || msr_content != 0 )
+        if ( !d->arch.cpuid->xstate.xsaves || msr_content != 0 )
             goto gp_fault;
         v->arch.hvm_vcpu.msr_xss = msr_content;
         break;
 
     case MSR_IA32_BNDCFGS:
-        ecx = 0;
-        hvm_cpuid(7, NULL, &ebx, &ecx, NULL);
-        if ( !(ebx & cpufeat_mask(X86_FEATURE_MPX)) ||
+        if ( !d->arch.cpuid->feat.mpx ||
              !hvm_set_guest_bndcfgs(v, msr_content) )
             goto gp_fault;
         break;
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 14/25] x86/svm: Improvements using named features
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (12 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 13/25] x86/hvm: Improve CPUID and MSR handling " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 16:38   ` Jan Beulich
  2017-01-09 23:34   ` Boris Ostrovsky
  2017-01-09 11:03 ` [PATCH v2 15/25] x86/pv: Use per-domain policy information when calculating the cpumasks Andrew Cooper
                   ` (10 subsequent siblings)
  24 siblings, 2 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel
  Cc: Andrew Cooper, Boris Ostrovsky, Suravee Suthikulpanit, Jan Beulich

This avoids calling into hvm_cpuid() to obtain information which is directly
available.  In particular, this avoids the need to overload flag_dr_dirty
because of hvm_cpuid() being unavailable in svm_save_dr().

flag_dr_dirty is returned to a boolean (as it was before c/s c097f549 which
introduced the need to overload it).  While returning it to type bool, remove
the use of bool_t for the adjacent fields.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>

v2:
 * Fix commit message.
 * Return flag_dr_dirty to being a boolean.
---
 xen/arch/x86/hvm/svm/svm.c     | 33 ++++++++-------------------------
 xen/include/asm-x86/hvm/vcpu.h | 10 +++++-----
 2 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 6fb1cbc..e9c6d69 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -173,7 +173,7 @@ static void svm_save_dr(struct vcpu *v)
     v->arch.hvm_vcpu.flag_dr_dirty = 0;
     vmcb_set_dr_intercepts(vmcb, ~0u);
 
-    if ( flag_dr_dirty & 2 )
+    if ( v->domain->arch.cpuid->extd.dbext )
     {
         svm_intercept_msr(v, MSR_AMD64_DR0_ADDRESS_MASK, MSR_INTERCEPT_RW);
         svm_intercept_msr(v, MSR_AMD64_DR1_ADDRESS_MASK, MSR_INTERCEPT_RW);
@@ -196,8 +196,6 @@ static void svm_save_dr(struct vcpu *v)
 
 static void __restore_debug_registers(struct vmcb_struct *vmcb, struct vcpu *v)
 {
-    unsigned int ecx;
-
     if ( v->arch.hvm_vcpu.flag_dr_dirty )
         return;
 
@@ -205,8 +203,8 @@ static void __restore_debug_registers(struct vmcb_struct *vmcb, struct vcpu *v)
     vmcb_set_dr_intercepts(vmcb, 0);
 
     ASSERT(v == current);
-    hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-    if ( test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+
+    if ( v->domain->arch.cpuid->extd.dbext )
     {
         svm_intercept_msr(v, MSR_AMD64_DR0_ADDRESS_MASK, MSR_INTERCEPT_NONE);
         svm_intercept_msr(v, MSR_AMD64_DR1_ADDRESS_MASK, MSR_INTERCEPT_NONE);
@@ -217,9 +215,6 @@ static void __restore_debug_registers(struct vmcb_struct *vmcb, struct vcpu *v)
         wrmsrl(MSR_AMD64_DR1_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[1]);
         wrmsrl(MSR_AMD64_DR2_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[2]);
         wrmsrl(MSR_AMD64_DR3_ADDRESS_MASK, v->arch.hvm_svm.dr_mask[3]);
-
-        /* Can't use hvm_cpuid() in svm_save_dr(): v != current. */
-        v->arch.hvm_vcpu.flag_dr_dirty |= 2;
     }
 
     write_debugreg(0, v->arch.debugreg[0]);
@@ -1359,11 +1354,7 @@ static void svm_init_erratum_383(struct cpuinfo_x86 *c)
 
 static int svm_handle_osvw(struct vcpu *v, uint32_t msr, uint64_t *val, bool_t read)
 {
-    unsigned int ecx;
-
-    /* Guest OSVW support */
-    hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-    if ( !test_bit((X86_FEATURE_OSVW & 31), &ecx) )
+    if ( !v->domain->arch.cpuid->extd.osvw )
         return -1;
 
     if ( read )
@@ -1622,8 +1613,6 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
 
     switch ( msr )
     {
-        unsigned int ecx;
-
     case MSR_IA32_SYSENTER_CS:
         *msr_content = v->arch.hvm_svm.guest_sysenter_cs;
         break;
@@ -1701,15 +1690,13 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
         break;
 
     case MSR_AMD64_DR0_ADDRESS_MASK:
-        hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-        if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+        if ( !v->domain->arch.cpuid->extd.dbext )
             goto gpf;
         *msr_content = v->arch.hvm_svm.dr_mask[0];
         break;
 
     case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
-        hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-        if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) )
+        if ( !v->domain->arch.cpuid->extd.dbext )
             goto gpf;
         *msr_content =
             v->arch.hvm_svm.dr_mask[msr - MSR_AMD64_DR1_ADDRESS_MASK + 1];
@@ -1783,8 +1770,6 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
 
     switch ( msr )
     {
-        unsigned int ecx;
-
     case MSR_IA32_SYSENTER_CS:
         vmcb->sysenter_cs = v->arch.hvm_svm.guest_sysenter_cs = msr_content;
         break;
@@ -1862,15 +1847,13 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
         break;
 
     case MSR_AMD64_DR0_ADDRESS_MASK:
-        hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-        if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) || (msr_content >> 32) )
+        if ( !v->domain->arch.cpuid->extd.dbext || (msr_content >> 32) )
             goto gpf;
         v->arch.hvm_svm.dr_mask[0] = msr_content;
         break;
 
     case MSR_AMD64_DR1_ADDRESS_MASK ... MSR_AMD64_DR3_ADDRESS_MASK:
-        hvm_cpuid(0x80000001, NULL, NULL, &ecx, NULL);
-        if ( !test_bit(X86_FEATURE_DBEXT & 31, &ecx) || (msr_content >> 32) )
+        if ( !v->domain->arch.cpuid->extd.dbext || (msr_content >> 32) )
             goto gpf;
         v->arch.hvm_svm.dr_mask[msr - MSR_AMD64_DR1_ADDRESS_MASK + 1] =
             msr_content;
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 7b411a8..17ab9c0 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -162,12 +162,12 @@ struct hvm_vcpu {
     spinlock_t          tm_lock;
     struct list_head    tm_list;
 
-    u8                  flag_dr_dirty;
-    bool_t              debug_state_latch;
-    bool_t              single_step;
+    bool                flag_dr_dirty;
+    bool                debug_state_latch;
+    bool                single_step;
 
-    bool_t              hcall_preempted;
-    bool_t              hcall_64bit;
+    bool                hcall_preempted;
+    bool                hcall_64bit;
 
     struct hvm_vcpu_asid n1asid;
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 15/25] x86/pv: Use per-domain policy information when calculating the cpumasks
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (13 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 14/25] x86/svm: Improvements " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid() Andrew Cooper
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

... rather than dynamically clamping against the PV maximum policy.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
 * Spelling fix in the commit message
---
 xen/arch/x86/domctl.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index a3b2b72..c538781 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -100,8 +100,8 @@ static void update_domain_cpuid_info(struct domain *d,
         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];
+            uint32_t ecx = p->basic._1c;
+            uint32_t edx = p->basic._1d;
 
             /*
              * Must expose hosts HTT and X2APIC value so a guest using native
@@ -175,7 +175,7 @@ static void update_domain_cpuid_info(struct domain *d,
         {
             uint64_t mask = cpuidmask_defaults._7ab0;
             uint32_t eax = ctl->eax;
-            uint32_t ebx = ctl->ebx & pv_featureset[FEATURESET_7b0];
+            uint32_t ebx = p->feat._7b0;
 
             if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
                 mask &= ((uint64_t)eax << 32) | ebx;
@@ -191,7 +191,7 @@ static void update_domain_cpuid_info(struct domain *d,
         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];
+            uint32_t eax = p->xstate.Da1;
 
             if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
                 mask &= (~0ULL << 32) | eax;
@@ -204,8 +204,8 @@ static void update_domain_cpuid_info(struct domain *d,
         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];
+            uint32_t ecx = p->extd.e1c;
+            uint32_t edx = p->extd.e1d;
 
             /*
              * Must expose hosts CMP_LEGACY value so a guest using native
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (14 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 15/25] x86/pv: Use per-domain policy information when calculating the cpumasks Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-12 15:22   ` Boris Ostrovsky
  2017-01-09 11:03 ` [PATCH v2 17/25] x86/hvm: Use per-domain policy information in hvm_cpuid() Andrew Cooper
                   ` (8 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

... rather than performing runtime adjustments.  This is safe now that
recalculate_cpuid_policy() perfoms suitable sanitisation when the policy data
is loaded.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/traps.c | 44 ++++++++++++--------------------------------
 1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 47c7ce7..360b10d 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1064,11 +1064,8 @@ void pv_cpuid(struct cpu_user_regs *regs)
         uint32_t tmp;
 
     case 0x00000001:
-        c &= pv_featureset[FEATURESET_1c];
-        d &= pv_featureset[FEATURESET_1d];
-
-        if ( is_pv_32bit_domain(currd) )
-            c &= ~cpufeat_mask(X86_FEATURE_CX16);
+        c = p->basic._1c;
+        d = p->basic._1d;
 
         if ( !is_pvh_domain(currd) )
         {
@@ -1127,7 +1124,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
              *    Emulated vs Faulted CPUID is distinguised based on whether a
              *    #UD or #GP is currently being serviced.
              */
-            /* OSXSAVE cleared by pv_featureset.  Fast-forward CR4 back in. */
+            /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
             if ( (curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE) ||
                  (regs->entry_vector == TRAP_invalid_op &&
                   guest_kernel_mode(curr, regs) &&
@@ -1203,21 +1200,14 @@ void pv_cpuid(struct cpu_user_regs *regs)
             if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
                 c |= cpufeat_mask(X86_FEATURE_DSCPL);
         }
-
-        c |= cpufeat_mask(X86_FEATURE_HYPERVISOR);
         break;
 
     case 0x00000007:
         if ( subleaf == 0 )
         {
-            /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
-            b &= (pv_featureset[FEATURESET_7b0] &
-                  ~special_features[FEATURESET_7b0]);
-            b |= (host_featureset[FEATURESET_7b0] &
-                  special_features[FEATURESET_7b0]);
-
-            c &= pv_featureset[FEATURESET_7c0];
-            d &= pv_featureset[FEATURESET_7d0];
+            b = currd->arch.cpuid->feat._7b0;
+            c = currd->arch.cpuid->feat._7c0;
+            d = currd->arch.cpuid->feat._7d0;
 
             if ( !is_pvh_domain(currd) )
             {
@@ -1226,7 +1216,7 @@ void pv_cpuid(struct cpu_user_regs *regs)
                  * and HVM guests no longer enter a PV codepath.
                  */
 
-                /* OSPKE cleared by pv_featureset.  Fast-forward CR4 back in. */
+                /* OSPKE clear in policy.  Fast-forward CR4 back in. */
                 if ( curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_PKE )
                     c |= cpufeat_mask(X86_FEATURE_OSPKE);
             }
@@ -1291,15 +1281,15 @@ void pv_cpuid(struct cpu_user_regs *regs)
         }
 
         case 1:
-            a &= pv_featureset[FEATURESET_Da1];
+            a = p->xstate.Da1;
             b = c = d = 0;
             break;
         }
         break;
 
     case 0x80000001:
-        c &= pv_featureset[FEATURESET_e1c];
-        d &= pv_featureset[FEATURESET_e1d];
+        c = p->extd.e1c;
+        d = p->extd.e1d;
 
         /* If not emulating AMD, clear the duplicated features in e1d. */
         if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
@@ -1317,25 +1307,15 @@ void pv_cpuid(struct cpu_user_regs *regs)
         if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) &&
              cpu_has_mtrr )
             d |= cpufeat_mask(X86_FEATURE_MTRR);
-
-        if ( is_pv_32bit_domain(currd) )
-        {
-            d &= ~cpufeat_mask(X86_FEATURE_LM);
-            c &= ~cpufeat_mask(X86_FEATURE_LAHF_LM);
-
-            if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
-                d &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
-        }
         break;
 
     case 0x80000007:
-        d &= (pv_featureset[FEATURESET_e7d] |
-              (host_featureset[FEATURESET_e7d] & cpufeat_mask(X86_FEATURE_ITSC)));
+        d = p->extd.e7d;
         break;
 
     case 0x80000008:
         a = paddr_bits | (vaddr_bits << 8);
-        b &= pv_featureset[FEATURESET_e8b];
+        b = p->extd.e8b;
         break;
 
     case 0x00000005: /* MONITOR/MWAIT */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 17/25] x86/hvm: Use per-domain policy information in hvm_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (15 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 18/25] x86/cpuid: Drop the temporary linear feature bitmap from struct cpuid_policy Andrew Cooper
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

... rather than performing runtime adjustments.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/hvm.c | 113 +++++++++++++++++++------------------------------
 1 file changed, 44 insertions(+), 69 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index a7fcb84..103f848 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3336,39 +3336,33 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         *ebx &= 0x00FFFFFFu;
         *ebx |= (v->vcpu_id * 2) << 24;
 
-        *ecx &= hvm_featureset[FEATURESET_1c];
-        *edx &= hvm_featureset[FEATURESET_1d];
+        *ecx = p->basic._1c;
+        *edx = p->basic._1d;
 
         /* APIC exposed to guests, but Fast-forward MSR_APIC_BASE.EN back in. */
         if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
             *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
 
-        /* OSXSAVE cleared by hvm_featureset.  Fast-forward CR4 back in. */
+        /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
         if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE )
             *ecx |= cpufeat_mask(X86_FEATURE_OSXSAVE);
 
-        /* Don't expose HAP-only features to non-hap guests. */
-        if ( !hap_enabled(d) )
-        {
-            *ecx &= ~cpufeat_mask(X86_FEATURE_PCID);
-
-            /*
-             * PSE36 is not supported in shadow mode.  This bit should be
-             * unilaterally cleared.
-             *
-             * However, an unspecified version of Hyper-V from 2011 refuses
-             * to start as the "cpu does not provide required hw features" if
-             * it can't see PSE36.
-             *
-             * As a workaround, leak the toolstack-provided PSE36 value into a
-             * shadow guest if the guest is already using PAE paging (and
-             * won't care about reverting back to PSE paging).  Otherwise,
-             * knoble it, so a 32bit guest doesn't get the impression that it
-             * could try to use PSE36 paging.
-             */
-            if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-                *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
-        }
+        /*
+         * PSE36 is not supported in shadow mode.  This bit should be
+         * unilaterally cleared.
+         *
+         * However, an unspecified version of Hyper-V from 2011 refuses
+         * to start as the "cpu does not provide required hw features" if
+         * it can't see PSE36.
+         *
+         * As a workaround, leak the toolstack-provided PSE36 value into a
+         * shadow guest if the guest is already using PAE paging (and won't
+         * care about reverting back to PSE paging).  Otherwise, knoble it, so
+         * a 32bit guest doesn't get the impression that it could try to use
+         * PSE36 paging.
+         */
+        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
+            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
 
         if ( vpmu_enabled(v) &&
              vpmu_is_set(vcpu_vpmu(v), VPMU_CPU_HAS_DS) )
@@ -3385,23 +3379,11 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     case 0x7:
         if ( count == 0 )
         {
-            /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
-            *ebx &= (hvm_featureset[FEATURESET_7b0] &
-                     ~special_features[FEATURESET_7b0]);
-            *ebx |= (host_featureset[FEATURESET_7b0] &
-                     special_features[FEATURESET_7b0]);
-
-            *ecx &= hvm_featureset[FEATURESET_7c0];
-            *edx &= hvm_featureset[FEATURESET_7d0];
-
-            /* Don't expose HAP-only features to non-hap guests. */
-            if ( !hap_enabled(d) )
-            {
-                 *ebx &= ~cpufeat_mask(X86_FEATURE_INVPCID);
-                 *ecx &= ~cpufeat_mask(X86_FEATURE_PKU);
-            }
+            *ebx = d->arch.cpuid->feat._7b0;
+            *ecx = d->arch.cpuid->feat._7c0;
+            *edx = d->arch.cpuid->feat._7d0;
 
-            /* OSPKE cleared by hvm_featureset.  Fast-forward CR4 back in. */
+            /* OSPKE clear in policy.  Fast-forward CR4 back in. */
             if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PKE )
                 *ecx |= cpufeat_mask(X86_FEATURE_OSPKE);
         }
@@ -3485,7 +3467,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         }
 
         case 1:
-            *eax &= hvm_featureset[FEATURESET_Da1];
+            *eax = p->xstate.Da1;
 
             if ( p->xstate.xsaves )
             {
@@ -3517,8 +3499,8 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         break;
 
     case 0x80000001:
-        *ecx &= hvm_featureset[FEATURESET_e1c];
-        *edx &= hvm_featureset[FEATURESET_e1d];
+        *ecx = p->extd.e1c;
+        *edx = p->extd.e1d;
 
         /* If not emulating AMD, clear the duplicated features in e1d. */
         if ( d->arch.x86_vendor != X86_VENDOR_AMD )
@@ -3527,28 +3509,22 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         else if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
             *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
 
-        /* Don't expose HAP-only features to non-hap guests. */
-        if ( !hap_enabled(d) )
-        {
-            *edx &= ~cpufeat_mask(X86_FEATURE_PAGE1GB);
-
-            /*
-             * PSE36 is not supported in shadow mode.  This bit should be
-             * unilaterally cleared.
-             *
-             * However, an unspecified version of Hyper-V from 2011 refuses
-             * to start as the "cpu does not provide required hw features" if
-             * it can't see PSE36.
-             *
-             * As a workaround, leak the toolstack-provided PSE36 value into a
-             * shadow guest if the guest is already using PAE paging (and
-             * won't care about reverting back to PSE paging).  Otherwise,
-             * knoble it, so a 32bit guest doesn't get the impression that it
-             * could try to use PSE36 paging.
-             */
-            if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-                *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
-        }
+        /*
+         * PSE36 is not supported in shadow mode.  This bit should be
+         * unilaterally cleared.
+         *
+         * However, an unspecified version of Hyper-V from 2011 refuses
+         * to start as the "cpu does not provide required hw features" if
+         * it can't see PSE36.
+         *
+         * As a workaround, leak the toolstack-provided PSE36 value into a
+         * shadow guest if the guest is already using PAE paging (and won't
+         * care about reverting back to PSE paging).  Otherwise, knoble it, so
+         * a 32bit guest doesn't get the impression that it could try to use
+         * PSE36 paging.
+         */
+        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
+            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
 
         /* SYSCALL is hidden outside of long mode on Intel. */
         if ( d->arch.x86_vendor == X86_VENDOR_INTEL &&
@@ -3558,8 +3534,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         break;
 
     case 0x80000007:
-        *edx &= (hvm_featureset[FEATURESET_e7d] |
-                 (host_featureset[FEATURESET_e7d] & cpufeat_mask(X86_FEATURE_ITSC)));
+        *edx = p->extd.e7d;
         break;
 
     case 0x80000008:
@@ -3574,7 +3549,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
 
         *eax |= (p->extd.lm ? vaddr_bits : 32) << 8;
 
-        *ebx &= hvm_featureset[FEATURESET_e8b];
+        *ebx = p->extd.e8b;
         break;
 
     case 0x8000001c:
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 18/25] x86/cpuid: Drop the temporary linear feature bitmap from struct cpuid_policy
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (16 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 17/25] x86/hvm: Use per-domain policy information in hvm_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 19/25] x86/cpuid: Calculate appropriate max_leaf values for the global policies Andrew Cooper
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

With most uses of the *_featureset API removed, the remaining uses are only
during XEN_SYSCTL_get_cpu_featureset, init_guest_cpuid(), and
recalculate_cpuid_policy(), none of which are hot paths.

Drop the temporary infrastructure, and have the current users recreate the
linear bitmap using cpuid_policy_to_featureset().  This avoids storing
duplicated information in struct cpuid_policy.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/cpuid.c        | 19 ++++++++++---------
 xen/arch/x86/sysctl.c       | 21 ++++++++++++---------
 xen/include/asm-x86/cpuid.h |  9 ---------
 3 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 37203eb..677688d 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -129,24 +129,23 @@ static void __init calculate_raw_policy(void)
     for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
                          p->extd.max_leaf + 1 - 0x80000000ul); ++i )
         cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
-
-    cpuid_policy_to_featureset(p, p->fs);
 }
 
 static void __init calculate_host_policy(void)
 {
     struct cpuid_policy *p = &host_policy;
 
-    memcpy(p->fs, boot_cpu_data.x86_capability, sizeof(p->fs));
-
-    cpuid_featureset_to_policy(host_featureset, p);
+    cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
 }
 
 static void __init calculate_pv_max_policy(void)
 {
     struct cpuid_policy *p = &pv_max_policy;
+    uint32_t pv_featureset[FSCAPINTS], host_featureset[FSCAPINTS];
     unsigned int i;
 
+    cpuid_policy_to_featureset(&host_policy, host_featureset);
+
     for ( i = 0; i < FSCAPINTS; ++i )
         pv_featureset[i] = host_featureset[i] & pv_featuremask[i];
 
@@ -168,12 +167,15 @@ static void __init calculate_pv_max_policy(void)
 static void __init calculate_hvm_max_policy(void)
 {
     struct cpuid_policy *p = &hvm_max_policy;
+    uint32_t hvm_featureset[FSCAPINTS], host_featureset[FSCAPINTS];
     unsigned int i;
     const uint32_t *hvm_featuremask;
 
     if ( !hvm_enabled )
         return;
 
+    cpuid_policy_to_featureset(&host_policy, host_featureset);
+
     hvm_featuremask = hvm_funcs.hap_supported ?
         hvm_hap_featuremask : hvm_shadow_featuremask;
 
@@ -202,8 +204,7 @@ static void __init calculate_hvm_max_policy(void)
      * long mode (and init_amd() has cleared it out of host capabilities), but
      * HVM guests are able if running in protected mode.
      */
-    if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
-         test_bit(X86_FEATURE_SEP, raw_featureset) )
+    if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && raw_policy.basic.sep )
         __set_bit(X86_FEATURE_SEP, hvm_featureset);
 
     /*
@@ -270,7 +271,7 @@ void recalculate_cpuid_policy(struct domain *d)
     unsigned int i;
 
     cpuid_policy_to_featureset(p, fs);
-    memcpy(max_fs, max->fs, sizeof(max_fs));
+    cpuid_policy_to_featureset(max, max_fs);
 
     /*
      * HVM domains using Shadow paging have further restrictions on their
@@ -309,7 +310,7 @@ void recalculate_cpuid_policy(struct domain *d)
 
     /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
     fs[FEATURESET_7b0] &= ~special_features[FEATURESET_7b0];
-    fs[FEATURESET_7b0] |= (host_featureset[FEATURESET_7b0] &
+    fs[FEATURESET_7b0] |= (host_policy.feat._7b0 &
                            special_features[FEATURESET_7b0]);
 
     cpuid_featureset_to_policy(fs, p);
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index 14e7dc7..87da541 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -199,13 +199,14 @@ long arch_do_sysctl(
 
     case XEN_SYSCTL_get_cpu_featureset:
     {
-        static const uint32_t *const featureset_table[] = {
-            [XEN_SYSCTL_cpu_featureset_raw]  = raw_featureset,
-            [XEN_SYSCTL_cpu_featureset_host] = host_featureset,
-            [XEN_SYSCTL_cpu_featureset_pv]   = pv_featureset,
-            [XEN_SYSCTL_cpu_featureset_hvm]  = hvm_featureset,
+        static const struct cpuid_policy *const policy_table[] = {
+            [XEN_SYSCTL_cpu_featureset_raw]  = &raw_policy,
+            [XEN_SYSCTL_cpu_featureset_host] = &host_policy,
+            [XEN_SYSCTL_cpu_featureset_pv]   = &pv_max_policy,
+            [XEN_SYSCTL_cpu_featureset_hvm]  = &hvm_max_policy,
         };
-        const uint32_t *featureset = NULL;
+        const struct cpuid_policy *p = NULL;
+        uint32_t featureset[FSCAPINTS];
         unsigned int nr;
 
         /* Request for maximum number of features? */
@@ -223,13 +224,15 @@ long arch_do_sysctl(
                    FSCAPINTS);
 
         /* Look up requested featureset. */
-        if ( sysctl->u.cpu_featureset.index < ARRAY_SIZE(featureset_table) )
-            featureset = featureset_table[sysctl->u.cpu_featureset.index];
+        if ( sysctl->u.cpu_featureset.index < ARRAY_SIZE(policy_table) )
+            p = policy_table[sysctl->u.cpu_featureset.index];
 
         /* Bad featureset index? */
-        if ( !featureset )
+        if ( !p )
             ret = -EINVAL;
 
+        cpuid_policy_to_featureset(p, featureset);
+
         /* Copy the requested featureset into place. */
         if ( !ret && copy_to_guest(sysctl->u.cpu_featureset.features,
                                    featureset, nr) )
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 924e5d4..4cb54f2 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -197,9 +197,6 @@ struct cpuid_policy
 #undef __DECL_BITFIELD
 #undef _DECL_BITFIELD
 #undef DECL_BITFIELD
-
-    /* Temporary featureset bitmap. */
-    uint32_t fs[FSCAPINTS];
 };
 
 /* Fill in a featureset bitmap from a CPUID policy. */
@@ -237,12 +234,6 @@ static inline void cpuid_featureset_to_policy(
 extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
     hvm_max_policy;
 
-/* Temporary compatibility defines. */
-#define raw_featureset raw_policy.fs
-#define host_featureset host_policy.fs
-#define pv_featureset pv_max_policy.fs
-#define hvm_featureset hvm_max_policy.fs
-
 /* Allocate and initialise a CPUID policy suitable for the domain. */
 int init_domain_cpuid_policy(struct domain *d);
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 19/25] x86/cpuid: Calculate appropriate max_leaf values for the global policies
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (17 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 18/25] x86/cpuid: Drop the temporary linear feature bitmap from struct cpuid_policy Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid() Andrew Cooper
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

Derive host_policy from raw_policy, and {pv,hvm}_max_policy from host_policy.
Clamp the raw values to the maximum we will offer to guests.

This simplifies the PV and HVM policy calculations, removing the need for an
intermediate linear host_featureset bitmap.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/cpuid.c        | 28 ++++++++++++++++++++--------
 xen/include/asm-x86/cpuid.h |  2 +-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 677688d..c9f882b 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -135,19 +135,30 @@ static void __init calculate_host_policy(void)
 {
     struct cpuid_policy *p = &host_policy;
 
+    *p = raw_policy;
+
+    p->basic.max_leaf =
+        min_t(uint32_t, p->basic.max_leaf,   ARRAY_SIZE(p->basic.raw) - 1);
+    p->feat.max_subleaf =
+        min_t(uint32_t, p->feat.max_subleaf, ARRAY_SIZE(p->feat.raw) - 1);
+    p->extd.max_leaf =
+        min_t(uint32_t, p->extd.max_leaf,
+              0x80000000u + ARRAY_SIZE(p->extd.raw) - 1);
+
     cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
 }
 
 static void __init calculate_pv_max_policy(void)
 {
     struct cpuid_policy *p = &pv_max_policy;
-    uint32_t pv_featureset[FSCAPINTS], host_featureset[FSCAPINTS];
+    uint32_t pv_featureset[FSCAPINTS];
     unsigned int i;
 
-    cpuid_policy_to_featureset(&host_policy, host_featureset);
+    *p = host_policy;
+    cpuid_policy_to_featureset(p, pv_featureset);
 
-    for ( i = 0; i < FSCAPINTS; ++i )
-        pv_featureset[i] = host_featureset[i] & pv_featuremask[i];
+    for ( i = 0; i < ARRAY_SIZE(pv_featureset); ++i )
+        pv_featureset[i] &= pv_featuremask[i];
 
     /* Unconditionally claim to be able to set the hypervisor bit. */
     __set_bit(X86_FEATURE_HYPERVISOR, pv_featureset);
@@ -167,20 +178,21 @@ static void __init calculate_pv_max_policy(void)
 static void __init calculate_hvm_max_policy(void)
 {
     struct cpuid_policy *p = &hvm_max_policy;
-    uint32_t hvm_featureset[FSCAPINTS], host_featureset[FSCAPINTS];
+    uint32_t hvm_featureset[FSCAPINTS];
     unsigned int i;
     const uint32_t *hvm_featuremask;
 
     if ( !hvm_enabled )
         return;
 
-    cpuid_policy_to_featureset(&host_policy, host_featureset);
+    *p = host_policy;
+    cpuid_policy_to_featureset(p, hvm_featureset);
 
     hvm_featuremask = hvm_funcs.hap_supported ?
         hvm_hap_featuremask : hvm_shadow_featuremask;
 
-    for ( i = 0; i < FSCAPINTS; ++i )
-        hvm_featureset[i] = host_featureset[i] & hvm_featuremask[i];
+    for ( i = 0; i < ARRAY_SIZE(hvm_featureset); ++i )
+        hvm_featureset[i] &= hvm_featuremask[i];
 
     /* Unconditionally claim to be able to set the hypervisor bit. */
     __set_bit(X86_FEATURE_HYPERVISOR, hvm_featureset);
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 4cb54f2..d7cf2e6 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -78,10 +78,10 @@ struct cpuid_policy
      * Global *_policy objects:
      *
      * - Host accurate:
-     *   - max_{,sub}leaf
      *   - {xcr0,xss}_{high,low}
      *
      * - Guest accurate:
+     *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
      * Per-domain objects:
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (18 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 19/25] x86/cpuid: Calculate appropriate max_leaf values for the global policies Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 16:40   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid() Andrew Cooper
                   ` (4 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

Clamp the toolstack-providied max_leaf values in recalculate_cpuid_policy(),
causing the per-domain policy to have guest-accurate data.

Have guest_cpuid() exit early if a requested leaf is out of range, rather than
falling into the legacy path.

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

v2:
 * Check 0x7 and 0xd against basic.max_leaf
 * Use XSTATE_CPUID.
---
 xen/arch/x86/cpuid.c        | 37 +++++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/hvm.c      | 21 ---------------------
 xen/arch/x86/traps.c        | 23 -----------------------
 xen/include/asm-x86/cpuid.h |  1 +
 4 files changed, 38 insertions(+), 44 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index c9f882b..d5a3bae 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -5,6 +5,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/vmx/vmcs.h>
 #include <asm/processor.h>
+#include <asm/xstate.h>
 
 const uint32_t known_features[] = INIT_KNOWN_FEATURES;
 const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
@@ -282,6 +283,10 @@ void recalculate_cpuid_policy(struct domain *d)
     uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS];
     unsigned int i;
 
+    p->basic.max_leaf   = min(p->basic.max_leaf,   max->basic.max_leaf);
+    p->feat.max_subleaf = min(p->feat.max_subleaf, max->feat.max_subleaf);
+    p->extd.max_leaf    = min(p->extd.max_leaf,    max->extd.max_leaf);
+
     cpuid_policy_to_featureset(p, fs);
     cpuid_policy_to_featureset(max, max_fs);
 
@@ -318,6 +323,9 @@ void recalculate_cpuid_policy(struct domain *d)
     for ( i = 0; i < ARRAY_SIZE(fs); i++ )
         fs[i] &= max_fs[i];
 
+    if ( p->basic.max_leaf < XSTATE_CPUID )
+        __clear_bit(X86_FEATURE_XSAVE, fs);
+
     sanitise_featureset(fs);
 
     /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
@@ -347,15 +355,36 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
 {
     const struct vcpu *curr = current;
     const struct domain *d = v->domain;
+    const struct cpuid_policy *p = d->arch.cpuid;
 
     *res = EMPTY_LEAF;
 
     /*
      * First pass:
+     * - Perform max_leaf/subleaf calculations.  Out-of-range leaves return
+     *   all zeros, following the AMD model.
      * - Dispatch the virtualised leaves to their respective handlers.
      */
     switch ( leaf )
     {
+    case 0 ... CPUID_GUEST_NR_BASIC - 1:
+        if ( leaf > p->basic.max_leaf )
+            return;
+
+        switch ( leaf )
+        {
+        case 0x7:
+            if ( subleaf > p->feat.max_subleaf )
+                return;
+            break;
+
+        case XSTATE_CPUID:
+            if ( subleaf > ARRAY_SIZE(p->xstate.raw) )
+                return;
+            break;
+        }
+        break;
+
     case 0x40000000 ... 0x400000ff:
         if ( is_viridian_domain(d) )
             return cpuid_viridian_leaves(v, leaf, subleaf, res);
@@ -363,6 +392,14 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
         /* Fallthrough. */
     case 0x40000100 ... 0x4fffffff:
         return cpuid_hypervisor_leaves(v, leaf, subleaf, res);
+
+    case 0x80000000 ... 0x80000000 + CPUID_GUEST_NR_EXTD - 1:
+        if ( leaf > p->extd.max_leaf )
+            return;
+        break;
+
+    default:
+        return;
     }
 
     /* {hvm,pv}_cpuid() have this expectation. */
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 103f848..fb8f3d9 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3306,27 +3306,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     if ( !edx )
         edx = &dummy;
 
-    if ( input & 0x7fffffff )
-    {
-        /*
-         * Requests outside the supported leaf ranges return zero on AMD
-         * and the highest basic leaf output on Intel. Uniformly follow
-         * the AMD model as the more sane one.
-         */
-        unsigned int limit;
-
-        domain_cpuid(d, (input >> 16) != 0x8000 ? 0 : 0x80000000, 0,
-                     &limit, &dummy, &dummy, &dummy);
-        if ( input > limit )
-        {
-            *eax = 0;
-            *ebx = 0;
-            *ecx = 0;
-            *edx = 0;
-            return;
-        }
-    }
-
     domain_cpuid(d, input, count, eax, ebx, ecx, edx);
 
     switch ( input )
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 360b10d..443948c 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1031,29 +1031,6 @@ void pv_cpuid(struct cpu_user_regs *regs)
     subleaf = c = regs->_ecx;
     d = regs->_edx;
 
-    if ( leaf & 0x7fffffff )
-    {
-        /*
-         * Requests outside the supported leaf ranges return zero on AMD
-         * and the highest basic leaf output on Intel. Uniformly follow
-         * the AMD model as the more sane one.
-         */
-        unsigned int limit = (leaf >> 16) != 0x8000 ? 0 : 0x80000000, dummy;
-
-        if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
-            domain_cpuid(currd, limit, 0, &limit, &dummy, &dummy, &dummy);
-        else
-            limit = cpuid_eax(limit);
-        if ( leaf > limit )
-        {
-            regs->rax = 0;
-            regs->rbx = 0;
-            regs->rcx = 0;
-            regs->rdx = 0;
-            return;
-        }
-    }
-
     if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
         domain_cpuid(currd, leaf, subleaf, &a, &b, &c, &d);
     else
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index d7cf2e6..b2ed725 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -87,6 +87,7 @@ struct cpuid_policy
      * Per-domain objects:
      *
      * - Guest accurate:
+     *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
      * Everything else should be considered inaccurate, and not necesserily 0.
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (19 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 16:46   ` Jan Beulich
  2017-01-09 11:03 ` [PATCH v2 22/25] x86/hvm: Use guest_cpuid() rather than hvm_cpuid() Andrew Cooper
                   ` (3 subsequent siblings)
  24 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

All per-domain policy data concerning leaf 7 is accurate.  Handle it all in
guest_cpuid() by reading out of the raw array block, and introduing a dynamic
adjustment for OSPKE.

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

v2:
 * Extend the comment concerning dynamic adjustments out of current context.
---
 xen/arch/x86/cpuid.c        | 46 +++++++++++++++++++++++++++++++++++++++++++--
 xen/arch/x86/hvm/hvm.c      | 17 ++++-------------
 xen/arch/x86/traps.c        | 28 ++++-----------------------
 xen/include/asm-x86/cpuid.h |  2 ++
 4 files changed, 54 insertions(+), 39 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index d5a3bae..44f52cf 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -363,6 +363,7 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
      * First pass:
      * - Perform max_leaf/subleaf calculations.  Out-of-range leaves return
      *   all zeros, following the AMD model.
+     * - Fill in *res for leaves no longer handled on the legacy path.
      * - Dispatch the virtualised leaves to their respective handlers.
      */
     switch ( leaf )
@@ -376,12 +377,18 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
         case 0x7:
             if ( subleaf > p->feat.max_subleaf )
                 return;
+
+            BUG_ON(subleaf >= ARRAY_SIZE(p->feat.raw));
+            *res = p->feat.raw[subleaf];
             break;
 
         case XSTATE_CPUID:
             if ( subleaf > ARRAY_SIZE(p->xstate.raw) )
                 return;
-            break;
+
+            /* Fallthrough. */
+        default:
+            goto legacy;
         }
         break;
 
@@ -396,12 +403,47 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
     case 0x80000000 ... 0x80000000 + CPUID_GUEST_NR_EXTD - 1:
         if ( leaf > p->extd.max_leaf )
             return;
-        break;
+        goto legacy;
 
     default:
         return;
     }
 
+    /*
+     * Skip dynamic adjustments if we are in the wrong context.
+     *
+     * All dynamic adjustments depends on current register state, which will
+     * be stale if the vcpu is running elsewhere.  It is simpler, quicker, and
+     * more reliable for the caller to nothing (consistently) than to hand
+     * back stale data which it can't use safely.
+     */
+    if ( v != curr )
+        return;
+
+    /*
+     * Second pass:
+     * - Dynamic adjustments
+     */
+    switch ( leaf )
+    {
+    case 0x7:
+        switch ( subleaf )
+        {
+        case 0:
+            /* OSPKE clear in policy.  Fast-forward CR4 back in. */
+            if ( (is_pv_vcpu(v)
+                  ? v->arch.pv_vcpu.ctrlreg[4]
+                  : v->arch.hvm_vcpu.guest_cr[4]) & X86_CR4_PKE )
+                res->c |= cpufeat_mask(X86_FEATURE_OSPKE);
+            break;
+        }
+        break;
+    }
+
+    /* Done. */
+    return;
+
+ legacy:
     /* {hvm,pv}_cpuid() have this expectation. */
     ASSERT(v == curr);
 
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index fb8f3d9..f706aad 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3355,19 +3355,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
 
         break;
 
-    case 0x7:
-        if ( count == 0 )
-        {
-            *ebx = d->arch.cpuid->feat._7b0;
-            *ecx = d->arch.cpuid->feat._7c0;
-            *edx = d->arch.cpuid->feat._7d0;
-
-            /* OSPKE clear in policy.  Fast-forward CR4 back in. */
-            if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PKE )
-                *ecx |= cpufeat_mask(X86_FEATURE_OSPKE);
-        }
-        break;
-
     case 0xb:
         /* Fix the x2APIC identifier. */
         *edx = v->vcpu_id * 2;
@@ -3544,6 +3531,10 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         else
             *eax = 0;
         break;
+
+    case 0x7:
+        ASSERT_UNREACHABLE();
+        /* Now handled in guest_cpuid(). */
     }
 }
 
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 443948c..47d313a 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1179,30 +1179,6 @@ void pv_cpuid(struct cpu_user_regs *regs)
         }
         break;
 
-    case 0x00000007:
-        if ( subleaf == 0 )
-        {
-            b = currd->arch.cpuid->feat._7b0;
-            c = currd->arch.cpuid->feat._7c0;
-            d = currd->arch.cpuid->feat._7d0;
-
-            if ( !is_pvh_domain(currd) )
-            {
-                /*
-                 * Delete the PVH condition when HVMLite formally replaces PVH,
-                 * and HVM guests no longer enter a PV codepath.
-                 */
-
-                /* OSPKE clear in policy.  Fast-forward CR4 back in. */
-                if ( curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_PKE )
-                    c |= cpufeat_mask(X86_FEATURE_OSPKE);
-            }
-        }
-        else
-            b = c = d = 0;
-        a = 0;
-        break;
-
     case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
         if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
              !vpmu_enabled(curr) )
@@ -1304,6 +1280,10 @@ void pv_cpuid(struct cpu_user_regs *regs)
     unsupported:
         a = b = c = d = 0;
         break;
+
+    case 0x7:
+        ASSERT_UNREACHABLE();
+        /* Now handled in guest_cpuid(). */
     }
 
     regs->rax = a;
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index b2ed725..c219f3c 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -81,12 +81,14 @@ struct cpuid_policy
      *   - {xcr0,xss}_{high,low}
      *
      * - Guest accurate:
+     *   - All of the feat union
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
      * Per-domain objects:
      *
      * - Guest accurate:
+     *   - All of the feat union
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 22/25] x86/hvm: Use guest_cpuid() rather than hvm_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (20 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 23/25] x86/svm: " Andrew Cooper
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

More work is required before maxphysaddr can be read straight out of the
cpuid_policy block, but in the meantime hvm_cpuid() wants to disappear so
update the code to use the newer interface.

Use the behaviour of max_leaf handling (returning all zeros) to avoid a double
call into guest_cpuid().

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/mtrr.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c
index 228dac1..709759c 100644
--- a/xen/arch/x86/hvm/mtrr.c
+++ b/xen/arch/x86/hvm/mtrr.c
@@ -440,7 +440,7 @@ bool_t mtrr_fix_range_msr_set(struct domain *d, struct mtrr_state *m,
 bool_t mtrr_var_range_msr_set(
     struct domain *d, struct mtrr_state *m, uint32_t msr, uint64_t msr_content)
 {
-    uint32_t index, phys_addr, eax;
+    uint32_t index, phys_addr;
     uint64_t msr_mask;
     uint64_t *var_range_base = (uint64_t*)m->var_ranges;
 
@@ -453,13 +453,10 @@ bool_t mtrr_var_range_msr_set(
 
     if ( d == current->domain )
     {
-        phys_addr = 36;
-        hvm_cpuid(0x80000000, &eax, NULL, NULL, NULL);
-        if ( (eax >> 16) == 0x8000 && eax >= 0x80000008 )
-        {
-            hvm_cpuid(0x80000008, &eax, NULL, NULL, NULL);
-            phys_addr = (uint8_t)eax;
-        }
+        struct cpuid_leaf res;
+
+        guest_cpuid(current, 0x80000008, 0, &res);
+        phys_addr = (uint8_t)res.a ?: 36;
     }
     else
         phys_addr = paddr_bits;
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 23/25] x86/svm: Use guest_cpuid() rather than hvm_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (21 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 22/25] x86/hvm: Use guest_cpuid() rather than hvm_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 24/25] x86/cpuid: Effectively remove pv_cpuid() and hvm_cpuid() Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 25/25] x86/cpuid: Alter the legacy-path prototypes to match guest_cpuid() Andrew Cooper
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

More work is required before LWP details can be read straight out of the
cpuid_policy block, but in the meantime hvm_cpuid() wants to disappear so
update the code to use the newer interface.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
 * Reduce scope of res
---
 xen/arch/x86/hvm/svm/svm.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index e9c6d69..86dcffc 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -926,17 +926,18 @@ static inline void svm_lwp_load(struct vcpu *v)
 /* Update LWP_CFG MSR (0xc0000105). Return -1 if error; otherwise returns 0. */
 static int svm_update_lwp_cfg(struct vcpu *v, uint64_t msr_content)
 {
-    unsigned int edx;
     uint32_t msr_low;
     static uint8_t lwp_intr_vector;
 
     if ( xsave_enabled(v) && cpu_has_lwp )
     {
-        hvm_cpuid(0x8000001c, NULL, NULL, NULL, &edx);
+        struct cpuid_leaf res;
+
+        guest_cpuid(v, 0x8000001c, 0, &res);
         msr_low = (uint32_t)msr_content;
         
         /* generate #GP if guest tries to turn on unsupported features. */
-        if ( msr_low & ~edx)
+        if ( msr_low & ~res.d)
             return -1;
 
         v->arch.hvm_svm.guest_lwp_cfg = msr_content;
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 24/25] x86/cpuid: Effectively remove pv_cpuid() and hvm_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (22 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 23/25] x86/svm: " Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  2017-01-09 11:03 ` [PATCH v2 25/25] x86/cpuid: Alter the legacy-path prototypes to match guest_cpuid() Andrew Cooper
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

All callers of pv_cpuid() and hvm_cpuid() (other than guest_cpuid() legacy
path) have been removed from the codebase.  Move them into cpuid.c to avoid
any further use, leaving guest_cpuid() as the sole API to use.

This is purely code motion, with no functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/cpuid.c            | 523 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/hvm.c          | 250 -------------------
 xen/arch/x86/traps.c            | 273 ---------------------
 xen/include/asm-x86/hvm/hvm.h   |   2 -
 xen/include/asm-x86/processor.h |   2 -
 5 files changed, 523 insertions(+), 527 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 44f52cf..822f109 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -350,6 +350,529 @@ int init_domain_cpuid_policy(struct domain *d)
     return 0;
 }
 
+static void pv_cpuid(struct cpu_user_regs *regs)
+{
+    uint32_t leaf, subleaf, a, b, c, d;
+    struct vcpu *curr = current;
+    struct domain *currd = curr->domain;
+    const struct cpuid_policy *p = currd->arch.cpuid;
+
+    leaf = a = regs->_eax;
+    b = regs->_ebx;
+    subleaf = c = regs->_ecx;
+    d = regs->_edx;
+
+    if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
+        domain_cpuid(currd, leaf, subleaf, &a, &b, &c, &d);
+    else
+        cpuid_count(leaf, subleaf, &a, &b, &c, &d);
+
+    switch ( leaf )
+    {
+        uint32_t tmp;
+
+    case 0x00000001:
+        c = p->basic._1c;
+        d = p->basic._1d;
+
+        if ( !is_pvh_domain(currd) )
+        {
+            /*
+             * Delete the PVH condition when HVMLite formally replaces PVH,
+             * and HVM guests no longer enter a PV codepath.
+             */
+
+            /*
+             * !!! OSXSAVE handling for PV guests is non-architectural !!!
+             *
+             * Architecturally, the correct code here is simply:
+             *
+             *   if ( curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE )
+             *       c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
+             *
+             * However because of bugs in Xen (before c/s bd19080b, Nov 2010,
+             * the XSAVE cpuid flag leaked into guests despite the feature not
+             * being available for use), buggy workarounds where introduced to
+             * Linux (c/s 947ccf9c, also Nov 2010) which relied on the fact
+             * that Xen also incorrectly leaked OSXSAVE into the guest.
+             *
+             * Furthermore, providing architectural OSXSAVE behaviour to a
+             * many Linux PV guests triggered a further kernel bug when the
+             * fpu code observes that XSAVEOPT is available, assumes that
+             * xsave state had been set up for the task, and follows a wild
+             * pointer.
+             *
+             * Older Linux PVOPS kernels however do require architectural
+             * behaviour.  They observe Xen's leaked OSXSAVE and assume they
+             * can already use XSETBV, dying with a #UD because the shadowed
+             * CR4.OSXSAVE is clear.  This behaviour has been adjusted in all
+             * observed cases via stable backports of the above changeset.
+             *
+             * Therefore, the leaking of Xen's OSXSAVE setting has become a
+             * defacto part of the PV ABI and can't reasonably be corrected.
+             * It can however be restricted to only the enlightened CPUID
+             * view, as seen by the guest kernel.
+             *
+             * The following situations and logic now applies:
+             *
+             * - Hardware without CPUID faulting support and native CPUID:
+             *    There is nothing Xen can do here.  The hosts XSAVE flag will
+             *    leak through and Xen's OSXSAVE choice will leak through.
+             *
+             *    In the case that the guest kernel has not set up OSXSAVE, only
+             *    SSE will be set in xcr0, and guest userspace can't do too much
+             *    damage itself.
+             *
+             * - Enlightened CPUID or CPUID faulting available:
+             *    Xen can fully control what is seen here.  Guest kernels need
+             *    to see the leaked OSXSAVE via the enlightened path, but
+             *    guest userspace and the native is given architectural
+             *    behaviour.
+             *
+             *    Emulated vs Faulted CPUID is distinguised based on whether a
+             *    #UD or #GP is currently being serviced.
+             */
+            /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
+            if ( (curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE) ||
+                 (regs->entry_vector == TRAP_invalid_op &&
+                  guest_kernel_mode(curr, regs) &&
+                  (read_cr4() & X86_CR4_OSXSAVE)) )
+                c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
+
+            /*
+             * At the time of writing, a PV domain is the only viable option
+             * for Dom0.  Several interactions between dom0 and Xen for real
+             * hardware setup have unfortunately been implemented based on
+             * state which incorrectly leaked into dom0.
+             *
+             * These leaks are retained for backwards compatibility, but
+             * restricted to the hardware domains kernel only.
+             */
+            if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) )
+            {
+                /*
+                 * MTRR used to unconditionally leak into PV guests.  They
+                 * cannot MTRR infrastructure at all, and shouldn't be able to
+                 * see the feature.
+                 *
+                 * Modern PVOPS Linux self-clobbers the MTRR feature, to avoid
+                 * trying to use the associated MSRs.  Xenolinux-based PV dom0's
+                 * however use the MTRR feature as an indication of the presence
+                 * of the XENPF_{add,del,read}_memtype hypercalls.
+                 */
+                if ( cpu_has_mtrr )
+                    d |= cpufeat_mask(X86_FEATURE_MTRR);
+
+                /*
+                 * MONITOR never leaked into PV guests, as PV guests cannot
+                 * use the MONITOR/MWAIT instructions.  As such, they require
+                 * the feature to not being present in emulated CPUID.
+                 *
+                 * Modern PVOPS Linux try to be cunning and use native CPUID
+                 * to see if the hardware actually supports MONITOR, and by
+                 * extension, deep C states.
+                 *
+                 * If the feature is seen, deep-C state information is
+                 * obtained from the DSDT and handed back to Xen via the
+                 * XENPF_set_processor_pminfo hypercall.
+                 *
+                 * This mechanism is incompatible with an HVM-based hardware
+                 * domain, and also with CPUID Faulting.
+                 *
+                 * Luckily, Xen can be just as 'cunning', and distinguish an
+                 * emulated CPUID from a faulted CPUID by whether a #UD or #GP
+                 * fault is currently being serviced.  Yuck...
+                 */
+                if ( cpu_has_monitor && regs->entry_vector == TRAP_gp_fault )
+                    c |= cpufeat_mask(X86_FEATURE_MONITOR);
+
+                /*
+                 * While MONITOR never leaked into PV guests, EIST always used
+                 * to.
+                 *
+                 * Modern PVOPS will only parse P state information from the
+                 * DSDT and return it to Xen if EIST is seen in the emulated
+                 * CPUID information.
+                 */
+                if ( cpu_has_eist )
+                    c |= cpufeat_mask(X86_FEATURE_EIST);
+            }
+        }
+
+        if ( vpmu_enabled(curr) &&
+             vpmu_is_set(vcpu_vpmu(curr), VPMU_CPU_HAS_DS) )
+        {
+            d |= cpufeat_mask(X86_FEATURE_DS);
+            if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
+                c |= cpufeat_mask(X86_FEATURE_DTES64);
+            if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
+                c |= cpufeat_mask(X86_FEATURE_DSCPL);
+        }
+        break;
+
+    case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
+        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+             !vpmu_enabled(curr) )
+            goto unsupported;
+
+        /* Report at most version 3 since that's all we currently emulate. */
+        if ( (a & 0xff) > 3 )
+            a = (a & ~0xff) | 3;
+        break;
+
+    case XSTATE_CPUID:
+        if ( !p->basic.xsave || subleaf >= 63 )
+            goto unsupported;
+        switch ( subleaf )
+        {
+        case 0:
+        {
+            uint64_t xfeature_mask = XSTATE_FP_SSE;
+            uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
+
+            if ( p->basic.avx )
+            {
+                xfeature_mask |= XSTATE_YMM;
+                xstate_size = (xstate_offsets[_XSTATE_YMM] +
+                               xstate_sizes[_XSTATE_YMM]);
+            }
+
+            if ( p->feat.avx512f )
+            {
+                xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_OPMASK] +
+                                  xstate_sizes[_XSTATE_OPMASK]);
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_ZMM] +
+                                  xstate_sizes[_XSTATE_ZMM]);
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_HI_ZMM] +
+                                  xstate_sizes[_XSTATE_HI_ZMM]);
+            }
+
+            a = (uint32_t)xfeature_mask;
+            d = (uint32_t)(xfeature_mask >> 32);
+            c = xstate_size;
+
+            /*
+             * Always read CPUID.0xD[ECX=0].EBX from hardware, rather than
+             * domain policy.  It varies with enabled xstate, and the correct
+             * xcr0 is in context.
+             */
+            cpuid_count(leaf, subleaf, &tmp, &b, &tmp, &tmp);
+            break;
+        }
+
+        case 1:
+            a = p->xstate.Da1;
+            b = c = d = 0;
+            break;
+        }
+        break;
+
+    case 0x80000001:
+        c = p->extd.e1c;
+        d = p->extd.e1d;
+
+        /* If not emulating AMD, clear the duplicated features in e1d. */
+        if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
+            d &= ~CPUID_COMMON_1D_FEATURES;
+
+        /*
+         * MTRR used to unconditionally leak into PV guests.  They cannot MTRR
+         * infrastructure at all, and shouldn't be able to see the feature.
+         *
+         * Modern PVOPS Linux self-clobbers the MTRR feature, to avoid trying
+         * to use the associated MSRs.  Xenolinux-based PV dom0's however use
+         * the MTRR feature as an indication of the presence of the
+         * XENPF_{add,del,read}_memtype hypercalls.
+         */
+        if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) &&
+             cpu_has_mtrr )
+            d |= cpufeat_mask(X86_FEATURE_MTRR);
+        break;
+
+    case 0x80000007:
+        d = p->extd.e7d;
+        break;
+
+    case 0x80000008:
+        a = paddr_bits | (vaddr_bits << 8);
+        b = p->extd.e8b;
+        break;
+
+    case 0x00000005: /* MONITOR/MWAIT */
+    case 0x0000000b: /* Extended Topology Enumeration */
+    case 0x8000000a: /* SVM revision and features */
+    case 0x8000001b: /* Instruction Based Sampling */
+    case 0x8000001c: /* Light Weight Profiling */
+    case 0x8000001e: /* Extended topology reporting */
+    unsupported:
+        a = b = c = d = 0;
+        break;
+
+    case 0x7:
+        ASSERT_UNREACHABLE();
+        /* Now handled in guest_cpuid(). */
+    }
+
+    regs->rax = a;
+    regs->rbx = b;
+    regs->rcx = c;
+    regs->rdx = d;
+}
+
+static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
+                      unsigned int *ecx, unsigned int *edx)
+{
+    struct vcpu *v = current;
+    struct domain *d = v->domain;
+    const struct cpuid_policy *p = d->arch.cpuid;
+    unsigned int count, dummy = 0;
+
+    if ( !eax )
+        eax = &dummy;
+    if ( !ebx )
+        ebx = &dummy;
+    if ( !ecx )
+        ecx = &dummy;
+    count = *ecx;
+    if ( !edx )
+        edx = &dummy;
+
+    domain_cpuid(d, input, count, eax, ebx, ecx, edx);
+
+    switch ( input )
+    {
+    case 0x1:
+        /* Fix up VLAPIC details. */
+        *ebx &= 0x00FFFFFFu;
+        *ebx |= (v->vcpu_id * 2) << 24;
+
+        *ecx = p->basic._1c;
+        *edx = p->basic._1d;
+
+        /* APIC exposed to guests, but Fast-forward MSR_APIC_BASE.EN back in. */
+        if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
+            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
+
+        /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
+        if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE )
+            *ecx |= cpufeat_mask(X86_FEATURE_OSXSAVE);
+
+        /*
+         * PSE36 is not supported in shadow mode.  This bit should be
+         * unilaterally cleared.
+         *
+         * However, an unspecified version of Hyper-V from 2011 refuses
+         * to start as the "cpu does not provide required hw features" if
+         * it can't see PSE36.
+         *
+         * As a workaround, leak the toolstack-provided PSE36 value into a
+         * shadow guest if the guest is already using PAE paging (and won't
+         * care about reverting back to PSE paging).  Otherwise, knoble it, so
+         * a 32bit guest doesn't get the impression that it could try to use
+         * PSE36 paging.
+         */
+        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
+            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
+
+        if ( vpmu_enabled(v) &&
+             vpmu_is_set(vcpu_vpmu(v), VPMU_CPU_HAS_DS) )
+        {
+            *edx |= cpufeat_mask(X86_FEATURE_DS);
+            if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
+                *ecx |= cpufeat_mask(X86_FEATURE_DTES64);
+            if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
+                *ecx |= cpufeat_mask(X86_FEATURE_DSCPL);
+        }
+
+        break;
+
+    case 0xb:
+        /* Fix the x2APIC identifier. */
+        *edx = v->vcpu_id * 2;
+        break;
+
+    case XSTATE_CPUID:
+        if ( !p->basic.xsave || count >= 63 )
+        {
+            *eax = *ebx = *ecx = *edx = 0;
+            break;
+        }
+        switch ( count )
+        {
+        case 0:
+        {
+            uint64_t xfeature_mask = XSTATE_FP_SSE;
+            uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
+
+            if ( p->basic.avx )
+            {
+                xfeature_mask |= XSTATE_YMM;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_YMM] +
+                                  xstate_sizes[_XSTATE_YMM]);
+            }
+
+            if ( p->feat.mpx )
+            {
+                xfeature_mask |= XSTATE_BNDREGS | XSTATE_BNDCSR;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_BNDCSR] +
+                                  xstate_sizes[_XSTATE_BNDCSR]);
+            }
+
+            if ( p->feat.avx512f )
+            {
+                xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_OPMASK] +
+                                  xstate_sizes[_XSTATE_OPMASK]);
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_ZMM] +
+                                  xstate_sizes[_XSTATE_ZMM]);
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_HI_ZMM] +
+                                  xstate_sizes[_XSTATE_HI_ZMM]);
+            }
+
+            if ( p->feat.pku )
+            {
+                xfeature_mask |= XSTATE_PKRU;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_PKRU] +
+                                  xstate_sizes[_XSTATE_PKRU]);
+            }
+
+            if ( p->extd.lwp )
+            {
+                xfeature_mask |= XSTATE_LWP;
+                xstate_size = max(xstate_size,
+                                  xstate_offsets[_XSTATE_LWP] +
+                                  xstate_sizes[_XSTATE_LWP]);
+            }
+
+            *eax = (uint32_t)xfeature_mask;
+            *edx = (uint32_t)(xfeature_mask >> 32);
+            *ecx = xstate_size;
+
+            /*
+             * Always read CPUID[0xD,0].EBX from hardware, rather than domain
+             * policy.  It varies with enabled xstate, and the correct xcr0 is
+             * in context.
+             */
+            cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
+            break;
+        }
+
+        case 1:
+            *eax = p->xstate.Da1;
+
+            if ( p->xstate.xsaves )
+            {
+                /*
+                 * Always read CPUID[0xD,1].EBX from hardware, rather than
+                 * domain policy.  It varies with enabled xstate, and the
+                 * correct xcr0/xss are in context.
+                 */
+                cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
+            }
+            else
+                *ebx = 0;
+
+            *ecx = *edx = 0;
+            break;
+        }
+        break;
+
+    case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
+        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || !vpmu_enabled(v) )
+        {
+            *eax = *ebx = *ecx = *edx = 0;
+            break;
+        }
+
+        /* Report at most version 3 since that's all we currently emulate */
+        if ( (*eax & 0xff) > 3 )
+            *eax = (*eax & ~0xff) | 3;
+        break;
+
+    case 0x80000001:
+        *ecx = p->extd.e1c;
+        *edx = p->extd.e1d;
+
+        /* If not emulating AMD, clear the duplicated features in e1d. */
+        if ( d->arch.x86_vendor != X86_VENDOR_AMD )
+            *edx &= ~CPUID_COMMON_1D_FEATURES;
+        /* fast-forward MSR_APIC_BASE.EN if it hasn't already been clobbered. */
+        else if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
+            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
+
+        /*
+         * PSE36 is not supported in shadow mode.  This bit should be
+         * unilaterally cleared.
+         *
+         * However, an unspecified version of Hyper-V from 2011 refuses
+         * to start as the "cpu does not provide required hw features" if
+         * it can't see PSE36.
+         *
+         * As a workaround, leak the toolstack-provided PSE36 value into a
+         * shadow guest if the guest is already using PAE paging (and won't
+         * care about reverting back to PSE paging).  Otherwise, knoble it, so
+         * a 32bit guest doesn't get the impression that it could try to use
+         * PSE36 paging.
+         */
+        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
+            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
+
+        /* SYSCALL is hidden outside of long mode on Intel. */
+        if ( d->arch.x86_vendor == X86_VENDOR_INTEL &&
+             !hvm_long_mode_enabled(v))
+            *edx &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
+
+        break;
+
+    case 0x80000007:
+        *edx = p->extd.e7d;
+        break;
+
+    case 0x80000008:
+        *eax &= 0xff;
+        count = d->arch.paging.gfn_bits + PAGE_SHIFT;
+        if ( *eax > count )
+            *eax = count;
+
+        count = (p->basic.pae || p->basic.pse36) ? 36 : 32;
+        if ( *eax < count )
+            *eax = count;
+
+        *eax |= (p->extd.lm ? vaddr_bits : 32) << 8;
+
+        *ebx = p->extd.e8b;
+        break;
+
+    case 0x8000001c:
+        if ( !cpu_has_svm )
+        {
+            *eax = *ebx = *ecx = *edx = 0;
+            break;
+        }
+
+        if ( cpu_has_lwp && (v->arch.xcr0 & XSTATE_LWP) )
+            /* Turn on available bit and other features specified in lwp_cfg. */
+            *eax = (*edx & v->arch.hvm_svm.guest_lwp_cfg) | 1;
+        else
+            *eax = 0;
+        break;
+
+    case 0x7:
+        ASSERT_UNREACHABLE();
+        /* Now handled in guest_cpuid(). */
+    }
+}
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res)
 {
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index f706aad..ff6d0b6 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3288,256 +3288,6 @@ unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
     return rc ? len : 0; /* fake a copy_from_user() return code */
 }
 
-void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
-                                   unsigned int *ecx, unsigned int *edx)
-{
-    struct vcpu *v = current;
-    struct domain *d = v->domain;
-    const struct cpuid_policy *p = d->arch.cpuid;
-    unsigned int count, dummy = 0;
-
-    if ( !eax )
-        eax = &dummy;
-    if ( !ebx )
-        ebx = &dummy;
-    if ( !ecx )
-        ecx = &dummy;
-    count = *ecx;
-    if ( !edx )
-        edx = &dummy;
-
-    domain_cpuid(d, input, count, eax, ebx, ecx, edx);
-
-    switch ( input )
-    {
-    case 0x1:
-        /* Fix up VLAPIC details. */
-        *ebx &= 0x00FFFFFFu;
-        *ebx |= (v->vcpu_id * 2) << 24;
-
-        *ecx = p->basic._1c;
-        *edx = p->basic._1d;
-
-        /* APIC exposed to guests, but Fast-forward MSR_APIC_BASE.EN back in. */
-        if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
-
-        /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
-        if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE )
-            *ecx |= cpufeat_mask(X86_FEATURE_OSXSAVE);
-
-        /*
-         * PSE36 is not supported in shadow mode.  This bit should be
-         * unilaterally cleared.
-         *
-         * However, an unspecified version of Hyper-V from 2011 refuses
-         * to start as the "cpu does not provide required hw features" if
-         * it can't see PSE36.
-         *
-         * As a workaround, leak the toolstack-provided PSE36 value into a
-         * shadow guest if the guest is already using PAE paging (and won't
-         * care about reverting back to PSE paging).  Otherwise, knoble it, so
-         * a 32bit guest doesn't get the impression that it could try to use
-         * PSE36 paging.
-         */
-        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
-
-        if ( vpmu_enabled(v) &&
-             vpmu_is_set(vcpu_vpmu(v), VPMU_CPU_HAS_DS) )
-        {
-            *edx |= cpufeat_mask(X86_FEATURE_DS);
-            if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
-                *ecx |= cpufeat_mask(X86_FEATURE_DTES64);
-            if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
-                *ecx |= cpufeat_mask(X86_FEATURE_DSCPL);
-        }
-
-        break;
-
-    case 0xb:
-        /* Fix the x2APIC identifier. */
-        *edx = v->vcpu_id * 2;
-        break;
-
-    case XSTATE_CPUID:
-        if ( !p->basic.xsave || count >= 63 )
-        {
-            *eax = *ebx = *ecx = *edx = 0;
-            break;
-        }
-        switch ( count )
-        {
-        case 0:
-        {
-            uint64_t xfeature_mask = XSTATE_FP_SSE;
-            uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
-
-            if ( p->basic.avx )
-            {
-                xfeature_mask |= XSTATE_YMM;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_YMM] +
-                                  xstate_sizes[_XSTATE_YMM]);
-            }
-
-            if ( p->feat.mpx )
-            {
-                xfeature_mask |= XSTATE_BNDREGS | XSTATE_BNDCSR;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_BNDCSR] +
-                                  xstate_sizes[_XSTATE_BNDCSR]);
-            }
-
-            if ( p->feat.avx512f )
-            {
-                xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_OPMASK] +
-                                  xstate_sizes[_XSTATE_OPMASK]);
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_ZMM] +
-                                  xstate_sizes[_XSTATE_ZMM]);
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_HI_ZMM] +
-                                  xstate_sizes[_XSTATE_HI_ZMM]);
-            }
-
-            if ( p->feat.pku )
-            {
-                xfeature_mask |= XSTATE_PKRU;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_PKRU] +
-                                  xstate_sizes[_XSTATE_PKRU]);
-            }
-
-            if ( p->extd.lwp )
-            {
-                xfeature_mask |= XSTATE_LWP;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_LWP] +
-                                  xstate_sizes[_XSTATE_LWP]);
-            }
-
-            *eax = (uint32_t)xfeature_mask;
-            *edx = (uint32_t)(xfeature_mask >> 32);
-            *ecx = xstate_size;
-
-            /*
-             * Always read CPUID[0xD,0].EBX from hardware, rather than domain
-             * policy.  It varies with enabled xstate, and the correct xcr0 is
-             * in context.
-             */
-            cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
-            break;
-        }
-
-        case 1:
-            *eax = p->xstate.Da1;
-
-            if ( p->xstate.xsaves )
-            {
-                /*
-                 * Always read CPUID[0xD,1].EBX from hardware, rather than
-                 * domain policy.  It varies with enabled xstate, and the
-                 * correct xcr0/xss are in context.
-                 */
-                cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
-            }
-            else
-                *ebx = 0;
-
-            *ecx = *edx = 0;
-            break;
-        }
-        break;
-
-    case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
-        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || !vpmu_enabled(v) )
-        {
-            *eax = *ebx = *ecx = *edx = 0;
-            break;
-        }
-
-        /* Report at most version 3 since that's all we currently emulate */
-        if ( (*eax & 0xff) > 3 )
-            *eax = (*eax & ~0xff) | 3;
-        break;
-
-    case 0x80000001:
-        *ecx = p->extd.e1c;
-        *edx = p->extd.e1d;
-
-        /* If not emulating AMD, clear the duplicated features in e1d. */
-        if ( d->arch.x86_vendor != X86_VENDOR_AMD )
-            *edx &= ~CPUID_COMMON_1D_FEATURES;
-        /* fast-forward MSR_APIC_BASE.EN if it hasn't already been clobbered. */
-        else if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
-
-        /*
-         * PSE36 is not supported in shadow mode.  This bit should be
-         * unilaterally cleared.
-         *
-         * However, an unspecified version of Hyper-V from 2011 refuses
-         * to start as the "cpu does not provide required hw features" if
-         * it can't see PSE36.
-         *
-         * As a workaround, leak the toolstack-provided PSE36 value into a
-         * shadow guest if the guest is already using PAE paging (and won't
-         * care about reverting back to PSE paging).  Otherwise, knoble it, so
-         * a 32bit guest doesn't get the impression that it could try to use
-         * PSE36 paging.
-         */
-        if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
-
-        /* SYSCALL is hidden outside of long mode on Intel. */
-        if ( d->arch.x86_vendor == X86_VENDOR_INTEL &&
-             !hvm_long_mode_enabled(v))
-            *edx &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
-
-        break;
-
-    case 0x80000007:
-        *edx = p->extd.e7d;
-        break;
-
-    case 0x80000008:
-        *eax &= 0xff;
-        count = d->arch.paging.gfn_bits + PAGE_SHIFT;
-        if ( *eax > count )
-            *eax = count;
-
-        count = (p->basic.pae || p->basic.pse36) ? 36 : 32;
-        if ( *eax < count )
-            *eax = count;
-
-        *eax |= (p->extd.lm ? vaddr_bits : 32) << 8;
-
-        *ebx = p->extd.e8b;
-        break;
-
-    case 0x8000001c:
-        if ( !cpu_has_svm )
-        {
-            *eax = *ebx = *ecx = *edx = 0;
-            break;
-        }
-
-        if ( cpu_has_lwp && (v->arch.xcr0 & XSTATE_LWP) )
-            /* Turn on available bit and other features specified in lwp_cfg. */
-            *eax = (*edx & v->arch.hvm_svm.guest_lwp_cfg) | 1;
-        else
-            *eax = 0;
-        break;
-
-    case 0x7:
-        ASSERT_UNREACHABLE();
-        /* Now handled in guest_cpuid(). */
-    }
-}
-
 bool hvm_check_cpuid_faulting(struct vcpu *v)
 {
     if ( !v->arch.cpuid_faulting )
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 47d313a..7bb42ac 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1019,279 +1019,6 @@ void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf,
     }
 }
 
-void pv_cpuid(struct cpu_user_regs *regs)
-{
-    uint32_t leaf, subleaf, a, b, c, d;
-    struct vcpu *curr = current;
-    struct domain *currd = curr->domain;
-    const struct cpuid_policy *p = currd->arch.cpuid;
-
-    leaf = a = regs->_eax;
-    b = regs->_ebx;
-    subleaf = c = regs->_ecx;
-    d = regs->_edx;
-
-    if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
-        domain_cpuid(currd, leaf, subleaf, &a, &b, &c, &d);
-    else
-        cpuid_count(leaf, subleaf, &a, &b, &c, &d);
-
-    switch ( leaf )
-    {
-        uint32_t tmp;
-
-    case 0x00000001:
-        c = p->basic._1c;
-        d = p->basic._1d;
-
-        if ( !is_pvh_domain(currd) )
-        {
-            /*
-             * Delete the PVH condition when HVMLite formally replaces PVH,
-             * and HVM guests no longer enter a PV codepath.
-             */
-
-            /*
-             * !!! OSXSAVE handling for PV guests is non-architectural !!!
-             *
-             * Architecturally, the correct code here is simply:
-             *
-             *   if ( curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE )
-             *       c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
-             *
-             * However because of bugs in Xen (before c/s bd19080b, Nov 2010,
-             * the XSAVE cpuid flag leaked into guests despite the feature not
-             * being available for use), buggy workarounds where introduced to
-             * Linux (c/s 947ccf9c, also Nov 2010) which relied on the fact
-             * that Xen also incorrectly leaked OSXSAVE into the guest.
-             *
-             * Furthermore, providing architectural OSXSAVE behaviour to a
-             * many Linux PV guests triggered a further kernel bug when the
-             * fpu code observes that XSAVEOPT is available, assumes that
-             * xsave state had been set up for the task, and follows a wild
-             * pointer.
-             *
-             * Older Linux PVOPS kernels however do require architectural
-             * behaviour.  They observe Xen's leaked OSXSAVE and assume they
-             * can already use XSETBV, dying with a #UD because the shadowed
-             * CR4.OSXSAVE is clear.  This behaviour has been adjusted in all
-             * observed cases via stable backports of the above changeset.
-             *
-             * Therefore, the leaking of Xen's OSXSAVE setting has become a
-             * defacto part of the PV ABI and can't reasonably be corrected.
-             * It can however be restricted to only the enlightened CPUID
-             * view, as seen by the guest kernel.
-             *
-             * The following situations and logic now applies:
-             *
-             * - Hardware without CPUID faulting support and native CPUID:
-             *    There is nothing Xen can do here.  The hosts XSAVE flag will
-             *    leak through and Xen's OSXSAVE choice will leak through.
-             *
-             *    In the case that the guest kernel has not set up OSXSAVE, only
-             *    SSE will be set in xcr0, and guest userspace can't do too much
-             *    damage itself.
-             *
-             * - Enlightened CPUID or CPUID faulting available:
-             *    Xen can fully control what is seen here.  Guest kernels need
-             *    to see the leaked OSXSAVE via the enlightened path, but
-             *    guest userspace and the native is given architectural
-             *    behaviour.
-             *
-             *    Emulated vs Faulted CPUID is distinguised based on whether a
-             *    #UD or #GP is currently being serviced.
-             */
-            /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
-            if ( (curr->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE) ||
-                 (regs->entry_vector == TRAP_invalid_op &&
-                  guest_kernel_mode(curr, regs) &&
-                  (read_cr4() & X86_CR4_OSXSAVE)) )
-                c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
-
-            /*
-             * At the time of writing, a PV domain is the only viable option
-             * for Dom0.  Several interactions between dom0 and Xen for real
-             * hardware setup have unfortunately been implemented based on
-             * state which incorrectly leaked into dom0.
-             *
-             * These leaks are retained for backwards compatibility, but
-             * restricted to the hardware domains kernel only.
-             */
-            if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) )
-            {
-                /*
-                 * MTRR used to unconditionally leak into PV guests.  They
-                 * cannot MTRR infrastructure at all, and shouldn't be able to
-                 * see the feature.
-                 *
-                 * Modern PVOPS Linux self-clobbers the MTRR feature, to avoid
-                 * trying to use the associated MSRs.  Xenolinux-based PV dom0's
-                 * however use the MTRR feature as an indication of the presence
-                 * of the XENPF_{add,del,read}_memtype hypercalls.
-                 */
-                if ( cpu_has_mtrr )
-                    d |= cpufeat_mask(X86_FEATURE_MTRR);
-
-                /*
-                 * MONITOR never leaked into PV guests, as PV guests cannot
-                 * use the MONITOR/MWAIT instructions.  As such, they require
-                 * the feature to not being present in emulated CPUID.
-                 *
-                 * Modern PVOPS Linux try to be cunning and use native CPUID
-                 * to see if the hardware actually supports MONITOR, and by
-                 * extension, deep C states.
-                 *
-                 * If the feature is seen, deep-C state information is
-                 * obtained from the DSDT and handed back to Xen via the
-                 * XENPF_set_processor_pminfo hypercall.
-                 *
-                 * This mechanism is incompatible with an HVM-based hardware
-                 * domain, and also with CPUID Faulting.
-                 *
-                 * Luckily, Xen can be just as 'cunning', and distinguish an
-                 * emulated CPUID from a faulted CPUID by whether a #UD or #GP
-                 * fault is currently being serviced.  Yuck...
-                 */
-                if ( cpu_has_monitor && regs->entry_vector == TRAP_gp_fault )
-                    c |= cpufeat_mask(X86_FEATURE_MONITOR);
-
-                /*
-                 * While MONITOR never leaked into PV guests, EIST always used
-                 * to.
-                 *
-                 * Modern PVOPS will only parse P state information from the
-                 * DSDT and return it to Xen if EIST is seen in the emulated
-                 * CPUID information.
-                 */
-                if ( cpu_has_eist )
-                    c |= cpufeat_mask(X86_FEATURE_EIST);
-            }
-        }
-
-        if ( vpmu_enabled(curr) &&
-             vpmu_is_set(vcpu_vpmu(curr), VPMU_CPU_HAS_DS) )
-        {
-            d |= cpufeat_mask(X86_FEATURE_DS);
-            if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
-                c |= cpufeat_mask(X86_FEATURE_DTES64);
-            if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
-                c |= cpufeat_mask(X86_FEATURE_DSCPL);
-        }
-        break;
-
-    case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
-        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-             !vpmu_enabled(curr) )
-            goto unsupported;
-
-        /* Report at most version 3 since that's all we currently emulate. */
-        if ( (a & 0xff) > 3 )
-            a = (a & ~0xff) | 3;
-        break;
-
-    case XSTATE_CPUID:
-        if ( !p->basic.xsave || subleaf >= 63 )
-            goto unsupported;
-        switch ( subleaf )
-        {
-        case 0:
-        {
-            uint64_t xfeature_mask = XSTATE_FP_SSE;
-            uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
-
-            if ( p->basic.avx )
-            {
-                xfeature_mask |= XSTATE_YMM;
-                xstate_size = (xstate_offsets[_XSTATE_YMM] +
-                               xstate_sizes[_XSTATE_YMM]);
-            }
-
-            if ( p->feat.avx512f )
-            {
-                xfeature_mask |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_OPMASK] +
-                                  xstate_sizes[_XSTATE_OPMASK]);
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_ZMM] +
-                                  xstate_sizes[_XSTATE_ZMM]);
-                xstate_size = max(xstate_size,
-                                  xstate_offsets[_XSTATE_HI_ZMM] +
-                                  xstate_sizes[_XSTATE_HI_ZMM]);
-            }
-
-            a = (uint32_t)xfeature_mask;
-            d = (uint32_t)(xfeature_mask >> 32);
-            c = xstate_size;
-
-            /*
-             * Always read CPUID.0xD[ECX=0].EBX from hardware, rather than
-             * domain policy.  It varies with enabled xstate, and the correct
-             * xcr0 is in context.
-             */
-            cpuid_count(leaf, subleaf, &tmp, &b, &tmp, &tmp);
-            break;
-        }
-
-        case 1:
-            a = p->xstate.Da1;
-            b = c = d = 0;
-            break;
-        }
-        break;
-
-    case 0x80000001:
-        c = p->extd.e1c;
-        d = p->extd.e1d;
-
-        /* If not emulating AMD, clear the duplicated features in e1d. */
-        if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
-            d &= ~CPUID_COMMON_1D_FEATURES;
-
-        /*
-         * MTRR used to unconditionally leak into PV guests.  They cannot MTRR
-         * infrastructure at all, and shouldn't be able to see the feature.
-         *
-         * Modern PVOPS Linux self-clobbers the MTRR feature, to avoid trying
-         * to use the associated MSRs.  Xenolinux-based PV dom0's however use
-         * the MTRR feature as an indication of the presence of the
-         * XENPF_{add,del,read}_memtype hypercalls.
-         */
-        if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) &&
-             cpu_has_mtrr )
-            d |= cpufeat_mask(X86_FEATURE_MTRR);
-        break;
-
-    case 0x80000007:
-        d = p->extd.e7d;
-        break;
-
-    case 0x80000008:
-        a = paddr_bits | (vaddr_bits << 8);
-        b = p->extd.e8b;
-        break;
-
-    case 0x00000005: /* MONITOR/MWAIT */
-    case 0x0000000b: /* Extended Topology Enumeration */
-    case 0x8000000a: /* SVM revision and features */
-    case 0x8000001b: /* Instruction Based Sampling */
-    case 0x8000001c: /* Light Weight Profiling */
-    case 0x8000001e: /* Extended topology reporting */
-    unsupported:
-        a = b = c = d = 0;
-        break;
-
-    case 0x7:
-        ASSERT_UNREACHABLE();
-        /* Now handled in guest_cpuid(). */
-    }
-
-    regs->rax = a;
-    regs->rbx = b;
-    regs->rcx = c;
-    regs->rdx = d;
-}
-
 static int emulate_invalid_rdtscp(struct cpu_user_regs *regs)
 {
     char opcode[3];
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 14b765e..04e67fe 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -392,8 +392,6 @@ bool hvm_set_guest_bndcfgs(struct vcpu *v, u64 val);
 #define has_viridian_apic_assist(d) \
     (is_viridian_domain(d) && (viridian_feature_mask(d) & HVMPV_apic_assist))
 
-void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
-                                   unsigned int *ecx, unsigned int *edx);
 bool hvm_check_cpuid_faulting(struct vcpu *v);
 void hvm_migrate_timers(struct vcpu *v);
 void hvm_do_resume(struct vcpu *v);
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 3e84164..b130f47 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -627,8 +627,6 @@ enum get_cpu_vendor {
 int get_cpu_vendor(uint32_t b, uint32_t c, uint32_t d, enum get_cpu_vendor mode);
 uint8_t get_cpu_family(uint32_t raw, uint8_t *model, uint8_t *stepping);
 
-void pv_cpuid(struct cpu_user_regs *regs);
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_X86_PROCESSOR_H */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2 25/25] x86/cpuid: Alter the legacy-path prototypes to match guest_cpuid()
  2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
                   ` (23 preceding siblings ...)
  2017-01-09 11:03 ` [PATCH v2 24/25] x86/cpuid: Effectively remove pv_cpuid() and hvm_cpuid() Andrew Cooper
@ 2017-01-09 11:03 ` Andrew Cooper
  24 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper

This allows the compiler to have a far easier time inlining the legacy paths
into guest_cpuid(), and avoids the need to have a full struct cpu_user_regs in
the guest_cpuid() stack frame.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <JBeulich@suse.com>
---
v2:
 * Reduce scope of guest_cpu_user_regs().
 * Drop unnecessary casts.
 * Consistently use uint32_t.
 * use cpuid_count_leaf() rather than opencoding it.
---
 xen/arch/x86/cpuid.c | 203 +++++++++++++++++++++------------------------------
 1 file changed, 82 insertions(+), 121 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 822f109..8482ece 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -350,33 +350,29 @@ int init_domain_cpuid_policy(struct domain *d)
     return 0;
 }
 
-static void pv_cpuid(struct cpu_user_regs *regs)
+static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
 {
-    uint32_t leaf, subleaf, a, b, c, d;
     struct vcpu *curr = current;
     struct domain *currd = curr->domain;
     const struct cpuid_policy *p = currd->arch.cpuid;
 
-    leaf = a = regs->_eax;
-    b = regs->_ebx;
-    subleaf = c = regs->_ecx;
-    d = regs->_edx;
-
     if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
-        domain_cpuid(currd, leaf, subleaf, &a, &b, &c, &d);
+        domain_cpuid(currd, leaf, subleaf, &res->a, &res->b, &res->c, &res->d);
     else
-        cpuid_count(leaf, subleaf, &a, &b, &c, &d);
+        cpuid_count_leaf(leaf, subleaf, res);
 
     switch ( leaf )
     {
         uint32_t tmp;
 
     case 0x00000001:
-        c = p->basic._1c;
-        d = p->basic._1d;
+        res->c = p->basic._1c;
+        res->d = p->basic._1d;
 
         if ( !is_pvh_domain(currd) )
         {
+            const struct cpu_user_regs *regs = guest_cpu_user_regs();
+
             /*
              * Delete the PVH condition when HVMLite formally replaces PVH,
              * and HVM guests no longer enter a PV codepath.
@@ -437,7 +433,7 @@ static void pv_cpuid(struct cpu_user_regs *regs)
                  (regs->entry_vector == TRAP_invalid_op &&
                   guest_kernel_mode(curr, regs) &&
                   (read_cr4() & X86_CR4_OSXSAVE)) )
-                c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
+                res->c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
 
             /*
              * At the time of writing, a PV domain is the only viable option
@@ -461,7 +457,7 @@ static void pv_cpuid(struct cpu_user_regs *regs)
                  * of the XENPF_{add,del,read}_memtype hypercalls.
                  */
                 if ( cpu_has_mtrr )
-                    d |= cpufeat_mask(X86_FEATURE_MTRR);
+                    res->d |= cpufeat_mask(X86_FEATURE_MTRR);
 
                 /*
                  * MONITOR never leaked into PV guests, as PV guests cannot
@@ -484,7 +480,7 @@ static void pv_cpuid(struct cpu_user_regs *regs)
                  * fault is currently being serviced.  Yuck...
                  */
                 if ( cpu_has_monitor && regs->entry_vector == TRAP_gp_fault )
-                    c |= cpufeat_mask(X86_FEATURE_MONITOR);
+                    res->c |= cpufeat_mask(X86_FEATURE_MONITOR);
 
                 /*
                  * While MONITOR never leaked into PV guests, EIST always used
@@ -495,18 +491,18 @@ static void pv_cpuid(struct cpu_user_regs *regs)
                  * CPUID information.
                  */
                 if ( cpu_has_eist )
-                    c |= cpufeat_mask(X86_FEATURE_EIST);
+                    res->c |= cpufeat_mask(X86_FEATURE_EIST);
             }
         }
 
         if ( vpmu_enabled(curr) &&
              vpmu_is_set(vcpu_vpmu(curr), VPMU_CPU_HAS_DS) )
         {
-            d |= cpufeat_mask(X86_FEATURE_DS);
+            res->d |= cpufeat_mask(X86_FEATURE_DS);
             if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
-                c |= cpufeat_mask(X86_FEATURE_DTES64);
+                res->c |= cpufeat_mask(X86_FEATURE_DTES64);
             if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
-                c |= cpufeat_mask(X86_FEATURE_DSCPL);
+                res->c |= cpufeat_mask(X86_FEATURE_DSCPL);
         }
         break;
 
@@ -516,8 +512,8 @@ static void pv_cpuid(struct cpu_user_regs *regs)
             goto unsupported;
 
         /* Report at most version 3 since that's all we currently emulate. */
-        if ( (a & 0xff) > 3 )
-            a = (a & ~0xff) | 3;
+        if ( (res->a & 0xff) > 3 )
+            res->a = (res->a & ~0xff) | 3;
         break;
 
     case XSTATE_CPUID:
@@ -551,33 +547,33 @@ static void pv_cpuid(struct cpu_user_regs *regs)
                                   xstate_sizes[_XSTATE_HI_ZMM]);
             }
 
-            a = (uint32_t)xfeature_mask;
-            d = (uint32_t)(xfeature_mask >> 32);
-            c = xstate_size;
+            res->a = xfeature_mask;
+            res->d = xfeature_mask >> 32;
+            res->c = xstate_size;
 
             /*
              * Always read CPUID.0xD[ECX=0].EBX from hardware, rather than
              * domain policy.  It varies with enabled xstate, and the correct
              * xcr0 is in context.
              */
-            cpuid_count(leaf, subleaf, &tmp, &b, &tmp, &tmp);
+            cpuid_count(leaf, subleaf, &tmp, &res->b, &tmp, &tmp);
             break;
         }
 
         case 1:
-            a = p->xstate.Da1;
-            b = c = d = 0;
+            res->a = p->xstate.Da1;
+            res->b = res->c = res->d = 0;
             break;
         }
         break;
 
     case 0x80000001:
-        c = p->extd.e1c;
-        d = p->extd.e1d;
+        res->c = p->extd.e1c;
+        res->d = p->extd.e1d;
 
         /* If not emulating AMD, clear the duplicated features in e1d. */
         if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
-            d &= ~CPUID_COMMON_1D_FEATURES;
+            res->d &= ~CPUID_COMMON_1D_FEATURES;
 
         /*
          * MTRR used to unconditionally leak into PV guests.  They cannot MTRR
@@ -588,18 +584,18 @@ static void pv_cpuid(struct cpu_user_regs *regs)
          * the MTRR feature as an indication of the presence of the
          * XENPF_{add,del,read}_memtype hypercalls.
          */
-        if ( is_hardware_domain(currd) && guest_kernel_mode(curr, regs) &&
-             cpu_has_mtrr )
-            d |= cpufeat_mask(X86_FEATURE_MTRR);
+        if ( is_hardware_domain(currd) && cpu_has_mtrr &&
+             guest_kernel_mode(curr, guest_cpu_user_regs()) )
+            res->d |= cpufeat_mask(X86_FEATURE_MTRR);
         break;
 
     case 0x80000007:
-        d = p->extd.e7d;
+        res->d = p->extd.e7d;
         break;
 
     case 0x80000008:
-        a = paddr_bits | (vaddr_bits << 8);
-        b = p->extd.e8b;
+        res->a = paddr_bits | (vaddr_bits << 8);
+        res->b = p->extd.e8b;
         break;
 
     case 0x00000005: /* MONITOR/MWAIT */
@@ -609,57 +605,42 @@ static void pv_cpuid(struct cpu_user_regs *regs)
     case 0x8000001c: /* Light Weight Profiling */
     case 0x8000001e: /* Extended topology reporting */
     unsupported:
-        a = b = c = d = 0;
+        *res = EMPTY_LEAF;
         break;
 
     case 0x7:
         ASSERT_UNREACHABLE();
         /* Now handled in guest_cpuid(). */
     }
-
-    regs->rax = a;
-    regs->rbx = b;
-    regs->rcx = c;
-    regs->rdx = d;
 }
 
-static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
-                      unsigned int *ecx, unsigned int *edx)
+static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
     const struct cpuid_policy *p = d->arch.cpuid;
-    unsigned int count, dummy = 0;
 
-    if ( !eax )
-        eax = &dummy;
-    if ( !ebx )
-        ebx = &dummy;
-    if ( !ecx )
-        ecx = &dummy;
-    count = *ecx;
-    if ( !edx )
-        edx = &dummy;
+    domain_cpuid(d, leaf, subleaf, &res->a, &res->b, &res->c, &res->d);
 
-    domain_cpuid(d, input, count, eax, ebx, ecx, edx);
-
-    switch ( input )
+    switch ( leaf )
     {
+        unsigned int tmp;
+
     case 0x1:
         /* Fix up VLAPIC details. */
-        *ebx &= 0x00FFFFFFu;
-        *ebx |= (v->vcpu_id * 2) << 24;
+        res->b &= 0x00FFFFFFu;
+        res->b |= (v->vcpu_id * 2) << 24;
 
-        *ecx = p->basic._1c;
-        *edx = p->basic._1d;
+        res->c = p->basic._1c;
+        res->d = p->basic._1d;
 
         /* APIC exposed to guests, but Fast-forward MSR_APIC_BASE.EN back in. */
         if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
+            res->d &= ~cpufeat_bit(X86_FEATURE_APIC);
 
         /* OSXSAVE clear in policy.  Fast-forward CR4 back in. */
         if ( v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE )
-            *ecx |= cpufeat_mask(X86_FEATURE_OSXSAVE);
+            res->c |= cpufeat_mask(X86_FEATURE_OSXSAVE);
 
         /*
          * PSE36 is not supported in shadow mode.  This bit should be
@@ -676,32 +657,32 @@ static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
          * PSE36 paging.
          */
         if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
+            res->d &= ~cpufeat_mask(X86_FEATURE_PSE36);
 
         if ( vpmu_enabled(v) &&
              vpmu_is_set(vcpu_vpmu(v), VPMU_CPU_HAS_DS) )
         {
-            *edx |= cpufeat_mask(X86_FEATURE_DS);
+            res->d |= cpufeat_mask(X86_FEATURE_DS);
             if ( cpu_has(&current_cpu_data, X86_FEATURE_DTES64) )
-                *ecx |= cpufeat_mask(X86_FEATURE_DTES64);
+                res->c |= cpufeat_mask(X86_FEATURE_DTES64);
             if ( cpu_has(&current_cpu_data, X86_FEATURE_DSCPL) )
-                *ecx |= cpufeat_mask(X86_FEATURE_DSCPL);
+                res->c |= cpufeat_mask(X86_FEATURE_DSCPL);
         }
 
         break;
 
     case 0xb:
         /* Fix the x2APIC identifier. */
-        *edx = v->vcpu_id * 2;
+        res->d = v->vcpu_id * 2;
         break;
 
     case XSTATE_CPUID:
-        if ( !p->basic.xsave || count >= 63 )
+        if ( !p->basic.xsave || subleaf >= 63 )
         {
-            *eax = *ebx = *ecx = *edx = 0;
+            *res = EMPTY_LEAF;
             break;
         }
-        switch ( count )
+        switch ( subleaf )
         {
         case 0:
         {
@@ -754,21 +735,21 @@ static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                   xstate_sizes[_XSTATE_LWP]);
             }
 
-            *eax = (uint32_t)xfeature_mask;
-            *edx = (uint32_t)(xfeature_mask >> 32);
-            *ecx = xstate_size;
+            res->a = xfeature_mask;
+            res->d = xfeature_mask >> 32;
+            res->c = xstate_size;
 
             /*
              * Always read CPUID[0xD,0].EBX from hardware, rather than domain
              * policy.  It varies with enabled xstate, and the correct xcr0 is
              * in context.
              */
-            cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
+            cpuid_count(leaf, subleaf, &tmp, &res->b, &tmp, &tmp);
             break;
         }
 
         case 1:
-            *eax = p->xstate.Da1;
+            res->a = p->xstate.Da1;
 
             if ( p->xstate.xsaves )
             {
@@ -777,12 +758,12 @@ static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                  * domain policy.  It varies with enabled xstate, and the
                  * correct xcr0/xss are in context.
                  */
-                cpuid_count(input, count, &dummy, ebx, &dummy, &dummy);
+                cpuid_count(leaf, subleaf, &tmp, &res->b, &tmp, &tmp);
             }
             else
-                *ebx = 0;
+                res->b = 0;
 
-            *ecx = *edx = 0;
+            res->c = res->d = 0;
             break;
         }
         break;
@@ -790,25 +771,25 @@ static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
         if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || !vpmu_enabled(v) )
         {
-            *eax = *ebx = *ecx = *edx = 0;
+            *res = EMPTY_LEAF;
             break;
         }
 
         /* Report at most version 3 since that's all we currently emulate */
-        if ( (*eax & 0xff) > 3 )
-            *eax = (*eax & ~0xff) | 3;
+        if ( (res->a & 0xff) > 3 )
+            res->a = (res->a & ~0xff) | 3;
         break;
 
     case 0x80000001:
-        *ecx = p->extd.e1c;
-        *edx = p->extd.e1d;
+        res->c = p->extd.e1c;
+        res->d = p->extd.e1d;
 
         /* If not emulating AMD, clear the duplicated features in e1d. */
         if ( d->arch.x86_vendor != X86_VENDOR_AMD )
-            *edx &= ~CPUID_COMMON_1D_FEATURES;
+            res->d &= ~CPUID_COMMON_1D_FEATURES;
         /* fast-forward MSR_APIC_BASE.EN if it hasn't already been clobbered. */
         else if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-            *edx &= ~cpufeat_bit(X86_FEATURE_APIC);
+            res->d &= ~cpufeat_bit(X86_FEATURE_APIC);
 
         /*
          * PSE36 is not supported in shadow mode.  This bit should be
@@ -825,46 +806,46 @@ static void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
          * PSE36 paging.
          */
         if ( !hap_enabled(d) && !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
-            *edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
+            res->d &= ~cpufeat_mask(X86_FEATURE_PSE36);
 
         /* SYSCALL is hidden outside of long mode on Intel. */
         if ( d->arch.x86_vendor == X86_VENDOR_INTEL &&
              !hvm_long_mode_enabled(v))
-            *edx &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
+            res->d &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
 
         break;
 
     case 0x80000007:
-        *edx = p->extd.e7d;
+        res->d = p->extd.e7d;
         break;
 
     case 0x80000008:
-        *eax &= 0xff;
-        count = d->arch.paging.gfn_bits + PAGE_SHIFT;
-        if ( *eax > count )
-            *eax = count;
+        res->a &= 0xff;
+        tmp = d->arch.paging.gfn_bits + PAGE_SHIFT;
+        if ( res->a > tmp )
+            res->a = tmp;
 
-        count = (p->basic.pae || p->basic.pse36) ? 36 : 32;
-        if ( *eax < count )
-            *eax = count;
+        tmp = (p->basic.pae || p->basic.pse36) ? 36 : 32;
+        if ( res->a < tmp )
+            res->a = tmp;
 
-        *eax |= (p->extd.lm ? vaddr_bits : 32) << 8;
+        res->a |= (p->extd.lm ? vaddr_bits : 32) << 8;
 
-        *ebx = p->extd.e8b;
+        res->b = p->extd.e8b;
         break;
 
     case 0x8000001c:
         if ( !cpu_has_svm )
         {
-            *eax = *ebx = *ecx = *edx = 0;
+            *res = EMPTY_LEAF;
             break;
         }
 
         if ( cpu_has_lwp && (v->arch.xcr0 & XSTATE_LWP) )
             /* Turn on available bit and other features specified in lwp_cfg. */
-            *eax = (*edx & v->arch.hvm_svm.guest_lwp_cfg) | 1;
+            res->a = (res->d & v->arch.hvm_svm.guest_lwp_cfg) | 1;
         else
-            *eax = 0;
+            res->a = 0;
         break;
 
     case 0x7:
@@ -969,27 +950,7 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
  legacy:
     /* {hvm,pv}_cpuid() have this expectation. */
     ASSERT(v == curr);
-
-    if ( is_hvm_domain(d) )
-    {
-        res->c = subleaf;
-
-        hvm_cpuid(leaf, &res->a, &res->b, &res->c, &res->d);
-    }
-    else
-    {
-        struct cpu_user_regs regs = *guest_cpu_user_regs();
-
-        regs._eax = leaf;
-        regs._ecx = subleaf;
-
-        pv_cpuid(&regs);
-
-        res->a = regs._eax;
-        res->b = regs._ebx;
-        res->c = regs._ecx;
-        res->d = regs._edx;
-    }
+    (is_hvm_domain(d) ? hvm_cpuid : pv_cpuid)(leaf, subleaf, res);
 }
 
 static void __init __maybe_unused build_assertions(void)
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate
  2017-01-09 11:03 ` [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate Andrew Cooper
@ 2017-01-09 11:35   ` Andrew Cooper
  2017-01-09 18:11     ` Stefano Stabellini
  2017-01-09 15:22   ` Jan Beulich
  1 sibling, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 11:35 UTC (permalink / raw)
  To: Xen-devel; +Cc: Julien Grall, Stefano Stabellini, Jan Beulich

On 09/01/17 11:03, Andrew Cooper wrote:
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 09d9959..fee4b17 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -115,6 +115,11 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
>  
>          return 0;
>      }
> +
> +    case XEN_DOMCTL_disable_migrate:
> +        d->disable_migrate = domctl->u.disable_migrate.disable;
> +        break;

Travis tells me I broke the ARM build with this.  (I thought I checked
locally).

Anyway, I have replaced the break with return 0; to match the prevailing
behaviour.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid()
  2017-01-09 11:03 ` [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid() Andrew Cooper
@ 2017-01-09 11:36   ` Paul Durrant
  2017-01-09 15:29   ` Jan Beulich
  1 sibling, 0 replies; 60+ messages in thread
From: Paul Durrant @ 2017-01-09 11:36 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

> -----Original Message-----
> From: Andrew Cooper [mailto:andrew.cooper3@citrix.com]
> Sent: 09 January 2017 11:03
> To: Xen-devel <xen-devel@lists.xen.org>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; Jan Beulich
> <JBeulich@suse.com>; Paul Durrant <Paul.Durrant@citrix.com>
> Subject: [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from
> guest_cpuid()
> 
> ... rather than from the legacy path.  Update the API to match guest_cpuid(),
> and remove its dependence on current.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Paul Durrant <paul.durrant@citrix.com>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Paul Durrant <paul.durrant@citrix.com>
> 
> v2:
>  * Introduce a break statement into guest_cpuid().
>  * Retain the explicit zeroing of SP and Service branch.
>  * Drop the EFER/SVM adjustment and leave the code as it was.
>  * Consistently use uint32_t.
> ---
>  xen/arch/x86/cpuid.c               | 12 +++++++
>  xen/arch/x86/hvm/hvm.c             |  3 --
>  xen/arch/x86/hvm/viridian.c        | 65 +++++++++++++++++++-----------------
> --
>  xen/include/asm-x86/hvm/viridian.h |  9 ++----
>  4 files changed, 46 insertions(+), 43 deletions(-)
> 
> diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
> index 0d54465..69a4f1b 100644
> --- a/xen/arch/x86/cpuid.c
> +++ b/xen/arch/x86/cpuid.c
> @@ -337,6 +337,18 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> 
>      *res = EMPTY_LEAF;
> 
> +    /*
> +     * First pass:
> +     * - Dispatch the virtualised leaves to their respective handlers.
> +     */
> +    switch ( leaf )
> +    {
> +    case 0x40000000 ... 0x400000ff:
> +        if ( is_viridian_domain(d) )
> +            return cpuid_viridian_leaves(v, leaf, subleaf, res);
> +        break;
> +    }
> +
>      /* {hvm,pv}_cpuid() have this expectation. */
>      ASSERT(v == curr);
> 
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 4c0f561..9ff5f92 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -3353,9 +3353,6 @@ void hvm_cpuid(unsigned int input, unsigned int
> *eax, unsigned int *ebx,
>      if ( !edx )
>          edx = &dummy;
> 
> -    if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
> -        return;
> -
>      if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
>          return;
> 
> diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c
> index f6abdd2..37c8f68 100644
> --- a/xen/arch/x86/hvm/viridian.c
> +++ b/xen/arch/x86/hvm/viridian.c
> @@ -66,77 +66,76 @@
>  #define CPUID6A_MSR_BITMAPS     (1 << 1)
>  #define CPUID6A_NESTED_PAGING   (1 << 3)
> 
> -int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax,
> -                          unsigned int *ebx, unsigned int *ecx,
> -                          unsigned int *edx)
> +void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
> +                           uint32_t subleaf, struct cpuid_leaf *res)
>  {
> -    struct domain *d = current->domain;
> +    const struct domain *d = v->domain;
> 
> -    if ( !is_viridian_domain(d) )
> -        return 0;
> +    ASSERT(is_viridian_domain(d));
> +    ASSERT(leaf >= 0x40000000 && leaf < 0x40000100);
> 
>      leaf -= 0x40000000;
> -    if ( leaf > 6 )
> -        return 0;
> 
> -    *eax = *ebx = *ecx = *edx = 0;
>      switch ( leaf )
>      {
>      case 0:
> -        *eax = 0x40000006; /* Maximum leaf */
> -        *ebx = 0x7263694d; /* Magic numbers  */
> -        *ecx = 0x666F736F;
> -        *edx = 0x76482074;
> +        res->a = 0x40000006; /* Maximum leaf */
> +        res->b = 0x7263694d; /* Magic numbers  */
> +        res->c = 0x666F736F;
> +        res->d = 0x76482074;
>          break;
> +
>      case 1:
> -        *eax = 0x31237648; /* Version number */
> +        res->a = 0x31237648; /* Version number */
>          break;
> +
>      case 2:
>          /* Hypervisor information, but only if the guest has set its
>             own version number. */
>          if ( d->arch.hvm_domain.viridian.guest_os_id.raw == 0 )
>              break;
> -        *eax = 1; /* Build number */
> -        *ebx = (xen_major_version() << 16) | xen_minor_version();
> -        *ecx = 0; /* SP */
> -        *edx = 0; /* Service branch and number */
> +        res->a = 1; /* Build number */
> +        res->b = (xen_major_version() << 16) | xen_minor_version();
> +        res->c = 0; /* SP */
> +        res->d = 0; /* Service branch and number */
>          break;
> +
>      case 3:
>          /* Which hypervisor MSRs are available to the guest */
> -        *eax = (CPUID3A_MSR_APIC_ACCESS |
> -                CPUID3A_MSR_HYPERCALL   |
> -                CPUID3A_MSR_VP_INDEX);
> +        res->a = (CPUID3A_MSR_APIC_ACCESS |
> +                  CPUID3A_MSR_HYPERCALL   |
> +                  CPUID3A_MSR_VP_INDEX);
>          if ( !(viridian_feature_mask(d) & HVMPV_no_freq) )
> -            *eax |= CPUID3A_MSR_FREQ;
> +            res->a |= CPUID3A_MSR_FREQ;
>          if ( viridian_feature_mask(d) & HVMPV_time_ref_count )
> -            *eax |= CPUID3A_MSR_TIME_REF_COUNT;
> +            res->a |= CPUID3A_MSR_TIME_REF_COUNT;
>          if ( viridian_feature_mask(d) & HVMPV_reference_tsc )
> -            *eax |= CPUID3A_MSR_REFERENCE_TSC;
> +            res->a |= CPUID3A_MSR_REFERENCE_TSC;
>          break;
> +
>      case 4:
>          /* Recommended hypercall usage. */
>          if ( (d->arch.hvm_domain.viridian.guest_os_id.raw == 0) ||
>               (d->arch.hvm_domain.viridian.guest_os_id.fields.os < 4) )
>              break;
> -        *eax = CPUID4A_RELAX_TIMER_INT;
> +        res->a = CPUID4A_RELAX_TIMER_INT;
>          if ( viridian_feature_mask(d) & HVMPV_hcall_remote_tlb_flush )
> -            *eax |= CPUID4A_HCALL_REMOTE_TLB_FLUSH;
> +            res->a |= CPUID4A_HCALL_REMOTE_TLB_FLUSH;
>          if ( !cpu_has_vmx_apic_reg_virt )
> -            *eax |= CPUID4A_MSR_BASED_APIC;
> -        *ebx = 2047; /* long spin count */
> +            res->a |= CPUID4A_MSR_BASED_APIC;
> +        res->b = 2047; /* long spin count */
>          break;
> +
>      case 6:
>          /* Detected and in use hardware features. */
>          if ( cpu_has_vmx_virtualize_apic_accesses )
> -            *eax |= CPUID6A_APIC_OVERLAY;
> +            res->a |= CPUID6A_APIC_OVERLAY;
>          if ( cpu_has_vmx_msr_bitmap || (read_efer() & EFER_SVME) )
> -            *eax |= CPUID6A_MSR_BITMAPS;
> +            res->a |= CPUID6A_MSR_BITMAPS;
>          if ( hap_enabled(d) )
> -            *eax |= CPUID6A_NESTED_PAGING;
> +            res->a |= CPUID6A_NESTED_PAGING;
>          break;
>      }
> -
> -    return 1;
>  }
> 
>  static void dump_guest_os_id(const struct domain *d)
> diff --git a/xen/include/asm-x86/hvm/viridian.h b/xen/include/asm-
> x86/hvm/viridian.h
> index bdbccd5..8c45d0f 100644
> --- a/xen/include/asm-x86/hvm/viridian.h
> +++ b/xen/include/asm-x86/hvm/viridian.h
> @@ -97,13 +97,8 @@ struct viridian_domain
>      union viridian_reference_tsc reference_tsc;
>  };
> 
> -int
> -cpuid_viridian_leaves(
> -    unsigned int leaf,
> -    unsigned int *eax,
> -    unsigned int *ebx,
> -    unsigned int *ecx,
> -    unsigned int *edx);
> +void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
> +                           uint32_t subleaf, struct cpuid_leaf *res);
> 
>  int
>  wrmsr_viridian_regs(
> --
> 2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
@ 2017-01-09 11:38   ` Paul Durrant
  2017-01-09 15:04   ` Jan Beulich
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 60+ messages in thread
From: Paul Durrant @ 2017-01-09 11:38 UTC (permalink / raw)
  To: Xen-devel
  Cc: Kevin Tian, Jan Beulich, Andrew Cooper, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

> -----Original Message-----
> From: Andrew Cooper [mailto:andrew.cooper3@citrix.com]
> Sent: 09 January 2017 11:03
> To: Xen-devel <xen-devel@lists.xen.org>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; Jan Beulich
> <JBeulich@suse.com>; Paul Durrant <Paul.Durrant@citrix.com>; Jun
> Nakajima <jun.nakajima@intel.com>; Kevin Tian <kevin.tian@intel.com>;
> Boris Ostrovsky <boris.ostrovsky@oracle.com>; Suravee Suthikulpanit
> <suravee.suthikulpanit@amd.com>
> Subject: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct
> cpuid_leaf
> 
> Longterm, pv_cpuid() and hvm_cpuid() will be merged into a single
> guest_cpuid(), which is also capable of working outside of current context.
> 
> To aid this transtion, introduce guest_cpuid() with the intended API, which
> simply defers back to pv_cpuid() or hvm_cpuid() as appropriate.
> 
> Introduce struct cpuid_leaf which is used to represent the results of a CPUID
> query in a more efficient mannor than passing four pointers through the
> calltree.
> 
> Update all codepaths which should use the new guest_cpuid() API.  These
> are
> the codepaths which have variable inputs, and (other than some specific
> x86_emulate() cases) all pertain to servicing a CPUID instruction from a
> guest.
> 
> The other codepaths using {pv,hvm}_cpuid() with fixed inputs will later be
> adjusted to read their data straight from the policy block.
> 
> No intended functional change.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Emulation changes...

Reviewed-by: Paul Durrant <paul.durrant@citrix.com>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Paul Durrant <paul.durrant@citrix.com>
> CC: Jun Nakajima <jun.nakajima@intel.com>
> CC: Kevin Tian <kevin.tian@intel.com>
> CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> ---
> v2:
>  * Rename res to cpuid_leaf in x86_emulate(), and make common to
> functions.
>  * Return lost const and newline in pv_emul_cpuid().
>  * Extra brackets around EMPTY_LEAF.
>  * Consistently use uint32_t.
>  * Tweak {hvm,pv}_cpuid() dispatch logic for a reduced delta later in the
> series.
> ---
>  tools/tests/x86_emulator/x86_emulate.c | 15 ++++-----
>  tools/tests/x86_emulator/x86_emulate.h | 60 ++++++++++++++++----------
> --------
>  xen/arch/x86/cpuid.c                   | 36 ++++++++++++++++++++
>  xen/arch/x86/hvm/emulate.c             | 10 ++----
>  xen/arch/x86/hvm/svm/svm.c             | 23 ++++++-------
>  xen/arch/x86/hvm/vmx/vmx.c             | 35 ++++++--------------
>  xen/arch/x86/traps.c                   | 25 +++++++-------
>  xen/arch/x86/x86_emulate/x86_emulate.c | 34 +++++++++----------
>  xen/arch/x86/x86_emulate/x86_emulate.h | 12 ++++---
>  xen/include/asm-x86/cpuid.h            |  4 +++
>  xen/include/asm-x86/hvm/emulate.h      |  8 ++---
>  xen/include/asm-x86/mm.h               |  4 +--
>  12 files changed, 137 insertions(+), 129 deletions(-)
> 
> diff --git a/tools/tests/x86_emulator/x86_emulate.c
> b/tools/tests/x86_emulator/x86_emulate.c
> index d48f78a..2e8dfbf 100644
> --- a/tools/tests/x86_emulator/x86_emulate.c
> +++ b/tools/tests/x86_emulator/x86_emulate.c
> @@ -41,22 +41,21 @@ bool emul_test_make_stack_executable(void)
>  }
> 
>  int emul_test_cpuid(
> -    unsigned int *eax,
> -    unsigned int *ebx,
> -    unsigned int *ecx,
> -    unsigned int *edx,
> +    uint32_t leaf,
> +    uint32_t subleaf,
> +    struct cpuid_leaf *res,
>      struct x86_emulate_ctxt *ctxt)
>  {
> -    unsigned int leaf = *eax;
> -
> -    asm ("cpuid" : "+a" (*eax), "+c" (*ecx), "=d" (*edx), "=b" (*ebx));
> +    asm ("cpuid"
> +         : "=a" (res->a), "=b" (res->b), "=c" (res->c), "=d" (res->d)
> +         : "a" (leaf), "c" (subleaf));
> 
>      /*
>       * The emulator doesn't itself use MOVBE, so we can always run the
>       * respective tests.
>       */
>      if ( leaf == 1 )
> -        *ecx |= 1U << 22;
> +        res->c |= 1U << 22;
> 
>      return X86EMUL_OKAY;
>  }
> diff --git a/tools/tests/x86_emulator/x86_emulate.h
> b/tools/tests/x86_emulator/x86_emulate.h
> index c14c613..8bc2e43 100644
> --- a/tools/tests/x86_emulator/x86_emulate.h
> +++ b/tools/tests/x86_emulator/x86_emulate.h
> @@ -58,61 +58,59 @@ static inline uint64_t xgetbv(uint32_t xcr)
>  }
> 
>  #define cache_line_size() ({		     \
> -    unsigned int eax = 1, ebx, ecx = 0, edx; \
> -    emul_test_cpuid(&eax, &ebx, &ecx, &edx, NULL); \
> -    edx & (1U << 19) ? (ebx >> 5) & 0x7f8 : 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    res.d & (1U << 19) ? (res.b >> 5) & 0x7f8 : 0; \
>  })
> 
>  #define cpu_has_mmx ({ \
> -    unsigned int eax = 1, ecx = 0, edx; \
> -    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
> -    (edx & (1U << 23)) != 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    (res.d & (1U << 23)) != 0; \
>  })
> 
>  #define cpu_has_sse ({ \
> -    unsigned int eax = 1, ecx = 0, edx; \
> -    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
> -    (edx & (1U << 25)) != 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    (res.d & (1U << 25)) != 0; \
>  })
> 
>  #define cpu_has_sse2 ({ \
> -    unsigned int eax = 1, ecx = 0, edx; \
> -    emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
> -    (edx & (1U << 26)) != 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    (res.d & (1U << 26)) != 0; \
>  })
> 
>  #define cpu_has_xsave ({ \
> -    unsigned int eax = 1, ecx = 0; \
> -    emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
>      /* Intentionally checking OSXSAVE here. */ \
> -    (ecx & (1U << 27)) != 0; \
> +    (res.c & (1U << 27)) != 0; \
>  })
> 
>  #define cpu_has_avx ({ \
> -    unsigned int eax = 1, ecx = 0; \
> -    emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
> -    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
> -        ecx = 0; \
> -    (ecx & (1U << 28)) != 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
> +        res.c = 0; \
> +    (res.c & (1U << 28)) != 0; \
>  })
> 
>  #define cpu_has_avx2 ({ \
> -    unsigned int eax = 1, ebx, ecx = 0; \
> -    emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
> -    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
> -        ebx = 0; \
> +    struct cpuid_leaf res; \
> +    emul_test_cpuid(1, 0, &res, NULL); \
> +    if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
> +        res.b = 0; \
>      else { \
> -        eax = 7, ecx = 0; \
> -        emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
> +        emul_test_cpuid(7, 0, &res, NULL); \
>      } \
> -    (ebx & (1U << 5)) != 0; \
> +    (res.b & (1U << 5)) != 0; \
>  })
> 
>  int emul_test_cpuid(
> -    unsigned int *eax,
> -    unsigned int *ebx,
> -    unsigned int *ecx,
> -    unsigned int *edx,
> +    uint32_t leaf,
> +    uint32_t subleaf,
> +    struct cpuid_leaf *res,
>      struct x86_emulate_ctxt *ctxt);
> 
>  int emul_test_read_cr(
> diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
> index 3e85a63..f3491ed 100644
> --- a/xen/arch/x86/cpuid.c
> +++ b/xen/arch/x86/cpuid.c
> @@ -1,5 +1,6 @@
>  #include <xen/init.h>
>  #include <xen/lib.h>
> +#include <xen/sched.h>
>  #include <asm/cpuid.h>
>  #include <asm/hvm/hvm.h>
>  #include <asm/hvm/vmx/vmcs.h>
> @@ -17,6 +18,8 @@ uint32_t __read_mostly raw_featureset[FSCAPINTS];
>  uint32_t __read_mostly pv_featureset[FSCAPINTS];
>  uint32_t __read_mostly hvm_featureset[FSCAPINTS];
> 
> +#define EMPTY_LEAF ((struct cpuid_leaf){})
> +
>  static void __init sanitise_featureset(uint32_t *fs)
>  {
>      /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
> @@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t
> feature)
>      return NULL;
>  }
> 
> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> +                 uint32_t subleaf, struct cpuid_leaf *res)
> +{
> +    const struct vcpu *curr = current;
> +    const struct domain *d = v->domain;
> +
> +    *res = EMPTY_LEAF;
> +
> +    /* {hvm,pv}_cpuid() have this expectation. */
> +    ASSERT(v == curr);
> +
> +    if ( is_hvm_domain(d) )
> +    {
> +        res->c = subleaf;
> +
> +        hvm_cpuid(leaf, &res->a, &res->b, &res->c, &res->d);
> +    }
> +    else
> +    {
> +        struct cpu_user_regs regs = *guest_cpu_user_regs();
> +
> +        regs._eax = leaf;
> +        regs._ecx = subleaf;
> +
> +        pv_cpuid(&regs);
> +
> +        res->a = regs._eax;
> +        res->b = regs._ebx;
> +        res->c = regs._ecx;
> +        res->d = regs._edx;
> +    }
> +}
> +
>  static void __init __maybe_unused build_assertions(void)
>  {
>      BUILD_BUG_ON(ARRAY_SIZE(known_features) != FSCAPINTS);
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index 41bd4f5..ecbac4b 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -1552,12 +1552,8 @@ static int hvmemul_wbinvd(
>      return X86EMUL_OKAY;
>  }
> 
> -int hvmemul_cpuid(
> -    unsigned int *eax,
> -    unsigned int *ebx,
> -    unsigned int *ecx,
> -    unsigned int *edx,
> -    struct x86_emulate_ctxt *ctxt)
> +int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
> +                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
>  {
>      /*
>       * x86_emulate uses this function to query CPU features for its own
> internal
> @@ -1568,7 +1564,7 @@ int hvmemul_cpuid(
>           hvm_check_cpuid_faulting(current) )
>          return X86EMUL_EXCEPTION;
> 
> -    hvm_cpuid(*eax, eax, ebx, ecx, edx);
> +    guest_cpuid(current, leaf, subleaf, res);
>      return X86EMUL_OKAY;
>  }
> 
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 04a7b60..6fb1cbc 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1572,23 +1572,20 @@ static void svm_fpu_dirty_intercept(void)
> 
>  static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
>  {
> -    unsigned int eax, ebx, ecx, edx, inst_len;
> +    struct vcpu *curr = current;
> +    unsigned int inst_len;
> +    struct cpuid_leaf res;
> 
> -    if ( (inst_len = __get_instruction_length(current, INSTR_CPUID)) == 0 )
> +    if ( (inst_len = __get_instruction_length(curr, INSTR_CPUID)) == 0 )
>          return;
> 
> -    eax = regs->_eax;
> -    ebx = regs->_ebx;
> -    ecx = regs->_ecx;
> -    edx = regs->_edx;
> -
> -    hvm_cpuid(regs->_eax, &eax, &ebx, &ecx, &edx);
> -    HVMTRACE_5D(CPUID, regs->_eax, eax, ebx, ecx, edx);
> +    guest_cpuid(curr, regs->_eax, regs->_ecx, &res);
> +    HVMTRACE_5D(CPUID, regs->_eax, res.a, res.b, res.c, res.d);
> 
> -    regs->rax = eax;
> -    regs->rbx = ebx;
> -    regs->rcx = ecx;
> -    regs->rdx = edx;
> +    regs->rax = res.a;
> +    regs->rbx = res.b;
> +    regs->rcx = res.c;
> +    regs->rdx = res.d;
> 
>      __update_guest_eip(regs, inst_len);
>  }
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index e75b190..01c225f 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2361,8 +2361,9 @@ static void vmx_fpu_dirty_intercept(void)
> 
>  static int vmx_do_cpuid(struct cpu_user_regs *regs)
>  {
> -    unsigned int eax, ebx, ecx, edx;
> -    unsigned int leaf, subleaf;
> +    struct vcpu *curr = current;
> +    unsigned int leaf = regs->_eax, subleaf = regs->_ecx;
> +    struct cpuid_leaf res;
> 
>      if ( hvm_check_cpuid_faulting(current) )
>      {
> @@ -2370,21 +2371,13 @@ static int vmx_do_cpuid(struct cpu_user_regs
> *regs)
>          return 1;  /* Don't advance the guest IP! */
>      }
> 
> -    eax = regs->_eax;
> -    ebx = regs->_ebx;
> -    ecx = regs->_ecx;
> -    edx = regs->_edx;
> -
> -    leaf = regs->_eax;
> -    subleaf = regs->_ecx;
> +    guest_cpuid(curr, leaf, subleaf, &res);
> +    HVMTRACE_5D(CPUID, leaf, res.a, res.b, res.c, res.d);
> 
> -    hvm_cpuid(leaf, &eax, &ebx, &ecx, &edx);
> -    HVMTRACE_5D(CPUID, leaf, eax, ebx, ecx, edx);
> -
> -    regs->rax = eax;
> -    regs->rbx = ebx;
> -    regs->rcx = ecx;
> -    regs->rdx = edx;
> +    regs->rax = res.a;
> +    regs->rbx = res.b;
> +    regs->rcx = res.c;
> +    regs->rdx = res.d;
> 
>      return hvm_monitor_cpuid(get_instruction_length(), leaf, subleaf);
>  }
> @@ -3559,15 +3552,7 @@ void vmx_vmexit_handler(struct cpu_user_regs
> *regs)
>      }
>      case EXIT_REASON_CPUID:
>      {
> -        int rc;
> -
> -        if ( is_pvh_vcpu(v) )
> -        {
> -            pv_cpuid(regs);
> -            rc = 0;
> -        }
> -        else
> -            rc = vmx_do_cpuid(regs);
> +        int rc = vmx_do_cpuid(regs);
> 
>          /*
>           * rc < 0 error in monitor/vm_event, crash
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index e45ff71..3acc244 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -1412,6 +1412,7 @@ static int emulate_forced_invalid_op(struct
> cpu_user_regs *regs)
>  {
>      char sig[5], instr[2];
>      unsigned long eip, rc;
> +    struct cpuid_leaf res;
> 
>      eip = regs->rip;
> 
> @@ -1444,7 +1445,12 @@ static int emulate_forced_invalid_op(struct
> cpu_user_regs *regs)
> 
>      eip += sizeof(instr);
> 
> -    pv_cpuid(regs);
> +    guest_cpuid(current, regs->_eax, regs->_ecx, &res);
> +
> +    regs->rax = res.a;
> +    regs->rbx = res.b;
> +    regs->rcx = res.c;
> +    regs->rdx = res.d;
> 
>      instruction_done(regs, eip);
> 
> @@ -3254,10 +3260,10 @@ static int priv_op_wbinvd(struct
> x86_emulate_ctxt *ctxt)
>      return X86EMUL_OKAY;
>  }
> 
> -int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
> -                  unsigned int *edx, struct x86_emulate_ctxt *ctxt)
> +int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
> +                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
>  {
> -    struct cpu_user_regs regs = *ctxt->regs;
> +    const struct vcpu *curr = current;
> 
>      /*
>       * x86_emulate uses this function to query CPU features for its own
> @@ -3266,7 +3272,6 @@ int pv_emul_cpuid(unsigned int *eax, unsigned int
> *ebx, unsigned int *ecx,
>       */
>      if ( ctxt->opcode == X86EMUL_OPC(0x0f, 0xa2) )
>      {
> -        const struct vcpu *curr = current;
> 
>          /* If cpuid faulting is enabled and CPL>0 leave the #GP untouched. */
>          if ( curr->arch.cpuid_faulting &&
> @@ -3274,15 +3279,7 @@ int pv_emul_cpuid(unsigned int *eax, unsigned
> int *ebx, unsigned int *ecx,
>              return X86EMUL_EXCEPTION;
>      }
> 
> -    regs._eax = *eax;
> -    regs._ecx = *ecx;
> -
> -    pv_cpuid(&regs);
> -
> -    *eax = regs._eax;
> -    *ebx = regs._ebx;
> -    *ecx = regs._ecx;
> -    *edx = regs._edx;
> +    guest_cpuid(curr, leaf, subleaf, res);
> 
>      return X86EMUL_OKAY;
>  }
> diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c
> b/xen/arch/x86/x86_emulate/x86_emulate.c
> index 98ba7c5..3dbc3ce 100644
> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
> @@ -1265,19 +1265,19 @@ static bool vcpu_has(
>      struct x86_emulate_ctxt *ctxt,
>      const struct x86_emulate_ops *ops)
>  {
> -    unsigned int ebx = 0, ecx = 0, edx = 0;
> +    struct cpuid_leaf res;
>      int rc = X86EMUL_OKAY;
> 
>      fail_if(!ops->cpuid);
> -    rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
> +    rc = ops->cpuid(eax, 0, &res, ctxt);
>      if ( rc == X86EMUL_OKAY )
>      {
>          switch ( reg )
>          {
> -        case EAX: reg = eax; break;
> -        case EBX: reg = ebx; break;
> -        case ECX: reg = ecx; break;
> -        case EDX: reg = edx; break;
> +        case EAX: reg = res.a; break;
> +        case EBX: reg = res.b; break;
> +        case ECX: reg = res.c; break;
> +        case EDX: reg = res.d; break;
>          default: BUG();
>          }
>          if ( !(reg & (1U << bit)) )
> @@ -2722,6 +2722,7 @@ x86_emulate(
>      {
>          enum x86_segment seg;
>          struct segment_register cs, sreg;
> +        struct cpuid_leaf cpuid_leaf;
> 
>      case 0x00 ... 0x05: add: /* add */
>          emulate_2op_SrcV("add", src, dst, _regs._eflags);
> @@ -4525,15 +4526,14 @@ x86_emulate(
> 
>          case 0xfc: /* clzero */
>          {
> -            unsigned int eax = 1, ebx = 0, dummy = 0;
>              unsigned long zero = 0;
> 
>              base = ad_bytes == 8 ? _regs.r(ax) :
>                     ad_bytes == 4 ? _regs._eax : _regs.ax;
>              limit = 0;
>              if ( vcpu_has_clflush() &&
> -                 ops->cpuid(&eax, &ebx, &dummy, &dummy, ctxt) ==
> X86EMUL_OKAY )
> -                limit = ((ebx >> 8) & 0xff) * 8;
> +                 ops->cpuid(1, 0, &cpuid_leaf, ctxt) == X86EMUL_OKAY )
> +                limit = ((cpuid_leaf.b >> 8) & 0xff) * 8;
>              generate_exception_if(limit < sizeof(long) ||
>                                    (limit & (limit - 1)), EXC_UD);
>              base &= ~(limit - 1);
> @@ -5265,22 +5265,18 @@ x86_emulate(
>          dst.val = test_cc(b, _regs._eflags);
>          break;
> 
> -    case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */ {
> -        unsigned int eax = _regs._eax, ebx = _regs._ebx;
> -        unsigned int ecx = _regs._ecx, edx = _regs._edx;
> -
> +    case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */
>          fail_if(ops->cpuid == NULL);
> -        rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
> +        rc = ops->cpuid(_regs._eax, _regs._ecx, &cpuid_leaf, ctxt);
>          generate_exception_if(rc == X86EMUL_EXCEPTION,
>                                EXC_GP, 0); /* CPUID Faulting? */
>          if ( rc != X86EMUL_OKAY )
>              goto done;
> -        _regs.r(ax) = eax;
> -        _regs.r(bx) = ebx;
> -        _regs.r(cx) = ecx;
> -        _regs.r(dx) = edx;
> +        _regs.r(ax) = cpuid_leaf.a;
> +        _regs.r(bx) = cpuid_leaf.b;
> +        _regs.r(cx) = cpuid_leaf.c;
> +        _regs.r(dx) = cpuid_leaf.d;
>          break;
> -    }
> 
>      case X86EMUL_OPC(0x0f, 0xa3): bt: /* bt */
>          emulate_2op_SrcV_nobyte("bt", src, dst, _regs._eflags);
> diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h
> b/xen/arch/x86/x86_emulate/x86_emulate.h
> index 43c0c5e..57ebfde 100644
> --- a/xen/arch/x86/x86_emulate/x86_emulate.h
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.h
> @@ -164,6 +164,11 @@ enum x86_emulate_fpu_type {
>      X86EMUL_FPU_ymm  /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
>  };
> 
> +struct cpuid_leaf
> +{
> +    uint32_t a, b, c, d;
> +};
> +
>  struct x86_emulate_state;
> 
>  /*
> @@ -415,10 +420,9 @@ struct x86_emulate_ops
>       * #GP[0].  Used to implement CPUID faulting.
>       */
>      int (*cpuid)(
> -        unsigned int *eax,
> -        unsigned int *ebx,
> -        unsigned int *ecx,
> -        unsigned int *edx,
> +        uint32_t leaf,
> +        uint32_t subleaf,
> +        struct cpuid_leaf *res,
>          struct x86_emulate_ctxt *ctxt);
> 
>      /*
> diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
> index 05f2c9a..4586c7d 100644
> --- a/xen/include/asm-x86/cpuid.h
> +++ b/xen/include/asm-x86/cpuid.h
> @@ -17,6 +17,7 @@
> 
>  #ifndef __ASSEMBLY__
>  #include <xen/types.h>
> +#include <asm/x86_emulate.h>
>  #include <public/sysctl.h>
> 
>  extern const uint32_t known_features[FSCAPINTS];
> @@ -64,6 +65,9 @@ extern struct cpuidmasks cpuidmask_defaults;
>  /* Whether or not cpuid faulting is available for the current domain. */
>  DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
> 
> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> +                 uint32_t subleaf, struct cpuid_leaf *res);
> +
>  #endif /* __ASSEMBLY__ */
>  #endif /* !__X86_CPUID_H__ */
> 
> diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-
> x86/hvm/emulate.h
> index 68a95e4..83266bb 100644
> --- a/xen/include/asm-x86/hvm/emulate.h
> +++ b/xen/include/asm-x86/hvm/emulate.h
> @@ -57,12 +57,8 @@ void hvm_emulate_init_per_insn(
>      unsigned int insn_bytes);
>  void hvm_emulate_writeback(
>      struct hvm_emulate_ctxt *hvmemul_ctxt);
> -int hvmemul_cpuid(
> -    unsigned int *eax,
> -    unsigned int *ebx,
> -    unsigned int *ecx,
> -    unsigned int *edx,
> -    struct x86_emulate_ctxt *ctxt);
> +int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
> +                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
>  struct segment_register *hvmemul_get_seg_reg(
>      enum x86_segment seg,
>      struct hvm_emulate_ctxt *hvmemul_ctxt);
> diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
> index a15029c..93a073d 100644
> --- a/xen/include/asm-x86/mm.h
> +++ b/xen/include/asm-x86/mm.h
> @@ -504,8 +504,8 @@ extern int mmcfg_intercept_write(enum
> x86_segment seg,
>                                   void *p_data,
>                                   unsigned int bytes,
>                                   struct x86_emulate_ctxt *ctxt);
> -int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
> -                  unsigned int *edx, struct x86_emulate_ctxt *ctxt);
> +int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
> +                  struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
> 
>  int  ptwr_do_page_fault(struct vcpu *, unsigned long,
>                          struct cpu_user_regs *);
> --
> 2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
  2017-01-09 11:38   ` Paul Durrant
@ 2017-01-09 15:04   ` Jan Beulich
  2017-01-09 15:09     ` Andrew Cooper
  2017-01-09 23:31   ` Boris Ostrovsky
  2017-01-11  5:47   ` Tian, Kevin
  3 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 15:04 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Kevin Tian, Suravee Suthikulpanit, Xen-devel, Paul Durrant,
	Jun Nakajima, Boris Ostrovsky

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> @@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
>      return NULL;
>  }
>  
> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> +                 uint32_t subleaf, struct cpuid_leaf *res)
> +{
> +    const struct vcpu *curr = current;
> +    const struct domain *d = v->domain;
> +
> +    *res = EMPTY_LEAF;
> +
> +    /* {hvm,pv}_cpuid() have this expectation. */
> +    ASSERT(v == curr);

You don't appear to use curr other than here, so I'd prefer if you
eliminated the local variable.

> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2361,8 +2361,9 @@ static void vmx_fpu_dirty_intercept(void)
>  
>  static int vmx_do_cpuid(struct cpu_user_regs *regs)
>  {
> -    unsigned int eax, ebx, ecx, edx;
> -    unsigned int leaf, subleaf;
> +    struct vcpu *curr = current;
> +    unsigned int leaf = regs->_eax, subleaf = regs->_ecx;

According to "Consistently use uint32_t" I'd have expected this to
now be uint32_t too.

In any event
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 15:04   ` Jan Beulich
@ 2017-01-09 15:09     ` Andrew Cooper
  2017-01-09 15:40       ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 15:09 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Suravee Suthikulpanit, Xen-devel, Paul Durrant,
	Jun Nakajima, Boris Ostrovsky

On 09/01/17 15:04, Jan Beulich wrote:
>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>> @@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
>>      return NULL;
>>  }
>>  
>> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>> +                 uint32_t subleaf, struct cpuid_leaf *res)
>> +{
>> +    const struct vcpu *curr = current;
>> +    const struct domain *d = v->domain;
>> +
>> +    *res = EMPTY_LEAF;
>> +
>> +    /* {hvm,pv}_cpuid() have this expectation. */
>> +    ASSERT(v == curr);
> You don't appear to use curr other than here, so I'd prefer if you
> eliminated the local variable.

Further uses are added in future changesets.

>
>> --- a/xen/arch/x86/hvm/vmx/vmx.c
>> +++ b/xen/arch/x86/hvm/vmx/vmx.c
>> @@ -2361,8 +2361,9 @@ static void vmx_fpu_dirty_intercept(void)
>>  
>>  static int vmx_do_cpuid(struct cpu_user_regs *regs)
>>  {
>> -    unsigned int eax, ebx, ecx, edx;
>> -    unsigned int leaf, subleaf;
>> +    struct vcpu *curr = current;
>> +    unsigned int leaf = regs->_eax, subleaf = regs->_ecx;
> According to "Consistently use uint32_t" I'd have expected this to
> now be uint32_t too.

Will fix.

>
> In any event
> Reviewed-by: Jan Beulich <jbeulich@suse.com>

Thanks.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy
  2017-01-09 11:03 ` [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy Andrew Cooper
@ 2017-01-09 15:15   ` Jan Beulich
  2017-01-09 16:08     ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 15:15 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> @@ -67,6 +80,58 @@ static void __init sanitise_featureset(uint32_t *fs)
>                            (fs[FEATURESET_e1d] & ~CPUID_COMMON_1D_FEATURES));
>  }
>  
> +static void __init calculate_raw_policy(void)
> +{
> +    struct cpuid_policy *p = &raw_policy;
> +    unsigned int i;
> +
> +    cpuid_leaf(0, &p->basic.raw[0]);
> +    for ( i = 1; i < min(ARRAY_SIZE(p->basic.raw),
> +                         p->basic.max_leaf + 1ul); ++i )
> +    {
> +        switch ( i )
> +        {
> +        case 0x2: case 0x4: case 0x7: case 0xd:
> +            /* Multi-invocation leaves.  Deferred. */
> +            continue;
> +        }
> +
> +        cpuid_leaf(i, &p->basic.raw[i]);
> +    }
> +
> +    if ( p->basic.max_leaf >= 7 )
> +    {
> +        cpuid_count_leaf(7, 0, &p->feat.raw[0]);
> +
> +        for ( i = 1; i < min(ARRAY_SIZE(p->feat.raw),
> +                             p->feat.max_subleaf + 1ul); ++i )
> +            cpuid_count_leaf(7, i, &p->feat.raw[i]);
> +    }
> +
> +    if ( p->basic.max_leaf >= 0xd )
> +    {
> +        uint64_t xstates;
> +
> +        cpuid_count_leaf(0xd, 0, &p->xstate.raw[0]);
> +        cpuid_count_leaf(0xd, 1, &p->xstate.raw[1]);
> +
> +        xstates = ((uint64_t)(p->xstate.xcr0_high | p->xstate.xss_high) << 32) |
> +            (p->xstate.xcr0_low | p->xstate.xss_low);
> +
> +        for ( i = 2; i < 63; ++i )

Perhaps better to use ARRAY_SIZE() (or min()) here, too?

> +        {
> +            if ( xstates & (1ul << i) )
> +                cpuid_count_leaf(0xd, i, &p->xstate.raw[i]);
> +        }

Also, overall in this code block I think you should really use
XSTATE_CPUID instead of 0xd.

> +    }
> +
> +    /* Extended leaves. */
> +    cpuid_leaf(0x80000000, &p->extd.raw[0]);
> +    for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
> +                         p->extd.max_leaf + 1 - 0x80000000ul); ++i )

Would it be worthwhile to make the code resilient to max_leaf not
having the high bit set?

Once again in any event
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate
  2017-01-09 11:03 ` [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate Andrew Cooper
  2017-01-09 11:35   ` Andrew Cooper
@ 2017-01-09 15:22   ` Jan Beulich
  1 sibling, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 15:22 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: JulienGrall, Stefano Stabellini, Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -51,6 +51,30 @@ static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
>  static void update_domain_cpuid_info(struct domain *d,
>                                       const xen_domctl_cpuid_t *ctl)
>  {
> +    struct cpuid_policy *p = d->arch.cpuid;
> +    const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
> +
> +    /* Insert ctl data into cpuid_policy. */
> +    if ( ctl->input[0] < ARRAY_SIZE(p->basic.raw) )
> +    {
> +        if ( ctl->input[0] == 7 )
> +        {
> +            if ( ctl->input[1] < ARRAY_SIZE(p->feat.raw) )
> +                p->feat.raw[ctl->input[1]] = leaf;
> +        }
> +        else if ( ctl->input[0] == 0xd )

XSTATE_CPUID again?

Reviewed-by: Jan Beulich <jbeulich@suse.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid()
  2017-01-09 11:03 ` [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid() Andrew Cooper
  2017-01-09 11:36   ` Paul Durrant
@ 2017-01-09 15:29   ` Jan Beulich
  1 sibling, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 15:29 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Paul Durrant, Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> ... rather than from the legacy path.  Update the API to match guest_cpuid(),
> and remove its dependence on current.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 15:09     ` Andrew Cooper
@ 2017-01-09 15:40       ` Jan Beulich
  2017-01-09 15:45         ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 15:40 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Kevin Tian, Suravee Suthikulpanit, Xen-devel, Paul Durrant,
	Jun Nakajima, Boris Ostrovsky

>>> On 09.01.17 at 16:09, <andrew.cooper3@citrix.com> wrote:
> On 09/01/17 15:04, Jan Beulich wrote:
>>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>>> @@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t 
> feature)
>>>      return NULL;
>>>  }
>>>  
>>> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>>> +                 uint32_t subleaf, struct cpuid_leaf *res)
>>> +{
>>> +    const struct vcpu *curr = current;
>>> +    const struct domain *d = v->domain;
>>> +
>>> +    *res = EMPTY_LEAF;
>>> +
>>> +    /* {hvm,pv}_cpuid() have this expectation. */
>>> +    ASSERT(v == curr);
>> You don't appear to use curr other than here, so I'd prefer if you
>> eliminated the local variable.
> 
> Further uses are added in future changesets.

Well, having both v and curr available in a function is likely going to
be (a little) confusing, especially if you mean to use curr (and hence
apparently ignore the passed in argument). I'd prefer if you ditched
curr, compared v against current, and used v throughout the
function (perhaps in anticipation of the expectation above to go
away eventually).

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 15:40       ` Jan Beulich
@ 2017-01-09 15:45         ` Andrew Cooper
  0 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 15:45 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Suravee Suthikulpanit, Xen-devel, Paul Durrant,
	Jun Nakajima, Boris Ostrovsky

On 09/01/17 15:40, Jan Beulich wrote:
>>>> On 09.01.17 at 16:09, <andrew.cooper3@citrix.com> wrote:
>> On 09/01/17 15:04, Jan Beulich wrote:
>>>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>>>> @@ -215,6 +218,39 @@ const uint32_t * __init lookup_deep_deps(uint32_t 
>> feature)
>>>>      return NULL;
>>>>  }
>>>>  
>>>> +void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>>>> +                 uint32_t subleaf, struct cpuid_leaf *res)
>>>> +{
>>>> +    const struct vcpu *curr = current;
>>>> +    const struct domain *d = v->domain;
>>>> +
>>>> +    *res = EMPTY_LEAF;
>>>> +
>>>> +    /* {hvm,pv}_cpuid() have this expectation. */
>>>> +    ASSERT(v == curr);
>>> You don't appear to use curr other than here, so I'd prefer if you
>>> eliminated the local variable.
>> Further uses are added in future changesets.
> Well, having both v and curr available in a function is likely going to
> be (a little) confusing, especially if you mean to use curr (and hence
> apparently ignore the passed in argument). I'd prefer if you ditched
> curr, compared v against current, and used v throughout the
> function (perhaps in anticipation of the expectation above to go
> away eventually).

The two uses of current are this one, and the decision to defer the
dynamic changes.

This one is temporary while the legacy path exists, while the dynamic
one will stay.  I will just use two manual uses of current.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy
  2017-01-09 15:15   ` Jan Beulich
@ 2017-01-09 16:08     ` Andrew Cooper
  2017-01-09 16:10       ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 16:08 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Xen-devel

On 09/01/17 15:15, Jan Beulich wrote:
>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>> @@ -67,6 +80,58 @@ static void __init sanitise_featureset(uint32_t *fs)
>>                            (fs[FEATURESET_e1d] & ~CPUID_COMMON_1D_FEATURES));
>>  }
>>  
>> +static void __init calculate_raw_policy(void)
>> +{
>> +    struct cpuid_policy *p = &raw_policy;
>> +    unsigned int i;
>> +
>> +    cpuid_leaf(0, &p->basic.raw[0]);
>> +    for ( i = 1; i < min(ARRAY_SIZE(p->basic.raw),
>> +                         p->basic.max_leaf + 1ul); ++i )
>> +    {
>> +        switch ( i )
>> +        {
>> +        case 0x2: case 0x4: case 0x7: case 0xd:
>> +            /* Multi-invocation leaves.  Deferred. */
>> +            continue;
>> +        }
>> +
>> +        cpuid_leaf(i, &p->basic.raw[i]);
>> +    }
>> +
>> +    if ( p->basic.max_leaf >= 7 )
>> +    {
>> +        cpuid_count_leaf(7, 0, &p->feat.raw[0]);
>> +
>> +        for ( i = 1; i < min(ARRAY_SIZE(p->feat.raw),
>> +                             p->feat.max_subleaf + 1ul); ++i )
>> +            cpuid_count_leaf(7, i, &p->feat.raw[i]);
>> +    }
>> +
>> +    if ( p->basic.max_leaf >= 0xd )
>> +    {
>> +        uint64_t xstates;
>> +
>> +        cpuid_count_leaf(0xd, 0, &p->xstate.raw[0]);
>> +        cpuid_count_leaf(0xd, 1, &p->xstate.raw[1]);
>> +
>> +        xstates = ((uint64_t)(p->xstate.xcr0_high | p->xstate.xss_high) << 32) |
>> +            (p->xstate.xcr0_low | p->xstate.xss_low);
>> +
>> +        for ( i = 2; i < 63; ++i )
> Perhaps better to use ARRAY_SIZE() (or min()) here, too?
>
>> +        {
>> +            if ( xstates & (1ul << i) )
>> +                cpuid_count_leaf(0xd, i, &p->xstate.raw[i]);
>> +        }
> Also, overall in this code block I think you should really use
> XSTATE_CPUID instead of 0xd.

Will do for both.

>
>> +    }
>> +
>> +    /* Extended leaves. */
>> +    cpuid_leaf(0x80000000, &p->extd.raw[0]);
>> +    for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
>> +                         p->extd.max_leaf + 1 - 0x80000000ul); ++i )
> Would it be worthwhile to make the code resilient to max_leaf not
> having the high bit set?

I'm tempted not to.  If we didn't have sensible higher leaves, we would
have failed the LM check in head.S and failed to boot.

~Andrew

>
> Once again in any event
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
>
> Jan
>
>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy
  2017-01-09 16:08     ` Andrew Cooper
@ 2017-01-09 16:10       ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:10 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 17:08, <andrew.cooper3@citrix.com> wrote:
> On 09/01/17 15:15, Jan Beulich wrote:
>>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>>> +    /* Extended leaves. */
>>> +    cpuid_leaf(0x80000000, &p->extd.raw[0]);
>>> +    for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
>>> +                         p->extd.max_leaf + 1 - 0x80000000ul); ++i )
>> Would it be worthwhile to make the code resilient to max_leaf not
>> having the high bit set?
> 
> I'm tempted not to.  If we didn't have sensible higher leaves, we would
> have failed the LM check in head.S and failed to boot.

Good point.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() from guest_cpuid()
  2017-01-09 11:03 ` [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() " Andrew Cooper
@ 2017-01-09 16:21   ` Jan Beulich
  2017-01-09 16:28     ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:21 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/arch/x86/cpuid.c
> +++ b/xen/arch/x86/cpuid.c
> @@ -346,7 +346,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>      case 0x40000000 ... 0x400000ff:
>          if ( is_viridian_domain(d) )
>              return cpuid_viridian_leaves(v, leaf, subleaf, res);
> -        break;
> +
> +        /* Fallthrough. */
> +    case 0x40000100 ... 0x4fffffff:
> +        return cpuid_hypervisor_leaves(v, leaf, subleaf, res);

Based on what was the upper bound here chosen? It would be rather
helpful if you could leave a pointer to whatever source here in a
comment. I would have expected 0x4000ffff or 0x7fffffff here ...

Other than that
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() from guest_cpuid()
  2017-01-09 16:21   ` Jan Beulich
@ 2017-01-09 16:28     ` Andrew Cooper
  2017-01-09 16:35       ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 16:28 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Xen-devel

On 09/01/17 16:21, Jan Beulich wrote:
>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>> --- a/xen/arch/x86/cpuid.c
>> +++ b/xen/arch/x86/cpuid.c
>> @@ -346,7 +346,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>>      case 0x40000000 ... 0x400000ff:
>>          if ( is_viridian_domain(d) )
>>              return cpuid_viridian_leaves(v, leaf, subleaf, res);
>> -        break;
>> +
>> +        /* Fallthrough. */
>> +    case 0x40000100 ... 0x4fffffff:
>> +        return cpuid_hypervisor_leaves(v, leaf, subleaf, res);
> Based on what was the upper bound here chosen? It would be rather
> helpful if you could leave a pointer to whatever source here in a
> comment. I would have expected 0x4000ffff or 0x7fffffff here ...

Intel reserves 0x40000000 ... 0x4fffffff for hypervisor use.

AMD only reserves 0x40000000 ... 0x400000ff for hypervisor use, but we
already use space beyond that region.

I could clip at 0x400001ff, as that is the realistic upper bound we
currently use?

~Andrew

>
> Other than that
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
>
> Jan
>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields
  2017-01-09 11:03 ` [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields Andrew Cooper
@ 2017-01-09 16:31   ` Jan Beulich
  2017-01-09 16:39     ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:31 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/include/asm-x86/cpuid.h
> +++ b/xen/include/asm-x86/cpuid.h
> @@ -92,6 +92,10 @@ struct cpuid_policy
>       * Everything else should be considered inaccurate, and not necesserily 0.
>       */
>  
> +#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
> +#define _DECL_BITFIELD(x)   __DECL_BITFIELD(x)
> +#define __DECL_BITFIELD(x)  NAMED_BITFIELD_ ## x

If this was a C file, I'd be fine with this naming choice, but in a header
I think it would be better to reduce the chance of name space issues
and use CPUID_BITFIELD_ ## x instead here (and - obviously - in the
script).

> @@ -291,6 +292,28 @@ def crunch_numbers(state):
>      for k, v in state.deep_deps.iteritems():
>          state.deep_deps[k] = featureset_to_uint32s(v, nr_entries)
>  
> +    # Calculate the bitfield name declarations
> +    for word in xrange(nr_entries):
> +
> +        names = []
> +        for bit in xrange(32):
> +
> +            name = state.names.get(word * 32 + bit, "")
> +
> +            # Prepend an underscore if the name starts with a digit.
> +            if name and name[0] in "0123456789":
> +                name = "_" + name
> +
> +            # Don't generate names for the duplicate features, or ones
> +            # fast-forwarded from other state
> +            if (name.startswith("E1D_") or
> +                name in ("APIC", "OSXSAVE", "OSPKE")):
> +                name = ""
> +
> +            names.append(name.lower())
> +
> +        state.bitfields.append("bool " + ":1, ".join(names) + ":1")

It's probably my rudimentary Python knowledge that makes me
confused by the two :1 here. I trust the result is what it needs
to be. So with the naming aspect addressed
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() from guest_cpuid()
  2017-01-09 16:28     ` Andrew Cooper
@ 2017-01-09 16:35       ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:35 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 17:28, <andrew.cooper3@citrix.com> wrote:
> On 09/01/17 16:21, Jan Beulich wrote:
>>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>>> --- a/xen/arch/x86/cpuid.c
>>> +++ b/xen/arch/x86/cpuid.c
>>> @@ -346,7 +346,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>>>      case 0x40000000 ... 0x400000ff:
>>>          if ( is_viridian_domain(d) )
>>>              return cpuid_viridian_leaves(v, leaf, subleaf, res);
>>> -        break;
>>> +
>>> +        /* Fallthrough. */
>>> +    case 0x40000100 ... 0x4fffffff:
>>> +        return cpuid_hypervisor_leaves(v, leaf, subleaf, res);
>> Based on what was the upper bound here chosen? It would be rather
>> helpful if you could leave a pointer to whatever source here in a
>> comment. I would have expected 0x4000ffff or 0x7fffffff here ...
> 
> Intel reserves 0x40000000 ... 0x4fffffff for hypervisor use.
> 
> AMD only reserves 0x40000000 ... 0x400000ff for hypervisor use, but we
> already use space beyond that region.
> 
> I could clip at 0x400001ff, as that is the realistic upper bound we
> currently use?

Sounds reasonable, together with a brief comment.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 14/25] x86/svm: Improvements using named features
  2017-01-09 11:03 ` [PATCH v2 14/25] x86/svm: Improvements " Andrew Cooper
@ 2017-01-09 16:38   ` Jan Beulich
  2017-01-09 23:34   ` Boris Ostrovsky
  1 sibling, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:38 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Boris Ostrovsky, SuraveeSuthikulpanit, Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> This avoids calling into hvm_cpuid() to obtain information which is directly
> available.  In particular, this avoids the need to overload flag_dr_dirty
> because of hvm_cpuid() being unavailable in svm_save_dr().
> 
> flag_dr_dirty is returned to a boolean (as it was before c/s c097f549 which
> introduced the need to overload it).  While returning it to type bool, remove
> the use of bool_t for the adjacent fields.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields
  2017-01-09 16:31   ` Jan Beulich
@ 2017-01-09 16:39     ` Andrew Cooper
  0 siblings, 0 replies; 60+ messages in thread
From: Andrew Cooper @ 2017-01-09 16:39 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Xen-devel

On 09/01/17 16:31, Jan Beulich wrote:
>>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
>> --- a/xen/include/asm-x86/cpuid.h
>> +++ b/xen/include/asm-x86/cpuid.h
>> @@ -92,6 +92,10 @@ struct cpuid_policy
>>       * Everything else should be considered inaccurate, and not necesserily 0.
>>       */
>>  
>> +#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
>> +#define _DECL_BITFIELD(x)   __DECL_BITFIELD(x)
>> +#define __DECL_BITFIELD(x)  NAMED_BITFIELD_ ## x
> If this was a C file, I'd be fine with this naming choice, but in a header
> I think it would be better to reduce the chance of name space issues
> and use CPUID_BITFIELD_ ## x instead here (and - obviously - in the
> script).

Ok.

>
>> @@ -291,6 +292,28 @@ def crunch_numbers(state):
>>      for k, v in state.deep_deps.iteritems():
>>          state.deep_deps[k] = featureset_to_uint32s(v, nr_entries)
>>  
>> +    # Calculate the bitfield name declarations
>> +    for word in xrange(nr_entries):
>> +
>> +        names = []
>> +        for bit in xrange(32):
>> +
>> +            name = state.names.get(word * 32 + bit, "")
>> +
>> +            # Prepend an underscore if the name starts with a digit.
>> +            if name and name[0] in "0123456789":
>> +                name = "_" + name
>> +
>> +            # Don't generate names for the duplicate features, or ones
>> +            # fast-forwarded from other state
>> +            if (name.startswith("E1D_") or
>> +                name in ("APIC", "OSXSAVE", "OSPKE")):
>> +                name = ""
>> +
>> +            names.append(name.lower())
>> +
>> +        state.bitfields.append("bool " + ":1, ".join(names) + ":1")
> It's probably my rudimentary Python knowledge that makes me
> confused by the two :1 here. I trust the result is what it needs
> to be.

"separator".join(array) is implode(array, "separator") in other languages.

The final entry in the array still needs a bitfield suffix to be correct C.

>  So with the naming aspect addressed
> Reviewed-by: Jan Beulich <jbeulich@suse.com>

Thanks.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid()
  2017-01-09 11:03 ` [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid() Andrew Cooper
@ 2017-01-09 16:40   ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:40 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> Clamp the toolstack-providied max_leaf values in recalculate_cpuid_policy(),
> causing the per-domain policy to have guest-accurate data.
> 
> Have guest_cpuid() exit early if a requested leaf is out of range, rather than
> falling into the legacy path.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid()
  2017-01-09 11:03 ` [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid() Andrew Cooper
@ 2017-01-09 16:46   ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2017-01-09 16:46 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel

>>> On 09.01.17 at 12:03, <andrew.cooper3@citrix.com> wrote:
> @@ -396,12 +403,47 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
>      case 0x80000000 ... 0x80000000 + CPUID_GUEST_NR_EXTD - 1:
>          if ( leaf > p->extd.max_leaf )
>              return;
> -        break;
> +        goto legacy;
>  
>      default:
>          return;
>      }
>  
> +    /*
> +     * Skip dynamic adjustments if we are in the wrong context.
> +     *
> +     * All dynamic adjustments depends on current register state, which will
> +     * be stale if the vcpu is running elsewhere.  It is simpler, quicker, and
> +     * more reliable for the caller to nothing (consistently) than to hand

Missing "do"?

> +     * back stale data which it can't use safely.
> +     */
> +    if ( v != curr )
> +        return;
> +
> +    /*
> +     * Second pass:
> +     * - Dynamic adjustments
> +     */
> +    switch ( leaf )
> +    {
> +    case 0x7:
> +        switch ( subleaf )
> +        {
> +        case 0:
> +            /* OSPKE clear in policy.  Fast-forward CR4 back in. */
> +            if ( (is_pv_vcpu(v)

is_pv_domain(d)?

With these taken care of if indeed applicable,
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate
  2017-01-09 11:35   ` Andrew Cooper
@ 2017-01-09 18:11     ` Stefano Stabellini
  0 siblings, 0 replies; 60+ messages in thread
From: Stefano Stabellini @ 2017-01-09 18:11 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Julien Grall, Stefano Stabellini, Jan Beulich, Xen-devel

On Mon, 9 Jan 2017, Andrew Cooper wrote:
> On 09/01/17 11:03, Andrew Cooper wrote:
> > diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> > index 09d9959..fee4b17 100644
> > --- a/xen/arch/arm/domctl.c
> > +++ b/xen/arch/arm/domctl.c
> > @@ -115,6 +115,11 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
> >  
> >          return 0;
> >      }
> > +
> > +    case XEN_DOMCTL_disable_migrate:
> > +        d->disable_migrate = domctl->u.disable_migrate.disable;
> > +        break;
> 
> Travis tells me I broke the ARM build with this.  (I thought I checked
> locally).
> 
> Anyway, I have replaced the break with return 0; to match the prevailing
> behaviour.

With that change you can add my Acked-by.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
  2017-01-09 11:38   ` Paul Durrant
  2017-01-09 15:04   ` Jan Beulich
@ 2017-01-09 23:31   ` Boris Ostrovsky
  2017-01-11  5:47   ` Tian, Kevin
  3 siblings, 0 replies; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-09 23:31 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Suravee Suthikulpanit, Kevin Tian, Paul Durrant, Jun Nakajima,
	Jan Beulich

On 01/09/2017 06:03 AM, Andrew Cooper wrote:
> Longterm, pv_cpuid() and hvm_cpuid() will be merged into a single
> guest_cpuid(), which is also capable of working outside of current context.
>
> To aid this transtion, introduce guest_cpuid() with the intended API, which
> simply defers back to pv_cpuid() or hvm_cpuid() as appropriate.
>
> Introduce struct cpuid_leaf which is used to represent the results of a CPUID
> query in a more efficient mannor than passing four pointers through the
> calltree.
>
> Update all codepaths which should use the new guest_cpuid() API.  These are
> the codepaths which have variable inputs, and (other than some specific
> x86_emulate() cases) all pertain to servicing a CPUID instruction from a
> guest.
>
> The other codepaths using {pv,hvm}_cpuid() with fixed inputs will later be
> adjusted to read their data straight from the policy block.
>
> No intended functional change.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---

Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 14/25] x86/svm: Improvements using named features
  2017-01-09 11:03 ` [PATCH v2 14/25] x86/svm: Improvements " Andrew Cooper
  2017-01-09 16:38   ` Jan Beulich
@ 2017-01-09 23:34   ` Boris Ostrovsky
  1 sibling, 0 replies; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-09 23:34 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel; +Cc: Suravee Suthikulpanit, Jan Beulich

On 01/09/2017 06:03 AM, Andrew Cooper wrote:
> This avoids calling into hvm_cpuid() to obtain information which is directly
> available.  In particular, this avoids the need to overload flag_dr_dirty
> because of hvm_cpuid() being unavailable in svm_save_dr().
>
> flag_dr_dirty is returned to a boolean (as it was before c/s c097f549 which
> introduced the need to overload it).  While returning it to type bool, remove
> the use of bool_t for the adjacent fields.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>


Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
  2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
                     ` (2 preceding siblings ...)
  2017-01-09 23:31   ` Boris Ostrovsky
@ 2017-01-11  5:47   ` Tian, Kevin
  3 siblings, 0 replies; 60+ messages in thread
From: Tian, Kevin @ 2017-01-11  5:47 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Suravee Suthikulpanit, Boris Ostrovsky, Paul Durrant, Nakajima,
	Jun, Jan Beulich

> From: Andrew Cooper [mailto:andrew.cooper3@citrix.com]
> Sent: Monday, January 09, 2017 7:03 PM
> 
> Longterm, pv_cpuid() and hvm_cpuid() will be merged into a single
> guest_cpuid(), which is also capable of working outside of current context.
> 
> To aid this transtion, introduce guest_cpuid() with the intended API, which
> simply defers back to pv_cpuid() or hvm_cpuid() as appropriate.
> 
> Introduce struct cpuid_leaf which is used to represent the results of a CPUID
> query in a more efficient mannor than passing four pointers through the
> calltree.
> 
> Update all codepaths which should use the new guest_cpuid() API.  These are
> the codepaths which have variable inputs, and (other than some specific
> x86_emulate() cases) all pertain to servicing a CPUID instruction from a
> guest.
> 
> The other codepaths using {pv,hvm}_cpuid() with fixed inputs will later be
> adjusted to read their data straight from the policy block.
> 
> No intended functional change.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Kevin Tian <kevint.tian@intel.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-09 11:03 ` [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid() Andrew Cooper
@ 2017-01-12 15:22   ` Boris Ostrovsky
  2017-01-12 15:31     ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-12 15:22 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel


>      case 0x80000001:
> -        c &= pv_featureset[FEATURESET_e1c];
> -        d &= pv_featureset[FEATURESET_e1d];
> +        c = p->extd.e1c;

This appears to crash guests Intel, at least for dom0.

p->extd.e1c is 0x3 and bit 1 is reserved on Intel.

I haven't traced it yet to exact place that causes dom0 to crash but
clearing this bit make dom0 boot.


-boris


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 15:22   ` Boris Ostrovsky
@ 2017-01-12 15:31     ` Andrew Cooper
  2017-01-12 15:50       ` Boris Ostrovsky
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-12 15:31 UTC (permalink / raw)
  To: Boris Ostrovsky, Xen-devel

On 12/01/17 15:22, Boris Ostrovsky wrote:
>>      case 0x80000001:
>> -        c &= pv_featureset[FEATURESET_e1c];
>> -        d &= pv_featureset[FEATURESET_e1d];
>> +        c = p->extd.e1c;
> This appears to crash guests Intel, at least for dom0.

Is this a PVH dom0?  I can't see from this snippet which function you
are in.

>
> p->extd.e1c is 0x3 and bit 1 is reserved on Intel.

>
> I haven't traced it yet to exact place that causes dom0 to crash but
> clearing this bit make dom0 boot.

The logic immediately below the snippet should clean out the common bits
if vendor != AMD.  Do we perhaps have a bad vendor setting?

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 15:31     ` Andrew Cooper
@ 2017-01-12 15:50       ` Boris Ostrovsky
  2017-01-12 16:14         ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-12 15:50 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel

On 01/12/2017 10:31 AM, Andrew Cooper wrote:
> On 12/01/17 15:22, Boris Ostrovsky wrote:
>>>      case 0x80000001:
>>> -        c &= pv_featureset[FEATURESET_e1c];
>>> -        d &= pv_featureset[FEATURESET_e1d];
>>> +        c = p->extd.e1c;
>> This appears to crash guests Intel, at least for dom0.
> Is this a PVH dom0?  I can't see from this snippet which function you
> are in.

No, this is normal PV dom0.

I may have gone too far trimming the patch. It's this chunk:


@@ -1291,15 +1281,15 @@ void pv_cpuid(struct cpu_user_regs *regs)
         }
 
         case 1:
-            a &= pv_featureset[FEATURESET_Da1];
+            a = p->xstate.Da1;
             b = c = d = 0;
             break;
         }
         break;
 
     case 0x80000001:
-        c &= pv_featureset[FEATURESET_e1c];
-        d &= pv_featureset[FEATURESET_e1d];
+        c = p->extd.e1c;
+        d = p->extd.e1d;


>
>> p->extd.e1c is 0x3 and bit 1 is reserved on Intel.
>> I haven't traced it yet to exact place that causes dom0 to crash but
>> clearing this bit make dom0 boot.
> The logic immediately below the snippet should clean out the common bits
> if vendor != AMD.  Do we perhaps have a bad vendor setting?
>

-bash-4.1# ./cpuid 0
CPUID 0x00000000: eax = 0x0000000d ebx = 0x756e6547 ecx = 0x6c65746e edx
= 0x49656e69
-bash-4.1#

This is machine that I run my nightly tests on and it failed this
morning so it's not a new HW.

As far as adjusting the bits based on vendor --- don't you only do this
for edx:

arch/x86/cpuid.c: pv_cpuid():

   case 0x80000001:
        res->c = p->extd.e1c;
        res->c &= ~2U; // My workaround
        res->d = p->extd.e1d;

        /* If not emulating AMD, clear the duplicated features in e1d. */
        if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
            res->d &= ~CPUID_COMMON_1D_FEATURES;


-boris



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 15:50       ` Boris Ostrovsky
@ 2017-01-12 16:14         ` Andrew Cooper
  2017-01-12 18:00           ` Boris Ostrovsky
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-12 16:14 UTC (permalink / raw)
  To: Boris Ostrovsky, Xen-devel

On 12/01/17 15:50, Boris Ostrovsky wrote:
> On 01/12/2017 10:31 AM, Andrew Cooper wrote:
>> On 12/01/17 15:22, Boris Ostrovsky wrote:
>>>>      case 0x80000001:
>>>> -        c &= pv_featureset[FEATURESET_e1c];
>>>> -        d &= pv_featureset[FEATURESET_e1d];
>>>> +        c = p->extd.e1c;
>>> This appears to crash guests Intel, at least for dom0.
>> Is this a PVH dom0?  I can't see from this snippet which function you
>> are in.
> No, this is normal PV dom0.
>
> I may have gone too far trimming the patch. It's this chunk:
>
>
> @@ -1291,15 +1281,15 @@ void pv_cpuid(struct cpu_user_regs *regs)
>          }
>  
>          case 1:
> -            a &= pv_featureset[FEATURESET_Da1];
> +            a = p->xstate.Da1;
>              b = c = d = 0;
>              break;
>          }
>          break;
>  
>      case 0x80000001:
> -        c &= pv_featureset[FEATURESET_e1c];
> -        d &= pv_featureset[FEATURESET_e1d];
> +        c = p->extd.e1c;
> +        d = p->extd.e1d;
>
>
>>> p->extd.e1c is 0x3 and bit 1 is reserved on Intel.
>>> I haven't traced it yet to exact place that causes dom0 to crash but
>>> clearing this bit make dom0 boot.
>> The logic immediately below the snippet should clean out the common bits
>> if vendor != AMD.  Do we perhaps have a bad vendor setting?
>>
> -bash-4.1# ./cpuid 0
> CPUID 0x00000000: eax = 0x0000000d ebx = 0x756e6547 ecx = 0x6c65746e edx
> = 0x49656e69
> -bash-4.1#
>
> This is machine that I run my nightly tests on and it failed this
> morning so it's not a new HW.
>
> As far as adjusting the bits based on vendor --- don't you only do this
> for edx:
>
> arch/x86/cpuid.c: pv_cpuid():
>
>    case 0x80000001:
>         res->c = p->extd.e1c;
>         res->c &= ~2U; // My workaround
>         res->d = p->extd.e1d;
>
>         /* If not emulating AMD, clear the duplicated features in e1d. */
>         if ( currd->arch.x86_vendor != X86_VENDOR_AMD )
>             res->d &= ~CPUID_COMMON_1D_FEATURES;

Ahh! found it.  This is a side effect of starting to generate the dom0
policy in Xen.

Can you try this patch?

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index b685874..1e5013d 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -164,14 +164,6 @@ static void __init calculate_pv_max_policy(void)
     /* Unconditionally claim to be able to set the hypervisor bit. */
     __set_bit(X86_FEATURE_HYPERVISOR, pv_featureset);
 
-    /*
-     * Allow the toolstack to set HTT, X2APIC and CMP_LEGACY.  These bits
-     * affect how to interpret topology information in other cpuid leaves.
-     */
-    __set_bit(X86_FEATURE_HTT, pv_featureset);
-    __set_bit(X86_FEATURE_X2APIC, pv_featureset);
-    __set_bit(X86_FEATURE_CMP_LEGACY, pv_featureset);
-
     sanitise_featureset(pv_featureset);
     cpuid_featureset_to_policy(pv_featureset, p);
 }
@@ -199,14 +191,6 @@ static void __init calculate_hvm_max_policy(void)
     __set_bit(X86_FEATURE_HYPERVISOR, hvm_featureset);
 
     /*
-     * Allow the toolstack to set HTT, X2APIC and CMP_LEGACY.  These bits
-     * affect how to interpret topology information in other cpuid leaves.
-     */
-    __set_bit(X86_FEATURE_HTT, hvm_featureset);
-    __set_bit(X86_FEATURE_X2APIC, hvm_featureset);
-    __set_bit(X86_FEATURE_CMP_LEGACY, hvm_featureset);
-
-    /*
      * Xen can provide an APIC emulation to HVM guests even if the
host's APIC
      * isn't enabled.
      */
@@ -301,6 +285,14 @@ void recalculate_cpuid_policy(struct domain *d)
     }
 
     /*
+     * Allow the toolstack to set HTT, X2APIC and CMP_LEGACY.  These bits
+     * affect how to interpret topology information in other cpuid leaves.
+     */
+    __set_bit(X86_FEATURE_HTT, max_fs);
+    __set_bit(X86_FEATURE_X2APIC, max_fs);
+    __set_bit(X86_FEATURE_CMP_LEGACY, max_fs);
+
+    /*
      * 32bit PV domains can't use any Long Mode features, and cannot use
      * SYSCALL on non-AMD hardware.
      */


The toolstack fudge is still necessary for PV guests (where faulting
isn't in use), and still necessary for HVM guests until I fix topology
representation, but we shouldn't be exposing them by default on hardware
which lacks the appropriate bits.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 16:14         ` Andrew Cooper
@ 2017-01-12 18:00           ` Boris Ostrovsky
  2017-01-12 19:27             ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-12 18:00 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel


> Ahh! found it.  This is a side effect of starting to generate the dom0
> policy in Xen.
>
> Can you try this patch?


Intel/AMD HVM/PV 64/32bit all look good. So

Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 18:00           ` Boris Ostrovsky
@ 2017-01-12 19:27             ` Andrew Cooper
  2017-01-12 20:46               ` Boris Ostrovsky
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-12 19:27 UTC (permalink / raw)
  To: Boris Ostrovsky, Xen-devel

On 12/01/17 18:00, Boris Ostrovsky wrote:
>> Ahh! found it.  This is a side effect of starting to generate the dom0
>> policy in Xen.
>>
>> Can you try this patch?
>
> Intel/AMD HVM/PV 64/32bit all look good. So
>
> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>

Does this mean that newer versions of Linux more picky about what they
tolerate in cpuid?

This bug highlights a hole in my testing strategy, which I will attempt
to plug.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 19:27             ` Andrew Cooper
@ 2017-01-12 20:46               ` Boris Ostrovsky
  2017-01-12 20:48                 ` Andrew Cooper
  0 siblings, 1 reply; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-12 20:46 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel

On 01/12/2017 02:27 PM, Andrew Cooper wrote:
> On 12/01/17 18:00, Boris Ostrovsky wrote:
>>> Ahh! found it.  This is a side effect of starting to generate the dom0
>>> policy in Xen.
>>>
>>> Can you try this patch?
>> Intel/AMD HVM/PV 64/32bit all look good. So
>>
>> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> Does this mean that newer versions of Linux more picky about what they
> tolerate in cpuid?

We started to fail after change in Xen so I am not sure it's something
new in Linux.

-boris


>
> This bug highlights a hole in my testing strategy, which I will attempt
> to plug.
>
> ~Andrew



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 20:46               ` Boris Ostrovsky
@ 2017-01-12 20:48                 ` Andrew Cooper
  2017-01-12 20:51                   ` Boris Ostrovsky
  0 siblings, 1 reply; 60+ messages in thread
From: Andrew Cooper @ 2017-01-12 20:48 UTC (permalink / raw)
  To: Boris Ostrovsky, Xen-devel

On 12/01/17 20:46, Boris Ostrovsky wrote:
> On 01/12/2017 02:27 PM, Andrew Cooper wrote:
>> On 12/01/17 18:00, Boris Ostrovsky wrote:
>>>> Ahh! found it.  This is a side effect of starting to generate the dom0
>>>> policy in Xen.
>>>>
>>>> Can you try this patch?
>>> Intel/AMD HVM/PV 64/32bit all look good. So
>>>
>>> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>> Does this mean that newer versions of Linux more picky about what they
>> tolerate in cpuid?
> We started to fail after change in Xen so I am not sure it's something
> new in Linux.

Right, but Linux 4.4 was entirely happy with this bug, both with and
without having CPUID faulting imposed on it.

Either way, it is definitely a bug in my code.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 20:48                 ` Andrew Cooper
@ 2017-01-12 20:51                   ` Boris Ostrovsky
  2017-01-13  2:19                     ` Boris Ostrovsky
  0 siblings, 1 reply; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-12 20:51 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel

On 01/12/2017 03:48 PM, Andrew Cooper wrote:
> On 12/01/17 20:46, Boris Ostrovsky wrote:
>> On 01/12/2017 02:27 PM, Andrew Cooper wrote:
>>> On 12/01/17 18:00, Boris Ostrovsky wrote:
>>>>> Ahh! found it.  This is a side effect of starting to generate the dom0
>>>>> policy in Xen.
>>>>>
>>>>> Can you try this patch?
>>>> Intel/AMD HVM/PV 64/32bit all look good. So
>>>>
>>>> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>>> Does this mean that newer versions of Linux more picky about what they
>>> tolerate in cpuid?
>> We started to fail after change in Xen so I am not sure it's something
>> new in Linux.
> Right, but Linux 4.4 was entirely happy with this bug, both with and
> without having CPUID faulting imposed on it.

Oh, I see. My tests (typically) build and run the latest Linux tree (and
Xen staging) every morning.

I am trying to see what part of Linux caused the crash.

-boris



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid()
  2017-01-12 20:51                   ` Boris Ostrovsky
@ 2017-01-13  2:19                     ` Boris Ostrovsky
  0 siblings, 0 replies; 60+ messages in thread
From: Boris Ostrovsky @ 2017-01-13  2:19 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel, Mohit Gambhir

On 01/12/2017 03:51 PM, Boris Ostrovsky wrote:
> On 01/12/2017 03:48 PM, Andrew Cooper wrote:
>> On 12/01/17 20:46, Boris Ostrovsky wrote:
>>> On 01/12/2017 02:27 PM, Andrew Cooper wrote:
>>>> On 12/01/17 18:00, Boris Ostrovsky wrote:
>>>>>> Ahh! found it.  This is a side effect of starting to generate the dom0
>>>>>> policy in Xen.
>>>>>>
>>>>>> Can you try this patch?
>>>>> Intel/AMD HVM/PV 64/32bit all look good. So
>>>>>
>>>>> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>>>> Does this mean that newer versions of Linux more picky about what they
>>>> tolerate in cpuid?
>>> We started to fail after change in Xen so I am not sure it's something
>>> new in Linux.
>> Right, but Linux 4.4 was entirely happy with this bug, both with and
>> without having CPUID faulting imposed on it.
> Oh, I see. My tests (typically) build and run the latest Linux tree (and
> Xen staging) every morning.
>
> I am trying to see what part of Linux caused the crash.


So the problem starts in Linux ht_detect(), where we check
X86_FEATURE_CMP_LEGACY. On Intel this is supposed to be clear and we
should end up setting phys_proc_id below. This value is then used in
topology_update_package_map(). If the value is incorrect (which it will
be if we bail early in ht_detect()) we may get a BUG_ON() at the caller.
Unfortunately we were too early to see the splat from the BUG_ON so it
wasn't clear right away why we were dying.

On AMD phys_proc_id is set elsewhere.

And the reason you haven't seen problems with earlier versions of Linux
is because the last two or so kernel releases saw major changes in
topology discovery (and, more importantly, topology validation). There
have been a bunch of Xen regressions due to that (the most recent is the
one Konrad reported a few days ago with 32 cores). This all is very
fragile for Xen guests due to bogus CPUID/APICID values.

(+Mohit who has been looking into another problem related to topology)

-boris


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 60+ messages in thread

end of thread, other threads:[~2017-01-13  2:19 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-09 11:03 [PATCH v2 00/25] xen/x86: Per-domain CPUID policies Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 01/25] x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf Andrew Cooper
2017-01-09 11:38   ` Paul Durrant
2017-01-09 15:04   ` Jan Beulich
2017-01-09 15:09     ` Andrew Cooper
2017-01-09 15:40       ` Jan Beulich
2017-01-09 15:45         ` Andrew Cooper
2017-01-09 23:31   ` Boris Ostrovsky
2017-01-11  5:47   ` Tian, Kevin
2017-01-09 11:03 ` [PATCH v2 02/25] x86/cpuid: Introduce struct cpuid_policy Andrew Cooper
2017-01-09 15:15   ` Jan Beulich
2017-01-09 16:08     ` Andrew Cooper
2017-01-09 16:10       ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 03/25] x86/cpuid: Move featuresets into " Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 04/25] x86/cpuid: Allocate a CPUID policy for every domain Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 05/25] x86/cpuid: Recalculate a domains CPUID policy when appropriate Andrew Cooper
2017-01-09 11:35   ` Andrew Cooper
2017-01-09 18:11     ` Stefano Stabellini
2017-01-09 15:22   ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 06/25] x86/hvm: Dispatch cpuid_viridian_leaves() from guest_cpuid() Andrew Cooper
2017-01-09 11:36   ` Paul Durrant
2017-01-09 15:29   ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 07/25] x86/cpuid: Dispatch cpuid_hypervisor_leaves() " Andrew Cooper
2017-01-09 16:21   ` Jan Beulich
2017-01-09 16:28     ` Andrew Cooper
2017-01-09 16:35       ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 08/25] x86/cpuid: Introduce named feature bitfields Andrew Cooper
2017-01-09 16:31   ` Jan Beulich
2017-01-09 16:39     ` Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 09/25] x86/hvm: Improve hvm_efer_valid() using named features Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 10/25] x86/hvm: Improve CR4 verification " Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 11/25] x86/vvmx: Use hvm_cr4_guest_valid_bits() to calculate MSR_IA32_VMX_CR4_FIXED1 Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 12/25] x86/pv: Improve pv_cpuid() using named features Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 13/25] x86/hvm: Improve CPUID and MSR handling " Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 14/25] x86/svm: Improvements " Andrew Cooper
2017-01-09 16:38   ` Jan Beulich
2017-01-09 23:34   ` Boris Ostrovsky
2017-01-09 11:03 ` [PATCH v2 15/25] x86/pv: Use per-domain policy information when calculating the cpumasks Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 16/25] x86/pv: Use per-domain policy information in pv_cpuid() Andrew Cooper
2017-01-12 15:22   ` Boris Ostrovsky
2017-01-12 15:31     ` Andrew Cooper
2017-01-12 15:50       ` Boris Ostrovsky
2017-01-12 16:14         ` Andrew Cooper
2017-01-12 18:00           ` Boris Ostrovsky
2017-01-12 19:27             ` Andrew Cooper
2017-01-12 20:46               ` Boris Ostrovsky
2017-01-12 20:48                 ` Andrew Cooper
2017-01-12 20:51                   ` Boris Ostrovsky
2017-01-13  2:19                     ` Boris Ostrovsky
2017-01-09 11:03 ` [PATCH v2 17/25] x86/hvm: Use per-domain policy information in hvm_cpuid() Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 18/25] x86/cpuid: Drop the temporary linear feature bitmap from struct cpuid_policy Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 19/25] x86/cpuid: Calculate appropriate max_leaf values for the global policies Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 20/25] x86/cpuid: Perform max_leaf calculations in guest_cpuid() Andrew Cooper
2017-01-09 16:40   ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 21/25] x86/cpuid: Move all leaf 7 handling into guest_cpuid() Andrew Cooper
2017-01-09 16:46   ` Jan Beulich
2017-01-09 11:03 ` [PATCH v2 22/25] x86/hvm: Use guest_cpuid() rather than hvm_cpuid() Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 23/25] x86/svm: " Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 24/25] x86/cpuid: Effectively remove pv_cpuid() and hvm_cpuid() Andrew Cooper
2017-01-09 11:03 ` [PATCH v2 25/25] x86/cpuid: Alter the legacy-path prototypes to match guest_cpuid() Andrew Cooper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.