From 5e1401969b25f676fee6b1c564441759cf967a43 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Mar 2019 11:54:23 -1000 Subject: cpu: Move icount_decr to CPUNegativeOffsetState Amusingly, we had already ignored the comment to keep this value at the end of CPUState. This restores the minimum negative offset from TCG_AREG0 for code generation. For the couple of uses within qom/cpu.c, without NEED_CPU_H, add a pointer from the CPUState object to the IcountDecr object within CPUNegativeOffsetState. Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson --- include/exec/cpu-all.h | 1 + include/exec/cpu-defs.h | 3 ++- include/exec/gen-icount.h | 16 ++++++++++------ include/qom/cpu.h | 40 ++++++++++++++++++---------------------- 4 files changed, 31 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 5ae8340..253dd1d 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -380,6 +380,7 @@ int cpu_exec(CPUState *cpu); 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; } /** diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 921fbb4..c067994 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -33,6 +33,7 @@ #include "exec/hwaddr.h" #endif #include "exec/memattrs.h" +#include "qom/cpu.h" #include "cpu-param.h" @@ -232,7 +233,7 @@ typedef struct CPUTLB { * before CPUArchState, as a field named "neg". */ typedef struct CPUNegativeOffsetState { - /* Empty */ + IcountDecr icount_decr; } CPUNegativeOffsetState; #endif diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 9cfa6cc..f7669b6 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -5,8 +5,6 @@ /* Helpers for instruction counting code generation. */ -#define ENV_OFFSET offsetof(ArchCPU, env) - static TCGOp *icount_start_insn; static inline void gen_tb_start(TranslationBlock *tb) @@ -21,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(); @@ -39,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); @@ -60,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/qom/cpu.h b/include/qom/cpu.h index 98e12d9..5ee0046 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; -- cgit v1.1