Sophie

Sophie

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

kernel-2.6.18-128.1.10.el5.src.rpm

From: Rik van Riel <riel@redhat.com>
Date: Thu, 11 Sep 2008 01:11:18 -0400
Subject: [xen] cpufreq: fix Nehalem/Supermicro systems
Message-id: 20080911011118.3824d1a0@riellaptop.surriel.com
O-Subject: [PATCH 5.3 v2] fix xen cpufreq on Nehalem/Supermicro systems
Bugzilla: 458894
RH-Acked-by: Chris Lalancette <clalance@redhat.com>
RH-Acked-by: Don Dutile <ddutile@redhat.com>
RH-Acked-by: Bill Burns <bburns@redhat.com>

On Thu, 11 Sep 2008 00:26:47 -0400
Rik van Riel <riel@redhat.com> wrote:
(lets try this again - now with the backported patch
and not the upstream changeset that does not apply)

This seemingly unrelated kernel-xen changeset resolves the
ACPI confusion that stopped cpu frequency scaling code from
working on the Intel Nehalem CPUs on Supermicro mainboards.

Fixes bug 458894

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1204715381 0
# Node ID 26e1e96bd46a53991e216271d077aa6fb20ea218
# Parent  1cf7ba68d855aa86b1c54c34c03fc62571eb5c94
x86 xen: New vcpu_op call to get physical CPU identity.

Some AMD machines have APIC IDs that not equal to CPU IDs. In
the default Xen configuration, ACPI calls on these machines
can get confused. This shows up most noticeably when running
AMD PowerNow!. The only solution is for dom0 to get the
hypervisor's cpuid to apicid table when needed (ie, when dom0
vcpus are pinned).

Add a vcpu op to Xen to allow dom0 to query the hypervisor for
architecture dependent physical cpu information if dom0 vcpus are
pinned.

Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>

diff --git a/drivers/xen/core/smpboot.c b/drivers/xen/core/smpboot.c
index 5f43010..d2d1182 100644
--- a/drivers/xen/core/smpboot.c
+++ b/drivers/xen/core/smpboot.c
@@ -249,17 +249,28 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	int cpu;
 	struct task_struct *idle;
+	int apicid, acpiid;
+	struct vcpu_get_physid cpu_id;
 #ifdef __x86_64__
 	struct desc_ptr *gdt_descr;
 #else
 	struct Xgt_desc_struct *gdt_descr;
 #endif
 
-	boot_cpu_data.apicid = 0;
+	apicid = 0;
+	if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0) {
+		apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
+		acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
+#ifdef CONFIG_ACPI
+		if (acpiid != 0xff)
+			x86_acpiid_to_apicid[acpiid] = apicid;
+#endif
+	}
+	boot_cpu_data.apicid = apicid;
 	cpu_data[0] = boot_cpu_data;
 
-	cpu_2_logical_apicid[0] = 0;
-	x86_cpu_to_apicid[0] = 0;
+	cpu_2_logical_apicid[0] = apicid;
+	x86_cpu_to_apicid[0] = apicid;
 
 	current_thread_info()->cpu = 0;
 
@@ -303,11 +314,20 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 			(void *)gdt_descr->address,
 			XENFEAT_writable_descriptor_tables);
 
+		apicid = cpu;
+		if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0) {
+			apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
+			acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
+#ifdef CONFIG_ACPI
+			if (acpiid != 0xff)
+				x86_acpiid_to_apicid[acpiid] = apicid;
+#endif
+		}
 		cpu_data[cpu] = boot_cpu_data;
-		cpu_data[cpu].apicid = cpu;
+		cpu_data[cpu].apicid = apicid;
 
-		cpu_2_logical_apicid[cpu] = cpu;
-		x86_cpu_to_apicid[cpu] = cpu;
+		cpu_2_logical_apicid[cpu] = apicid;
+		x86_cpu_to_apicid[cpu] = apicid;
 
 		idle = fork_idle(cpu);
 		if (IS_ERR(idle))
diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
index 377defe..eb8b5a1 100644
--- a/include/xen/interface/vcpu.h
+++ b/include/xen/interface/vcpu.h
@@ -108,6 +108,24 @@ struct vcpu_register_runstate_memory_area {
 };
 typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
 
+#define VCPUOP_register_vcpu_info   10  /* arg == vcpu_register_vcpu_info_t */
+
+/*
+ * Get the physical ID information for a pinned vcpu's underlying physical
+ * processor.  The physical ID informmation is architecture-specific.
+ * On x86: id[7:0]=apic_id, id[15:8]=acpi_id, id[63:16]=mbz,
+ *         and an unavailable identifier is returned as 0xff.
+ * This command returns -EINVAL if it is not a valid operation for this VCPU.
+ */
+#define VCPUOP_get_physid           12 /* arg == vcpu_get_physid_t */
+struct vcpu_get_physid {
+    uint64_t phys_id;
+};
+typedef struct vcpu_get_physid vcpu_get_physid_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
+#define xen_vcpu_physid_to_x86_apicid(physid) ((uint8_t)((physid)>>0))
+#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint8_t)((physid)>>8))
+
 #endif /* __XEN_PUBLIC_VCPU_H__ */
 
 /*