qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] cpu_get_phys_page_debug/PAE


From: Filip Navara
Subject: [Qemu-devel] [PATCH] cpu_get_phys_page_debug/PAE
Date: Mon, 24 Jan 2005 23:48:12 +0100
User-agent: Mozilla Thunderbird 0.9 (Windows/20041103)

Changelog:

2005-01-24  Filip Navara <address@hidden>
* Support resolving addresses in PAE mode in cpu_get_phys_page_debug.

Index: target-i386/helper2.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper2.c,v
retrieving revision 1.29
diff -u -r1.29 helper2.c
--- target-i386/helper2.c       12 Jan 2005 22:46:19 -0000      1.29
+++ target-i386/helper2.c       24 Jan 2005 22:08:51 -0000
@@ -745,30 +756,86 @@
     uint8_t *pde_ptr, *pte_ptr;
     uint32_t pde, pte, paddr, page_offset, page_size;
 
-    if (!(env->cr[0] & CR0_PG_MASK)) {
-        pte = addr;
-        page_size = 4096;
-    } else {
-        /* page directory entry */
-        pde_ptr = phys_ram_base + 
-            (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
-        pde = ldl_raw(pde_ptr);
-        if (!(pde & PG_PRESENT_MASK)) 
+    if (env->cr[4] & CR4_PAE_MASK) {
+        uint32_t pdpe_addr, pde_addr, pte_addr;
+        uint32_t pdpe;
+
+        /* XXX: we only use 32 bit physical addresses */
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_LMA_MASK) {
+            uint32_t pml4e_addr, pml4e;
+            int32_t sext;
+
+            /* test virtual address sign extension */
+            sext = (int64_t)addr >> 47;
+            if (sext != 0 && sext != -1)
+                return -1;
+            
+            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 
3)) & 
+                env->a20_mask;
+            pml4e = ldl_phys_aligned(pml4e_addr);
+            if (!(pml4e & PG_PRESENT_MASK))
+                return -1;
+            
+            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
+                env->a20_mask;
+            pdpe = ldl_phys_aligned(pdpe_addr);
+            if (!(pdpe & PG_PRESENT_MASK))
+                return -1;
+        } else 
+#endif
+        {
+            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
+                env->a20_mask;
+            pdpe = ldl_phys_aligned(pdpe_addr);
+            if (!(pdpe & PG_PRESENT_MASK))
+                return -1;
+        }
+
+        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
+            env->a20_mask;
+        pde = ldl_phys_aligned(pde_addr);
+        if (!(pde & PG_PRESENT_MASK)) {
             return -1;
-        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
-            pte = pde & ~0x003ff000; /* align to 4MB */
-            page_size = 4096 * 1024;
+        }
+        if (pde & PG_PSE_MASK) {
+            /* 2 MB page */
+            page_size = 2048 * 1024;
+            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
+        } else {
+            /* 4 KB page */
+            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
+                env->a20_mask;
+            page_size = 4096;
+            pte = ldl_phys_aligned(pte_addr);
+        }
+    } else {
+        if (!(env->cr[0] & CR0_PG_MASK)) {
+            pte = addr;
+            page_size = 4096;
         } else {
             /* page directory entry */
-            pte_ptr = phys_ram_base + 
-                (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
-            pte = ldl_raw(pte_ptr);
-            if (!(pte & PG_PRESENT_MASK))
+            pde_ptr = phys_ram_base + 
+                (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & 
env->a20_mask);
+            pde = ldl_raw(pde_ptr);
+            if (!(pde & PG_PRESENT_MASK)) 
                 return -1;
-            page_size = 4096;
+            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
+                pte = pde & ~0x003ff000; /* align to 4MB */
+                page_size = 4096 * 1024;
+            } else {
+                /* page directory entry */
+                pte_ptr = phys_ram_base + 
+                    (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & 
env->a20_mask);
+                pte = ldl_raw(pte_ptr);
+                if (!(pte & PG_PRESENT_MASK))
+                    return -1;
+                page_size = 4096;
+            }
         }
+        pte = pte & env->a20_mask;
     }
-    pte = pte & env->a20_mask;
+
     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
     return paddr;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]