|  | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | 
|  | /* | 
|  | * guest <-> host helpers. | 
|  | * | 
|  | *  Copyright (c) 2003 Fabrice Bellard | 
|  | */ | 
|  |  | 
|  | #ifndef USER_GUEST_HOST_H | 
|  | #define USER_GUEST_HOST_H | 
|  |  | 
|  | #include "user/abitypes.h" | 
|  | #include "user/guest-base.h" | 
|  | #include "cpu.h" | 
|  |  | 
|  | /* | 
|  | * If non-zero, the guest virtual address space is a contiguous subset | 
|  | * of the host virtual address space, i.e. '-R reserved_va' is in effect | 
|  | * either from the command-line or by default.  The value is the last | 
|  | * byte of the guest address space e.g. UINT32_MAX. | 
|  | * | 
|  | * If zero, the host and guest virtual address spaces are intermingled. | 
|  | */ | 
|  | extern unsigned long reserved_va; | 
|  |  | 
|  | /* | 
|  | * Limit the guest addresses as best we can. | 
|  | * | 
|  | * When not using -R reserved_va, we cannot really limit the guest | 
|  | * to less address space than the host.  For 32-bit guests, this | 
|  | * acts as a sanity check that we're not giving the guest an address | 
|  | * that it cannot even represent.  For 64-bit guests... the address | 
|  | * might not be what the real kernel would give, but it is at least | 
|  | * representable in the guest. | 
|  | * | 
|  | * TODO: Improve address allocation to avoid this problem, and to | 
|  | * avoid setting bits at the top of guest addresses that might need | 
|  | * to be used for tags. | 
|  | */ | 
|  | #define GUEST_ADDR_MAX_                                                 \ | 
|  | ((MIN_CONST(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32) ?  \ | 
|  | UINT32_MAX : ~0ul) | 
|  | #define GUEST_ADDR_MAX    (reserved_va ? : GUEST_ADDR_MAX_) | 
|  |  | 
|  | #ifndef TARGET_TAGGED_ADDRESSES | 
|  | static inline abi_ptr cpu_untagged_addr(CPUState *cs, abi_ptr x) | 
|  | { | 
|  | return x; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */ | 
|  | static inline void *g2h_untagged(abi_ptr x) | 
|  | { | 
|  | return (void *)((uintptr_t)(x) + guest_base); | 
|  | } | 
|  |  | 
|  | static inline void *g2h(CPUState *cs, abi_ptr x) | 
|  | { | 
|  | return g2h_untagged(cpu_untagged_addr(cs, x)); | 
|  | } | 
|  |  | 
|  | static inline bool guest_addr_valid_untagged(abi_ulong x) | 
|  | { | 
|  | return x <= GUEST_ADDR_MAX; | 
|  | } | 
|  |  | 
|  | static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len) | 
|  | { | 
|  | return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1; | 
|  | } | 
|  |  | 
|  | #define h2g_valid(x) \ | 
|  | (HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS || \ | 
|  | (uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX) | 
|  |  | 
|  | #define h2g_nocheck(x) ({ \ | 
|  | uintptr_t __ret = (uintptr_t)(x) - guest_base; \ | 
|  | (abi_ptr)__ret; \ | 
|  | }) | 
|  |  | 
|  | #define h2g(x) ({ \ | 
|  | /* Check if given address fits target address space */ \ | 
|  | assert(h2g_valid(x)); \ | 
|  | h2g_nocheck(x); \ | 
|  | }) | 
|  |  | 
|  | #endif |