Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2877

kernel-2.6.18-128.1.10.el5.src.rpm

From: Chris Lalancette <clalance@redhat.com>
Date: Thu, 5 Mar 2009 14:20:03 +0100
Subject: [xen] x86: fix dom0 panic when using dom0_max_vcpus
Message-id: 49AFD183.5060300@redhat.com
O-Subject: [RHEL5.4 PATCH]: Fix dom0 panic when using dom0_max_vcpus
Bugzilla: 485119
RH-Acked-by: Justin M. Forbes <jforbes@redhat.com>

All,
     When you boot the Xen hypervisor with the dom0_max_vcpus parameter, Xen
automatically disables CPU frequency scaling.  However, if you then start the
cpuspeed service, Xen injects a #GP into the dom0, causing the machine to crash.
 The fix is to tighten up the checks surrounding CPUfreq MSR writes, such that
the writes from the dom0 succeed even if they don't actually change the frequency.
     This patch is a backport of xen-unstable c/s 16616 and 19056, and fixes the
issue for the reporter.  This should fix BZ 485119.  Please review and ACK.

--
Chris Lalancette

diff --git a/arch/x86/traps.c b/arch/x86/traps.c
index 42d5274..911694a 100644
--- a/arch/x86/traps.c
+++ b/arch/x86/traps.c
@@ -1200,6 +1200,12 @@ unsigned long guest_to_host_gpr_switch(unsigned long)
 # define read_sreg(regs, sr) read_segment_register(sr)
 #endif
 
+static int is_cpufreq_controller(struct domain *d)
+{
+    return ((cpufreq_controller == FREQCTL_dom0_kernel) &&
+            (d->domain_id == 0));
+}
+
 static int emulate_privileged_op(struct cpu_user_regs *regs)
 {
     struct vcpu *v = current;
@@ -1702,7 +1708,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         eax = regs->eax;
         edx = regs->edx;
         res = ((u64)edx << 32) | eax;
-        switch ( regs->ecx )
+        switch ( (u32)regs->ecx )
         {
 #ifdef CONFIG_X86_64
         case MSR_FS_BASE:
@@ -1740,15 +1746,19 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         case MSR_K8_PSTATE5:
         case MSR_K8_PSTATE6:
         case MSR_K8_PSTATE7:
-            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
-                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
-                 wrmsr_safe(regs->ecx, eax, edx) )
-                eax = 0;
+            if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+                goto fail;
+            if ( !is_cpufreq_controller(v->domain) )
+                break;
+            if ( wrmsr_safe(regs->ecx, eax, edx) != 0 )
+                goto fail;
             break;
         case MSR_IA32_PERF_CTL:
-            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
-                 (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ||
-                 wrmsr_safe(regs->ecx, eax, edx) )
+            if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
+                goto fail;
+            if ( !is_cpufreq_controller(v->domain) )
+                break;
+            if ( wrmsr_safe(regs->ecx, eax, edx) != 0 )
                 goto fail;
             break;
 	case MSR_IA32_MPERF:
@@ -1774,7 +1784,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         break;
 
     case 0x32: /* RDMSR */
-        switch ( regs->ecx )
+        switch ( (u32)regs->ecx )
         {
 #ifdef CONFIG_X86_64
         case MSR_FS_BASE:
@@ -1809,10 +1819,15 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         case MSR_K8_PSTATE5:
         case MSR_K8_PSTATE6:
         case MSR_K8_PSTATE7:
-            if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
-                 (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
-                 rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
+            if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+                goto fail;
+            if ( !is_cpufreq_controller(v->domain) )
+            {
                 regs->eax = regs->edx = 0;
+                break;
+            }
+            if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) != 0 )
+                goto fail;
             break;
         case MSR_EFER:
             if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )