diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 1f0d6af603..0e6a156bcd 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -42,8 +42,7 @@ #include "tcg/tcg.h" #include "library.h" #include "fileutils.h" -#include "bridge_private.h" -void *getAlternate(void *addr); +#include "bridge.h" extern struct elfheader_s * elf_header; #endif #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY) @@ -195,8 +194,10 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) if (qemu_loglevel_mask(CPU_LOG_EXEC)) { #ifdef CONFIG_LATX_KZT Dl_info dl_info; - if (latx_kzt_runtime_enabled() && itb->pc > reserved_va && - dladdr ((const void *)((onebridge_t *)itb->pc)->f, &dl_info)) { + uintptr_t function; + if (latx_kzt_runtime_enabled() && + kzt_registered_onebridge_snapshot(itb->pc, NULL, &function) && + dladdr((const void *)function, &dl_info)) { qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc, "pid(%d) - tid(%" PRIuPTR ") Trace cpu%d: %p [ " TARGET_FMT_lx "/%#x] KZT:%s\n", diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 6cac103e56..f4d515e257 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -3816,11 +3816,6 @@ void *page_alloc_target_data(target_ulong address, size_t size) bool page_check_range(target_ulong start, target_ulong len, int flags) { -#if defined(CONFIG_LATX_KZT) - if (latx_kzt_runtime_enabled() && start > reserved_va) { - return true; - } -#endif target_ulong last; int locked; /* tri-state: =0: unlocked, +1: global, -1: local */ bool ret; diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index b5f38f390b..748f8177ca 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -37,6 +37,10 @@ #include "latx-options.h" #include "latx-backtrace.h" #include "latx-smc.h" +#if defined(CONFIG_LATX_KZT) +#include "bridge.h" +#include "wrappertbbridge.h" +#endif #endif #ifdef CONFIG_LATX_DEBUG #include "latx-debug.h" @@ -724,8 +728,21 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, g_assert_not_reached(); } - if (!guest_addr_valid_untagged(addr) || - !page_check_range(addr, 1, flags)) { + bool valid = guest_addr_valid_untagged(addr) && + page_check_range(addr, 1, flags); + +#if defined(CONFIG_LATX_KZT) + if (!valid && latx_kzt_runtime_enabled()) { + if (access_type == MMU_INST_FETCH) { + valid = kzt_is_registered_onebridge(addr) || + kzt_tbbridge_contains(addr); + } else if (!guest_addr_valid_untagged(addr)) { + valid = kzt_data_addr_valid_untagged(addr); + } + } +#endif + + if (!valid) { if (nonfault) { return TLB_INVALID_MASK; } else { diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index 9e0fd328e3..71502fdd06 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -59,6 +59,7 @@ #if defined(CONFIG_LATX_KZT) #include "kzt-runtime.h" +#include "kzt-address-policy.h" #endif #if defined(CONFIG_USER_ONLY) /* sparc32plus has 64bit long but 32bit space address @@ -93,23 +94,42 @@ static inline void *g2h(CPUState *cs, abi_ptr x) static inline bool guest_addr_valid_untagged(abi_ulong x) { #if defined(CONFIG_LATX_KZT) - if (latx_kzt_runtime_enabled()) { - return true; - } else -#endif + return kzt_guest_addr_is_valid(x, GUEST_ADDR_MAX); +#else return x <= GUEST_ADDR_MAX; +#endif } static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len) { #if defined(CONFIG_LATX_KZT) - if (latx_kzt_runtime_enabled()) { - return true; - } else -#endif + return kzt_guest_range_is_valid(start, len, GUEST_ADDR_MAX); +#else return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1; +#endif +} + +#if defined(CONFIG_LATX_KZT) +/* + * KZT wrappers may expose host-owned objects to translated code. Keep that + * compatibility permission separate from the guest virtual-address policy: + * callers which create, remove, or protect guest mappings must continue to + * use guest_addr_valid_untagged() and guest_range_valid_untagged(). + */ +static inline bool kzt_data_addr_valid_untagged(abi_ulong addr) +{ + return kzt_data_addr_is_valid(latx_kzt_runtime_enabled(), addr, + GUEST_ADDR_MAX); } +static inline bool kzt_data_range_valid_untagged(abi_ulong start, + abi_ulong len) +{ + return kzt_data_range_is_valid(latx_kzt_runtime_enabled(), start, len, + GUEST_ADDR_MAX); +} +#endif + #define h2g_valid(x) \ (HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS || \ (uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index cba8f748b3..70d1c8c2aa 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -638,11 +638,28 @@ extern unsigned long vir_rlimit_as_acc; static inline bool access_ok_untagged(int type, abi_ulong addr, abi_ulong size) { +#if defined(CONFIG_LATX_KZT) + bool guest_range = size == 0 + ? guest_addr_valid_untagged(addr) + : guest_range_valid_untagged(addr, size); + + if (size == 0 + ? !kzt_data_addr_valid_untagged(addr) + : !kzt_data_range_valid_untagged(addr, size)) { + return false; + } + + /* Native wrapper objects do not have entries in the guest page map. */ + if (!guest_range) { + return true; + } +#else if (size == 0 ? !guest_addr_valid_untagged(addr) : !guest_range_valid_untagged(addr, size)) { return false; } +#endif return page_check_range((target_ulong)addr, size, type); } diff --git a/target/i386/latx/context/bridge.c b/target/i386/latx/context/bridge.c index 6083f9d357..ce2a066d15 100755 --- a/target/i386/latx/context/bridge.c +++ b/target/i386/latx/context/bridge.c @@ -29,14 +29,46 @@ typedef struct brick_s { onebridge_t *b; int sz; brick_t *next; + brick_t *registry_next; } brick_t; typedef struct bridge_s { brick_t *head; brick_t *last; // to speed up kh_bridgemap_t *bridgemap; + GMutex lock; } bridge_t; +static GMutex bridge_registry_lock; +static brick_t *bridge_registry; + +static void register_brick(brick_t *brick) +{ + if (brick->b == MAP_FAILED) { + return; + } + + g_mutex_lock(&bridge_registry_lock); + brick->registry_next = bridge_registry; + bridge_registry = brick; + g_mutex_unlock(&bridge_registry_lock); +} + +static void unregister_brick(brick_t *brick) +{ + brick_t **link; + + g_mutex_lock(&bridge_registry_lock); + for (link = &bridge_registry; *link; link = &(*link)->registry_next) { + if (*link == brick) { + *link = brick->registry_next; + break; + } + } + brick->registry_next = NULL; + g_mutex_unlock(&bridge_registry_lock); +} + //from wrapped/wrappedlibc.c //void* my_mmap(x64emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int64_t offset); //int my_munmap(x64emu_t* emu, void* addr, unsigned long length); @@ -50,12 +82,14 @@ brick_t* NewBrick(void) printf("Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t)); } ret->b = ptr; + register_brick(ret); return ret; } bridge_t *NewBridge(void) { bridge_t *b = (bridge_t*)box_calloc(1, sizeof(bridge_t)); + g_mutex_init(&b->lock); b->head = NewBrick(); b->last = b->head; b->bridgemap = kh_init(bridgemap); @@ -66,14 +100,18 @@ void FreeBridge(bridge_t** bridge) { if(!bridge || !*bridge) return; + g_mutex_lock(&(*bridge)->lock); brick_t *b = (*bridge)->head; while(b) { brick_t *n = b->next; + unregister_brick(b); munmap(b->b, NBRICK*sizeof(onebridge_t)); box_free(b); b = n; } kh_destroy(bridgemap, (*bridge)->bridgemap); + g_mutex_unlock(&(*bridge)->lock); + g_mutex_clear(&(*bridge)->lock); box_free(*bridge); *bridge = NULL; } @@ -82,6 +120,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* { brick_t *b = NULL; int sz = -1; + g_mutex_lock(&bridge->lock); b = bridge->last; if(b->sz == NBRICK) { b->next = NewBrick(); @@ -89,28 +128,81 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* bridge->last = b; } sz = b->sz; - b->sz++; + g_mutex_lock(&bridge_registry_lock); b->b[sz].CC = 0xCC; b->b[sz].S = 'S'; b->b[sz].C='C'; b->b[sz].w = w; b->b[sz].f = (uintptr_t)fnc; b->b[sz].C3 = N?0xC2:0xC3; b->b[sz].N = N; + b->sz++; + g_mutex_unlock(&bridge_registry_lock); // add bridge to map, for fast recovery int ret; khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret); kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC; + g_mutex_unlock(&bridge->lock); return (uintptr_t)&b->b[sz].CC; } +static onebridge_t *find_registered_onebridge(uintptr_t addr) +{ + for (brick_t *brick = bridge_registry; brick; + brick = brick->registry_next) { + uintptr_t start = (uintptr_t)brick->b; + uintptr_t used_end = start + brick->sz * sizeof(onebridge_t); + + if (addr >= start && addr < used_end && + (addr - start) % sizeof(onebridge_t) == 0) { + onebridge_t *slot = (onebridge_t *)addr; + + return slot->CC == 0xCC && slot->S == 'S' && slot->C == 'C' && + (slot->C3 == 0xC3 || slot->C3 == 0xC2) ? slot : NULL; + } + } + + return NULL; +} + +bool kzt_is_registered_onebridge(uintptr_t addr) +{ + g_mutex_lock(&bridge_registry_lock); + bool found = find_registered_onebridge(addr) != NULL; + g_mutex_unlock(&bridge_registry_lock); + return found; +} + +bool kzt_registered_onebridge_snapshot(uintptr_t addr, wrapper_t *wrapper, + uintptr_t *function) +{ + g_mutex_lock(&bridge_registry_lock); + onebridge_t *slot = find_registered_onebridge(addr); + + if (slot) { + if (wrapper) { + *wrapper = slot->w; + } + if (function) { + *function = slot->f; + } + } + g_mutex_unlock(&bridge_registry_lock); + return slot != NULL; +} + uintptr_t CheckBridged(bridge_t* bridge, void* fnc) { // check if function alread have a bridge (the function wrapper will not be tested) + g_mutex_lock(&bridge->lock); khint_t k = kh_get(bridgemap, bridge->bridgemap, (uintptr_t)fnc); - if(k==kh_end(bridge->bridgemap)) + if (k == kh_end(bridge->bridgemap)) { + g_mutex_unlock(&bridge->lock); return 0; - return kh_value(bridge->bridgemap, k); + } + uintptr_t ret = kh_value(bridge->bridgemap, k); + g_mutex_unlock(&bridge->lock); + return ret; } uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name) diff --git a/target/i386/latx/context/wrappertbbridge.c b/target/i386/latx/context/wrappertbbridge.c index 2305058a41..fb3f4ffd39 100644 --- a/target/i386/latx/context/wrappertbbridge.c +++ b/target/i386/latx/context/wrappertbbridge.c @@ -37,15 +37,23 @@ void* kzt_tbbridge_init(void) } struct kzt_tbbridge* kzt_tbbridge_lookup(target_ulong pc) { - lsassert(tree&&pc); + if (!pc) { + return NULL; + } struct kzt_tbbridge key = {.pc = pc}; g_mutex_lock(&tree_lock); - struct kzt_tbbridge *bridge = - (struct kzt_tbbridge *)g_tree_lookup(tree, &key); + struct kzt_tbbridge *bridge = tree + ? (struct kzt_tbbridge *)g_tree_lookup(tree, &key) + : NULL; g_mutex_unlock(&tree_lock); return bridge; } +bool kzt_tbbridge_contains(target_ulong pc) +{ + return kzt_tbbridge_lookup(pc) != NULL; +} + int kzt_tbbridge_insert(target_ulong pc, ADDR func, void * wrapper) { lsassert(tree&&pc&&wrapper); diff --git a/target/i386/latx/include/bridge.h b/target/i386/latx/include/bridge.h index 67166a9f3b..fec6511d65 100755 --- a/target/i386/latx/include/bridge.h +++ b/target/i386/latx/include/bridge.h @@ -15,6 +15,9 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* uintptr_t CheckBridged(bridge_t* bridge, void* fnc); uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name); uintptr_t AddAutomaticBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N); +bool kzt_is_registered_onebridge(uintptr_t addr); +bool kzt_registered_onebridge_snapshot(uintptr_t addr, wrapper_t *wrapper, + uintptr_t *function); void* GetNativeFnc(uintptr_t fnc); void* GetNativeFncOrFnc(uintptr_t fnc); diff --git a/target/i386/latx/include/kzt-address-policy.h b/target/i386/latx/include/kzt-address-policy.h new file mode 100644 index 0000000000..85a2371fb2 --- /dev/null +++ b/target/i386/latx/include/kzt-address-policy.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2026 LAT Project Authors + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef KZT_ADDRESS_POLICY_H +#define KZT_ADDRESS_POLICY_H + +#include +#include + +static inline bool kzt_guest_addr_is_valid(uint64_t addr, + uint64_t guest_addr_max) +{ + return addr <= guest_addr_max; +} + +static inline bool kzt_guest_range_is_valid(uint64_t start, uint64_t len, + uint64_t guest_addr_max) +{ + return len - 1 <= guest_addr_max && + start <= guest_addr_max - len + 1; +} + +static inline bool kzt_data_addr_is_valid(bool kzt_enabled, uint64_t addr, + uint64_t guest_addr_max) +{ + return kzt_guest_addr_is_valid(addr, guest_addr_max) || kzt_enabled; +} + +static inline bool kzt_data_range_is_valid(bool kzt_enabled, uint64_t start, + uint64_t len, + uint64_t guest_addr_max) +{ + if (kzt_guest_range_is_valid(start, len, guest_addr_max)) { + return true; + } + + /* A host-pointer exception must never make an overflowing range valid. */ + return kzt_enabled && start > guest_addr_max && len != 0 && + start <= UINT64_MAX - len + 1; +} + +#endif diff --git a/target/i386/latx/include/wrappertbbridge.h b/target/i386/latx/include/wrappertbbridge.h index c1af2127d2..b2cf8d3a91 100644 --- a/target/i386/latx/include/wrappertbbridge.h +++ b/target/i386/latx/include/wrappertbbridge.h @@ -13,5 +13,6 @@ struct kzt_tbbridge { void* kzt_tbbridge_init(void); struct kzt_tbbridge* kzt_tbbridge_lookup(target_ulong pc); +bool kzt_tbbridge_contains(target_ulong pc); int kzt_tbbridge_insert(target_ulong pc, ADDR func, void * wrapper); #endif diff --git a/target/i386/latx/latx-config.c b/target/i386/latx/latx-config.c index 536d2d4b61..3d067e169b 100644 --- a/target/i386/latx/latx-config.c +++ b/target/i386/latx/latx-config.c @@ -18,6 +18,9 @@ #include "translate.h" #include "latx-config.h" #include "syscall-tunnel.h" +#if defined(CONFIG_LATX_KZT) +#include "wrappertbbridge.h" +#endif #ifdef CONFIG_LATX_TU #include "tu.h" @@ -97,9 +100,16 @@ int target_latx_host(CPUArchState *env, struct TranslationBlock *tb, if (option_anonym && (tb->flags & HF_TF_MASK)) { max_insns = 1; } - tr_disasm(tb, max_insns); + bool is_tbbridge = false; +#if defined(CONFIG_LATX_KZT) + is_tbbridge = latx_kzt_runtime_enabled() && + kzt_tbbridge_contains(tb->pc); +#endif + if (!is_tbbridge) { + tr_disasm(tb, max_insns); + } /* return code_size and skip translate */ - if (!tb->icount && tb->pc < reserved_va) { + if (!tb->icount && !is_tbbridge) { return 0; } diff --git a/target/i386/latx/translator/tr-misc.c b/target/i386/latx/translator/tr-misc.c index ee73075049..d1fd068950 100644 --- a/target/i386/latx/translator/tr-misc.c +++ b/target/i386/latx/translator/tr-misc.c @@ -9,6 +9,9 @@ #include "latx-config.h" #include "lsenv.h" #include "flag-lbt.h" +#if defined(CONFIG_LATX_KZT) +#include "bridge.h" +#endif #include "translate.h" #include "syscall-tunnel.h" #include "profile.h" @@ -19,7 +22,6 @@ #if defined(CONFIG_LATX_KZT) #include "wrapper.h" #include "debug.h" -#include "bridge_private.h" #include "exec/tb-lookup.h" #include "elfloader.h" @@ -41,11 +43,6 @@ bool translate_endbr32(IR1_INST *pir1) { return true; } bool translate_endbr64(IR1_INST *pir1) { return true; } #if defined(CONFIG_LATX_KZT) -static uint8_t Peek8(uintptr_t addr, uintptr_t offset) -{ - return *(uint8_t*)(addr+offset); -} - static void gen_set_next_tb_code(IR2_OPND *esp_ir2_opnd) { IR2_OPND nextip_ir2_opnd = ra_alloc_dbt_arg2(); @@ -203,22 +200,28 @@ static void do_translate_free_brick_tb(void) tr_generate_exit_tb_for_bridge(); } -static void do_translate_brick_tb(onebridge_t *bridge, struct cpu_state_info *state_info, CPUState *cpu, target_ulong tb_pc, TranslationBlock *tb) +static void do_translate_brick_tb(wrapper_t wrapper, uintptr_t function, + struct cpu_state_info *state_info, + CPUState *cpu, target_ulong tb_pc, + TranslationBlock *tb) { tb = lsenv->tr_data->curr_tb; IR2_OPND esp_ir2_opnd = ra_alloc_gpr(esp_index); - if (bridge->f == (uintptr_t)my_free ||bridge->f == (uintptr_t)my___libc_free ||bridge->f == (uintptr_t)my___free ||bridge->f == (uintptr_t)my_cfree ) { + if (function == (uintptr_t)my_free || + function == (uintptr_t)my___libc_free || + function == (uintptr_t)my___free || + function == (uintptr_t)my_cfree) { do_translate_free_brick_tb(); return; - } else if (bridge->f == (uintptr_t)my_realloc) { + } else if (function == (uintptr_t)my_realloc) { do_translate_realloc_brick_tb(); return; } kzt_native_to_wrapper(); - wrapper_gpr_trans((ADDR)bridge->f); + wrapper_gpr_trans((ADDR)function); tr_set_running_of_cs(false); - li_d(ra_ir2_opnd, (ADDR)bridge->w); + li_d(ra_ir2_opnd, (ADDR)wrapper); la_jirl(ra_ir2_opnd, ra_ir2_opnd, 0); tr_set_running_of_cs(true); @@ -256,14 +259,15 @@ bool translate_int_3(IR1_INST *pir1) state_info.cflags = cpu->tcg_cflags; cpu_get_tb_cpu_state(cpu->env_ptr, &state_info.current_pc, &state_info.cs_base, &state_info.flags); + wrapper_t wrapper; + uintptr_t function; if (latx_kzt_runtime_enabled() && - Peek8(state_info.current_pc + 1, 0) == 'S' && - Peek8(state_info.current_pc + 1, 1) == 'C') - { + kzt_registered_onebridge_snapshot(state_info.current_pc, + &wrapper, &function)) { TranslationBlock *tb = NULL; mmap_lock(); - onebridge_t *bridge= (onebridge_t*)state_info.current_pc; - do_translate_brick_tb(bridge, &state_info, cpu, state_info.current_pc, tb); + do_translate_brick_tb(wrapper, function, &state_info, cpu, + state_info.current_pc, tb); mmap_unlock(); } else { la_break(0x5); diff --git a/target/i386/latx/translator/translate.c b/target/i386/latx/translator/translate.c index c7787b2f84..01d2f35b35 100644 --- a/target/i386/latx/translator/translate.c +++ b/target/i386/latx/translator/translate.c @@ -2305,7 +2305,9 @@ void do_translate_tbbridge(ADDR func_pc, ADDR wrapper, TranslationBlock *tb); static int kzt_tr_bridge(struct TranslationBlock *tb) { struct kzt_tbbridge* bridge = kzt_tbbridge_lookup(tb->pc); - lsassert(bridge); + if (!bridge) { + return 0; + } do_translate_tbbridge(bridge->func, (ADDR)bridge->wrapper, tb); return 1; } @@ -2350,7 +2352,8 @@ int tr_translate_tb(struct TranslationBlock *tb) /* generate ir2 from ir1 */ #if defined(CONFIG_LATX_KZT) int translation_done = 0; - if (unlikely(!tb->icount && tb->pc > reserved_va)) { + if (unlikely(latx_kzt_runtime_enabled() && + kzt_tbbridge_contains(tb->pc))) { translation_done = kzt_tr_bridge(tb); } else { translation_done = tr_ir2_generate(tb); diff --git a/tests/unit/kzt/test_kzt_address_policy.c b/tests/unit/kzt/test_kzt_address_policy.c new file mode 100644 index 0000000000..18d8c6cda6 --- /dev/null +++ b/tests/unit/kzt/test_kzt_address_policy.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2026 LAT Project Authors + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include + +#include "kzt-address-policy.h" + +static const uint64_t guest_addr_max = 0x3fffffffffULL; + +#define CHECK(condition) do { \ + if (!(condition)) { \ + abort(); \ + } \ +} while (0) + +static void test_guest_vm_policy_stays_strict(void) +{ + CHECK(kzt_guest_addr_is_valid(guest_addr_max, guest_addr_max)); + CHECK(!kzt_guest_addr_is_valid(guest_addr_max + 1, guest_addr_max)); + + CHECK(kzt_guest_range_is_valid(guest_addr_max - 0xfff, 0x1000, + guest_addr_max)); + CHECK(!kzt_guest_range_is_valid(guest_addr_max, 2, guest_addr_max)); + CHECK(!kzt_guest_range_is_valid(UINT64_MAX - 1, 4, guest_addr_max)); + CHECK(!kzt_guest_range_is_valid(0, 0, guest_addr_max)); +} + +static void test_kzt_data_policy_keeps_host_pointer_compatibility(void) +{ + uint64_t host_pointer = guest_addr_max + 0x10000; + + CHECK(!kzt_data_addr_is_valid(false, host_pointer, guest_addr_max)); + CHECK(kzt_data_addr_is_valid(true, host_pointer, guest_addr_max)); + + CHECK(!kzt_data_range_is_valid(false, host_pointer, 32, + guest_addr_max)); + CHECK(kzt_data_range_is_valid(true, host_pointer, 32, + guest_addr_max)); + + CHECK(!kzt_data_range_is_valid(true, guest_addr_max, 2, + guest_addr_max)); + CHECK(!kzt_data_range_is_valid(true, UINT64_MAX - 1, 4, + guest_addr_max)); + CHECK(!kzt_data_range_is_valid(true, host_pointer, 0, + guest_addr_max)); +} + +int main(void) +{ + test_guest_vm_policy_stays_strict(); + test_kzt_data_policy_keeps_host_pointer_compatibility(); + return 0; +} diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 458cc540cd..50280c8dc8 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -154,3 +154,18 @@ test( test_kzt_relocation_transaction, suite: 'lat-pr-fast', ) + +test_kzt_address_policy = executable( + 'test-kzt-address-policy', + files('kzt/test_kzt_address_policy.c'), + include_directories: include_directories( + '../../target/i386/latx/include', + ), + build_by_default: false, +) + +test( + 'test-kzt-address-policy', + test_kzt_address_policy, + suite: 'lat-pr-fast', +)