diff --git a/include/uc_priv.h b/include/uc_priv.h index de2e457f..91be9bac 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -54,6 +54,9 @@ typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly); // which interrupt should make emulation stop? typedef bool (*uc_args_int_t)(int intno); +// some architecture redirect virtual memory to physical memory like Mips +typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); + struct hook_struct { int hook_type; // uc_tracecode_type & uc_tracemem_type @@ -94,6 +97,7 @@ struct uc_struct { uc_args_uc_ram_size_t memory_map; uc_mem_unmap_t memory_unmap; uc_readonly_mem_t readonly_mem; + uc_mem_redirect_t mem_redirect; // list of cpu void* cpu; diff --git a/qemu/target-mips/unicorn.c b/qemu/target-mips/unicorn.c index 7ff8250c..3885d02d 100644 --- a/qemu/target-mips/unicorn.c +++ b/qemu/target-mips/unicorn.c @@ -17,6 +17,21 @@ #define READ_BYTE_L(x) (x & 0xff) +static uint64_t mips_mem_redirect(uint64_t address) +{ + // kseg0 range masks off high address bit + if (address >= 0x80000000 && address <= 0x9fffffff) + return address & 0x7fffffff; + + // kseg1 range masks off top 3 address bits + if (address >= 0xa0000000 && address <= 0xbfffffff) { + return address & 0x1fffffff; + } + + // no redirect + return address; +} + static void mips_set_pc(struct uc_struct *uc, uint64_t address) { ((CPUMIPSState *)uc->current_cpu->env_ptr)->active_tc.PC = address; @@ -96,5 +111,6 @@ __attribute__ ((visibility ("default"))) uc->reg_write = mips_reg_write; uc->reg_reset = mips_reg_reset; uc->set_pc = mips_set_pc; + uc->mem_redirect = mips_mem_redirect; uc_common_init(uc); } diff --git a/tests/regress/mips_kseg0_1.c b/tests/regress/mips_kseg0_1.c index a5ca90bf..be47bf50 100644 --- a/tests/regress/mips_kseg0_1.c +++ b/tests/regress/mips_kseg0_1.c @@ -69,5 +69,7 @@ int main() uc_close(uc); + printf("Good, this bug is fixed!\n"); + return 0; } diff --git a/uc.c b/uc.c index 02c157bc..0478391b 100644 --- a/uc.c +++ b/uc.c @@ -811,6 +811,10 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) if (uc->mapped_block_count == 0) return NULL; + if (uc->mem_redirect) { + address = uc->mem_redirect(address); + } + // try with the cache index first i = uc->mapped_block_cache_index;