From b55b1afda942306e4e40420aced1524bd83ba16d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 28 Feb 2018 11:48:04 -0800 Subject: target/xtensa: dump correct physical registers xtensa_cpu_dump_state outputs CPU physical registers as is, without synchronization from current window. That may result in different values printed for the current window and corresponding physical registers. Synchronize physical registers from window before dumping. Cc: qemu-stable@nongnu.org Signed-off-by: Max Filippov --- target/xtensa/translate.c | 1 + 1 file changed, 1 insertion(+) (limited to 'target') diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 671d934..3ad86d4 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1215,6 +1215,7 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, (i % 4) == 3 ? '\n' : ' '); } + xtensa_sync_phys_from_window(env); cpu_fprintf(f, "\n"); for (i = 0; i < env->config->nareg; ++i) { -- cgit v1.1 From b9317a2a69ac78f79ee4965037c8eaa407ed0724 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 4 Feb 2018 13:22:46 -0800 Subject: target/xtensa: mark register windows in the dump Add arrows that mark beginning of register windows and position of the current window in the windowed register file. Signed-off-by: Max Filippov --- target/xtensa/translate.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'target') diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 3ad86d4..5969d7c 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1219,8 +1219,13 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, "\n"); for (i = 0; i < env->config->nareg; ++i) { - cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i], - (i % 4) == 3 ? '\n' : ' '); + cpu_fprintf(f, "AR%02d=%08x ", i, env->phys_regs[i]); + if (i % 4 == 3) { + bool ws = (env->sregs[WINDOW_START] & (1 << (i / 4))) != 0; + bool cw = env->sregs[WINDOW_BASE] == i / 4; + + cpu_fprintf(f, "%c%c\n", ws ? '<' : ' ', cw ? '=' : ' '); + } } if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) { -- cgit v1.1 From 1b7b26e4748580dce3ec671ce7ed3d65a986cf9c Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 3 Feb 2018 23:55:06 -0800 Subject: target/xtensa: use correct number of registers in gdbstub System emulation should provide access to all registers, userspace emulation should only provide access to unprivileged registers. Record register flags from GDB register map definition, calculate both num_regs and num_core_regs if either is zero. Use num_regs in system emulation, num_core_regs in userspace emulation gdbstub. Signed-off-by: Max Filippov --- target/xtensa/cpu.h | 1 + target/xtensa/gdbstub.c | 14 ++++++++++++-- target/xtensa/helper.c | 28 ++++++++++++++++++++-------- target/xtensa/overlay_tool.h | 11 ++++++++--- 4 files changed, 41 insertions(+), 13 deletions(-) (limited to 'target') diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 49c2e3c..255cc9e 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -310,6 +310,7 @@ typedef struct xtensa_tlb { typedef struct XtensaGdbReg { int targno; + unsigned flags; int type; int group; unsigned size; diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c index d78a1b4..a8ea98d 100644 --- a/target/xtensa/gdbstub.c +++ b/target/xtensa/gdbstub.c @@ -28,9 +28,14 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n; +#ifdef CONFIG_USER_ONLY + int num_regs = env->config->gdb_regmap.num_core_regs; +#else + int num_regs = env->config->gdb_regmap.num_regs; +#endif unsigned i; - if (n < 0 || n >= env->config->gdb_regmap.num_regs) { + if (n < 0 || n >= num_regs) { return 0; } @@ -81,8 +86,13 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) CPUXtensaState *env = &cpu->env; uint32_t tmp; const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n; +#ifdef CONFIG_USER_ONLY + int num_regs = env->config->gdb_regmap.num_core_regs; +#else + int num_regs = env->config->gdb_regmap.num_regs; +#endif - if (n < 0 || n >= env->config->gdb_regmap.num_regs) { + if (n < 0 || n >= num_regs) { return 0; } diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 5009fec..3488503 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -88,19 +88,31 @@ static void init_libisa(XtensaConfig *config) void xtensa_finalize_config(XtensaConfig *config) { - unsigned i, n = 0; - if (config->isa_internal) { init_libisa(config); } - if (config->gdb_regmap.num_regs) { - return; - } - for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) { - n += (config->gdb_regmap.reg[i].type != 6); + if (config->gdb_regmap.num_regs == 0 || + config->gdb_regmap.num_core_regs == 0) { + unsigned i; + unsigned n_regs = 0; + unsigned n_core_regs = 0; + + for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) { + if (config->gdb_regmap.reg[i].type != 6) { + ++n_regs; + if ((config->gdb_regmap.reg[i].flags & 0x1) == 0) { + ++n_core_regs; + } + } + } + if (config->gdb_regmap.num_regs == 0) { + config->gdb_regmap.num_regs = n_regs; + } + if (config->gdb_regmap.num_core_regs == 0) { + config->gdb_regmap.num_core_regs = n_core_regs; + } } - config->gdb_regmap.num_regs = n; } void xtensa_register_core(XtensaConfigList *node) diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h index 589dd62..b24ad11 100644 --- a/target/xtensa/overlay_tool.h +++ b/target/xtensa/overlay_tool.h @@ -25,9 +25,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define XTREG(idx, ofs, bi, sz, al, no, flags, cp, typ, grp, name, \ - a1, a2, a3, a4, a5, a6) \ - { .targno = (no), .type = (typ), .group = (grp), .size = (sz) }, +#define XTREG(idx, ofs, bi, sz, al, no, fl, cp, typ, grp, name, \ + a1, a2, a3, a4, a5, a6) { \ + .targno = (no), \ + .flags = (fl), \ + .type = (typ), \ + .group = (grp), \ + .size = (sz), \ +}, #define XTREG_END { .targno = -1 }, #ifndef XCHAL_HAVE_DEPBITS -- cgit v1.1 From 9fb40342d4b32152cedf32efe28b59ec3b932bd8 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 6 Mar 2017 17:17:43 -0800 Subject: target/xtensa: support MTTCG - emit TCG barriers for MEMW, EXTW, S32RI and L32AI; - do atomic_cmpxchg_i32 for S32C1I. Cc: Emilio G. Cota Signed-off-by: Max Filippov --- target/xtensa/cpu.h | 3 +++ target/xtensa/translate.c | 46 +++++++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 15 deletions(-) (limited to 'target') diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 255cc9e..d9d3b33 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -31,6 +31,9 @@ #define ALIGNED_ONLY #define TARGET_LONG_BITS 32 +/* Xtensa processors have a weak memory model */ +#define TCG_GUEST_DEFAULT_MO (0) + #define CPUArchState struct CPUXtensaState #include "qemu-common.h" diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 5969d7c..c06d30d 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1664,9 +1664,15 @@ static void translate_ldst(DisasContext *dc, const uint32_t arg[], gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]); } if (par[2]) { + if (par[1]) { + tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL); + } tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); } else { tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); + if (par[1]) { + tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL); + } } tcg_temp_free(addr); } @@ -1823,6 +1829,12 @@ static void translate_mac16(DisasContext *dc, const uint32_t arg[], } } +static void translate_memw(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); +} + static void translate_minmax(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -2193,29 +2205,33 @@ static void translate_setb_expstate(DisasContext *dc, const uint32_t arg[], tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0]); } +#ifdef CONFIG_USER_ONLY +static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr) +{ +} +#else +static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr) +{ + TCGv_i32 tpc = tcg_const_i32(dc->pc); + + gen_helper_check_atomctl(cpu_env, tpc, addr); + tcg_temp_free(tpc); +} +#endif + static void translate_s32c1i(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { if (gen_window_check2(dc, arg[0], arg[1])) { - TCGLabel *label = gen_new_label(); TCGv_i32 tmp = tcg_temp_local_new_i32(); TCGv_i32 addr = tcg_temp_local_new_i32(); - TCGv_i32 tpc; tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); gen_load_store_alignment(dc, 2, addr, true); - - tpc = tcg_const_i32(dc->pc); - gen_helper_check_atomctl(cpu_env, tpc, addr); - tcg_gen_qemu_ld32u(cpu_R[arg[0]], addr, dc->cring); - tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[arg[0]], - cpu_SR[SCOMPARE1], label); - - tcg_gen_qemu_st32(tmp, addr, dc->cring); - - gen_set_label(label); - tcg_temp_free(tpc); + gen_check_atomctl(dc, addr); + tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1], + tmp, dc->cring, MO_32); tcg_temp_free(addr); tcg_temp_free(tmp); } @@ -2828,7 +2844,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_extui, }, { .name = "extw", - .translate = translate_nop, + .translate = translate_memw, }, { .name = "hwwdtlba", .translate = translate_ill, @@ -2945,7 +2961,7 @@ static const XtensaOpcodeOps core_ops[] = { .par = (const uint32_t[]){TCG_COND_GEU}, }, { .name = "memw", - .translate = translate_nop, + .translate = translate_memw, }, { .name = "min", .translate = translate_minmax, -- cgit v1.1 From ba7651fba54199e5dedbbd08157687291b9dbae3 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 25 Jan 2017 10:54:11 -0800 Subject: target/xtensa: add linux-user support Import list of syscalls from the kernel source. Conditionalize code/data that is only used with softmmu. Implement exception handlers. Implement signal hander (only the core registers for now, no coprocessors or TIE). Cc: Riku Voipio Cc: Laurent Vivier Signed-off-by: Max Filippov --- target/xtensa/Makefile.objs | 3 +-- target/xtensa/cpu.c | 26 +++++++++++++++++---- target/xtensa/cpu.h | 56 ++++++++++++++++++++++++++++++--------------- target/xtensa/helper.c | 31 +++++++++++++++++++++++++ target/xtensa/helper.h | 4 ++++ target/xtensa/op_helper.c | 50 ++++++++++++++++++++++++++++++++-------- target/xtensa/translate.c | 43 +++++++++++++++++++++++++++++----- 7 files changed, 173 insertions(+), 40 deletions(-) (limited to 'target') diff --git a/target/xtensa/Makefile.objs b/target/xtensa/Makefile.objs index e158515..2fae785 100644 --- a/target/xtensa/Makefile.objs +++ b/target/xtensa/Makefile.objs @@ -1,10 +1,9 @@ -obj-y += xtensa-semi.o obj-y += core-dc232b.o obj-y += core-dc233c.o obj-y += core-de212.o obj-y += core-fsf.o obj-y += core-sample_controller.o -obj-$(CONFIG_SOFTMMU) += monitor.o +obj-$(CONFIG_SOFTMMU) += monitor.o xtensa-semi.o obj-y += xtensa-isa.o obj-y += translate.o op_helper.o helper.o cpu.o obj-y += gdbstub.o diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 4573388..2b5b537 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -45,9 +45,13 @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value) static bool xtensa_cpu_has_work(CPUState *cs) { +#ifndef CONFIG_USER_ONLY XtensaCPU *cpu = XTENSA_CPU(cs); return !cpu->env.runstall && cpu->env.pending_irq_level; +#else + return true; +#endif } /* CPUClass::reset() */ @@ -62,8 +66,16 @@ static void xtensa_cpu_reset(CPUState *s) env->exception_taken = 0; env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors]; env->sregs[LITBASE] &= ~1; +#ifndef CONFIG_USER_ONLY env->sregs[PS] = xtensa_option_enabled(env->config, XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; + env->pending_irq_level = 0; +#else + env->sregs[PS] = + (xtensa_option_enabled(env->config, + XTENSA_OPTION_WINDOWED_REGISTER) ? PS_WOE : 0) | + PS_UM | (3 << PS_RING_SHIFT); +#endif env->sregs[VECBASE] = env->config->vecbase; env->sregs[IBREAKENABLE] = 0; env->sregs[MEMCTL] = MEMCTL_IL0EN & env->config->memctl_mask; @@ -73,9 +85,10 @@ static void xtensa_cpu_reset(CPUState *s) env->sregs[CONFIGID0] = env->config->configid[0]; env->sregs[CONFIGID1] = env->config->configid[1]; - env->pending_irq_level = 0; +#ifndef CONFIG_USER_ONLY reset_mmu(env); s->halted = env->runstall; +#endif } static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model) @@ -104,11 +117,12 @@ static void xtensa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); - XtensaCPU *cpu = XTENSA_CPU(dev); XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev); Error *local_err = NULL; - xtensa_irq_init(&cpu->env); +#ifndef CONFIG_USER_ONLY + xtensa_irq_init(&XTENSA_CPU(dev)->env); +#endif cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { @@ -133,11 +147,13 @@ static void xtensa_cpu_initfn(Object *obj) cs->env_ptr = env; env->config = xcc->config; +#ifndef CONFIG_USER_ONLY env->address_space_er = g_malloc(sizeof(*env->address_space_er)); env->system_er = g_malloc(sizeof(*env->system_er)); memory_region_init_io(env->system_er, NULL, NULL, env, "er", UINT64_C(0x100000000)); address_space_init(env->address_space_er, env->system_er, "ER"); +#endif } static const VMStateDescription vmstate_xtensa_cpu = { @@ -166,7 +182,9 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_read_register = xtensa_cpu_gdb_read_register; cc->gdb_write_register = xtensa_cpu_gdb_write_register; cc->gdb_stop_before_watchpoint = true; -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY + cc->handle_mmu_fault = xtensa_cpu_handle_mmu_fault; +#else cc->do_unaligned_access = xtensa_cpu_do_unaligned_access; cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; cc->do_unassigned_access = xtensa_cpu_do_unassigned_access; diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index d9d3b33..957f0fd 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -44,7 +44,11 @@ #define NB_MMU_MODES 4 #define TARGET_PHYS_ADDR_SPACE_BITS 32 +#ifdef CONFIG_USER_ONLY +#define TARGET_VIRT_ADDR_SPACE_BITS 30 +#else #define TARGET_VIRT_ADDR_SPACE_BITS 32 +#endif #define TARGET_PAGE_BITS 12 enum { @@ -176,6 +180,7 @@ enum { #define PS_OWB 0xf00 #define PS_OWB_SHIFT 8 +#define PS_OWB_LEN 4 #define PS_CALLINC 0x30000 #define PS_CALLINC_SHIFT 16 @@ -438,6 +443,7 @@ typedef struct CPUXtensaState { } fregs[16]; float_status fp_status; +#ifndef CONFIG_USER_ONLY xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE]; xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE]; unsigned autorefill_idx; @@ -450,6 +456,7 @@ typedef struct CPUXtensaState { uint64_t time_base; uint64_t ccount_time; uint32_t ccount_base; +#endif int exception_taken; int yield_needed; @@ -484,6 +491,9 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env) #define ENV_OFFSET offsetof(XtensaCPU, env) + +int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int size, + int mmu_idx); void xtensa_cpu_do_interrupt(CPUState *cpu); bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request); void xtensa_cpu_do_unassigned_access(CPUState *cpu, hwaddr addr, @@ -531,26 +541,9 @@ int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc); void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf); void xtensa_sync_window_from_phys(CPUXtensaState *env); void xtensa_sync_phys_from_window(CPUXtensaState *env); -uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way); -void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb, - uint32_t *vpn, uint32_t wi, uint32_t *ei); -int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb, - uint32_t *pwi, uint32_t *pei, uint8_t *pring); -void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, - xtensa_tlb_entry *entry, bool dtlb, - unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); -void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, - unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); -int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, - uint32_t vaddr, int is_write, int mmu_idx, - uint32_t *paddr, uint32_t *page_size, unsigned *access); -void reset_mmu(CPUXtensaState *env); -void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env); +void xtensa_rotate_window(CPUXtensaState *env, uint32_t delta); +void xtensa_restore_owb(CPUXtensaState *env); void debug_exception_env(CPUXtensaState *new_env, uint32_t cause); -static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env) -{ - return env->system_er; -} static inline void xtensa_select_static_vectors(CPUXtensaState *env, unsigned n) @@ -604,6 +597,29 @@ static inline int xtensa_get_cring(const CPUXtensaState *env) } } +#ifndef CONFIG_USER_ONLY +uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, + bool dtlb, uint32_t way); +void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb, + uint32_t *vpn, uint32_t wi, uint32_t *ei); +int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb, + uint32_t *pwi, uint32_t *pei, uint8_t *pring); +void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, + xtensa_tlb_entry *entry, bool dtlb, + unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); +void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, + unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); +int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, + uint32_t vaddr, int is_write, int mmu_idx, + uint32_t *paddr, uint32_t *page_size, unsigned *access); +void reset_mmu(CPUXtensaState *env); +void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env); + +static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env) +{ + return env->system_er; +} + static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb, unsigned wi, unsigned ei) { @@ -611,6 +627,7 @@ static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, env->dtlb[wi] + ei : env->itlb[wi] + ei; } +#endif static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env) { @@ -623,6 +640,7 @@ static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env) #define MMU_MODE1_SUFFIX _ring1 #define MMU_MODE2_SUFFIX _ring2 #define MMU_MODE3_SUFFIX _ring3 +#define MMU_USER_IDX 3 static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch) { diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 3488503..34844ee 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -173,6 +173,7 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf) hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { +#ifndef CONFIG_USER_ONLY XtensaCPU *cpu = XTENSA_CPU(cs); uint32_t paddr; uint32_t page_size; @@ -187,8 +188,13 @@ hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return paddr; } return ~0; +#else + return addr; +#endif } +#ifndef CONFIG_USER_ONLY + static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector) { if (xtensa_option_enabled(env->config, @@ -298,6 +304,11 @@ void xtensa_cpu_do_interrupt(CPUState *cs) } check_interrupts(env); } +#else +void xtensa_cpu_do_interrupt(CPUState *cs) +{ +} +#endif bool xtensa_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { @@ -309,6 +320,25 @@ bool xtensa_cpu_exec_interrupt(CPUState *cs, int interrupt_request) return false; } +#ifdef CONFIG_USER_ONLY + +int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, + int mmu_idx) +{ + XtensaCPU *cpu = XTENSA_CPU(cs); + CPUXtensaState *env = &cpu->env; + + qemu_log_mask(CPU_LOG_INT, + "%s: rw = %d, address = 0x%08" VADDR_PRIx ", size = %d\n", + __func__, rw, address, size); + env->sregs[EXCVADDR] = address; + env->sregs[EXCCAUSE] = rw ? STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE; + cs->exception_index = EXC_USER; + return 1; +} + +#else + static void reset_tlb_mmu_all_ways(CPUXtensaState *env, const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE]) { @@ -769,3 +799,4 @@ void xtensa_runstall(CPUXtensaState *env, bool runstall) cpu_reset_interrupt(cpu, CPU_INTERRUPT_HALT); } } +#endif diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h index cc751c9..73444ae 100644 --- a/target/xtensa/helper.h +++ b/target/xtensa/helper.h @@ -12,9 +12,12 @@ DEF_HELPER_1(restore_owb, void, env) DEF_HELPER_2(movsp, void, env, i32) DEF_HELPER_2(wsr_lbeg, void, env, i32) DEF_HELPER_2(wsr_lend, void, env, i32) +#ifndef CONFIG_USER_ONLY DEF_HELPER_1(simcall, void, env) +#endif DEF_HELPER_1(dump_state, void, env) +#ifndef CONFIG_USER_ONLY DEF_HELPER_3(waiti, void, env, i32, i32) DEF_HELPER_1(update_ccount, void, env) DEF_HELPER_2(wsr_ccount, void, env, i32) @@ -35,6 +38,7 @@ DEF_HELPER_2(wsr_ibreakenable, void, env, i32) DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) +#endif DEF_HELPER_2(wur_fcr, void, env, i32) DEF_HELPER_FLAGS_1(abs_s, TCG_CALL_NO_RWG_SE, f32, f32) diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 7486b99..d401105 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -36,6 +36,13 @@ #include "qemu/timer.h" #include "fpu/softfloat.h" +#ifdef CONFIG_USER_ONLY +/* tb_invalidate_phys_range */ +#include "accel/tcg/translate-all.h" +#endif + +#ifndef CONFIG_USER_ONLY + void xtensa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) @@ -102,6 +109,17 @@ static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) } } +#else + +static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) +{ + mmap_lock(); + tb_invalidate_phys_range(vaddr, vaddr + 1); + mmap_unlock(); +} + +#endif + void HELPER(exception)(CPUXtensaState *env, uint32_t excp) { CPUState *cs = CPU(xtensa_env_get_cpu(env)); @@ -219,21 +237,21 @@ void xtensa_sync_phys_from_window(CPUXtensaState *env) copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16); } -static void rotate_window_abs(CPUXtensaState *env, uint32_t position) +static void xtensa_rotate_window_abs(CPUXtensaState *env, uint32_t position) { xtensa_sync_phys_from_window(env); env->sregs[WINDOW_BASE] = windowbase_bound(position, env); xtensa_sync_window_from_phys(env); } -static void rotate_window(CPUXtensaState *env, uint32_t delta) +void xtensa_rotate_window(CPUXtensaState *env, uint32_t delta) { - rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta); + xtensa_rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta); } void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v) { - rotate_window_abs(env, v); + xtensa_rotate_window_abs(env, v); } void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) @@ -251,7 +269,7 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) HELPER(window_check)(env, pc, callinc); } env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm; - rotate_window(env, callinc); + xtensa_rotate_window(env, callinc); env->sregs[WINDOW_START] |= windowstart_bit(env->sregs[WINDOW_BASE], env); } @@ -266,7 +284,7 @@ void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w) assert(n <= w); - rotate_window(env, n); + xtensa_rotate_window(env, n); env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | (windowbase << PS_OWB_SHIFT) | PS_EXCM; env->sregs[EPC1] = env->pc = pc; @@ -311,7 +329,7 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); - rotate_window(env, -n); + xtensa_rotate_window(env, -n); if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env); } else { @@ -334,12 +352,17 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4) { - rotate_window(env, imm4); + xtensa_rotate_window(env, imm4); +} + +void xtensa_restore_owb(CPUXtensaState *env) +{ + xtensa_rotate_window_abs(env, (env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT); } void HELPER(restore_owb)(CPUXtensaState *env) { - rotate_window_abs(env, (env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT); + xtensa_restore_owb(env); } void HELPER(movsp)(CPUXtensaState *env, uint32_t pc) @@ -376,6 +399,8 @@ void HELPER(dump_state)(CPUXtensaState *env) cpu_dump_state(CPU(cpu), stderr, fprintf, 0); } +#ifndef CONFIG_USER_ONLY + void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel) { CPUState *cpu; @@ -888,6 +913,7 @@ void HELPER(wsr_dbreakc)(CPUXtensaState *env, uint32_t i, uint32_t v) } env->sregs[DBREAKC + i] = v; } +#endif void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v) { @@ -1025,12 +1051,18 @@ void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) uint32_t HELPER(rer)(CPUXtensaState *env, uint32_t addr) { +#ifndef CONFIG_USER_ONLY return address_space_ldl(env->address_space_er, addr, MEMTXATTRS_UNSPECIFIED, NULL); +#else + return 0; +#endif } void HELPER(wer)(CPUXtensaState *env, uint32_t data, uint32_t addr) { +#ifndef CONFIG_USER_ONLY address_space_stl(env->address_space_er, addr, data, MEMTXATTRS_UNSPECIFIED, NULL); +#endif } diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index c06d30d..4f6d030 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -345,12 +345,14 @@ static void gen_debug_exception(DisasContext *dc, uint32_t cause) static bool gen_check_privilege(DisasContext *dc) { - if (dc->cring) { - gen_exception_cause(dc, PRIVILEGED_CAUSE); - dc->is_jmp = DISAS_UPDATE; - return false; +#ifndef CONFIG_USER_ONLY + if (!dc->cring) { + return true; } - return true; +#endif + gen_exception_cause(dc, PRIVILEGED_CAUSE); + dc->is_jmp = DISAS_UPDATE; + return false; } static bool gen_check_cpenable(DisasContext *dc, unsigned cp) @@ -498,6 +500,7 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) return true; } +#ifndef CONFIG_USER_ONLY static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) { if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { @@ -519,14 +522,17 @@ static bool gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr) tcg_gen_andi_i32(d, d, 0xfffffffc); return false; } +#endif static bool gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) { static bool (* const rsr_handler[256])(DisasContext *dc, TCGv_i32 d, uint32_t sr) = { +#ifndef CONFIG_USER_ONLY [CCOUNT] = gen_rsr_ccount, [INTSET] = gen_rsr_ccount, [PTEVADDR] = gen_rsr_ptevaddr, +#endif }; if (rsr_handler[sr]) { @@ -582,6 +588,7 @@ static bool gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s) return false; } +#ifndef CONFIG_USER_ONLY static bool gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_windowbase(cpu_env, v); @@ -797,6 +804,11 @@ static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) } return ret; } +#else +static void gen_check_interrupts(DisasContext *dc) +{ +} +#endif static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) { @@ -808,6 +820,7 @@ static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) [BR] = gen_wsr_br, [LITBASE] = gen_wsr_litbase, [ACCHI] = gen_wsr_acchi, +#ifndef CONFIG_USER_ONLY [WINDOW_BASE] = gen_wsr_windowbase, [WINDOW_START] = gen_wsr_windowstart, [PTEVADDR] = gen_wsr_ptevaddr, @@ -834,6 +847,7 @@ static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) [CCOMPARE] = gen_wsr_ccompare, [CCOMPARE + 1] = gen_wsr_ccompare, [CCOMPARE + 2] = gen_wsr_ccompare, +#endif }; if (wsr_handler[sr]) { @@ -878,6 +892,7 @@ static void gen_load_store_alignment(DisasContext *dc, int shift, } } +#ifndef CONFIG_USER_ONLY static void gen_waiti(DisasContext *dc, uint32_t imm4) { TCGv_i32 pc = tcg_const_i32(dc->next_pc); @@ -894,6 +909,7 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4) tcg_temp_free(intlevel); gen_jumpi_check_loop_end(dc, 0); } +#endif static bool gen_window_check1(DisasContext *dc, unsigned r1) { @@ -1596,12 +1612,14 @@ static void translate_icache(DisasContext *dc, const uint32_t arg[], { if ((!par[0] || gen_check_privilege(dc)) && gen_window_check1(dc, arg[0]) && par[1]) { +#ifndef CONFIG_USER_ONLY TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_movi_i32(cpu_pc, dc->pc); tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); gen_helper_itlb_hit_test(cpu_env, addr); tcg_temp_free(addr); +#endif } } @@ -1610,12 +1628,14 @@ static void translate_itlb(DisasContext *dc, const uint32_t arg[], { if (gen_check_privilege(dc) && gen_window_check1(dc, arg[0])) { +#ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb); /* This could change memory mapping, so exit tb */ gen_jumpi_check_loop_end(dc, -1); tcg_temp_free(dtlb); +#endif } } @@ -1985,11 +2005,13 @@ static void translate_ptlb(DisasContext *dc, const uint32_t arg[], { if (gen_check_privilege(dc) && gen_window_check2(dc, arg[0], arg[1])) { +#ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); tcg_gen_movi_i32(cpu_pc, dc->pc); gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); tcg_temp_free(dtlb); +#endif } } @@ -2173,8 +2195,10 @@ static void translate_rtlb(DisasContext *dc, const uint32_t arg[], { static void (* const helper[])(TCGv_i32 r, TCGv_env env, TCGv_i32 a1, TCGv_i32 a2) = { +#ifndef CONFIG_USER_ONLY gen_helper_rtlb0, gen_helper_rtlb1, +#endif }; if (gen_check_privilege(dc) && @@ -2283,11 +2307,14 @@ static void translate_sext(DisasContext *dc, const uint32_t arg[], static void translate_simcall(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { +#ifndef CONFIG_USER_ONLY if (semihosting_enabled()) { if (gen_check_privilege(dc)) { gen_helper_simcall(cpu_env); } - } else { + } else +#endif + { qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); } @@ -2470,7 +2497,9 @@ static void translate_waiti(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { if (gen_check_privilege(dc)) { +#ifndef CONFIG_USER_ONLY gen_waiti(dc, arg[0]); +#endif } } @@ -2479,12 +2508,14 @@ static void translate_wtlb(DisasContext *dc, const uint32_t arg[], { if (gen_check_privilege(dc) && gen_window_check2(dc, arg[0], arg[1])) { +#ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb); /* This could change memory mapping, so exit tb */ gen_jumpi_check_loop_end(dc, -1); tcg_temp_free(dtlb); +#endif } } -- cgit v1.1