linux-user: fix 32bit g2h()/h2g()

sparc32plus has 64bit long type but only 32bit virtual address space.

For instance, "apt-get upgrade" failed because of a mmap()/msync()
sequence.

mmap() returned 0xff252000 but msync() used g2h(0xffffffffff252000)
to find the host address. The "(target_ulong)" in g2h() doesn't fix the
address because it is 64bit long.

This patch introduces an "abi_ptr" that is set to uint32_t
if the virtual address space is addressed using 32bit in the linux-user
case. It stays set to target_ulong with softmmu case.

Backports commit 3e23de15237c81fe7af7c3ffa299a6ae5fec7d43 from qemu
This commit is contained in:
Laurent Vivier 2019-05-16 18:20:47 -04:00 committed by Lioncash
parent e736ef3238
commit 8cdfed1032
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -48,8 +48,19 @@
#define CPU_LDST_H #define CPU_LDST_H
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
/* sparc32plus has 64bit long but 32bit space address
* this can make bad result with g2h() and h2g()
*/
#if TARGET_VIRT_ADDR_SPACE_BITS <= 32
typedef uint32_t abi_ptr;
#define TARGET_ABI_FMT_ptr "%x"
#else
typedef uint64_t abi_ptr;
#define TARGET_ABI_FMT_ptr "%"PRIx64
#endif
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */ /* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE)) #define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + GUEST_BASE))
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1 #define h2g_valid(x) 1
@ -63,7 +74,7 @@
#define h2g_nocheck(x) ({ \ #define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \ unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
(abi_ulong)__ret; \ (abi_ptr)__ret; \
}) })
#define h2g(x) ({ \ #define h2g(x) ({ \
@ -71,7 +82,9 @@
assert(h2g_valid(x)); \ assert(h2g_valid(x)); \
h2g_nocheck(x); \ h2g_nocheck(x); \
}) })
#else
typedef target_ulong abi_ptr;
#define TARGET_ABI_FMT_ptr TARGET_ABI_FMT_lx
#endif #endif
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
@ -420,14 +433,14 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
* This is the equivalent of the initial fast-path code used by * This is the equivalent of the initial fast-path code used by
* TCG backends for guest load and store accesses. * TCG backends for guest load and store accesses.
*/ */
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr, static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
int access_type, int mmu_idx) int access_type, int mmu_idx)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
return g2h(addr); return g2h(addr);
#else #else
CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr); CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
target_ulong tlb_addr; abi_ptr tlb_addr;
uintptr_t haddr; uintptr_t haddr;
switch (access_type) { switch (access_type) {