aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>2006-03-23 12:59:50 +0100
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>2006-03-23 12:59:50 +0100
commit2a07425a76ad5d78aee7e5be078b10af413f04dd (patch)
treed105bf89503878aef8658881ebfbd50507974710
parent88aea7e5a858e5489df0d50ad2b0459ba17354d2 (diff)
parent5b1fe770e06885646e98b8d48fdf4daf7c59ba7c (diff)
downloadxen-2a07425a76ad5d78aee7e5be078b10af413f04dd.tar.gz
xen-2a07425a76ad5d78aee7e5be078b10af413f04dd.tar.bz2
xen-2a07425a76ad5d78aee7e5be078b10af413f04dd.zip
Merged.
-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
}