[XEN][PAE] Handle non-page-aligned CR3 when walking
authorkfraser@dhcp93.uk.xensource.com <kfraser@dhcp93.uk.xensource.com>
Mon, 19 Jun 2006 13:03:04 +0000 (14:03 +0100)
committerkfraser@dhcp93.uk.xensource.com <kfraser@dhcp93.uk.xensource.com>
Mon, 19 Jun 2006 13:03:04 +0000 (14:03 +0100)
page tables.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/traps.c
xen/arch/x86/x86_32/traps.c

index 6d442ed4cade626621e9b09c02c9ed1d5f858754..7dba5ed84bc97e2200e167d721506d9fe5b9b0a7 100644 (file)
@@ -633,7 +633,7 @@ static int handle_gdt_ldt_mapping_fault(
 static int __spurious_page_fault(
     unsigned long addr, struct cpu_user_regs *regs)
 {
-    unsigned long mfn = read_cr3() >> PAGE_SHIFT;
+    unsigned long mfn, cr3 = read_cr3();
 #if CONFIG_PAGING_LEVELS >= 4
     l4_pgentry_t l4e, *l4t;
 #endif
@@ -658,6 +658,8 @@ static int __spurious_page_fault(
     if ( regs->error_code & PGERR_instr_fetch )
         disallowed_flags |= _PAGE_NX;
 
+    mfn = cr3 >> PAGE_SHIFT;
+
 #if CONFIG_PAGING_LEVELS >= 4
     l4t = map_domain_page(mfn);
     l4e = l4t[l4_table_offset(addr)];
@@ -669,7 +671,10 @@ static int __spurious_page_fault(
 #endif
 
 #if CONFIG_PAGING_LEVELS >= 3
-    l3t = map_domain_page(mfn);
+    l3t  = map_domain_page(mfn); 
+#ifdef CONFIG_X86_PAE
+    l3t += (cr3 & 0xFE0UL) >> 3;
+#endif
     l3e = l3t[l3_table_offset(addr)];
     mfn = l3e_get_pfn(l3e);
     unmap_domain_page(l3t);
index 8a4cd31a078d60cd7ed4de639260d73bc02ca2e0..c47ce087082ac22c4e2802127044ea8e66ccc634 100644 (file)
@@ -72,7 +72,7 @@ void show_registers(struct cpu_user_regs *regs)
 
 void show_page_walk(unsigned long addr)
 {
-    unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT;
+    unsigned long pfn, mfn, cr3 = read_cr3();
 #ifdef CONFIG_X86_PAE
     l3_pgentry_t l3e, *l3t;
 #endif
@@ -81,8 +81,11 @@ void show_page_walk(unsigned long addr)
 
     printk("Pagetable walk from %08lx:\n", addr);
 
+    mfn = cr3 >> PAGE_SHIFT;
+
 #ifdef CONFIG_X86_PAE
-    l3t = map_domain_page(mfn);
+    l3t  = map_domain_page(mfn);
+    l3t += (cr3 & 0xFE0UL) >> 3;
     l3e = l3t[l3_table_offset(addr)];
     mfn = l3e_get_pfn(l3e);
     pfn = get_gpfn_from_mfn(mfn);