From bc73cb232d0122b28dd49d96e74661a76ca05d57 Mon Sep 17 00:00:00 2001 From: ExhoAR22 Date: Tue, 1 Apr 2025 05:53:18 +0300 Subject: [PATCH] Fix physical address truncation on 32-bit systems with addressing extensions (#2139) * use hwaddr for paddrs * Fix the truncation for memory hooks as well * Add LPAE regression test Co-authored-by: Takacs, Philipp --- qemu/accel/tcg/cputlb.c | 4 ++-- qemu/include/exec/cpu-defs.h | 2 +- qemu/include/exec/exec-all.h | 2 +- tests/unit/test_arm.c | 42 ++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 30e47e24..f7ffee48 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1469,7 +1469,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read; - target_ulong paddr; + hwaddr paddr; const size_t tlb_off = code_read ? offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read); const MMUAccessType access_type = @@ -2090,7 +2090,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); target_ulong tlb_addr = tlb_addr_write(entry); - target_ulong paddr; + hwaddr paddr; const size_t tlb_off = offsetof(CPUTLBEntry, addr_write); unsigned a_bits = get_alignment_bits(get_memop(oi)); void *haddr; diff --git a/qemu/include/exec/cpu-defs.h b/qemu/include/exec/cpu-defs.h index 8c42b4fa..5c110155 100644 --- a/qemu/include/exec/cpu-defs.h +++ b/qemu/include/exec/cpu-defs.h @@ -112,7 +112,7 @@ typedef struct CPUTLBEntry { target_ulong addr_read; target_ulong addr_write; target_ulong addr_code; - target_ulong paddr; + hwaddr paddr; /* Addend to virtual address to get host address. IO accesses use the corresponding iotlb value. */ uintptr_t addend; diff --git a/qemu/include/exec/exec-all.h b/qemu/include/exec/exec-all.h index 3b23c304..68c65678 100644 --- a/qemu/include/exec/exec-all.h +++ b/qemu/include/exec/exec-all.h @@ -477,7 +477,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, hwaddr memory_region_section_get_iotlb(CPUState *cpu, MemoryRegionSection *section); -static inline bool uc_mem_hook_installed(struct uc_struct *uc, target_ulong paddr) +static inline bool uc_mem_hook_installed(struct uc_struct *uc, hwaddr paddr) { if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_MEM_FETCH_UNMAPPED, paddr)) return true; diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 538a91c0..309b5ccb 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -956,6 +956,47 @@ static void test_arm_cp15_c1_c0_2(void) OK(uc_close(uc)); } +static bool test_arm_v7_lpae_hook_tlb(uc_engine *uc, uint64_t addr, + uc_mem_type type, uc_tlb_entry *result, + void *user_data) +{ + result->paddr = addr + 0x100000000; + result->perms = UC_PROT_ALL; + return 1; +} + +static void test_arm_v7_lpae_hook_read(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, uint64_t value, + void *user_data) +{ + TEST_CHECK(address == 0x100001000); +} + +static void test_arm_v7_lpae(void) +{ + uc_engine *uc; + uc_hook hook_read, hook_tlb; + uint32_t reg; + char code[] = "\x00\x10\x90\xe5"; // ldr r1, [r0] + OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc)); + OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_A7)); + + + OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)); + OK(uc_hook_add(uc, &hook_tlb, UC_HOOK_TLB_FILL, test_arm_v7_lpae_hook_tlb, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook_read, UC_HOOK_MEM_READ, test_arm_v7_lpae_hook_read, NULL, 1, 0)); + + reg = 0x1000; + OK(uc_reg_write(uc, UC_ARM_REG_R0, ®)); + OK(uc_mem_map(uc, 0x100001000, 0x1000, UC_PROT_ALL)); + OK(uc_mem_write(uc, 0x100001000, code, sizeof(code))); + OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 0)); + OK(uc_reg_read(uc, UC_ARM_REG_R1, ®)); + TEST_CHECK(reg == 0xe5901000); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb_sub", test_arm_thumb_sub}, {"test_armeb_sub", test_armeb_sub}, @@ -985,4 +1026,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_tcg_opcode_cmp", test_arm_tcg_opcode_cmp}, {"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn}, {"test_arm_cp15_c1_c0_2", test_arm_cp15_c1_c0_2}, + {"test_arm_v7_lpae", test_arm_v7_lpae}, {NULL, NULL}};