diff options
Diffstat (limited to 'target/loongarch/cpu.h')
| -rw-r--r-- | target/loongarch/cpu.h | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h new file mode 100644 index 0000000000..71a5036c3c --- /dev/null +++ b/target/loongarch/cpu.h @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + */ + +#ifndef LOONGARCH_CPU_H +#define LOONGARCH_CPU_H + +#include "exec/cpu-defs.h" +#include "fpu/softfloat-types.h" +#include "hw/registerfields.h" +#include "qemu/timer.h" +#include "exec/memory.h" +#include "hw/sysbus.h" + +#define IOCSRF_TEMP 0 +#define IOCSRF_NODECNT 1 +#define IOCSRF_MSI 2 +#define IOCSRF_EXTIOI 3 +#define IOCSRF_CSRIPI 4 +#define IOCSRF_FREQCSR 5 +#define IOCSRF_FREQSCALE 6 +#define IOCSRF_DVFSV1 7 +#define IOCSRF_GMOD 9 +#define IOCSRF_VM 11 + +#define FEATURE_REG 0x8 +#define VENDOR_REG 0x10 +#define CPUNAME_REG 0x20 +#define MISC_FUNC_REG 0x420 +#define IOCSRM_EXTIOI_EN 48 + +#define IOCSR_MEM_SIZE 0x428 + +#define TCG_GUEST_DEFAULT_MO (0) + +#define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ +#define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ +#define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ +#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ + +FIELD(FCSR0, ENABLES, 0, 5) +FIELD(FCSR0, RM, 8, 2) +FIELD(FCSR0, FLAGS, 16, 5) +FIELD(FCSR0, CAUSE, 24, 5) + +#define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE) +#define SET_FP_CAUSE(REG, V) FIELD_DP32(REG, FCSR0, CAUSE, V) +#define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES) +#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V) +#define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS) +#define SET_FP_FLAGS(REG, V) FIELD_DP32(REG, FCSR0, FLAGS, V) +#define UPDATE_FP_FLAGS(REG, V) \ + do { \ + (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \ + } while (0) + +#define FP_INEXACT 1 +#define FP_UNDERFLOW 2 +#define FP_OVERFLOW 4 +#define FP_DIV0 8 +#define FP_INVALID 16 + +#define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */ +#define EXCCODE_INT 0 +#define EXCCODE_PIL 1 +#define EXCCODE_PIS 2 +#define EXCCODE_PIF 3 +#define EXCCODE_PME 4 +#define EXCCODE_PNR 5 +#define EXCCODE_PNX 6 +#define EXCCODE_PPI 7 +#define EXCCODE_ADEF 8 /* Different exception subcode */ +#define EXCCODE_ADEM 8 +#define EXCCODE_ALE 9 +#define EXCCODE_BCE 10 +#define EXCCODE_SYS 11 +#define EXCCODE_BRK 12 +#define EXCCODE_INE 13 +#define EXCCODE_IPE 14 +#define EXCCODE_FPD 15 +#define EXCCODE_SXD 16 +#define EXCCODE_ASXD 17 +#define EXCCODE_FPE 18 /* Different exception subcode */ +#define EXCCODE_VFPE 18 +#define EXCCODE_WPEF 19 /* Different exception subcode */ +#define EXCCODE_WPEM 19 +#define EXCCODE_BTD 20 +#define EXCCODE_BTE 21 +#define EXCCODE_DBP 26 /* Reserved subcode used for debug */ + +/* cpucfg[0] bits */ +FIELD(CPUCFG0, PRID, 0, 32) + +/* cpucfg[1] bits */ +FIELD(CPUCFG1, ARCH, 0, 2) +FIELD(CPUCFG1, PGMMU, 2, 1) +FIELD(CPUCFG1, IOCSR, 3, 1) +FIELD(CPUCFG1, PALEN, 4, 8) +FIELD(CPUCFG1, VALEN, 12, 8) +FIELD(CPUCFG1, UAL, 20, 1) +FIELD(CPUCFG1, RI, 21, 1) +FIELD(CPUCFG1, EP, 22, 1) +FIELD(CPUCFG1, RPLV, 23, 1) +FIELD(CPUCFG1, HP, 24, 1) +FIELD(CPUCFG1, IOCSR_BRD, 25, 1) +FIELD(CPUCFG1, MSG_INT, 26, 1) + +/* cpucfg[2] bits */ +FIELD(CPUCFG2, FP, 0, 1) +FIELD(CPUCFG2, FP_SP, 1, 1) +FIELD(CPUCFG2, FP_DP, 2, 1) +FIELD(CPUCFG2, FP_VER, 3, 3) +FIELD(CPUCFG2, LSX, 6, 1) +FIELD(CPUCFG2, LASX, 7, 1) +FIELD(CPUCFG2, COMPLEX, 8, 1) +FIELD(CPUCFG2, CRYPTO, 9, 1) +FIELD(CPUCFG2, LVZ, 10, 1) +FIELD(CPUCFG2, LVZ_VER, 11, 3) +FIELD(CPUCFG2, LLFTP, 14, 1) +FIELD(CPUCFG2, LLFTP_VER, 15, 3) +FIELD(CPUCFG2, LBT_X86, 18, 1) +FIELD(CPUCFG2, LBT_ARM, 19, 1) +FIELD(CPUCFG2, LBT_MIPS, 20, 1) +FIELD(CPUCFG2, LSPW, 21, 1) +FIELD(CPUCFG2, LAM, 22, 1) + +/* cpucfg[3] bits */ +FIELD(CPUCFG3, CCDMA, 0, 1) +FIELD(CPUCFG3, SFB, 1, 1) +FIELD(CPUCFG3, UCACC, 2, 1) +FIELD(CPUCFG3, LLEXC, 3, 1) +FIELD(CPUCFG3, SCDLY, 4, 1) +FIELD(CPUCFG3, LLDBAR, 5, 1) +FIELD(CPUCFG3, ITLBHMC, 6, 1) +FIELD(CPUCFG3, ICHMC, 7, 1) +FIELD(CPUCFG3, SPW_LVL, 8, 3) +FIELD(CPUCFG3, SPW_HP_HF, 11, 1) +FIELD(CPUCFG3, RVA, 12, 1) +FIELD(CPUCFG3, RVAMAX, 13, 4) + +/* cpucfg[4] bits */ +FIELD(CPUCFG4, CC_FREQ, 0, 32) + +/* cpucfg[5] bits */ +FIELD(CPUCFG5, CC_MUL, 0, 16) +FIELD(CPUCFG5, CC_DIV, 16, 16) + +/* cpucfg[6] bits */ +FIELD(CPUCFG6, PMP, 0, 1) +FIELD(CPUCFG6, PMVER, 1, 3) +FIELD(CPUCFG6, PMNUM, 4, 4) +FIELD(CPUCFG6, PMBITS, 8, 6) +FIELD(CPUCFG6, UPM, 14, 1) + +/* cpucfg[16] bits */ +FIELD(CPUCFG16, L1_IUPRE, 0, 1) +FIELD(CPUCFG16, L1_IUUNIFY, 1, 1) +FIELD(CPUCFG16, L1_DPRE, 2, 1) +FIELD(CPUCFG16, L2_IUPRE, 3, 1) +FIELD(CPUCFG16, L2_IUUNIFY, 4, 1) +FIELD(CPUCFG16, L2_IUPRIV, 5, 1) +FIELD(CPUCFG16, L2_IUINCL, 6, 1) +FIELD(CPUCFG16, L2_DPRE, 7, 1) +FIELD(CPUCFG16, L2_DPRIV, 8, 1) +FIELD(CPUCFG16, L2_DINCL, 9, 1) +FIELD(CPUCFG16, L3_IUPRE, 10, 1) +FIELD(CPUCFG16, L3_IUUNIFY, 11, 1) +FIELD(CPUCFG16, L3_IUPRIV, 12, 1) +FIELD(CPUCFG16, L3_IUINCL, 13, 1) +FIELD(CPUCFG16, L3_DPRE, 14, 1) +FIELD(CPUCFG16, L3_DPRIV, 15, 1) +FIELD(CPUCFG16, L3_DINCL, 16, 1) + +/* cpucfg[17] bits */ +FIELD(CPUCFG17, L1IU_WAYS, 0, 16) +FIELD(CPUCFG17, L1IU_SETS, 16, 8) +FIELD(CPUCFG17, L1IU_SIZE, 24, 7) + +/* cpucfg[18] bits */ +FIELD(CPUCFG18, L1D_WAYS, 0, 16) +FIELD(CPUCFG18, L1D_SETS, 16, 8) +FIELD(CPUCFG18, L1D_SIZE, 24, 7) + +/* cpucfg[19] bits */ +FIELD(CPUCFG19, L2IU_WAYS, 0, 16) +FIELD(CPUCFG19, L2IU_SETS, 16, 8) +FIELD(CPUCFG19, L2IU_SIZE, 24, 7) + +/* cpucfg[20] bits */ +FIELD(CPUCFG20, L3IU_WAYS, 0, 16) +FIELD(CPUCFG20, L3IU_SETS, 16, 8) +FIELD(CPUCFG20, L3IU_SIZE, 24, 7) + +/*CSR_CRMD */ +FIELD(CSR_CRMD, PLV, 0, 2) +FIELD(CSR_CRMD, IE, 2, 1) +FIELD(CSR_CRMD, DA, 3, 1) +FIELD(CSR_CRMD, PG, 4, 1) +FIELD(CSR_CRMD, DATF, 5, 2) +FIELD(CSR_CRMD, DATM, 7, 2) +FIELD(CSR_CRMD, WE, 9, 1) + +extern const char * const regnames[32]; +extern const char * const fregnames[32]; + +#define N_IRQS 13 +#define IRQ_TIMER 11 +#define IRQ_IPI 12 + +#define LOONGARCH_STLB 2048 /* 2048 STLB */ +#define LOONGARCH_MTLB 64 /* 64 MTLB */ +#define LOONGARCH_TLB_MAX (LOONGARCH_STLB + LOONGARCH_MTLB) + +/* + * define the ASID PS E VPPN field of TLB + */ +FIELD(TLB_MISC, E, 0, 1) +FIELD(TLB_MISC, ASID, 1, 10) +FIELD(TLB_MISC, VPPN, 13, 35) +FIELD(TLB_MISC, PS, 48, 6) + +struct LoongArchTLB { + uint64_t tlb_misc; + /* Fields corresponding to CSR_TLBELO0/1 */ + uint64_t tlb_entry0; + uint64_t tlb_entry1; +}; +typedef struct LoongArchTLB LoongArchTLB; + +typedef struct CPUArchState { + uint64_t gpr[32]; + uint64_t pc; + + uint64_t fpr[32]; + float_status fp_status; + bool cf[8]; + + uint32_t fcsr0; + uint32_t fcsr0_mask; + + uint32_t cpucfg[21]; + + uint64_t lladdr; /* LL virtual address compared against SC */ + uint64_t llval; + + uint64_t badaddr; + + /* LoongArch CSRs */ + uint64_t CSR_CRMD; + uint64_t CSR_PRMD; + uint64_t CSR_EUEN; + uint64_t CSR_MISC; + uint64_t CSR_ECFG; + uint64_t CSR_ESTAT; + uint64_t CSR_ERA; + uint64_t CSR_BADV; + uint64_t CSR_BADI; + uint64_t CSR_EENTRY; + uint64_t CSR_TLBIDX; + uint64_t CSR_TLBEHI; + uint64_t CSR_TLBELO0; + uint64_t CSR_TLBELO1; + uint64_t CSR_ASID; + uint64_t CSR_PGDL; + uint64_t CSR_PGDH; + uint64_t CSR_PGD; + uint64_t CSR_PWCL; + uint64_t CSR_PWCH; + uint64_t CSR_STLBPS; + uint64_t CSR_RVACFG; + uint64_t CSR_PRCFG1; + uint64_t CSR_PRCFG2; + uint64_t CSR_PRCFG3; + uint64_t CSR_SAVE[16]; + uint64_t CSR_TID; + uint64_t CSR_TCFG; + uint64_t CSR_TVAL; + uint64_t CSR_CNTC; + uint64_t CSR_TICLR; + uint64_t CSR_LLBCTL; + uint64_t CSR_IMPCTL1; + uint64_t CSR_IMPCTL2; + uint64_t CSR_TLBRENTRY; + uint64_t CSR_TLBRBADV; + uint64_t CSR_TLBRERA; + uint64_t CSR_TLBRSAVE; + uint64_t CSR_TLBRELO0; + uint64_t CSR_TLBRELO1; + uint64_t CSR_TLBREHI; + uint64_t CSR_TLBRPRMD; + uint64_t CSR_MERRCTL; + uint64_t CSR_MERRINFO1; + uint64_t CSR_MERRINFO2; + uint64_t CSR_MERRENTRY; + uint64_t CSR_MERRERA; + uint64_t CSR_MERRSAVE; + uint64_t CSR_CTAG; + uint64_t CSR_DMW[4]; + uint64_t CSR_DBG; + uint64_t CSR_DERA; + uint64_t CSR_DSAVE; + + LoongArchTLB tlb[LOONGARCH_TLB_MAX]; + + AddressSpace address_space_iocsr; + MemoryRegion system_iocsr; + MemoryRegion iocsr_mem; + bool load_elf; + uint64_t elf_address; +} CPULoongArchState; + +/** + * LoongArchCPU: + * @env: #CPULoongArchState + * + * A LoongArch CPU. + */ +struct ArchCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUNegativeOffsetState neg; + CPULoongArchState env; + QEMUTimer timer; +}; + +#define TYPE_LOONGARCH_CPU "loongarch-cpu" + +OBJECT_DECLARE_CPU_TYPE(LoongArchCPU, LoongArchCPUClass, + LOONGARCH_CPU) + +/** + * LoongArchCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * + * A LoongArch CPU model. + */ +struct LoongArchCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + DeviceReset parent_reset; +}; + +/* + * LoongArch CPUs has 4 privilege levels. + * 0 for kernel mode, 3 for user mode. + * Define an extra index for DA(direct addressing) mode. + */ +#define MMU_KERNEL_IDX 0 +#define MMU_USER_IDX 3 +#define MMU_DA_IDX 4 + +static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) +{ + uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG); + + if (!pg) { + return MMU_DA_IDX; + } + return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); +} + +static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, + target_ulong *pc, + target_ulong *cs_base, + uint32_t *flags) +{ + *pc = env->pc; + *cs_base = 0; + *flags = cpu_mmu_index(env, false); +} + +void loongarch_cpu_list(void); + +#define cpu_list loongarch_cpu_list + +#include "exec/cpu-all.h" + +#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU +#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU + +#endif /* LOONGARCH_CPU_H */ |