Add declarations and templates of extended MMU helpers. An extended helper takes an additional argument of the host address accessing a guest memory which differs from the address of the call site to the helper because helper call sites locate at the end of a generated code block.
Signed-off-by: Yeongkyoon Lee <yeongkyoon....@samsung.com> --- softmmu_defs.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ softmmu_header.h | 25 ++++++++++++++++++++ softmmu_template.h | 48 ++++++++++++++++++++++++++++++++------ 3 files changed, 129 insertions(+), 8 deletions(-) diff --git a/softmmu_defs.h b/softmmu_defs.h index 8d59f9d..505f6ba 100644 --- a/softmmu_defs.h +++ b/softmmu_defs.h @@ -10,6 +10,8 @@ #define SOFTMMU_DEFS_H #ifndef CONFIG_TCG_PASS_AREG0 + +#ifndef CONFIG_QEMU_LDST_OPTIMIZATION uint8_t __ldb_mmu(target_ulong addr, int mmu_idx); void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx); uint16_t __ldw_mmu(target_ulong addr, int mmu_idx); @@ -28,6 +30,30 @@ void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx); uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx); void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx); #else +/* Extended versions of MMU helpers for qemu_ld/st optimization. + The additional argument is a host code address accessing guest memory */ +uint8_t ext_ldb_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stb_mmu(target_ulong addr, uint8_t val, int mmu_idx, uintptr_t ra); +uint16_t ext_ldw_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stw_mmu(target_ulong addr, uint16_t val, int mmu_idx, uintptr_t ra); +uint32_t ext_ldl_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stl_mmu(target_ulong addr, uint32_t val, int mmu_idx, uintptr_t ra); +uint64_t ext_ldq_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stq_mmu(target_ulong addr, uint64_t val, int mmu_idx, uintptr_t ra); + +uint8_t ext_ldb_cmmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx, uintptr_t ra); +uint16_t ext_ldw_cmmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx, uintptr_t ra); +uint32_t ext_ldl_cmmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx, uintptr_t ra); +uint64_t ext_ldq_cmmu(target_ulong addr, int mmu_idx, uintptr_t ra); +void ext_stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx, uintptr_t ra); +#endif /* !CONFIG_QEMU_LDST_OPTIMIZATION */ + +#else + +#ifndef CONFIG_QEMU_LDST_OPTIMIZATION uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, int mmu_idx); @@ -53,6 +79,44 @@ void helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val, uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val, int mmu_idx); +#else +/* Extended versions of MMU helpers for qemu_ld/st optimization. + The additional argument is a host code address accessing guest memory */ +uint8_t ext_helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, + int mmu_idx, uintptr_t ra); +uint16_t ext_helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, + int mmu_idx, uintptr_t ra); +uint32_t ext_helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, + int mmu_idx, uintptr_t ra); +uint64_t ext_helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, + int mmu_idx, uintptr_t ra); + +uint8_t ext_helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stb_cmmu(CPUArchState *env, target_ulong addr, uint8_t val, + int mmu_idx, uintptr_t ra); +uint16_t ext_helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stw_cmmu(CPUArchState *env, target_ulong addr, uint16_t val, + int mmu_idx, uintptr_t ra); +uint32_t ext_helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val, + int mmu_idx, uintptr_t ra); +uint64_t ext_helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t ra); +void ext_helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val, + int mmu_idx, uintptr_t ra); +#endif /* !CONFIG_QEMU_LDST_OPTIMIZATION */ + #endif #endif diff --git a/softmmu_header.h b/softmmu_header.h index cf1aa38..13bec62 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -82,12 +82,20 @@ #define ENV_PARAM #define ENV_VAR #define CPU_PREFIX +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION +#define HELPER_PREFIX ext_ +#else #define HELPER_PREFIX __ +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ #else #define ENV_PARAM CPUArchState *env, #define ENV_VAR env, #define CPU_PREFIX cpu_ +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION +#define HELPER_PREFIX ext_helper_ +#else #define HELPER_PREFIX helper_ +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ #endif /* generic load/store macros */ @@ -106,9 +114,14 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION + res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), + MMUSUFFIX)(ENV_VAR addr, mmu_idx, (uintptr_t)NULL); +#else res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR addr, mmu_idx); +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; res = glue(glue(ld, USUFFIX), _raw)(hostaddr); @@ -130,8 +143,14 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION + res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), + MMUSUFFIX)(ENV_VAR addr, mmu_idx, + (uintptr_t)NULL); +#else res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR addr, mmu_idx); +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; res = glue(glue(lds, SUFFIX), _raw)(hostaddr); @@ -157,8 +176,14 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION + glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v, + mmu_idx, + (uintptr_t)NULL); +#else glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v, mmu_idx); +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; glue(glue(st, SUFFIX), _raw)(hostaddr, v); diff --git a/softmmu_template.h b/softmmu_template.h index b8bd700..82f2710 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -66,6 +66,21 @@ #define HELPER_PREFIX helper_ #endif +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION +#undef HELPER_PREFIX +/* Redefine helper prefix */ +#ifndef CONFIG_TCG_PASS_AREG0 +#define HELPER_PREFIX ext_ +#else +#define HELPER_PREFIX ext_helper_ +#endif +/* An extended MMU helper takes one more argument which is + a host address of generated code accessing guest memory */ +#define GET_RET_ADDR() ra +#else +#define GET_RET_ADDR() GETPC() +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ + static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM target_ulong addr, int mmu_idx, @@ -103,10 +118,18 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM } /* handle all cases except unaligned access which span two pages */ +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION +DATA_TYPE +glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM + target_ulong addr, + int mmu_idx, + uintptr_t ra) +#else DATA_TYPE glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM target_ulong addr, int mmu_idx) +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ { DATA_TYPE res; int index; @@ -124,13 +147,13 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); ioaddr = env->iotlb[mmu_idx][index]; res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { /* slow unaligned access (it spans two pages or IO) */ do_unaligned_access: - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); #ifdef ALIGNED_ONLY do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif @@ -141,7 +164,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif @@ -151,7 +174,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM } } else { /* the page is not in the TLB : fill it */ - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); @@ -253,10 +276,18 @@ static inline void glue(io_write, SUFFIX)(ENV_PARAM #endif /* SHIFT > 2 */ } +#ifdef CONFIG_QEMU_LDST_OPTIMIZATION +void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM + target_ulong addr, + DATA_TYPE val, + int mmu_idx, + uintptr_t ra) +#else void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM target_ulong addr, DATA_TYPE val, int mmu_idx) +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ { target_phys_addr_t ioaddr; target_ulong tlb_addr; @@ -271,12 +302,12 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); ioaddr = env->iotlb[mmu_idx][index]; glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); #ifdef ALIGNED_ONLY do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); #endif @@ -287,7 +318,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); } #endif @@ -297,7 +328,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM } } else { /* the page is not in the TLB : fill it */ - retaddr = GETPC(); + retaddr = GET_RET_ADDR(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); @@ -370,3 +401,4 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM #undef ENV_VAR #undef CPU_PREFIX #undef HELPER_PREFIX +#undef GET_RET_ADDR -- 1.7.4.1