]> git.proxmox.com Git - mirror_qemu.git/commitdiff
x86: only allow real mode to access 32bit without LMA
authorAlexander Graf <agraf@suse.de>
Fri, 6 Dec 2013 12:52:24 +0000 (13:52 +0100)
committerMichael Tokarev <mjt@tls.msk.ru>
Mon, 23 Dec 2013 12:02:20 +0000 (16:02 +0400)
When we're running in non-64bit mode with qemu-system-x86_64 we can
still end up with virtual addresses that are above the 32bit boundary
if a segment offset is set up.

GNU Hurd does exactly that. It sets the segment offset to 0x80000000 and
puts its EIP value to 0x8xxxxxxx to access low memory.

This doesn't hit us when we enable paging, as there we just mask away the
unused bits. But with real mode, we assume that vaddr == paddr which is
wrong in this case. Real hardware wraps the virtual address around at the
32bit boundary. So let's do the same.

This fixes booting GNU Hurd in qemu-system-x86_64 for me.

Reported-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
target-i386/helper.c

index 7c196ffc42167d1ec5777b7c9588478ee7e2aa05..ed965d634d3e7bda91be67c1fe312db146ed0a2d 100644 (file)
@@ -531,6 +531,12 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
         pte = addr;
+#ifdef TARGET_X86_64
+        if (!(env->hflags & HF_LMA_MASK)) {
+            /* Without long mode we can only address 32bits in real mode */
+            pte = (uint32_t)pte;
+        }
+#endif
         virt_addr = addr & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         page_size = 4096;