diff mbox

[05/10] x86/cpuid: Handle leaf 0x5 in guest_cpuid()

Message ID 1487588434-4359-6-git-send-email-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Cooper Feb. 20, 2017, 11 a.m. UTC
The MONITOR flag isn't exposed to guests.  The existing toolstack logic, and
pv_cpuid() in the hypervisor, zero the MONITOR leaf for queries.

However, the MONITOR leaf is still visible in the hardware domains native
CPUID view, and Linux depends on this to set up C-state information.  Leak the
hosts MONITOR leaf under the same circumstances that the MONITOR feature is
leaked.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
---
 xen/arch/x86/cpuid.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

Comments

Jan Beulich Feb. 21, 2017, 5:22 p.m. UTC | #1
>>> On 20.02.17 at 12:00, <andrew.cooper3@citrix.com> wrote:
> The MONITOR flag isn't exposed to guests.  The existing toolstack logic, and
> pv_cpuid() in the hypervisor, zero the MONITOR leaf for queries.
> 
> However, the MONITOR leaf is still visible in the hardware domains native
> CPUID view, and Linux depends on this to set up C-state information.  Leak the
> hosts MONITOR leaf under the same circumstances that the MONITOR feature is
> leaked.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

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

Patch

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index ca38d04..7862d62 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -166,6 +166,8 @@  static void recalculate_misc(struct cpuid_policy *p)
     /* Leaves with subleaf unions. */
     p->basic.raw[0x4] = p->basic.raw[0x7] = p->basic.raw[0xd] = EMPTY_LEAF;
 
+    p->basic.raw[0x5] = EMPTY_LEAF; /* MONITOR not exposed to guests. */
+
     p->basic.raw[0x8] = EMPTY_LEAF;
     p->basic.raw[0xc] = EMPTY_LEAF;
 
@@ -641,13 +643,12 @@  static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
             res->a = (res->a & ~0xff) | 3;
         break;
 
-    case 0x00000005: /* MONITOR/MWAIT */
     case 0x0000000b: /* Extended Topology Enumeration */
     unsupported:
         *res = EMPTY_LEAF;
         break;
 
-    case 0x0 ... 0x4:
+    case 0x0 ... 0x5:
     case 0x7 ... 0x9:
     case 0xc ... XSTATE_CPUID:
     case 0x80000000 ... 0xffffffff:
@@ -682,7 +683,7 @@  static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
             res->a = (res->a & ~0xff) | 3;
         break;
 
-    case 0x0 ... 0x4:
+    case 0x0 ... 0x5:
     case 0x7 ... 0x9:
     case 0xc ... XSTATE_CPUID:
     case 0x80000000 ... 0xffffffff:
@@ -743,6 +744,7 @@  void guest_cpuid(const struct vcpu *v, uint32_t leaf,
             goto legacy;
 
         case 0x0 ... 0x3:
+        case 0x5:
         case 0x8 ... 0x9:
         case 0xc:
             *res = p->basic.raw[leaf];
@@ -928,6 +930,18 @@  void guest_cpuid(const struct vcpu *v, uint32_t leaf,
         /* Adjustments common with leaf 0x80000001. */
         goto common_dynamic_adjustments;
 
+    case 0x5:
+        /*
+         * Leak the hardware MONITOR leaf under the same conditions that the
+         * MONITOR feature flag is leaked.  See above for details.
+         */
+        regs = guest_cpu_user_regs();
+        if ( is_pv_domain(d) && is_hardware_domain(d) &&
+             guest_kernel_mode(v, regs) && cpu_has_monitor &&
+             regs->entry_vector == TRAP_gp_fault )
+            *res = raw_policy.basic.raw[leaf];
+        break;
+
     case 0x7:
         switch ( subleaf )
         {