X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=target-xtensa%2Fcpu.h;h=6c9fc35dcc438061f9e5d840c7c19d84024e9973;hb=97a8ea5a3ae7938cb54fd4dc19d3a413024bc6c0;hp=939222ca8c3ccb141f014829a93fc001bf9fc732;hpb=f0a548b93da07b6546e4f8178a93c47284a27d05;p=qemu.git diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 939222ca8..6c9fc35dc 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -31,11 +31,12 @@ #define TARGET_LONG_BITS 32 #define ELF_MACHINE EM_XTENSA -#define CPUState struct CPUXtensaState +#define CPUArchState struct CPUXtensaState #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 @@ -52,14 +53,19 @@ enum { XTENSA_OPTION_EXTENDED_L32R, XTENSA_OPTION_16_BIT_IMUL, XTENSA_OPTION_32_BIT_IMUL, + XTENSA_OPTION_32_BIT_IMUL_HIGH, XTENSA_OPTION_32_BIT_IDIV, XTENSA_OPTION_MAC16, - XTENSA_OPTION_MISC_OP, + XTENSA_OPTION_MISC_OP_NSA, + XTENSA_OPTION_MISC_OP_MINMAX, + XTENSA_OPTION_MISC_OP_SEXT, + XTENSA_OPTION_MISC_OP_CLAMPS, XTENSA_OPTION_COPROCESSOR, XTENSA_OPTION_BOOLEAN, XTENSA_OPTION_FP_COPROCESSOR, XTENSA_OPTION_MP_SYNCHRO, XTENSA_OPTION_CONDITIONAL_STORE, + XTENSA_OPTION_ATOMCTL, /* Interrupts and exceptions */ XTENSA_OPTION_EXCEPTION, @@ -88,6 +94,7 @@ enum { XTENSA_OPTION_REGION_PROTECTION, XTENSA_OPTION_REGION_TRANSLATION, XTENSA_OPTION_MMU, + XTENSA_OPTION_CACHEATTR, /* Other */ XTENSA_OPTION_WINDOWED_REGISTER, @@ -106,9 +113,47 @@ enum { }; enum { + LBEG = 0, + LEND = 1, + LCOUNT = 2, SAR = 3, + BR = 4, + LITBASE = 5, SCOMPARE1 = 12, + ACCLO = 16, + ACCHI = 17, + MR = 32, + WINDOW_BASE = 72, + WINDOW_START = 73, + PTEVADDR = 83, + RASID = 90, + ITLBCFG = 91, + DTLBCFG = 92, + IBREAKENABLE = 96, + CACHEATTR = 98, + ATOMCTL = 99, + IBREAKA = 128, + DBREAKA = 144, + DBREAKC = 160, + EPC1 = 177, + DEPC = 192, + EPS2 = 194, + EXCSAVE1 = 209, + CPENABLE = 224, + INTSET = 226, + INTCLEAR = 227, + INTENABLE = 228, PS = 230, + VECBASE = 231, + EXCCAUSE = 232, + DEBUGCAUSE = 233, + CCOUNT = 234, + PRID = 235, + ICOUNT = 236, + ICOUNTLEVEL = 237, + EXCVADDR = 238, + CCOMPARE = 240, + MISC = 244, }; #define PS_INTLEVEL 0xf @@ -129,42 +174,272 @@ enum { #define PS_WOE 0x40000 +#define DEBUGCAUSE_IC 0x1 +#define DEBUGCAUSE_IB 0x2 +#define DEBUGCAUSE_DB 0x4 +#define DEBUGCAUSE_BI 0x8 +#define DEBUGCAUSE_BN 0x10 +#define DEBUGCAUSE_DI 0x20 +#define DEBUGCAUSE_DBNUM 0xf00 +#define DEBUGCAUSE_DBNUM_SHIFT 8 + +#define DBREAKC_SB 0x80000000 +#define DBREAKC_LB 0x40000000 +#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB) +#define DBREAKC_MASK 0x3f + +#define MAX_NAREG 64 +#define MAX_NINTERRUPT 32 +#define MAX_NLEVEL 6 +#define MAX_NNMI 1 +#define MAX_NCCOMPARE 3 +#define MAX_TLB_WAY_SIZE 8 +#define MAX_NDBREAK 2 + +#define REGION_PAGE_MASK 0xe0000000 + +#define PAGE_CACHE_MASK 0x700 +#define PAGE_CACHE_SHIFT 8 +#define PAGE_CACHE_INVALID 0x000 +#define PAGE_CACHE_BYPASS 0x100 +#define PAGE_CACHE_WT 0x200 +#define PAGE_CACHE_WB 0x400 +#define PAGE_CACHE_ISOLATE 0x600 + +enum { + /* Static vectors */ + EXC_RESET, + EXC_MEMORY_ERROR, + + /* Dynamic vectors */ + EXC_WINDOW_OVERFLOW4, + EXC_WINDOW_UNDERFLOW4, + EXC_WINDOW_OVERFLOW8, + EXC_WINDOW_UNDERFLOW8, + EXC_WINDOW_OVERFLOW12, + EXC_WINDOW_UNDERFLOW12, + EXC_IRQ, + EXC_KERNEL, + EXC_USER, + EXC_DOUBLE, + EXC_DEBUG, + EXC_MAX +}; + +enum { + ILLEGAL_INSTRUCTION_CAUSE = 0, + SYSCALL_CAUSE, + INSTRUCTION_FETCH_ERROR_CAUSE, + LOAD_STORE_ERROR_CAUSE, + LEVEL1_INTERRUPT_CAUSE, + ALLOCA_CAUSE, + INTEGER_DIVIDE_BY_ZERO_CAUSE, + PRIVILEGED_CAUSE = 8, + LOAD_STORE_ALIGNMENT_CAUSE, + + INSTR_PIF_DATA_ERROR_CAUSE = 12, + LOAD_STORE_PIF_DATA_ERROR_CAUSE, + INSTR_PIF_ADDR_ERROR_CAUSE, + LOAD_STORE_PIF_ADDR_ERROR_CAUSE, + + INST_TLB_MISS_CAUSE, + INST_TLB_MULTI_HIT_CAUSE, + INST_FETCH_PRIVILEGE_CAUSE, + INST_FETCH_PROHIBITED_CAUSE = 20, + LOAD_STORE_TLB_MISS_CAUSE = 24, + LOAD_STORE_TLB_MULTI_HIT_CAUSE, + LOAD_STORE_PRIVILEGE_CAUSE, + LOAD_PROHIBITED_CAUSE = 28, + STORE_PROHIBITED_CAUSE, + + COPROCESSOR0_DISABLED = 32, +}; + +typedef enum { + INTTYPE_LEVEL, + INTTYPE_EDGE, + INTTYPE_NMI, + INTTYPE_SOFTWARE, + INTTYPE_TIMER, + INTTYPE_DEBUG, + INTTYPE_WRITE_ERR, + INTTYPE_MAX +} interrupt_type; + +typedef struct xtensa_tlb_entry { + uint32_t vaddr; + uint32_t paddr; + uint8_t asid; + uint8_t attr; + bool variable; +} xtensa_tlb_entry; + +typedef struct xtensa_tlb { + unsigned nways; + const unsigned way_size[10]; + bool varway56; + unsigned nrefillentries; +} xtensa_tlb; + +typedef struct XtensaGdbReg { + int targno; + int type; + int group; +} XtensaGdbReg; + +typedef struct XtensaGdbRegmap { + int num_regs; + int num_core_regs; + /* PC + a + ar + sr + ur */ + XtensaGdbReg reg[1 + 16 + 64 + 256 + 256]; +} XtensaGdbRegmap; + typedef struct XtensaConfig { const char *name; uint64_t options; + XtensaGdbRegmap gdb_regmap; + unsigned nareg; + int excm_level; + int ndepc; + uint32_t vecbase; + uint32_t exception_vector[EXC_MAX]; + unsigned ninterrupt; + unsigned nlevel; + uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1]; + uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1]; + uint32_t inttype_mask[INTTYPE_MAX]; + struct { + uint32_t level; + interrupt_type inttype; + } interrupt[MAX_NINTERRUPT]; + unsigned nccompare; + uint32_t timerint[MAX_NCCOMPARE]; + unsigned nextint; + unsigned extint[MAX_NINTERRUPT]; + + unsigned debug_level; + unsigned nibreak; + unsigned ndbreak; + + uint32_t clock_freq_khz; + + xtensa_tlb itlb; + xtensa_tlb dtlb; } XtensaConfig; +typedef struct XtensaConfigList { + const XtensaConfig *config; + struct XtensaConfigList *next; +} XtensaConfigList; + typedef struct CPUXtensaState { const XtensaConfig *config; uint32_t regs[16]; uint32_t pc; uint32_t sregs[256]; uint32_t uregs[256]; + uint32_t phys_regs[MAX_NAREG]; + float32 fregs[16]; + float_status fp_status; + + xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE]; + xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE]; + unsigned autorefill_idx; + + int pending_irq_level; /* level of last raised IRQ */ + void **irq_inputs; + QEMUTimer *ccompare_timer; + uint32_t wake_ccount; + int64_t halt_clock; + + int exception_taken; + + /* Watchpoints for DBREAK registers */ + CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK]; CPU_COMMON } CPUXtensaState; -#define cpu_init cpu_xtensa_init +#include "cpu-qom.h" + #define cpu_exec cpu_xtensa_exec #define cpu_gen_code cpu_xtensa_gen_code #define cpu_signal_handler cpu_xtensa_signal_handler #define cpu_list xtensa_cpu_list -CPUXtensaState *cpu_xtensa_init(const char *cpu_model); +#ifdef TARGET_WORDS_BIGENDIAN +#define XTENSA_DEFAULT_CPU_MODEL "fsf" +#else +#define XTENSA_DEFAULT_CPU_MODEL "dc232b" +#endif + +XtensaCPU *cpu_xtensa_init(const char *cpu_model); + +static inline CPUXtensaState *cpu_init(const char *cpu_model) +{ + XtensaCPU *cpu = cpu_xtensa_init(cpu_model); + if (cpu == NULL) { + return NULL; + } + return &cpu->env; +} + void xtensa_translate_init(void); +void xtensa_breakpoint_handler(CPUXtensaState *env); int cpu_xtensa_exec(CPUXtensaState *s); -void do_interrupt(CPUXtensaState *s); +void xtensa_register_core(XtensaConfigList *node); +void check_interrupts(CPUXtensaState *s); +void xtensa_irq_init(CPUXtensaState *env); +void *xtensa_get_extint(CPUXtensaState *env, unsigned extint); +void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d); +void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active); +void xtensa_rearm_ccompare_timer(CPUXtensaState *env); 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 debug_exception_env(CPUXtensaState *new_env, uint32_t cause); + #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt)) +#define XTENSA_OPTION_ALL (~(uint64_t)0) + +static inline bool xtensa_option_bits_enabled(const XtensaConfig *config, + uint64_t opt) +{ + return (config->options & opt) != 0; +} static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt) { - return (config->options & XTENSA_OPTION_BIT(opt)) != 0; + return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt)); +} + +static inline int xtensa_get_cintlevel(const CPUXtensaState *env) +{ + int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT; + if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) { + level = env->config->excm_level; + } + return level; } -static inline int xtensa_get_ring(const CPUState *env) +static inline int xtensa_get_ring(const CPUXtensaState *env) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT; @@ -173,7 +448,7 @@ static inline int xtensa_get_ring(const CPUState *env) } } -static inline int xtensa_get_cring(const CPUState *env) +static inline int xtensa_get_cring(const CPUXtensaState *env) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) && (env->sregs[PS] & PS_EXCM) == 0) { @@ -183,21 +458,34 @@ static inline int xtensa_get_cring(const CPUState *env) } } +static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, + bool dtlb, unsigned wi, unsigned ei) +{ + return dtlb ? + env->dtlb[wi] + ei : + env->itlb[wi] + ei; +} + /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _ring0 #define MMU_MODE1_SUFFIX _ring1 #define MMU_MODE2_SUFFIX _ring2 #define MMU_MODE3_SUFFIX _ring3 -static inline int cpu_mmu_index(CPUState *env) +static inline int cpu_mmu_index(CPUXtensaState *env) { return xtensa_get_cring(env); } #define XTENSA_TBFLAG_RING_MASK 0x3 #define XTENSA_TBFLAG_EXCM 0x4 +#define XTENSA_TBFLAG_LITBASE 0x8 +#define XTENSA_TBFLAG_DEBUG 0x10 +#define XTENSA_TBFLAG_ICOUNT 0x20 +#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0 +#define XTENSA_TBFLAG_CPENABLE_SHIFT 6 -static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, +static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { *pc = env->pc; @@ -207,17 +495,34 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, if (env->sregs[PS] & PS_EXCM) { *flags |= XTENSA_TBFLAG_EXCM; } + if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) && + (env->sregs[LITBASE] & 1)) { + *flags |= XTENSA_TBFLAG_LITBASE; + } + if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) { + if (xtensa_get_cintlevel(env) < env->config->debug_level) { + *flags |= XTENSA_TBFLAG_DEBUG; + } + if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) { + *flags |= XTENSA_TBFLAG_ICOUNT; + } + } + if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) { + *flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT; + } } -#include "cpu-all.h" -#include "exec-all.h" +#include "exec/cpu-all.h" +#include "exec/exec-all.h" -static inline int cpu_has_work(CPUState *env) +static inline int cpu_has_work(CPUState *cpu) { - return 1; + CPUXtensaState *env = &XTENSA_CPU(cpu)->env; + + return env->pending_irq_level; } -static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb) +static inline void cpu_pc_from_tb(CPUXtensaState *env, TranslationBlock *tb) { env->pc = tb->pc; }