X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?p=kvmfornfv.git;a=blobdiff_plain;f=qemu%2Ftarget-mips%2Fcpu.h;h=866924d1884638060bc439871048018945cbdeca;hp=075c561c81bef52212dfbc2dbf071d4559218fbe;hb=437fd90c0250dee670290f9b714253671a990160;hpb=5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index 075c561c8..866924d18 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -5,11 +5,8 @@ #define ALIGNED_ONLY -#define ELF_MACHINE EM_MIPS - #define CPUArchState struct CPUMIPSState -#include "config.h" #include "qemu-common.h" #include "mips-defs.h" #include "exec/cpu-defs.h" @@ -21,19 +18,19 @@ typedef struct r4k_tlb_t r4k_tlb_t; struct r4k_tlb_t { target_ulong VPN; uint32_t PageMask; - uint_fast8_t ASID; - uint_fast16_t G:1; - uint_fast16_t C0:3; - uint_fast16_t C1:3; - uint_fast16_t V0:1; - uint_fast16_t V1:1; - uint_fast16_t D0:1; - uint_fast16_t D1:1; - uint_fast16_t XI0:1; - uint_fast16_t XI1:1; - uint_fast16_t RI0:1; - uint_fast16_t RI1:1; - uint_fast16_t EHINV:1; + uint8_t ASID; + unsigned int G:1; + unsigned int C0:3; + unsigned int C1:3; + unsigned int V0:1; + unsigned int V1:1; + unsigned int D0:1; + unsigned int D1:1; + unsigned int XI0:1; + unsigned int XI1:1; + unsigned int RI0:1; + unsigned int RI1:1; + unsigned int EHINV:1; uint64_t PFN[2]; }; @@ -102,6 +99,7 @@ struct CPUMIPSFPUContext { uint32_t fcr0; #define FCR0_FREP 29 #define FCR0_UFRP 28 +#define FCR0_HAS2008 23 #define FCR0_F64 22 #define FCR0_L 21 #define FCR0_W 20 @@ -113,6 +111,8 @@ struct CPUMIPSFPUContext { #define FCR0_REV 0 /* fcsr */ uint32_t fcr31; +#define FCR31_ABS2008 19 +#define FCR31_NAN2008 18 #define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) #define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) #define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1)) @@ -132,6 +132,7 @@ struct CPUMIPSFPUContext { }; #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 2 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { @@ -164,6 +165,7 @@ typedef struct mips_def_t mips_def_t; #define MIPS_FPU_MAX 1 #define MIPS_DSP_ACC 4 #define MIPS_KSCRATCH_NUM 6 +#define MIPS_MAAR_MAX 16 /* Must be an even number. */ typedef struct TCState TCState; struct TCState { @@ -239,6 +241,8 @@ struct CPUMIPSState { int32_t CP0_Index; /* CP0_MVP* are per MVP registers. */ + int32_t CP0_VPControl; +#define CP0VPCtl_DIS 0 int32_t CP0_Random; int32_t CP0_VPEControl; #define CP0VPECo_YSI 21 @@ -288,6 +292,8 @@ struct CPUMIPSState { # define CP0EnLo_RI 31 # define CP0EnLo_XI 30 #endif + int32_t CP0_GlobalNumber; +#define CP0GN_VPId 0 target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; @@ -359,7 +365,7 @@ struct CPUMIPSState { #define CP0St_IE 0 int32_t CP0_IntCtl; #define CP0IntCtl_IPTI 29 -#define CP0IntCtl_IPPC1 26 +#define CP0IntCtl_IPPCI 26 #define CP0IntCtl_VS 5 int32_t CP0_SRSCtl; #define CP0SRSCtl_HSS 26 @@ -390,12 +396,13 @@ struct CPUMIPSState { target_ulong CP0_EPC; int32_t CP0_PRid; int32_t CP0_EBase; + target_ulong CP0_CMGCRBase; int32_t CP0_Config0; #define CP0C0_M 31 #define CP0C0_K23 28 #define CP0C0_KU 25 #define CP0C0_MDU 20 -#define CP0C0_MM 17 +#define CP0C0_MM 18 #define CP0C0_BM 16 #define CP0C0_BE 15 #define CP0C0_AT 13 @@ -432,7 +439,7 @@ struct CPUMIPSState { int32_t CP0_Config3; #define CP0C3_M 31 #define CP0C3_BPG 30 -#define CP0C3_CMCGR 29 +#define CP0C3_CMGCR 29 #define CP0C3_MSAP 28 #define CP0C3_BP 27 #define CP0C3_BI 26 @@ -470,15 +477,20 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA 28 #define CP0C5_MSAEn 27 +#define CP0C5_XNP 13 #define CP0C5_UFE 9 #define CP0C5_FRE 8 +#define CP0C5_VP 7 #define CP0C5_SBRI 6 #define CP0C5_MVH 5 #define CP0C5_LLB 4 +#define CP0C5_MRP 3 #define CP0C5_UFR 2 #define CP0C5_NFExists 0 int32_t CP0_Config6; int32_t CP0_Config7; + uint64_t CP0_MAAR[MIPS_MAAR_MAX]; + int32_t CP0_MAARI; /* XXX: Maybe make LLAddr per-TC? */ uint64_t lladdr; target_ulong llval; @@ -511,6 +523,10 @@ struct CPUMIPSState { #define CP0DB_DSS 0 target_ulong CP0_DEPC; int32_t CP0_Performance0; + int32_t CP0_ErrCtl; +#define CP0EC_WST 29 +#define CP0EC_SPR 28 +#define CP0EC_ITC 26 uint64_t CP0_TagLo; int32_t CP0_DataLo; int32_t CP0_TagHi; @@ -526,7 +542,7 @@ struct CPUMIPSState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x75807FF +#define MIPS_HFLAG_TMASK 0xF5807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -575,6 +591,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_MSA 0x1000000 #define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */ #define MIPS_HFLAG_ELPA 0x4000000 +#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */ target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -595,6 +612,7 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; QEMUTimer *timer; /* Internal timer */ + MemoryRegion *itc_tag; /* ITC Configuration Tags */ }; #include "cpu-qom.h" @@ -621,7 +639,6 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); #define cpu_exec cpu_mips_exec -#define cpu_gen_code cpu_mips_gen_code #define cpu_signal_handler cpu_mips_signal_handler #define cpu_list mips_cpu_list @@ -634,28 +651,29 @@ extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); #define MMU_MODE1_SUFFIX _super #define MMU_MODE2_SUFFIX _user #define MMU_USER_IDX 2 -static inline int cpu_mmu_index (CPUMIPSState *env) +static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch) { return env->hflags & MIPS_HFLAG_KSU; } -static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) +static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env) { - int32_t pending; - int32_t status; - int r; - - if (!(env->CP0_Status & (1 << CP0St_IE)) || - (env->CP0_Status & (1 << CP0St_EXL)) || - (env->CP0_Status & (1 << CP0St_ERL)) || + return (env->CP0_Status & (1 << CP0St_IE)) && + !(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM) && /* Note that the TCStatus IXMT field is initialized to zero, and only MT capable cores can set it to one. So we don't need to check for MT capabilities here. */ - (env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) || - (env->hflags & MIPS_HFLAG_DM)) { - /* Interrupts are disabled */ - return 0; - } + !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)); +} + +/* Check if there is pending and not masked out interrupt */ +static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) +{ + int32_t pending; + int32_t status; + bool r; pending = env->CP0_Cause & CP0Ca_IP_mask; status = env->CP0_Status & CP0Ca_IP_mask; @@ -669,7 +687,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) /* A MIPS configured with compatibility or VInt (Vectored Interrupts) treats the pending lines as individual interrupt lines, the status lines are individual masks. */ - r = pending & status; + r = (pending & status) != 0; } return r; } @@ -752,6 +770,7 @@ MIPSCPU *cpu_mips_init(const char *cpu_model); int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); #define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model)) +bool cpu_supports_cps_smp(const char *cpu_model); /* TODO QOM'ify CPU reset and remove */ void cpu_state_reset(CPUMIPSState *s); @@ -859,6 +878,26 @@ static inline int mips_vpe_active(CPUMIPSState *env) return active; } +static inline int mips_vp_active(CPUMIPSState *env) +{ + CPUState *other_cs = first_cpu; + + /* Check if the VP disabled other VPs (which means the VP is enabled) */ + if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) { + return 1; + } + + /* Check if the virtual processor is disabled due to a DVP */ + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); + if ((&other_cpu->env != env) && + ((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) { + return 0; + } + } + return 1; +} + #include "exec/exec-all.h" static inline void compute_hflags(CPUMIPSState *env) @@ -961,6 +1000,15 @@ static inline void compute_hflags(CPUMIPSState *env) } #ifndef CONFIG_USER_ONLY +static inline void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global) +{ + MIPSCPU *cpu = mips_env_get_cpu(env); + + /* Flush qemu's TLB and discard all shadowed entries. */ + tlb_flush(CPU(cpu), flush_global); + env->tlb->tlb_in_use = env->tlb->nb_tlb; +} + /* Called for updates to CP0_Status. */ static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) { @@ -999,17 +1047,29 @@ static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) { uint32_t mask = env->CP0_Status_rw_bitmask; + target_ulong old = env->CP0_Status; if (env->insn_flags & ISA_MIPS32R6) { bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; - +#if defined(TARGET_MIPS64) + uint32_t ksux = (1 << CP0St_KX) & val; + ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */ + ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */ + val = (val & ~(7 << CP0St_UX)) | ksux; +#endif if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) { mask &= ~(3 << CP0St_KSU); } mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val); } - env->CP0_Status = (env->CP0_Status & ~mask) | (val & mask); + env->CP0_Status = (old & ~mask) | (val & mask); +#if defined(TARGET_MIPS64) + if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) { + /* Access to at least one of the 64-bit segments has been disabled */ + cpu_mips_tlb_flush(env, 1); + } +#endif if (env->CP0_Config3 & (1 << CP0C3_MT)) { sync_c0_status(env, env, env->current_tc); } else { @@ -1049,4 +1109,28 @@ static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val) } #endif +static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, + uint32_t exception, + int error_code, + uintptr_t pc) +{ + CPUState *cs = CPU(mips_env_get_cpu(env)); + + if (exception < EXCP_SC) { + qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", + __func__, exception, error_code); + } + cs->exception_index = exception; + env->error_code = error_code; + + cpu_loop_exit_restore(cs, pc); +} + +static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, + uint32_t exception, + uintptr_t pc) +{ + do_raise_exception_err(env, exception, 0, pc); +} + #endif /* !defined (__MIPS_CPU_H__) */