To enable 64-bit guest support in Wasm 32bit memory model today, it was necessary to partially revert recent changes that removed support for different pointer widths between the host and guest (e.g. commits a70af12addd9060fdf8f3dbd42b42e3072c3914f and bf455ec50b6fea15b4d2493059365bf94c706273) when compiling with Emscripten. While this serves as a temporary workaround, a long-term solution could involve adopting Wasm's 64-bit memory model once it gains broader support, as it is currently not widely adopted (e.g. unsupported by Safari and libffi).
Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com> --- accel/tcg/cputlb.c | 8 ++++---- include/exec/helper-head.h.inc | 6 ++++++ include/exec/tlb-common.h | 14 ++++++++++---- include/exec/vaddr.h | 11 +++++++++++ include/qemu/atomic.h | 4 ++++ include/tcg/tcg.h | 4 ++++ meson.build | 8 +++++--- 7 files changed, 44 insertions(+), 11 deletions(-) V1: - Although I tried to use "#if HOST_LONG_BITS >= TARGET_LONG_BITS" based on Paolo's suggestion from the previous patch series, TARGET_LONG_BITS is marked as poisoned in include/exec/poison.h and cannot be used directly. diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 5f6d7c601c..b15e9e80ee 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -109,13 +109,13 @@ static inline uint64_t tlb_read_idx(const CPUTLBEntry *entry, { /* Do not rearrange the CPUTLBEntry structure members. */ QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_read) != - MMU_DATA_LOAD * sizeof(uintptr_t)); + MMU_DATA_LOAD * sizeof(tlb_addr)); QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_write) != - MMU_DATA_STORE * sizeof(uintptr_t)); + MMU_DATA_STORE * sizeof(tlb_addr)); QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_code) != - MMU_INST_FETCH * sizeof(uintptr_t)); + MMU_INST_FETCH * sizeof(tlb_addr)); - const uintptr_t *ptr = &entry->addr_idx[access_type]; + const tlb_addr *ptr = &entry->addr_idx[access_type]; /* ofs might correspond to .addr_write, so use qatomic_read */ return qatomic_read(ptr); } diff --git a/include/exec/helper-head.h.inc b/include/exec/helper-head.h.inc index 5b248fd713..7dfb4cfa46 100644 --- a/include/exec/helper-head.h.inc +++ b/include/exec/helper-head.h.inc @@ -58,6 +58,7 @@ # define dh_ctype_tl target_ulong #endif /* COMPILING_PER_TARGET */ +#ifndef EMSCRIPTEN #if __SIZEOF_POINTER__ == 4 # define dh_alias_vaddr i32 # define dh_typecode_vaddr dh_typecode_i32 @@ -68,6 +69,11 @@ # error "sizeof pointer is different from {4,8}" #endif /* __SIZEOF_POINTER__ */ # define dh_ctype_vaddr uintptr_t +#else +# define dh_alias_vaddr i64 +# define dh_typecode_vaddr dh_typecode_i64 +# define dh_ctype_vaddr uint64_t +#endif /* We can't use glue() here because it falls foul of C preprocessor recursive expansion rules. */ diff --git a/include/exec/tlb-common.h b/include/exec/tlb-common.h index 03b5a8ffc7..679054bb44 100644 --- a/include/exec/tlb-common.h +++ b/include/exec/tlb-common.h @@ -19,14 +19,20 @@ #ifndef EXEC_TLB_COMMON_H #define EXEC_TLB_COMMON_H 1 +#ifndef EMSCRIPTEN #define CPU_TLB_ENTRY_BITS (HOST_LONG_BITS == 32 ? 4 : 5) +typedef uintptr_t tlb_addr; +#else +#define CPU_TLB_ENTRY_BITS 5 +typedef uint64_t tlb_addr; +#endif /* Minimalized TLB entry for use by TCG fast path. */ typedef union CPUTLBEntry { struct { - uintptr_t addr_read; - uintptr_t addr_write; - uintptr_t addr_code; + tlb_addr addr_read; + tlb_addr addr_write; + tlb_addr addr_code; /* * Addend to virtual address to get host address. IO accesses * use the corresponding iotlb value. @@ -37,7 +43,7 @@ typedef union CPUTLBEntry { * Padding to get a power of two size, as well as index * access to addr_{read,write,code}. */ - uintptr_t addr_idx[(1 << CPU_TLB_ENTRY_BITS) / sizeof(uintptr_t)]; + tlb_addr addr_idx[(1 << CPU_TLB_ENTRY_BITS) / sizeof(tlb_addr)]; } CPUTLBEntry; QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS)); diff --git a/include/exec/vaddr.h b/include/exec/vaddr.h index 28bec632fb..ff57f944dd 100644 --- a/include/exec/vaddr.h +++ b/include/exec/vaddr.h @@ -9,6 +9,7 @@ * We do not support 64-bit guest on 32-host and detect at configure time. * Therefore, a host pointer width will always fit a guest pointer. */ +#ifndef EMSCRIPTEN typedef uintptr_t vaddr; #define VADDR_PRId PRIdPTR #define VADDR_PRIu PRIuPTR @@ -16,5 +17,15 @@ typedef uintptr_t vaddr; #define VADDR_PRIx PRIxPTR #define VADDR_PRIX PRIXPTR #define VADDR_MAX UINTPTR_MAX +#else +/* Explicitly define this as 64bit on emscripten */ +typedef uint64_t vaddr; +#define VADDR_PRId PRId64 +#define VADDR_PRIu PRIu64 +#define VADDR_PRIo PRIo64 +#define VADDR_PRIx PRIx64 +#define VADDR_PRIX PRIX64 +#define VADDR_MAX UINT64_MAX +#endif #endif diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index f80cba24cf..76a8fbcd8c 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -56,6 +56,7 @@ */ #define signal_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST) +#ifndef EMSCRIPTEN /* * Sanity check that the size of an atomic operation isn't "overly large". * Despite the fact that e.g. i686 has 64-bit atomic operations, we do not @@ -63,6 +64,9 @@ * bit of sanity checking that other 32-bit hosts might build. */ #define ATOMIC_REG_SIZE sizeof(void *) +#else +#define ATOMIC_REG_SIZE 8 /* wasm supports 64bit atomics */ +#endif /* Weak atomic operations prevent the compiler moving other * loads/stores past the atomic operation load/store. However there is diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 041d8035bc..62bc2c4ea8 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -218,6 +218,7 @@ typedef struct TCGv_ptr_d *TCGv_ptr; typedef struct TCGv_vec_d *TCGv_vec; typedef TCGv_ptr TCGv_env; +#ifndef EMSCRIPTEN #if __SIZEOF_POINTER__ == 4 typedef TCGv_i32 TCGv_vaddr; #elif __SIZEOF_POINTER__ == 8 @@ -225,6 +226,9 @@ typedef TCGv_i64 TCGv_vaddr; #else # error "sizeof pointer is different from {4,8}" #endif /* __SIZEOF_POINTER__ */ +#else +typedef TCGv_i64 TCGv_vaddr; +#endif /* call flags */ /* Helper does not read globals (either directly or through an exception). It diff --git a/meson.build b/meson.build index c533243157..f6ed867819 100644 --- a/meson.build +++ b/meson.build @@ -3322,9 +3322,11 @@ foreach target : target_dirs target_kconfig = [] foreach sym: accelerators - # Disallow 64-bit on 32-bit emulation and virtualization - if host_long_bits < config_target['TARGET_LONG_BITS'].to_int() - continue + if host_arch != 'wasm32' + # Disallow 64-bit on 32-bit emulation and virtualization + if host_long_bits < config_target['TARGET_LONG_BITS'].to_int() + continue + endif endif if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, []) config_target += { sym: 'y' } -- 2.43.0