[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/4] linux-user: Fix page_find_alloc for 32-bit use
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH 4/4] linux-user: Fix page_find_alloc for 32-bit use on 64-bit hosts |
Date: |
Tue, 15 Jul 2008 00:09:46 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 |
page_find_alloc, used e.g. for TB allocation, is not safe on 64-bit
hosts for 32-bit guests. Patch below fixes this by requesting new pages
only from the guest-reachable address range.
Signed-off-by: Jan Kiszka <address@hidden>
---
exec.c | 24 +++++++++++++++++-------
linux-user/mmap.c | 2 +-
linux-user/qemu.h | 1 +
3 files changed, 19 insertions(+), 8 deletions(-)
Index: b/linux-user/qemu.h
===================================================================
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -232,6 +232,7 @@ void sparc64_get_context(CPUSPARCState *
#endif
/* mmap.c */
+abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
int flags, int fd, abi_ulong offset);
Index: b/linux-user/mmap.c
===================================================================
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -297,7 +297,7 @@ unsigned long last_brk;
*/
/* page_init() marks pages used by the host as reserved to be sure not
to use them. */
-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
+abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
{
abi_ulong addr, addr1, addr_start;
int prot;
Index: b/exec.c
===================================================================
--- a/exec.c
+++ b/exec.c
@@ -294,18 +294,28 @@ static inline PageDesc *page_find_alloc(
if (!p) {
/* allocate if not found */
#if defined(CONFIG_USER_ONLY)
+ void *start = NULL;
unsigned long addr;
size_t len = sizeof(PageDesc) * L2_SIZE;
- /* Don't use qemu_malloc because it may recurse. */
- p = mmap(0, len, PROT_READ | PROT_WRITE,
+
+#if TARGET_LONG_BITS < HOST_LONG_BITS
+ {
+ /* Ensure we allocate from the guest-reachable rage */
+ abi_ulong guest_start;
+
+ len = HOST_PAGE_ALIGN(len);
+ guest_start = mmap_find_vma(0, len);
+ assert(guest_start != (abi_ulong)-1);
+ start = g2h(guest_start);
+ }
+#endif
+ p = mmap(start, len, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(p != MAP_FAILED);
*lp = p;
addr = h2g(p);
- if (addr == (target_ulong)addr) {
- page_set_flags(addr & TARGET_PAGE_MASK,
- TARGET_PAGE_ALIGN(addr + len),
- PAGE_RESERVED);
- }
+ page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + len),
+ PAGE_RESERVED);
#else
p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
*lp = p;