diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-06-10 16:09:19 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-06-10 16:09:19 +0100 |
commit | a578cdfbdd8f9beff5ced52b7826ddb1669abbbf (patch) | |
tree | 90697278e6aefd0b91858c403ddb5670f6bdf053 /include | |
parent | 19735c837ae2056b4651720290eda59498eca65a (diff) | |
parent | 43b3952dea0f763ceeaa2f119c473b5cc6d29c90 (diff) |
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20190610' into staging
Move softmmu tlb into CPUNegativeOffsetState
# gpg: Signature made Mon 10 Jun 2019 15:07:55 BST
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* remotes/rth/tags/pull-tcg-20190610: (39 commits)
tcg/arm: Remove mostly unreachable tlb special case
tcg/arm: Use LDRD to load tlb mask+table
tcg/aarch64: Use LDP to load tlb mask+table
cpu: Remove CPU_COMMON
cpu: Move the softmmu tlb to CPUNegativeOffsetState
cpu: Move icount_decr to CPUNegativeOffsetState
cpu: Introduce CPUNegativeOffsetState
cpu: Introduce cpu_set_cpustate_pointers
cpu: Move ENV_OFFSET to exec/gen-icount.h
target/xtensa: Use env_cpu, env_archcpu
target/unicore32: Use env_cpu, env_archcpu
target/tricore: Use env_cpu
target/tilegx: Use env_cpu
target/sparc: Use env_cpu, env_archcpu
target/sh4: Use env_cpu, env_archcpu
target/s390x: Use env_cpu, env_archcpu
target/riscv: Use env_cpu, env_archcpu
target/ppc: Use env_cpu, env_archcpu
target/openrisc: Use env_cpu, env_archcpu
target/nios2: Use env_cpu, env_archcpu
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/exec/cpu-all.h | 69 | ||||
-rw-r--r-- | include/exec/cpu-defs.h | 107 | ||||
-rw-r--r-- | include/exec/cpu_ldst.h | 6 | ||||
-rw-r--r-- | include/exec/cpu_ldst_template.h | 6 | ||||
-rw-r--r-- | include/exec/cpu_ldst_useronly_template.h | 6 | ||||
-rw-r--r-- | include/exec/gen-icount.h | 14 | ||||
-rw-r--r-- | include/exec/softmmu-semi.h | 16 | ||||
-rw-r--r-- | include/qom/cpu.h | 40 |
8 files changed, 184 insertions, 80 deletions
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index da07ce311f..f4fed7d82e 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -371,4 +371,73 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, int cpu_exec(CPUState *cpu); +/** + * cpu_set_cpustate_pointers(cpu) + * @cpu: The cpu object + * + * Set the generic pointers in CPUState into the outer object. + */ +static inline void cpu_set_cpustate_pointers(ArchCPU *cpu) +{ + cpu->parent_obj.env_ptr = &cpu->env; + cpu->parent_obj.icount_decr_ptr = &cpu->neg.icount_decr; +} + +/** + * env_archcpu(env) + * @env: The architecture environment + * + * Return the ArchCPU associated with the environment. + */ +static inline ArchCPU *env_archcpu(CPUArchState *env) +{ + return container_of(env, ArchCPU, env); +} + +/** + * env_cpu(env) + * @env: The architecture environment + * + * Return the CPUState associated with the environment. + */ +static inline CPUState *env_cpu(CPUArchState *env) +{ + return &env_archcpu(env)->parent_obj; +} + +/** + * env_neg(env) + * @env: The architecture environment + * + * Return the CPUNegativeOffsetState associated with the environment. + */ +static inline CPUNegativeOffsetState *env_neg(CPUArchState *env) +{ + ArchCPU *arch_cpu = container_of(env, ArchCPU, env); + return &arch_cpu->neg; +} + +/** + * cpu_neg(cpu) + * @cpu: The generic CPUState + * + * Return the CPUNegativeOffsetState associated with the cpu. + */ +static inline CPUNegativeOffsetState *cpu_neg(CPUState *cpu) +{ + ArchCPU *arch_cpu = container_of(cpu, ArchCPU, parent_obj); + return &arch_cpu->neg; +} + +/** + * env_tlb(env) + * @env: The architecture environment + * + * Return the CPUTLB state associated with the environment. + */ +static inline CPUTLB *env_tlb(CPUArchState *env) +{ + return &env_neg(env)->tlb; +} + #endif /* CPU_ALL_H */ diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 8f2a848bf5..9bc713a70b 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -33,9 +33,30 @@ #include "exec/hwaddr.h" #endif #include "exec/memattrs.h" +#include "qom/cpu.h" + +#include "cpu-param.h" #ifndef TARGET_LONG_BITS -#error TARGET_LONG_BITS must be defined before including this header +# error TARGET_LONG_BITS must be defined in cpu-param.h +#endif +#ifndef NB_MMU_MODES +# error NB_MMU_MODES must be defined in cpu-param.h +#endif +#ifndef TARGET_PHYS_ADDR_SPACE_BITS +# error TARGET_PHYS_ADDR_SPACE_BITS must be defined in cpu-param.h +#endif +#ifndef TARGET_VIRT_ADDR_SPACE_BITS +# error TARGET_VIRT_ADDR_SPACE_BITS must be defined in cpu-param.h +#endif +#ifndef TARGET_PAGE_BITS +# ifdef TARGET_PAGE_BITS_VARY +# ifndef TARGET_PAGE_BITS_MIN +# error TARGET_PAGE_BITS_MIN must be defined in cpu-param.h +# endif +# else +# error TARGET_PAGE_BITS must be defined in cpu-param.h +# endif #endif #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) @@ -58,6 +79,7 @@ typedef uint64_t target_ulong; #endif #if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG) + /* use a fully associative victim tlb of 8 entries */ #define CPU_VTLB_SIZE 8 @@ -127,18 +149,10 @@ typedef struct CPUIOTLBEntry { MemTxAttrs attrs; } CPUIOTLBEntry; -/** - * struct CPUTLBWindow - * @begin_ns: host time (in ns) at the beginning of the time window - * @max_entries: maximum number of entries observed in the window - * - * See also: tlb_mmu_resize_locked() +/* + * Data elements that are per MMU mode, minus the bits accessed by + * the TCG fast path. */ -typedef struct CPUTLBWindow { - int64_t begin_ns; - size_t max_entries; -} CPUTLBWindow; - typedef struct CPUTLBDesc { /* * Describe a region covering all of the large pages allocated @@ -148,17 +162,36 @@ typedef struct CPUTLBDesc { */ target_ulong large_page_addr; target_ulong large_page_mask; + /* host time (in ns) at the beginning of the time window */ + int64_t window_begin_ns; + /* maximum number of entries observed in the window */ + size_t window_max_entries; + size_t n_used_entries; /* The next index to use in the tlb victim table. */ size_t vindex; - CPUTLBWindow window; - size_t n_used_entries; + /* The tlb victim table, in two parts. */ + CPUTLBEntry vtable[CPU_VTLB_SIZE]; + CPUIOTLBEntry viotlb[CPU_VTLB_SIZE]; + /* The iotlb. */ + CPUIOTLBEntry *iotlb; } CPUTLBDesc; /* + * Data elements that are per MMU mode, accessed by the fast path. + * The structure is aligned to aid loading the pair with one insn. + */ +typedef struct CPUTLBDescFast { + /* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */ + uintptr_t mask; + /* The array of tlb entries itself. */ + CPUTLBEntry *table; +} CPUTLBDescFast QEMU_ALIGNED(2 * sizeof(void *)); + +/* * Data elements that are shared between all MMU modes. */ typedef struct CPUTLBCommon { - /* Serialize updates to tlb_table and tlb_v_table, and others as noted. */ + /* Serialize updates to f.table and d.vtable, and others as noted. */ QemuSpin lock; /* * Within dirty, for each bit N, modifications have been made to @@ -176,35 +209,35 @@ typedef struct CPUTLBCommon { size_t elide_flush_count; } CPUTLBCommon; -# define CPU_TLB \ - /* tlb_mask[i] contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */ \ - uintptr_t tlb_mask[NB_MMU_MODES]; \ - CPUTLBEntry *tlb_table[NB_MMU_MODES]; -# define CPU_IOTLB \ - CPUIOTLBEntry *iotlb[NB_MMU_MODES]; - /* + * The entire softmmu tlb, for all MMU modes. * The meaning of each of the MMU modes is defined in the target code. - * Note that NB_MMU_MODES is not yet defined; we can only reference it - * within preprocessor defines that will be expanded later. + * Since this is placed within CPUNegativeOffsetState, the smallest + * negative offsets are at the end of the struct. */ -#define CPU_COMMON_TLB \ - CPUTLBCommon tlb_c; \ - CPUTLBDesc tlb_d[NB_MMU_MODES]; \ - CPU_TLB \ - CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \ - CPU_IOTLB \ - CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; +typedef struct CPUTLB { + CPUTLBCommon c; + CPUTLBDesc d[NB_MMU_MODES]; + CPUTLBDescFast f[NB_MMU_MODES]; +} CPUTLB; -#else +/* This will be used by TCG backends to compute offsets. */ +#define TLB_MASK_TABLE_OFS(IDX) \ + ((int)offsetof(ArchCPU, neg.tlb.f[IDX]) - (int)offsetof(ArchCPU, env)) -#define CPU_COMMON_TLB +#else -#endif +typedef struct CPUTLB { } CPUTLB; +#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */ -#define CPU_COMMON \ - /* soft mmu support */ \ - CPU_COMMON_TLB \ +/* + * This structure must be placed in ArchCPU immedately + * before CPUArchState, as a field named "neg". + */ +typedef struct CPUNegativeOffsetState { + CPUTLB tlb; + IcountDecr icount_decr; +} CPUNegativeOffsetState; #endif diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index 7b28a839d2..a08b11bd2c 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -139,21 +139,21 @@ static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry) static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx, target_ulong addr) { - uintptr_t size_mask = env->tlb_mask[mmu_idx] >> CPU_TLB_ENTRY_BITS; + uintptr_t size_mask = env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS; return (addr >> TARGET_PAGE_BITS) & size_mask; } static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx) { - return (env->tlb_mask[mmu_idx] >> CPU_TLB_ENTRY_BITS) + 1; + return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1; } /* Find the TLB entry corresponding to the mmu_idx + address pair. */ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx, target_ulong addr) { - return &env->tlb_table[mmu_idx][tlb_index(env, mmu_idx, addr)]; + return &env_tlb(env)->f[mmu_idx].table[tlb_index(env, mmu_idx, addr)]; } #ifdef MMU_MODE0_SUFFIX diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h index 0f061d47ef..af7e0b49f2 100644 --- a/include/exec/cpu_ldst_template.h +++ b/include/exec/cpu_ldst_template.h @@ -89,7 +89,7 @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, false, MO_TE, false)); #endif @@ -128,7 +128,7 @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, true, MO_TE, false)); #endif @@ -170,7 +170,7 @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, false, MO_TE, true)); #endif diff --git a/include/exec/cpu_ldst_useronly_template.h b/include/exec/cpu_ldst_useronly_template.h index 0fd6019af0..bc45e2b8d4 100644 --- a/include/exec/cpu_ldst_useronly_template.h +++ b/include/exec/cpu_ldst_useronly_template.h @@ -66,7 +66,7 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr) { #if !defined(CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, false, MO_TE, false)); #endif return glue(glue(ld, USUFFIX), _p)(g2h(ptr)); @@ -90,7 +90,7 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr) { #if !defined(CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, true, MO_TE, false)); #endif return glue(glue(lds, SUFFIX), _p)(g2h(ptr)); @@ -116,7 +116,7 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr, { #if !defined(CODE_ACCESS) trace_guest_mem_before_exec( - ENV_GET_CPU(env), ptr, + env_cpu(env), ptr, trace_mem_build_info(SHIFT, false, MO_TE, true)); #endif glue(glue(st, SUFFIX), _p)(g2h(ptr), v); diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 24f7991781..f7669b6841 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -19,7 +19,8 @@ static inline void gen_tb_start(TranslationBlock *tb) } tcg_gen_ld_i32(count, cpu_env, - -ENV_OFFSET + offsetof(CPUState, icount_decr.u32)); + offsetof(ArchCPU, neg.icount_decr.u32) - + offsetof(ArchCPU, env)); if (tb_cflags(tb) & CF_USE_ICOUNT) { imm = tcg_temp_new_i32(); @@ -37,7 +38,8 @@ static inline void gen_tb_start(TranslationBlock *tb) if (tb_cflags(tb) & CF_USE_ICOUNT) { tcg_gen_st16_i32(count, cpu_env, - -ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low)); + offsetof(ArchCPU, neg.icount_decr.u16.low) - + offsetof(ArchCPU, env)); } tcg_temp_free_i32(count); @@ -58,14 +60,18 @@ static inline void gen_tb_end(TranslationBlock *tb, int num_insns) static inline void gen_io_start(void) { TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); + tcg_gen_st_i32(tmp, cpu_env, + offsetof(ArchCPU, parent_obj.can_do_io) - + offsetof(ArchCPU, env)); tcg_temp_free_i32(tmp); } static inline void gen_io_end(void) { TCGv_i32 tmp = tcg_const_i32(0); - tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); + tcg_gen_st_i32(tmp, cpu_env, + offsetof(ArchCPU, parent_obj.can_do_io) - + offsetof(ArchCPU, env)); tcg_temp_free_i32(tmp); } diff --git a/include/exec/softmmu-semi.h b/include/exec/softmmu-semi.h index 7eefad8f39..970837992e 100644 --- a/include/exec/softmmu-semi.h +++ b/include/exec/softmmu-semi.h @@ -14,7 +14,7 @@ static inline uint64_t softmmu_tget64(CPUArchState *env, target_ulong addr) { uint64_t val; - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 8, 0); + cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 8, 0); return tswap64(val); } @@ -22,7 +22,7 @@ static inline uint32_t softmmu_tget32(CPUArchState *env, target_ulong addr) { uint32_t val; - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0); + cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 4, 0); return tswap32(val); } @@ -30,7 +30,7 @@ static inline uint32_t softmmu_tget8(CPUArchState *env, target_ulong addr) { uint8_t val; - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &val, 1, 0); + cpu_memory_rw_debug(env_cpu(env), addr, &val, 1, 0); return val; } @@ -43,14 +43,14 @@ static inline void softmmu_tput64(CPUArchState *env, target_ulong addr, uint64_t val) { val = tswap64(val); - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 8, 1); + cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 8, 1); } static inline void softmmu_tput32(CPUArchState *env, target_ulong addr, uint32_t val) { val = tswap32(val); - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1); + cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 4, 1); } #define put_user_u64(arg, p) ({ softmmu_tput64(env, p, arg) ; 0; }) #define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; }) @@ -63,7 +63,7 @@ static void *softmmu_lock_user(CPUArchState *env, /* TODO: Make this something that isn't fixed size. */ p = malloc(len); if (p && copy) { - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 0); + cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0); } return p; } @@ -79,7 +79,7 @@ static char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr) return NULL; } do { - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &c, 1, 0); + cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0); addr++; *(p++) = c; } while (c); @@ -90,7 +90,7 @@ static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr, target_ulong len) { if (len) { - cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 1); + cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1); } free(p); } diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 98e12d914c..5ee0046b62 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -232,17 +232,25 @@ typedef struct CPUClass { bool gdb_stop_before_watchpoint; } CPUClass; +/* + * Low 16 bits: number of cycles left, used only in icount mode. + * High 16 bits: Set to -1 to force TCG to stop executing linked TBs + * for this CPU and return to its top level loop (even in non-icount mode). + * This allows a single read-compare-cbranch-write sequence to test + * for both decrementer underflow and exceptions. + */ +typedef union IcountDecr { + uint32_t u32; + struct { #ifdef HOST_WORDS_BIGENDIAN -typedef struct icount_decr_u16 { - uint16_t high; - uint16_t low; -} icount_decr_u16; + uint16_t high; + uint16_t low; #else -typedef struct icount_decr_u16 { - uint16_t low; - uint16_t high; -} icount_decr_u16; + uint16_t low; + uint16_t high; #endif + } u16; +} IcountDecr; typedef struct CPUBreakpoint { vaddr pc; @@ -314,11 +322,6 @@ struct qemu_work_item; * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU * @singlestep_enabled: Flags for single-stepping. * @icount_extra: Instructions until next timer event. - * @icount_decr: Low 16 bits: number of cycles left, only used in icount mode. - * High 16 bits: Set to -1 to force TCG to stop executing linked TBs for this - * CPU and return to its top level loop (even in non-icount mode). - * This allows a single read-compare-cbranch-write sequence to test - * for both decrementer underflow and exceptions. * @can_do_io: Nonzero if memory-mapped IO is safe. Deterministic execution * requires that IO only be performed on the last instruction of a TB * so that interrupts take effect immediately. @@ -328,6 +331,7 @@ struct qemu_work_item; * @as: Pointer to the first AddressSpace, for the convenience of targets which * only have a single AddressSpace * @env_ptr: Pointer to subclass-specific CPUArchState field. + * @icount_decr_ptr: Pointer to IcountDecr field within subclass. * @gdb_regs: Additional GDB registers. * @gdb_num_regs: Number of total registers accessible to GDB. * @gdb_num_g_regs: Number of registers in GDB 'g' packets. @@ -387,6 +391,7 @@ struct CPUState { MemoryRegion *memory; void *env_ptr; /* CPUArchState */ + IcountDecr *icount_decr_ptr; /* Accessed in parallel; all accesses must be atomic */ struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; @@ -441,15 +446,6 @@ struct CPUState { bool ignore_memory_transaction_failures; - /* Note that this is accessed at the start of every TB via a negative - offset from AREG0. Leave this field at the end so as to make the - (absolute value) offset as small as possible. This reduces code - size, especially for hosts without large memory offsets. */ - union { - uint32_t u32; - icount_decr_u16 u16; - } icount_decr; - struct hax_vcpu_state *hax_vcpu; int hvf_fd; |