aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-23 12:51:10 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-23 12:51:10 +0100
commit5b1fe770e06885646e98b8d48fdf4daf7c59ba7c (patch)
treed36401b12d14ae7edf6f50d739ef5c9b2ac1ccf1
parentb699d329f76ec8578a03ec9b131e9e03245de3fd (diff)
downloadxen-5b1fe770e06885646e98b8d48fdf4daf7c59ba7c.tar.gz
xen-5b1fe770e06885646e98b8d48fdf4daf7c59ba7c.tar.bz2
xen-5b1fe770e06885646e98b8d48fdf4daf7c59ba7c.zip
Enable Windows PAE guest on x86-64. Deals with two issues:
1) To handle the situation when PE=1 and PG=0. 2) Windows PAE guest seems to enable PAE first and then enable PG. Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com>
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 191344e835..0235d066f9 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -1308,7 +1308,8 @@ static int vmx_set_cr0(unsigned long value)
vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE;
__vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
- if ( !shadow_set_guest_paging_levels(v->domain, 4) ) {
+ if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L4) )
+ {
printk("Unsupported guest paging levels\n");
domain_crash_synchronous(); /* need to take a clean path */
}
@@ -1317,9 +1318,26 @@ static int vmx_set_cr0(unsigned long value)
#endif /* __x86_64__ */
{
#if CONFIG_PAGING_LEVELS >= 3
- if ( !shadow_set_guest_paging_levels(v->domain, 2) ) {
- printk("Unsupported guest paging levels\n");
- domain_crash_synchronous(); /* need to take a clean path */
+ /* seems it's a 32-bit or 32-bit PAE guest */
+
+ if ( test_bit(VMX_CPU_STATE_PAE_ENABLED,
+ &v->arch.hvm_vmx.cpu_state) )
+ {
+ /* The guest enables PAE first and then it enables PG, it is
+ * really a PAE guest */
+ if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
+ {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous();
+ }
+ }
+ else
+ {
+ if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L2) )
+ {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
}
#endif
}
@@ -1399,6 +1417,12 @@ static int vmx_set_cr0(unsigned long value)
return 0; /* do not update eip! */
}
}
+ else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
+ {
+ /* we should take care of this kind of situation */
+ clear_all_shadow_status(v->domain);
+ __vmwrite(GUEST_CR3, pagetable_get_paddr(v->domain->arch.phys_table));
+ }
return 1;
}
@@ -1528,11 +1552,11 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
if ( vmx_pgbit_test(v) )
{
- /* The guest is 32 bit. */
+ /* The guest is a 32-bit PAE guest. */
#if CONFIG_PAGING_LEVELS >= 4
unsigned long mfn, old_base_mfn;
- if( !shadow_set_guest_paging_levels(v->domain, 3) )
+ if( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
{
printk("Unsupported guest paging levels\n");
domain_crash_synchronous(); /* need to take a clean path */
@@ -1572,12 +1596,31 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
}
else
{
- /* The guest is 64 bit. */
+ /* The guest is a 64 bit or 32-bit PAE guest. */
#if CONFIG_PAGING_LEVELS >= 4
- if ( !shadow_set_guest_paging_levels(v->domain, 4) )
+ if ( (v->domain->arch.ops != NULL) &&
+ v->domain->arch.ops->guest_paging_levels == PAGING_L2)
{
- printk("Unsupported guest paging levels\n");
- domain_crash_synchronous(); /* need to take a clean path */
+ /* Seems the guest first enables PAE without enabling PG,
+ * it must enable PG after that, and it is a 32-bit PAE
+ * guest */
+
+ if ( !shadow_set_guest_paging_levels(v->domain,
+ PAGING_L3) )
+ {
+ printk("Unsupported guest paging levels\n");
+ /* need to take a clean path */
+ domain_crash_synchronous();
+ }
+ }
+ else
+ {
+ if ( !shadow_set_guest_paging_levels(v->domain,
+ PAGING_L4) )
+ {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous();
+ }
}
#endif
}