# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1294742831 0
# Node ID 1d1ae9c19591075dd50f7fb566247adf7945b3b9
# Parent 9b5d121c8805b40a4338248c346303e1e18d0c4e
XCP.PQ: Add a new hypercall and libxc wrapper to get the CPUID feature leaves
as they were before and after the FlexMigrate/Extended Migration masks.
This is not the ideal way to do it - in particular I think probably
platform_ops is the wrong hypercall, and it definitely needs to
allocate a better cmd number before going upstream.
diff -r 9b5d121c8805 -r 1d1ae9c19591 tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c Mon Jan 10 08:45:19 2011 +0000
+++ b/tools/libxc/xc_misc.c Tue Jan 11 10:47:11 2011 +0000
@@ -323,6 +323,31 @@ int xc_getcpuinfo(xc_interface *xch, int
}
+int xc_get_boot_cpufeatures(xc_interface *xch,
+ uint32_t *base_ecx, uint32_t *base_edx,
+ uint32_t *ext_ecx, uint32_t *ext_edx,
+ uint32_t *masked_base_ecx,
+ uint32_t *masked_base_edx,
+ uint32_t *masked_ext_ecx,
+ uint32_t *masked_ext_edx)
+{
+ xen_platform_op_t pm = {0};
+ int rc;
+
+ pm.cmd = XENPF_get_cpu_features;
+ rc = do_platform(xch, &pm);
+
+ *base_ecx = pm.u.cpu_features.base_ecx;
+ *base_edx = pm.u.cpu_features.base_edx;
+ *ext_ecx = pm.u.cpu_features.ext_ecx;
+ *ext_edx = pm.u.cpu_features.ext_edx;
+ *masked_base_ecx = pm.u.cpu_features.masked_base_ecx;
+ *masked_base_edx = pm.u.cpu_features.masked_base_edx;
+ *masked_ext_ecx = pm.u.cpu_features.masked_ext_ecx;
+ *masked_ext_edx = pm.u.cpu_features.masked_ext_edx;
+ return rc;
+}
+
int xc_hvm_set_pci_intx_level(
xc_interface *xch, domid_t dom,
uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
diff -r 9b5d121c8805 -r 1d1ae9c19591 tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h Mon Jan 10 08:45:19 2011 +0000
+++ b/tools/libxc/xc_private.h Tue Jan 11 10:47:11 2011 +0000
@@ -262,6 +262,27 @@ static inline int do_sysctl(xc_interface
int do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len);
+static inline int do_platform(xc_interface *xch, struct xen_platform_op *pm)
+{
+ int ret = -1;
+ DECLARE_HYPERCALL;
+ DECLARE_HYPERCALL_BOUNCE(pm, sizeof(*pm), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+
+ pm->interface_version = XENPF_INTERFACE_VERSION;
+
+ hypercall.op = __HYPERVISOR_platform_op;
+ hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(pm);
+ if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ {
+ if ( errno == EACCES )
+ DPRINTF("platform operation failed -- need to"
+ " rebuild the user-space tool set?\n");
+ }
+
+ xc_hypercall_bounce_post(xch, pm);
+ return ret;
+}
+
void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom,
size_t size, int prot, size_t chunksize,
privcmd_mmap_entry_t entries[], int nentries);
diff -r 9b5d121c8805 -r 1d1ae9c19591 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Jan 10 08:45:19 2011 +0000
+++ b/tools/libxc/xenctrl.h Tue Jan 11 10:47:11 2011 +0000
@@ -38,6 +38,7 @@
#include <xen/domctl.h>
#include <xen/physdev.h>
#include <xen/sysctl.h>
+#include <xen/platform.h>
#include <xen/version.h>
#include <xen/event_channel.h>
#include <xen/sched.h>
@@ -1801,4 +1802,15 @@ void xc_elf_set_logfile(xc_interface *xc
int verbose);
/* Useful for callers who also use libelf. */
+
+/* Get the CPUID feature lists before and after any hardware masks
+ * were applied. Returns the ANDed aggregate of all online CPUs. */
+int xc_get_boot_cpufeatures(xc_interface *xc_handle,
+ uint32_t *base_ecx, uint32_t *base_edx,
+ uint32_t *ext_ecx, uint32_t *ext_edx,
+ uint32_t *masked_base_ecx,
+ uint32_t *masked_base_edx,
+ uint32_t *masked_ext_ecx,
+ uint32_t *masked_ext_edx);
+
#endif /* XENCTRL_H */
diff -r 9b5d121c8805 -r 1d1ae9c19591 xen/arch/x86/cpu/amd.c
--- a/xen/arch/x86/cpu/amd.c Mon Jan 10 08:45:19 2011 +0000
+++ b/xen/arch/x86/cpu/amd.c Tue Jan 11 10:47:11 2011 +0000
@@ -89,12 +89,16 @@ static inline int wrmsr_amd_safe(unsigne
*/
static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
{
+ unsigned int eax, ebx;
static unsigned int feat_ecx, feat_edx;
static unsigned int extfeat_ecx, extfeat_edx;
static enum { not_parsed, no_mask, set_mask } status;
+ cpuid(0x1, &eax, &ebx, &c->boot_base_ecx, &c->boot_base_edx);
+ cpuid(0x80000001, &eax, &ebx, &c->boot_ext_ecx, &c->boot_ext_edx);
+
if (status == no_mask)
- return;
+ goto out;
if (status == set_mask)
goto setmask;
@@ -109,7 +113,7 @@ static void __devinit set_cpuidmask(cons
extfeat_ecx = opt_cpuid_mask_ext_ecx;
extfeat_edx = opt_cpuid_mask_ext_edx;
} else if (*opt_famrev == '\0') {
- return;
+ goto out;
} else if (!strcmp(opt_famrev, "fam_0f_rev_c")) {
feat_ecx = AMD_FEATURES_K8_REV_C_ECX;
feat_edx = AMD_FEATURES_K8_REV_C_EDX;
@@ -153,7 +157,7 @@ static void __devinit set_cpuidmask(cons
} else {
printk("Invalid processor string: %s\n", opt_famrev);
printk("CPUID will not be masked\n");
- return;
+ goto out;
}
/* Setting bits in the CPUID mask MSR that are not set in the
@@ -170,7 +174,7 @@ static void __devinit set_cpuidmask(cons
printk("Writing CPUID extended feature mask ECX:EDX -> %08Xh:%08Xh\n",
extfeat_ecx, extfeat_edx);
- setmask:
+setmask:
/* FIXME check if processor supports CPUID masking */
/* AMD processors prior to family 10h required a 32-bit password */
if (c->x86 >= 0x10) {
@@ -180,6 +184,10 @@ static void __devinit set_cpuidmask(cons
wrmsr_amd(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx);
wrmsr_amd(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx);
}
+
+out:
+ cpuid(0x1, &eax, &ebx, &c->masked_base_ecx, &c->masked_base_edx);
+ cpuid(0x80000001, &eax, &ebx, &c->masked_ext_ecx, &c->masked_ext_edx);
}
/*
diff -r 9b5d121c8805 -r 1d1ae9c19591 xen/arch/x86/cpu/intel.c
--- a/xen/arch/x86/cpu/intel.c Mon Jan 10 08:45:19 2011 +0000
+++ b/xen/arch/x86/cpu/intel.c Tue Jan 11 10:47:11 2011 +0000
@@ -35,11 +35,15 @@ struct movsl_mask movsl_mask __read_most
*/
static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
{
+ unsigned int eax, ebx;
const char *extra = "";
+ cpuid(0x1, &eax, &ebx, &c->boot_base_ecx, &c->boot_base_edx);
+ cpuid(0x80000001, &eax, &ebx, &c->boot_ext_ecx, &c->boot_ext_edx);
+
if (!~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx))
- return;
+ goto out;
/* Only family 6 supports this feature */
switch ((c->x86 == 6) * c->x86_model) {
@@ -78,6 +82,9 @@ static void __devinit set_cpuidmask(cons
printk(XENLOG_ERR "Cannot set CPU feature mask on CPU#%d\n",
smp_processor_id());
+out:
+ cpuid(0x1, &eax, &ebx, &c->masked_base_ecx, &c->masked_base_edx);
+ cpuid(0x80000001, &eax, &ebx, &c->masked_ext_ecx, &c->masked_ext_edx);
}
void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
diff -r 9b5d121c8805 -r 1d1ae9c19591 xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Mon Jan 10 08:45:19 2011 +0000
+++ b/xen/arch/x86/platform_hypercall.c Tue Jan 11 10:47:11 2011 +0000
@@ -492,6 +492,35 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
op->u.mem_add.epfn,
op->u.mem_add.pxm);
break;
+
+ case XENPF_get_cpu_features:
+ {
+ uint32_t cpu;
+
+ op->u.cpu_features.base_ecx = 0xffffffff;
+ op->u.cpu_features.base_edx = 0xffffffff;
+ op->u.cpu_features.ext_ecx = 0xffffffff;
+ op->u.cpu_features.ext_edx = 0xffffffff;
+ op->u.cpu_features.masked_base_ecx = 0xffffffff;
+ op->u.cpu_features.masked_base_edx = 0xffffffff;
+ op->u.cpu_features.masked_ext_ecx = 0xffffffff;
+ op->u.cpu_features.masked_ext_edx = 0xffffffff;
+ for_each_online_cpu( cpu )
+ {
+ op->u.cpu_features.base_ecx &= cpu_data[cpu].boot_base_ecx;
+ op->u.cpu_features.base_edx &= cpu_data[cpu].boot_base_edx;
+ op->u.cpu_features.ext_ecx &= cpu_data[cpu].boot_ext_ecx;
+ op->u.cpu_features.ext_edx &= cpu_data[cpu].boot_ext_edx;
+ op->u.cpu_features.masked_base_ecx &=
cpu_data[cpu].masked_base_ecx;
+ op->u.cpu_features.masked_base_edx &=
cpu_data[cpu].masked_base_edx;
+ op->u.cpu_features.masked_ext_ecx &= cpu_data[cpu].masked_ext_ecx;
+ op->u.cpu_features.masked_ext_edx &= cpu_data[cpu].masked_ext_edx;
+ }
+
+ ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
+ }
+ break;
+
default:
ret = -ENOSYS;
break;
diff -r 9b5d121c8805 -r 1d1ae9c19591 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h Mon Jan 10 08:45:19 2011 +0000
+++ b/xen/include/asm-x86/processor.h Tue Jan 11 10:47:11 2011 +0000
@@ -166,6 +166,10 @@ struct cpuinfo_x86 {
__u8 x86_mask;
int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */
unsigned int x86_capability[NCAPINTS];
+ unsigned int boot_base_ecx, boot_base_edx;
+ unsigned int boot_ext_ecx, boot_ext_edx;
+ unsigned int masked_base_ecx, masked_base_edx;
+ unsigned int masked_ext_ecx, masked_ext_edx;
char x86_vendor_id[16];
char x86_model_id[64];
int x86_cache_size; /* in KB - valid for CPUS which support this call */
diff -r 9b5d121c8805 -r 1d1ae9c19591 xen/include/public/platform.h
--- a/xen/include/public/platform.h Mon Jan 10 08:45:19 2011 +0000
+++ b/xen/include/public/platform.h Tue Jan 11 10:47:11 2011 +0000
@@ -355,6 +355,24 @@ struct xenpf_mem_hotadd
uint32_t flags;
};
+
+/* Get the CPUID feature lists before and after any hardware masks
+ * were applied. Returns the ANDed aggregate of all online CPUs. */
+#define XENPF_get_cpu_features 511
+struct xenpf_cpu_features {
+ uint32_t base_ecx; /* CPUID leaf 0x00000001:ECX */
+ uint32_t base_edx; /* CPUID leaf 0x00000001:EDX */
+ uint32_t ext_ecx; /* CPUID leaf 0x80000001:ECX */
+ uint32_t ext_edx; /* CPUID leaf 0x80000001:EDX */
+ uint32_t masked_base_ecx; /* CPUID leaf 0x00000001:ECX */
+ uint32_t masked_base_edx; /* CPUID leaf 0x00000001:EDX */
+ uint32_t masked_ext_ecx; /* CPUID leaf 0x80000001:ECX */
+ uint32_t masked_ext_edx; /* CPUID leaf 0x80000001:EDX */
+};
+typedef struct xenpf_cpu_features xenpf_cpu_features_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_features_t);
+
+
struct xen_platform_op {
uint32_t cmd;
uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -374,6 +392,7 @@ struct xen_platform_op {
struct xenpf_cpu_ol cpu_ol;
struct xenpf_cpu_hotadd cpu_add;
struct xenpf_mem_hotadd mem_add;
+ struct xenpf_cpu_features cpu_features;
uint8_t pad[128];
} u;
};
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|