|
@@ -0,0 +1,87 @@
|
|
|
|
+/* 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
|