From: Jean Guyader <jean.guyader@eu.citrix.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] cpuid configuration for PV guest
Date: Wed, 04 Jun 2008 12:13:26 +0100 [thread overview]
Message-ID: <484678D6.3060003@eu.citrix.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 392 bytes --]
Hi,
This patch add the pv guest support for the cpuid configuration and
checking. That feature only works for cpuid request which are coming
from the guest's kernel, a process could still call the cpuid directly.
A new policy for pv guest has been created in libxc. dom0 cpuid
emulation is left hardcoded in Xen.
Signed-off-by: Jean Guyader <jean.guyader@eu.citrix.com>
--
Jean Guyader
[-- Attachment #2: cpuid_pv.patch --]
[-- Type: text/plain, Size: 15132 bytes --]
diff -r 5603534c62f9 tools/libxc/xc_cpuid_x86.c
--- a/tools/libxc/xc_cpuid_x86.c Tue Jun 03 09:41:19 2008 +0100
+++ b/tools/libxc/xc_cpuid_x86.c Wed Jun 04 11:31:19 2008 +0100
@@ -140,14 +140,66 @@ static void xc_cpuid_brand_get(char *str
str[12] = '\0';
}
-static void xc_cpuid_policy(
+static void xc_cpuid_pv_policy(
int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
{
- char brand[13];
- unsigned long pae;
+ switch ( input[0] )
+ {
+ case 0x00000000:
+ if ( regs[0] > DEF_MAX_BASE )
+ regs[0] = DEF_MAX_BASE;
+ break;
- xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
+ case 1:
+ clear_bit(X86_FEATURE_DTES64 % 32, regs[2]);
+ clear_bit(X86_FEATURE_MWAIT % 32, regs[2]);
+ clear_bit(X86_FEATURE_DSCPL % 32, regs[2]);
+ clear_bit(X86_FEATURE_VMXE % 32, regs[2]);
+ clear_bit(X86_FEATURE_SMXE % 32, regs[2]);
+ clear_bit(X86_FEATURE_EST % 32, regs[2]);
+ clear_bit(X86_FEATURE_TM2 % 32, regs[2]);
+ clear_bit(X86_FEATURE_CX16 % 32, regs[2]);
+ clear_bit(X86_FEATURE_XTPR % 32, regs[2]);
+ clear_bit(X86_FEATURE_PDCM % 32, regs[2]);
+ clear_bit(X86_FEATURE_DCA % 32, regs[2]);
+
+ clear_bit(X86_FEATURE_VME % 32, regs[3]);
+ clear_bit(X86_FEATURE_PSE % 32, regs[3]);
+ clear_bit(X86_FEATURE_PGE % 32, regs[3]);
+ clear_bit(X86_FEATURE_MCE % 32, regs[3]);
+ clear_bit(X86_FEATURE_MCA % 32, regs[3]);
+ clear_bit(X86_FEATURE_MTRR % 32, regs[3]);
+ clear_bit(X86_FEATURE_DS % 32, regs[3]);
+ clear_bit(X86_FEATURE_ACC % 32, regs[3]);
+ clear_bit(X86_FEATURE_PBE % 32, regs[3]);
+ break;
+ case 0x80000000:
+ if ( regs[0] > DEF_MAX_EXT )
+ regs[0] = DEF_MAX_EXT;
+ break;
+
+ case 0x80000001:
+ clear_bit(X86_FEATURE_NX & 31, regs[3]);
+ break;
+
+ case 0x00000002:
+ case 0x00000004:
+ case 0x80000002:
+ case 0x80000003:
+ case 0x80000004:
+ case 0x80000006:
+ break;
+
+ default:
+ regs[0] = regs[1] = regs[2] = regs[3] = 0;
+ }
+}
+
+static void xc_cpuid_hvm_policy(
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs,
+ int is_pae)
+{
switch( input[0] )
{
case 0x00000000:
@@ -188,7 +240,7 @@ static void xc_cpuid_policy(
/* We always support MTRR MSRs. */
regs[3] |= bitmaskof(X86_FEATURE_MTRR);
- if ( !pae )
+ if ( !is_pae )
clear_bit(X86_FEATURE_PAE & 31, regs[3]);
break;
@@ -198,7 +250,7 @@ static void xc_cpuid_policy(
break;
case 0x80000001:
- if ( !pae )
+ if ( !is_pae )
clear_bit(X86_FEATURE_NX & 31, regs[3]);
break;
@@ -221,11 +273,32 @@ static void xc_cpuid_policy(
break;
}
+}
+
+static int xc_cpuid_policy(
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+{
+ xc_dominfo_t info;
+ unsigned long pae = 1;
+ char brand[13];
+
+ if ( xc_domain_getinfo(xc, domid, 1, &info) == 0 )
+ return -EINVAL;
+ if ( info.hvm )
+ {
+ xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
+ xc_cpuid_hvm_policy(xc, domid, input, regs, !!pae);
+ }
+ else
+ xc_cpuid_pv_policy(xc, domid, input, regs);
+
xc_cpuid_brand_get(brand);
if ( strstr(brand, "AMD") )
- amd_xc_cpuid_policy(xc, domid, input, regs, !!pae);
+ amd_xc_cpuid_policy(xc, domid, input, regs, pae);
else
- intel_xc_cpuid_policy(xc, domid, input, regs, !!pae);
+ intel_xc_cpuid_policy(xc, domid, input, regs, pae);
+
+ return 0;
}
static int xc_cpuid_do_domctl(
diff -r 5603534c62f9 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Tue Jun 03 09:41:19 2008 +0100
+++ b/tools/python/xen/xend/image.py Wed Jun 04 11:31:19 2008 +0100
@@ -103,6 +103,12 @@ class ImageHandler:
if rtc_timeoffset is not None:
xc.domain_set_time_offset(self.vm.getDomid(), int(rtc_timeoffset))
+ self.cpuid = None
+ self.cpuid_check = None
+ if 'cpuid' in vmConfig:
+ self.cpuid = vmConfig['cpuid'];
+ if 'cpuid_check' in vmConfig:
+ self.cpuid_check = vmConfig['cpuid_check']
def cleanupBootloading(self):
if self.bootloader:
@@ -454,6 +460,37 @@ class ImageHandler:
except:
pass
+ def setCpuid(self):
+ xc.domain_set_policy_cpuid(self.vm.getDomid())
+
+ if self.cpuid is not None:
+ cpuid = self.cpuid
+ transformed = {}
+ for sinput, regs in cpuid.iteritems():
+ inputs = sinput.split(',')
+ input = long(inputs[0])
+ sub_input = None
+ if len(inputs) == 2:
+ sub_input = long(inputs[1])
+ t = xc.domain_set_cpuid(self.vm.getDomid(),
+ input, sub_input, regs)
+ transformed[sinput] = t
+ self.cpuid = transformed
+
+ if self.cpuid_check is not None:
+ cpuid_check = self.cpuid_check
+ transformed = {}
+ for sinput, regs_check in cpuid_check.iteritems():
+ inputs = sinput.split(',')
+ input = long(inputs[0])
+ sub_input = None
+ if len(inputs) == 2:
+ sub_input = long(inputs[1])
+ t = xc.domain_check_cpuid(input, sub_input, regs_check)
+ transformed[sinput] = t
+ self.cpuid_check = transformed
+
+
class LinuxImageHandler(ImageHandler):
@@ -536,38 +573,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
-
- self.vmConfig = vmConfig
- def setCpuid(self):
- xc.domain_set_policy_cpuid(self.vm.getDomid())
-
- if 'cpuid' in self.vmConfig:
- cpuid = self.vmConfig['cpuid']
- transformed = {}
- for sinput, regs in cpuid.iteritems():
- inputs = sinput.split(',')
- input = long(inputs[0])
- sub_input = None
- if len(inputs) == 2:
- sub_input = long(inputs[1])
- t = xc.domain_set_cpuid(self.vm.getDomid(),
- input, sub_input, regs)
- transformed[sinput] = t
- self.vmConfig['cpuid'] = transformed
-
- if 'cpuid_check' in self.vmConfig:
- cpuid_check = self.vmConfig['cpuid_check']
- transformed = {}
- for sinput, regs_check in cpuid_check.iteritems():
- inputs = sinput.split(',')
- input = long(inputs[0])
- sub_input = None
- if len(inputs) == 2:
- sub_input = long(inputs[1])
- t = xc.domain_check_cpuid(input, sub_input, regs_check)
- transformed[sinput] = t
- self.vmConfig['cpuid_check'] = transformed
# Return a list of cmd line args to the device models based on the
# xm config file
@@ -730,6 +736,9 @@ class IA64_Linux_ImageHandler(LinuxImage
LinuxImageHandler.configure(self, vmConfig)
self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
+ def setCpuid(self):
+ # Guest CPUID configuration is not implemented yet.
+ return
class X86_HVM_ImageHandler(HVMImageHandler):
@@ -769,6 +778,7 @@ class X86_Linux_ImageHandler(LinuxImageH
# add an 8MB slack to balance backend allocations.
mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
+ self.setCpuid()
return LinuxImageHandler.buildDomain(self)
_handlers = {
diff -r 5603534c62f9 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Tue Jun 03 09:41:19 2008 +0100
+++ b/xen/arch/x86/traps.c Wed Jun 04 11:31:19 2008 +0100
@@ -654,6 +654,7 @@ static int emulate_forced_invalid_op(str
char sig[5], instr[2];
uint32_t a, b, c, d;
unsigned long eip, rc;
+ struct segment_register cs;
a = regs->eax;
b = regs->ebx;
@@ -681,81 +682,103 @@ static int emulate_forced_invalid_op(str
return 0;
eip += sizeof(instr);
- asm (
- "cpuid"
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d)
- : "0" (a), "1" (b), "2" (c), "3" (d) );
+ if (!IS_PRIV(current->domain))
+ {
+ if ( !cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d) )
+ domain_cpuid(current->domain, regs->eax, regs->ebx,
+ &a, &b, &c, &d);
+
+ switch ( regs->eax )
+ {
+ case 0x80000001:
+ /* SYSCALL is visible if running in long mode. */
+ memcpy(&cs, ®s->cs, sizeof (cs));
+ if ( cs.attr.fields.l ||
+ boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ __set_bit(X86_FEATURE_SYSCALL, &d);
+ else
+ __clear_bit(X86_FEATURE_SYSCALL, &d);
+ break;
+ }
+ }
+ else
+ {
+ asm (
+ "cpuid"
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d)
+ : "0" (a), "1" (b), "2" (c), "3" (d) );
- if ( (regs->eax & 0x7fffffff) == 1 )
- {
- /* Modify Feature Information. */
- __clear_bit(X86_FEATURE_VME, &d);
- __clear_bit(X86_FEATURE_PSE, &d);
- __clear_bit(X86_FEATURE_PGE, &d);
- __clear_bit(X86_FEATURE_MCE, &d);
- __clear_bit(X86_FEATURE_MCA, &d);
- if ( !IS_PRIV(current->domain) )
- __clear_bit(X86_FEATURE_MTRR, &d);
- __clear_bit(X86_FEATURE_PSE36, &d);
- }
- switch ( (uint32_t)regs->eax )
- {
- case 1:
- /* Modify Feature Information. */
- if ( !cpu_has_sep )
- __clear_bit(X86_FEATURE_SEP, &d);
+ if ( (regs->eax & 0x7fffffff) == 1 )
+ {
+ /* Modify Feature Information. */
+ __clear_bit(X86_FEATURE_VME, &d);
+ __clear_bit(X86_FEATURE_PSE, &d);
+ __clear_bit(X86_FEATURE_PGE, &d);
+ __clear_bit(X86_FEATURE_MCE, &d);
+ __clear_bit(X86_FEATURE_MCA, &d);
+ if ( !IS_PRIV(current->domain) )
+ __clear_bit(X86_FEATURE_MTRR, &d);
+ __clear_bit(X86_FEATURE_PSE36, &d);
+ }
+ switch ( (uint32_t)regs->eax )
+ {
+ case 1:
+ /* Modify Feature Information. */
+ if ( !cpu_has_sep )
+ __clear_bit(X86_FEATURE_SEP, &d);
#ifdef __i386__
- if ( !supervisor_mode_kernel )
- __clear_bit(X86_FEATURE_SEP, &d);
+ if ( !supervisor_mode_kernel )
+ __clear_bit(X86_FEATURE_SEP, &d);
#endif
- __clear_bit(X86_FEATURE_DS, &d);
- __clear_bit(X86_FEATURE_ACC, &d);
- __clear_bit(X86_FEATURE_PBE, &d);
+ __clear_bit(X86_FEATURE_DS, &d);
+ __clear_bit(X86_FEATURE_ACC, &d);
+ __clear_bit(X86_FEATURE_PBE, &d);
- __clear_bit(X86_FEATURE_DTES64 % 32, &c);
- __clear_bit(X86_FEATURE_MWAIT % 32, &c);
- __clear_bit(X86_FEATURE_DSCPL % 32, &c);
- __clear_bit(X86_FEATURE_VMXE % 32, &c);
- __clear_bit(X86_FEATURE_SMXE % 32, &c);
- if ( !IS_PRIV(current->domain) )
- __clear_bit(X86_FEATURE_EST % 32, &c);
- __clear_bit(X86_FEATURE_TM2 % 32, &c);
- if ( is_pv_32bit_vcpu(current) )
- __clear_bit(X86_FEATURE_CX16 % 32, &c);
- __clear_bit(X86_FEATURE_XTPR % 32, &c);
- __clear_bit(X86_FEATURE_PDCM % 32, &c);
- __clear_bit(X86_FEATURE_DCA % 32, &c);
- break;
- case 0x80000001:
- /* Modify Feature Information. */
- if ( is_pv_32bit_vcpu(current) )
- {
- __clear_bit(X86_FEATURE_LM % 32, &d);
- __clear_bit(X86_FEATURE_LAHF_LM % 32, &c);
+ __clear_bit(X86_FEATURE_DTES64 % 32, &c);
+ __clear_bit(X86_FEATURE_MWAIT % 32, &c);
+ __clear_bit(X86_FEATURE_DSCPL % 32, &c);
+ __clear_bit(X86_FEATURE_VMXE % 32, &c);
+ __clear_bit(X86_FEATURE_SMXE % 32, &c);
+ if ( !IS_PRIV(current->domain) )
+ __clear_bit(X86_FEATURE_EST % 32, &c);
+ __clear_bit(X86_FEATURE_TM2 % 32, &c);
+ if ( is_pv_32bit_vcpu(current) )
+ __clear_bit(X86_FEATURE_CX16 % 32, &c);
+ __clear_bit(X86_FEATURE_XTPR % 32, &c);
+ __clear_bit(X86_FEATURE_PDCM % 32, &c);
+ __clear_bit(X86_FEATURE_DCA % 32, &c);
+ break;
+ case 0x80000001:
+ /* Modify Feature Information. */
+ if ( is_pv_32bit_vcpu(current) )
+ {
+ __clear_bit(X86_FEATURE_LM % 32, &d);
+ __clear_bit(X86_FEATURE_LAHF_LM % 32, &c);
+ }
+#ifndef __i386__
+ if ( is_pv_32on64_vcpu(current) &&
+ boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+#endif
+ __clear_bit(X86_FEATURE_SYSCALL % 32, &d);
+ __clear_bit(X86_FEATURE_PAGE1GB % 32, &d);
+ __clear_bit(X86_FEATURE_RDTSCP % 32, &d);
+
+ __clear_bit(X86_FEATURE_SVME % 32, &c);
+ __clear_bit(X86_FEATURE_OSVW % 32, &c);
+ __clear_bit(X86_FEATURE_IBS % 32, &c);
+ __clear_bit(X86_FEATURE_SKINIT % 32, &c);
+ __clear_bit(X86_FEATURE_WDT % 32, &c);
+ break;
+ case 5: /* MONITOR/MWAIT */
+ case 0xa: /* Architectural Performance Monitor Features */
+ case 0x8000000a: /* SVM revision and features */
+ case 0x8000001b: /* Instruction Based Sampling */
+ a = b = c = d = 0;
+ break;
+ default:
+ (void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
+ break;
}
-#ifndef __i386__
- if ( is_pv_32on64_vcpu(current) &&
- boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
-#endif
- __clear_bit(X86_FEATURE_SYSCALL % 32, &d);
- __clear_bit(X86_FEATURE_PAGE1GB % 32, &d);
- __clear_bit(X86_FEATURE_RDTSCP % 32, &d);
-
- __clear_bit(X86_FEATURE_SVME % 32, &c);
- __clear_bit(X86_FEATURE_OSVW % 32, &c);
- __clear_bit(X86_FEATURE_IBS % 32, &c);
- __clear_bit(X86_FEATURE_SKINIT % 32, &c);
- __clear_bit(X86_FEATURE_WDT % 32, &c);
- break;
- case 5: /* MONITOR/MWAIT */
- case 0xa: /* Architectural Performance Monitor Features */
- case 0x8000000a: /* SVM revision and features */
- case 0x8000001b: /* Instruction Based Sampling */
- a = b = c = d = 0;
- break;
- default:
- (void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
- break;
}
regs->eax = a;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
next reply other threads:[~2008-06-04 11:13 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-04 11:13 Jean Guyader [this message]
2008-07-13 2:49 ` [PATCH] cpuid configuration for PV guest Jeremy Fitzhardinge
2008-07-13 6:00 ` Jeremy Fitzhardinge
2008-07-13 6:27 ` Jeremy Fitzhardinge
2008-07-14 7:12 ` Keir Fraser
2008-07-14 9:55 ` Samuel Thibault
2008-07-14 21:40 ` qemu-dm without slirp Jeremy Fitzhardinge
2008-07-15 8:58 ` [PATCH] xend: PV machines have no ioemu network Kevin Wolf
2008-07-15 15:01 ` Jeremy Fitzhardinge
2008-07-15 16:44 ` Kevin Wolf
2008-07-15 16:36 ` qemu-dm without slirp Ian Jackson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=484678D6.3060003@eu.citrix.com \
--to=jean.guyader@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.