| /* | |
| * QEMU RISC-V CPU | |
| * | |
| * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu | |
| * Copyright (c) 2017-2018 SiFive, Inc. | |
| * | |
| * This program is free software; you can redistribute it and/or modify it | |
| * under the terms and conditions of the GNU General Public License, | |
| * version 2 or later, as published by the Free Software Foundation. | |
| * | |
| * This program is distributed in the hope it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| * more details. | |
| * | |
| * You should have received a copy of the GNU General Public License along with | |
| * this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #ifndef RISCV_CPU_H | |
| #define RISCV_CPU_H | |
| #include "hw/core/cpu.h" | |
| #include "hw/core/registerfields.h" | |
| #include "hw/core/qdev-properties.h" | |
| #include "exec/cpu-common.h" | |
| #include "exec/cpu-interrupt.h" | |
| #include "exec/gdbstub.h" | |
| #include "exec/target_long.h" | |
| #include "qemu/cpu-float.h" | |
| #include "qom/object.h" | |
| #include "qemu/int128.h" | |
| #include "cpu_bits.h" | |
| #include "cpu_cfg.h" | |
| #include "qapi/qapi-types-common.h" | |
| #include "cpu-qom.h" | |
| typedef struct CPUArchState CPURISCVState; | |
| #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU | |
| #if defined(TARGET_RISCV32) | |
| # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32 | |
| #elif defined(TARGET_RISCV64) | |
| # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64 | |
| #endif | |
| /* | |
| * b0: Whether a instruction always raise a store AMO or not. | |
| */ | |
| #define RISCV_UW2_ALWAYS_STORE_AMO 1 | |
| #define RV(x) BIT(x - 'A') | |
| /* | |
| * Update misa_bits[], misa_ext_info_arr[] and misa_ext_cfgs[] | |
| * when adding new MISA bits here. | |
| */ | |
| #define RVI RV('I') | |
| #define RVE RV('E') /* E and I are mutually exclusive */ | |
| #define RVM RV('M') | |
| #define RVA RV('A') | |
| #define RVF RV('F') | |
| #define RVD RV('D') | |
| #define RVV RV('V') | |
| #define RVC RV('C') | |
| #define RVS RV('S') | |
| #define RVU RV('U') | |
| #define RVH RV('H') | |
| #define RVG RV('G') | |
| #define RVB RV('B') | |
| #define RVX RV('X') | |
| extern const uint32_t misa_bits[]; | |
| const char *riscv_get_misa_ext_name(uint32_t bit); | |
| const char *riscv_get_misa_ext_description(uint32_t bit); | |
| #define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop) | |
| #define ENV_CSR_OFFSET(_csr) offsetof(CPURISCVState, _csr) | |
| typedef struct riscv_cpu_profile { | |
| struct riscv_cpu_profile *u_parent; | |
| struct riscv_cpu_profile *s_parent; | |
| const char *name; | |
| uint32_t misa_ext; | |
| /* | |
| * The profile is enabled/disabled via command line or | |
| * via cpu_init(). Enabling a profile will add all its | |
| * mandatory extensions in the CPU during init(). | |
| */ | |
| bool enabled; | |
| /* | |
| * The profile is present in the CPU, i.e. the current set of | |
| * CPU extensions complies with it. A profile can be enabled | |
| * and not present (e.g. the user disabled a mandatory extension) | |
| * and the other way around (e.g. all mandatory extensions are | |
| * present in a non-profile CPU). | |
| * | |
| * QMP uses this flag. | |
| */ | |
| bool present; | |
| bool user_set; | |
| int priv_spec; | |
| int satp_mode; | |
| const int32_t ext_offsets[]; | |
| } RISCVCPUProfile; | |
| #define RISCV_PROFILE_EXT_LIST_END -1 | |
| #define RISCV_PROFILE_ATTR_UNUSED -1 | |
| extern RISCVCPUProfile *riscv_profiles[]; | |
| /* | |
| * Type large enough to hold all PRV_* fields, update CPUArchState::priv | |
| * migration field if changing this type. | |
| */ | |
| typedef uint8_t privilege_mode_t; | |
| /* Privileged specification version */ | |
| #define PRIV_VER_1_10_0_STR "v1.10.0" | |
| #define PRIV_VER_1_11_0_STR "v1.11.0" | |
| #define PRIV_VER_1_12_0_STR "v1.12.0" | |
| #define PRIV_VER_1_13_0_STR "v1.13.0" | |
| enum { | |
| PRIV_VERSION_1_10_0 = 0, | |
| PRIV_VERSION_1_11_0, | |
| PRIV_VERSION_1_12_0, | |
| PRIV_VERSION_1_13_0, | |
| PRIV_VERSION_LATEST = PRIV_VERSION_1_13_0, | |
| }; | |
| #define VEXT_VERSION_1_00_0 0x00010000 | |
| #define VEXT_VER_1_00_0_STR "v1.0" | |
| enum { | |
| TRANSLATE_SUCCESS, | |
| TRANSLATE_FAIL, | |
| TRANSLATE_PMP_FAIL, | |
| TRANSLATE_G_STAGE_FAIL, | |
| TRANSLATE_PMA_FAIL, | |
| }; | |
| /* Extension context status */ | |
| typedef enum { | |
| EXT_STATUS_DISABLED = 0, | |
| EXT_STATUS_INITIAL, | |
| EXT_STATUS_CLEAN, | |
| EXT_STATUS_DIRTY, | |
| } RISCVExtStatus; | |
| /* Enum holds PMM field values for Zjpm v1.0 extension */ | |
| typedef enum { | |
| PMM_FIELD_DISABLED = 0, | |
| PMM_FIELD_RESERVED = 1, | |
| PMM_FIELD_PMLEN7 = 2, | |
| PMM_FIELD_PMLEN16 = 3, | |
| } RISCVPmPmm; | |
| typedef struct riscv_cpu_implied_exts_rule { | |
| #ifndef CONFIG_USER_ONLY | |
| /* | |
| * Bitmask indicates the rule enabled status for the harts. | |
| * This enhancement is only available in system-mode QEMU, | |
| * as we don't have a good way (e.g. mhartid) to distinguish | |
| * the SMP cores in user-mode QEMU. | |
| */ | |
| unsigned long *enabled; | |
| #endif | |
| /* True if this is a MISA implied rule. */ | |
| bool is_misa; | |
| /* ext is MISA bit if is_misa flag is true, else multi extension offset. */ | |
| const uint32_t ext; | |
| const uint32_t implied_misa_exts; | |
| const uint32_t implied_multi_exts[]; | |
| } RISCVCPUImpliedExtsRule; | |
| extern RISCVCPUImpliedExtsRule *riscv_misa_ext_implied_rules[]; | |
| extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[]; | |
| #define RISCV_IMPLIED_EXTS_RULE_END -1 | |
| #define MMU_USER_IDX 3 | |
| #if !defined(CONFIG_USER_ONLY) | |
| #include "tcg/pmp.h" | |
| #endif | |
| #define RV_VLEN_MAX 1024 | |
| #define RV_MAX_MHPMEVENTS 32 | |
| #define RV_MAX_MHPMCOUNTERS 32 | |
| /* | |
| * The Debug 1.0 spec allows a humongous amount of triggers. Section | |
| * "Enumeration" says: "The above algorithm reads back tselect so that | |
| * implementations which have 2^n triggers only need to implement n | |
| * bits of tselect.". tselect can have up to XLEN bits, so the max | |
| * theoretical RV_MAX_TRIGGERS value is 2^XLEN. | |
| * | |
| * Allowing 2^XLEN triggers per hart is silly so we'll set a max to a | |
| * modest 1024 triggers, which is way more than what we see current | |
| * hardware use (most chips uses 2-4 triggers per hart, RISC-V Server | |
| * Ref requires at least 11). With a 1024 max per hart we'll be set | |
| * for a long time ... hopefully. | |
| */ | |
| #define RV_MAX_TRIGGERS 1024 | |
| #define RV_DEFAULT_NUM_TRIGGERS 2 | |
| FIELD(VTYPE, VLMUL, 0, 3) | |
| FIELD(VTYPE, VSEW, 3, 3) | |
| FIELD(VTYPE, VTA, 6, 1) | |
| FIELD(VTYPE, VMA, 7, 1) | |
| FIELD(VTYPE, ALTFMT, 8, 1) | |
| FIELD(VTYPE, RESERVED, 9, sizeof(uint64_t) * 8 - 10) | |
| #ifndef CONFIG_USER_ONLY | |
| /* machine specific AIA ireg read-modify-write callback */ | |
| #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \ | |
| ((uint32_t)((((__xlen) & 0xff) << 24) | \ | |
| (((__vgein) & 0x3f) << 20) | \ | |
| (((__virt) & 0x1) << 18) | \ | |
| (((__priv) & 0x3) << 16) | \ | |
| (__isel & 0xffff))) | |
| #define AIA_IREG_ISEL(__ireg) ((__ireg) & 0xffff) | |
| #define AIA_IREG_PRIV(__ireg) (((__ireg) >> 16) & 0x3) | |
| #define AIA_IREG_VIRT(__ireg) (((__ireg) >> 18) & 0x1) | |
| #define AIA_IREG_VGEIN(__ireg) (((__ireg) >> 20) & 0x3f) | |
| #define AIA_IREG_XLEN(__ireg) (((__ireg) >> 24) & 0xff) | |
| typedef int (*aia_ireg_rmw_fn)(void *arg, uint32_t reg, uint64_t *val, | |
| uint64_t new_val, uint64_t write_mask); | |
| #endif | |
| typedef struct PMUCTRState { | |
| /* Current value of a counter */ | |
| uint64_t mhpmcounter_val; | |
| /* Snapshot value of a counter */ | |
| uint64_t mhpmcounter_prev; | |
| /* Value beyond INT64_MAX before overflow interrupt trigger */ | |
| uint64_t irq_overflow_left; | |
| } PMUCTRState; | |
| typedef struct PMUFixedCtrState { | |
| /* Track cycle and icount for each privilege mode */ | |
| uint64_t counter[4]; | |
| uint64_t counter_prev[4]; | |
| /* Track cycle and icount for each privilege mode when V = 1*/ | |
| uint64_t counter_virt[2]; | |
| uint64_t counter_virt_prev[2]; | |
| } PMUFixedCtrState; | |
| struct CPUArchState { | |
| uint64_t gpr[32]; | |
| uint64_t gprh[32]; /* 64 top bits of the 128-bit registers */ | |
| /* vector coprocessor state. */ | |
| uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16); | |
| uint64_t vtype; | |
| uint32_t vl; | |
| uint32_t vstart; | |
| uint8_t vxrm; | |
| uint8_t vxsat; | |
| bool vill; | |
| uint64_t pc; | |
| uint64_t load_res; | |
| uint64_t load_val; | |
| /* Floating-Point state */ | |
| uint64_t fpr[32]; /* assume both F and D extensions */ | |
| uint8_t frm; | |
| float_status fp_status; | |
| uint64_t badaddr; | |
| uint64_t bins; | |
| uint64_t guest_phys_fault_addr; | |
| uint32_t priv_ver; | |
| uint32_t vext_ver; | |
| /* RISCVMXL, but uint32_t for vmstate migration */ | |
| uint32_t misa_mxl; /* current mxl */ | |
| uint32_t misa_ext; /* current extensions */ | |
| uint32_t misa_ext_mask; /* max ext for this cpu */ | |
| uint32_t xl; /* current xlen */ | |
| /* 128-bit helpers upper part return value */ | |
| uint64_t retxh; | |
| uint64_t jvt; | |
| /* elp state for zicfilp extension */ | |
| bool elp; | |
| /* shadow stack register for zicfiss extension */ | |
| uint64_t ssp; | |
| /* env place holder for extra word 2 during unwind */ | |
| uint64_t excp_uw2; | |
| /* sw check code for sw check exception */ | |
| uint8_t sw_check_code; | |
| #ifdef CONFIG_USER_ONLY | |
| uint32_t elf_flags; | |
| #endif | |
| privilege_mode_t priv; | |
| /* CSRs for execution environment configuration */ | |
| uint64_t menvcfg; | |
| uint64_t senvcfg; | |
| #ifndef CONFIG_USER_ONLY | |
| /* This contains QEMU specific information about the virt state. */ | |
| bool virt_enabled; | |
| uint8_t geilen; | |
| uint64_t resetvec; | |
| uint64_t mhartid; | |
| /* | |
| * For RV32 this is 32-bit mstatus and 32-bit mstatush. | |
| * For RV64 this is a 64-bit mstatus. | |
| */ | |
| uint64_t mstatus; | |
| uint64_t mip; | |
| /* | |
| * MIP contains the software writable version of SEIP ORed with the | |
| * external interrupt value. The MIP register is always up-to-date. | |
| * To keep track of the current source, we also save booleans of the values | |
| * here. | |
| */ | |
| bool external_seip; | |
| bool software_seip; | |
| uint64_t miclaim; | |
| uint64_t mie; | |
| uint64_t mideleg; | |
| /* | |
| * When mideleg[i]=0 and mvien[i]=1, sie[i] is no more | |
| * alias of mie[i] and needs to be maintained separately. | |
| */ | |
| uint64_t sie; | |
| /* | |
| * When hideleg[i]=0 and hvien[i]=1, vsie[i] is no more | |
| * alias of sie[i] (mie[i]) and needs to be maintained separately. | |
| */ | |
| uint64_t vsie; | |
| uint64_t satp; /* since: priv-1.10.0 */ | |
| uint64_t stval; | |
| uint64_t medeleg; | |
| uint64_t stvec; | |
| uint64_t sepc; | |
| uint64_t scause; | |
| uint64_t mtvec; | |
| uint64_t mepc; | |
| uint64_t mcause; | |
| uint64_t mtval; /* since: priv-1.10.0 */ | |
| uint64_t mctrctl; | |
| uint32_t sctrdepth; | |
| uint32_t sctrstatus; | |
| uint64_t vsctrctl; | |
| uint64_t ctr_src[16 << SCTRDEPTH_MAX]; | |
| uint64_t ctr_dst[16 << SCTRDEPTH_MAX]; | |
| uint64_t ctr_data[16 << SCTRDEPTH_MAX]; | |
| /* Machine and Supervisor interrupt priorities */ | |
| uint8_t miprio[64]; | |
| uint8_t siprio[64]; | |
| /* AIA CSRs */ | |
| uint16_t miselect; | |
| uint16_t siselect; | |
| uint64_t mvien; | |
| uint64_t mvip; | |
| /* Hypervisor CSRs */ | |
| uint64_t hstatus; | |
| uint64_t hedeleg; | |
| uint64_t hideleg; | |
| uint32_t hcounteren; | |
| uint64_t htval; | |
| uint64_t htinst; | |
| uint64_t hgatp; | |
| uint64_t hgeie; | |
| uint64_t hgeip; | |
| uint64_t htimedelta; | |
| uint64_t hvien; | |
| /* | |
| * Bits VSSIP, VSTIP and VSEIP in hvip are maintained in mip. Other bits | |
| * from 0:12 are reserved. Bits 13:63 are not aliased and must be separately | |
| * maintain in hvip. | |
| */ | |
| uint64_t hvip; | |
| /* Hypervisor controlled virtual interrupt priorities */ | |
| uint32_t hvictl; | |
| uint8_t hviprio[64]; | |
| /* Upper 64-bits of 128-bit CSRs */ | |
| uint64_t mscratchh; | |
| uint64_t sscratchh; | |
| /* Virtual CSRs */ | |
| /* | |
| * For RV32 this is 32-bit vsstatus and 32-bit vsstatush. | |
| * For RV64 this is a 64-bit vsstatus. | |
| */ | |
| uint64_t vsstatus; | |
| uint64_t vstvec; | |
| uint64_t vsscratch; | |
| uint64_t vsepc; | |
| uint64_t vscause; | |
| uint64_t vstval; | |
| uint64_t vsatp; | |
| /* AIA VS-mode CSRs */ | |
| uint16_t vsiselect; | |
| uint64_t mtval2; | |
| uint64_t mtinst; | |
| /* HS Backup CSRs */ | |
| uint64_t stvec_hs; | |
| uint64_t sscratch_hs; | |
| uint64_t sepc_hs; | |
| uint64_t scause_hs; | |
| uint64_t stval_hs; | |
| uint64_t satp_hs; | |
| uint64_t mstatus_hs; | |
| /* | |
| * Signals whether the current exception occurred with two-stage address | |
| * translation active. | |
| */ | |
| bool two_stage_lookup; | |
| /* | |
| * Signals whether the current exception occurred while doing two-stage | |
| * address translation for the VS-stage page table walk. | |
| */ | |
| bool two_stage_indirect_lookup; | |
| uint32_t scounteren; | |
| uint32_t mcounteren; | |
| uint32_t scountinhibit; | |
| uint32_t mcountinhibit; | |
| /* PMU cycle & instret privilege mode filtering */ | |
| uint64_t mcyclecfg; | |
| uint64_t minstretcfg; | |
| /* PMU counter state */ | |
| PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS]; | |
| /* | |
| * PMU event selector configured values. First three are unused. | |
| * For RV32 top 32 bits are accessed via the mhpmeventh CSR. | |
| */ | |
| uint64_t mhpmevent_val[RV_MAX_MHPMEVENTS]; | |
| PMUFixedCtrState pmu_fixed_ctrs[2]; | |
| uint64_t sscratch; | |
| uint64_t mscratch; | |
| /* Sstc CSRs */ | |
| uint64_t stimecmp; | |
| uint64_t vstimecmp; | |
| /* physical memory protection */ | |
| pmp_table_t pmp_state; | |
| uint64_t mseccfg; | |
| /* trigger module */ | |
| uint16_t mcontext; | |
| uint8_t trigger_cur; | |
| /* | |
| * num_triggers is the length of tdata1, tdata2, tdata3, | |
| * cpu_breakpoint, cpu_watchpoint and itrigger_timer | |
| * arrays. | |
| */ | |
| uint32_t num_triggers; | |
| uint64_t *tdata1; | |
| uint64_t *tdata2; | |
| uint64_t *tdata3; | |
| struct CPUBreakpoint **cpu_breakpoint; | |
| struct CPUWatchpoint **cpu_watchpoint; | |
| QEMUTimer **itrigger_timer; | |
| int64_t last_icount; | |
| bool itrigger_enabled; | |
| /* machine specific rdtime callback */ | |
| uint64_t (*rdtime_fn)(void *); | |
| void *rdtime_fn_arg; | |
| /* machine specific AIA ireg read-modify-write callback */ | |
| aia_ireg_rmw_fn aia_ireg_rmw_cb[4]; | |
| void *aia_ireg_rmw_cb_arg[4]; | |
| /* True if in debugger mode. */ | |
| bool debugger; | |
| bool debug_mode; | |
| uint32_t dcsr; | |
| target_ulong dpc; | |
| target_ulong dscratch[2]; | |
| uint64_t mstateen[SMSTATEEN_MAX_COUNT]; | |
| uint64_t hstateen[SMSTATEEN_MAX_COUNT]; | |
| uint64_t sstateen[SMSTATEEN_MAX_COUNT]; | |
| uint64_t henvcfg; | |
| /* RNMI */ | |
| uint64_t mnscratch; | |
| uint64_t mnepc; | |
| uint64_t mncause; /* mncause without bit XLEN-1 set to 1 */ | |
| uint64_t mnstatus; | |
| uint64_t rnmip; | |
| uint64_t rnmi_irqvec; | |
| uint64_t rnmi_excpvec; | |
| #endif | |
| /* Fields from here on are preserved across CPU reset. */ | |
| QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ | |
| QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ | |
| bool vstime_irq; | |
| hwaddr kernel_addr; | |
| hwaddr fdt_addr; | |
| #ifdef CONFIG_KVM | |
| /* KVM floating-point state */ | |
| uint32_t kvm_fcsr; | |
| /* kvm timer */ | |
| bool kvm_timer_dirty; | |
| uint64_t kvm_timer_time; | |
| uint64_t kvm_timer_compare; | |
| uint64_t kvm_timer_state; | |
| uint64_t kvm_timer_frequency; | |
| bool kvm_timer_frequency_loaded; | |
| /* KVM multiprocessor state */ | |
| uint32_t kvm_mp_state; | |
| bool kvm_mp_state_loaded; | |
| #endif /* CONFIG_KVM */ | |
| }; | |
| /* | |
| * map is a 16-bit bitmap: the most significant set bit in map is the maximum | |
| * satp mode that is supported. It may be chosen by the user and must respect | |
| * what qemu implements (valid_1_10_32/64) and what the hw is capable of | |
| * (supported bitmap below). | |
| * | |
| * init is a 16-bit bitmap used to make sure the user selected a correct | |
| * configuration as per the specification. | |
| */ | |
| typedef struct { | |
| uint16_t map, init; | |
| } RISCVSATPModes; | |
| /* | |
| * RISCVCPU: | |
| * @env: #CPURISCVState | |
| * | |
| * A RISCV CPU. | |
| */ | |
| struct ArchCPU { | |
| CPUState parent_obj; | |
| CPURISCVState env; | |
| GDBFeature dyn_csr_feature; | |
| GDBFeature dyn_vreg_feature; | |
| /* Configuration Settings */ | |
| RISCVCPUConfig cfg; | |
| RISCVSATPModes satp_modes; | |
| QEMUTimer *pmu_timer; | |
| /* A bitmask of Available programmable counters */ | |
| uint32_t pmu_avail_ctrs; | |
| /* Mapping of events to counters */ | |
| GHashTable *pmu_event_ctr_map; | |
| GHashTable *user_options; | |
| GHashTable *misa_ext_user_opts; | |
| GHashTable *multi_ext_user_opts; | |
| const GPtrArray *decoders; | |
| }; | |
| typedef struct RISCVCSR RISCVCSR; | |
| typedef struct RISCVCPUDef { | |
| RISCVMXL misa_mxl_max; /* max mxl for this cpu */ | |
| RISCVCPUProfile *profile; | |
| uint32_t misa_ext; | |
| int priv_spec; | |
| int32_t vext_spec; | |
| RISCVCPUConfig cfg; | |
| bool bare; | |
| #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) | |
| const RISCVCSR *custom_csrs; | |
| #endif | |
| /* This is just a setter for env->num_triggers. */ | |
| uint32_t num_triggers; | |
| } RISCVCPUDef; | |
| /** | |
| * RISCVCPUClass: | |
| * @parent_realize: The parent class' realize handler. | |
| * @parent_unrealize: The parent class' unrealize handler. | |
| * @parent_phases: The parent class' reset phase handlers. | |
| * | |
| * A RISCV CPU model. | |
| */ | |
| struct RISCVCPUClass { | |
| CPUClass parent_class; | |
| DeviceRealize parent_realize; | |
| DeviceUnrealize parent_unrealize; | |
| ResettablePhases parent_phases; | |
| RISCVCPUDef *def; | |
| }; | |
| static inline bool riscv_has_ext(const CPURISCVState *env, uint32_t ext) | |
| { | |
| return (env->misa_ext & ext) != 0; | |
| } | |
| #include "cpu_user.h" | |
| extern const char * const riscv_int_regnames[]; | |
| extern const char * const riscv_int_regnamesh[]; | |
| extern const char * const riscv_fpr_regnames[]; | |
| extern const char * const riscv_rvv_regnames[]; | |
| const char *riscv_cpu_get_trap_name(uint64_t cause, bool async); | |
| int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, | |
| int cpuid, DumpState *s); | |
| int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, | |
| int cpuid, DumpState *s); | |
| int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); | |
| int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); | |
| int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero); | |
| uint8_t riscv_cpu_default_priority(int irq); | |
| uint64_t riscv_cpu_all_pending(CPURISCVState *env); | |
| int riscv_cpu_mirq_pending(CPURISCVState *env); | |
| int riscv_cpu_sirq_pending(CPURISCVState *env); | |
| int riscv_cpu_vsirq_pending(CPURISCVState *env); | |
| int riscv_cpu_pending_to_irq(CPURISCVState *env, | |
| int extirq, unsigned int extirq_def_prio, | |
| uint64_t pending, const uint8_t *iprio); | |
| bool riscv_cpu_fp_enabled(CPURISCVState *env); | |
| bool riscv_cpu_vector_enabled(CPURISCVState *env); | |
| void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); | |
| int riscv_env_mmu_index(CPURISCVState *env, bool ifetch); | |
| bool cpu_get_fcfien(CPURISCVState *env); | |
| bool cpu_get_bcfien(CPURISCVState *env); | |
| bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt); | |
| G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, | |
| MMUAccessType access_type, | |
| int mmu_idx, uintptr_t retaddr); | |
| bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | |
| MMUAccessType access_type, int mmu_idx, | |
| bool probe, uintptr_t retaddr); | |
| char *riscv_isa_string(RISCVCPU *cpu); | |
| int riscv_cpu_max_xlen(RISCVCPUClass *mcc); | |
| bool riscv_cpu_option_set(RISCVCPU *cpu, const char *optname); | |
| void riscv_cpu_enter_debug_mode(CPURISCVState *env, target_ulong pc, | |
| uint32_t cause); | |
| void riscv_cpu_leave_debug_mode(CPURISCVState *env); | |
| #ifndef CONFIG_USER_ONLY | |
| void riscv_cpu_do_interrupt(CPUState *cpu); | |
| void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename); | |
| void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, | |
| vaddr addr, unsigned size, | |
| MMUAccessType access_type, | |
| int mmu_idx, MemTxAttrs attrs, | |
| MemTxResult response, uintptr_t retaddr); | |
| bool riscv_cpu_translate_for_debug(CPUState *cs, vaddr addr, | |
| TranslateForDebugResult *result); | |
| bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request); | |
| void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); | |
| int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); | |
| /** | |
| * riscv_cpu_get_mip: | |
| * @env: CPURISCVState | |
| * | |
| * Returns: the current value of the Machine Interrupt Pending (MIP) register. | |
| */ | |
| uint64_t riscv_cpu_get_mip(const CPURISCVState *env); | |
| /** | |
| * riscv_cpu_update_mip: | |
| * @env: CPURISCVState | |
| * @mask: Mask of the MIP bits to update | |
| * @value: New values for the bits set in @mask. | |
| * Use BOOL_TO_MASK() for boolean values. | |
| * | |
| * Set or clear the Machine Interrupt Pending register (MIP) | |
| * bits selected by @mask. | |
| * | |
| * Note: VSTIP is not maintained in MIP, so it is ignored here. | |
| * | |
| * Returns: the value of mip before the update. | |
| */ | |
| uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, | |
| uint64_t value); | |
| void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level); | |
| void riscv_cpu_interrupt(CPURISCVState *env); | |
| #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ | |
| RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit); | |
| #endif /* !CONFIG_USER_ONLY */ | |
| void riscv_cpu_set_mode(CPURISCVState *env, privilege_mode_t newpriv, | |
| bool virt_en); | |
| void riscv_ctr_add_entry(CPURISCVState *env, uint64_t src, uint64_t dst, | |
| enum CTRType type, privilege_mode_t prev_priv, | |
| bool prev_virt); | |
| void riscv_ctr_clear(CPURISCVState *env); | |
| void riscv_translate_init(void); | |
| void riscv_translate_code(CPUState *cs, TranslationBlock *tb, | |
| int *max_insns, vaddr pc, void *host_pc); | |
| G_NORETURN void riscv_raise_exception(CPURISCVState *env, | |
| RISCVException exception, | |
| uintptr_t pc); | |
| uint8_t riscv_cpu_get_fflags(CPURISCVState *env); | |
| void riscv_cpu_set_fflags(CPURISCVState *env, uint8_t); | |
| void riscv_cpu_check_fflags(CPURISCVState *env, FloatExceptionFlags); | |
| #ifndef CONFIG_USER_ONLY | |
| void cpu_set_exception_base(int vp_index, uint64_t address); | |
| #endif | |
| FIELD(TB_FLAGS, MEM_IDX, 0, 3) | |
| FIELD(TB_FLAGS, FS, 3, 2) | |
| /* Vector flags */ | |
| FIELD(TB_FLAGS, VS, 5, 2) | |
| FIELD(TB_FLAGS, LMUL, 7, 3) | |
| FIELD(TB_FLAGS, SEW, 10, 3) | |
| FIELD(TB_FLAGS, VL_EQ_VLMAX, 13, 1) | |
| FIELD(TB_FLAGS, VILL, 14, 1) | |
| FIELD(TB_FLAGS, VSTART_EQ_ZERO, 15, 1) | |
| /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */ | |
| FIELD(TB_FLAGS, XL, 16, 2) | |
| /* If PointerMasking should be applied */ | |
| FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1) | |
| FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1) | |
| FIELD(TB_FLAGS, VTA, 18, 1) | |
| FIELD(TB_FLAGS, VMA, 19, 1) | |
| /* Native debug itrigger */ | |
| FIELD(TB_FLAGS, ITRIGGER, 20, 1) | |
| /* Virtual mode enabled */ | |
| FIELD(TB_FLAGS, VIRT_ENABLED, 21, 1) | |
| FIELD(TB_FLAGS, PRIV, 22, 2) | |
| FIELD(TB_FLAGS, AXL, 24, 2) | |
| /* zicfilp needs a TB flag to track indirect branches */ | |
| FIELD(TB_FLAGS, FCFI_ENABLED, 26, 1) | |
| FIELD(TB_FLAGS, FCFI_LP_EXPECTED, 27, 1) | |
| /* zicfiss needs a TB flag so that correct TB is located based on tb flags */ | |
| FIELD(TB_FLAGS, BCFI_ENABLED, 28, 1) | |
| /* If pointer masking should be applied and address sign extended */ | |
| FIELD(TB_FLAGS, PM_PMM, 29, 2) | |
| FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1) | |
| FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32) | |
| FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1) | |
| FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1) | |
| /* sdext single-step needs a TB flag to build 1-insn TBs */ | |
| FIELD(EXT_TB_FLAGS, SDEXT_STEP, 34, 1) | |
| #ifdef TARGET_RISCV32 | |
| #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) | |
| #else | |
| static inline RISCVMXL riscv_cpu_mxl(const CPURISCVState *env) | |
| { | |
| return env->misa_mxl; | |
| } | |
| #endif | |
| #define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env))) | |
| static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env) | |
| { | |
| return &env_archcpu(env)->cfg; | |
| } | |
| #if !defined(CONFIG_USER_ONLY) | |
| static inline privilege_mode_t cpu_address_mode(CPURISCVState *env) | |
| { | |
| privilege_mode_t mode = env->priv; | |
| if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { | |
| mode = get_field(env->mstatus, MSTATUS_MPP); | |
| } | |
| return mode; | |
| } | |
| static inline RISCVMXL cpu_get_xl(CPURISCVState *env, privilege_mode_t mode) | |
| { | |
| RISCVMXL xl = env->misa_mxl; | |
| /* | |
| * When emulating a 32-bit-only cpu, use RV32. | |
| * When emulating a 64-bit cpu, and MXL has been reduced to RV32, | |
| * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened | |
| * back to RV64 for lower privs. | |
| */ | |
| if (xl != MXL_RV32) { | |
| switch (mode) { | |
| case PRV_M: | |
| break; | |
| case PRV_U: | |
| xl = get_field(env->mstatus, MSTATUS64_UXL); | |
| break; | |
| default: /* PRV_S */ | |
| xl = get_field(env->mstatus, MSTATUS64_SXL); | |
| break; | |
| } | |
| } | |
| return xl; | |
| } | |
| #endif | |
| #if defined(TARGET_RISCV32) | |
| #define cpu_recompute_xl(env) ((void)(env), MXL_RV32) | |
| #else | |
| static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env) | |
| { | |
| #if !defined(CONFIG_USER_ONLY) | |
| return cpu_get_xl(env, env->priv); | |
| #else | |
| return env->misa_mxl; | |
| #endif | |
| } | |
| #endif | |
| #if defined(TARGET_RISCV32) | |
| #define cpu_address_xl(env) ((void)(env), MXL_RV32) | |
| #else | |
| static inline RISCVMXL cpu_address_xl(CPURISCVState *env) | |
| { | |
| #ifdef CONFIG_USER_ONLY | |
| return env->xl; | |
| #else | |
| privilege_mode_t mode = cpu_address_mode(env); | |
| return cpu_get_xl(env, mode); | |
| #endif | |
| } | |
| #endif | |
| static inline uint16_t riscv_cpu_xlen(CPURISCVState *env) | |
| { | |
| return 16 << env->xl; | |
| } | |
| #ifdef TARGET_RISCV32 | |
| #define riscv_cpu_sxl(env) ((void)(env), MXL_RV32) | |
| #else | |
| static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env) | |
| { | |
| #ifdef CONFIG_USER_ONLY | |
| return env->misa_mxl; | |
| #else | |
| if (env->misa_mxl != MXL_RV32) { | |
| return get_field(env->mstatus, MSTATUS64_SXL); | |
| } | |
| #endif | |
| return MXL_RV32; | |
| } | |
| #endif | |
| /* | |
| * Returns the current effective privilege mode. | |
| * | |
| * @env: CPURISCVState | |
| * @priv: The returned effective privilege mode. | |
| * @virt: The returned effective virtualization mode. | |
| * | |
| * Returns true if the effective privilege mode is modified. | |
| */ | |
| static inline QEMU_ALWAYS_INLINE | |
| bool riscv_cpu_eff_priv(CPURISCVState *env, privilege_mode_t *priv, bool *virt) | |
| { | |
| privilege_mode_t mode = env->priv; | |
| bool virt_enabled = false; | |
| bool mode_modified = false; | |
| #ifndef CONFIG_USER_ONLY | |
| if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { | |
| mode = get_field(env->mstatus, MSTATUS_MPP); | |
| virt_enabled = get_field(env->mstatus, MSTATUS_MPV) && (mode != PRV_M); | |
| mode_modified = true; | |
| } else { | |
| virt_enabled = env->virt_enabled; | |
| } | |
| #endif | |
| if (priv) { | |
| *priv = mode; | |
| } | |
| if (virt) { | |
| *virt = virt_enabled; | |
| } | |
| return mode_modified; | |
| } | |
| static inline bool riscv_cpu_allow_16bit_insn(const RISCVCPUConfig *cfg, | |
| uint32_t priv_ver, | |
| uint32_t misa_ext) | |
| { | |
| /* In priv spec version 1.12 or newer, C always implies Zca */ | |
| if (priv_ver >= PRIV_VERSION_1_12_0) { | |
| return cfg->ext_zca; | |
| } else { | |
| return misa_ext & RVC; | |
| } | |
| } | |
| /* | |
| * Encode LMUL to lmul as follows: | |
| * LMUL vlmul lmul | |
| * 1 000 0 | |
| * 2 001 1 | |
| * 4 010 2 | |
| * 8 011 3 | |
| * - 100 - | |
| * 1/8 101 -3 | |
| * 1/4 110 -2 | |
| * 1/2 111 -1 | |
| * | |
| * then, we can calculate VLMAX = vlen >> (vsew + 3 - lmul) | |
| * e.g. vlen = 256 bits, SEW = 16, LMUL = 1/8 | |
| * => VLMAX = vlen >> (1 + 3 - (-3)) | |
| * = 256 >> 7 | |
| * = 2 | |
| */ | |
| static inline uint32_t vext_get_vlmax(uint32_t vlenb, uint32_t vsew, | |
| int8_t lmul) | |
| { | |
| uint32_t vlen = vlenb << 3; | |
| /* | |
| * We need to use 'vlen' instead of 'vlenb' to | |
| * preserve the '+ 3' in the formula. Otherwise | |
| * we risk a negative shift if vsew < lmul. | |
| */ | |
| return vlen >> (vsew + 3 - lmul); | |
| } | |
| bool riscv_cpu_is_32bit(RISCVCPU *cpu); | |
| bool riscv_cpu_virt_mem_enabled(CPURISCVState *env, bool is_vm_ldst); | |
| RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env); | |
| RISCVPmPmm riscv_pm_get_vm_ldst_pmm(CPURISCVState *env); | |
| uint32_t riscv_pm_get_pmlen(RISCVPmPmm pmm); | |
| /* | |
| * Externally facing CSR access functions, wrappers around riscv_csr*(). | |
| */ | |
| RISCVException riscv_csr_write_i64(CPURISCVState *env, int csrno, uint64_t val); | |
| RISCVException riscv_csr_read_i64(CPURISCVState *env, int csrn, uint64_t *res); | |
| /* | |
| * The event id are encoded based on the encoding specified in the | |
| * SBI specification v0.3 | |
| */ | |
| enum riscv_pmu_event_idx { | |
| RISCV_PMU_EVENT_HW_CPU_CYCLES = 0x01, | |
| RISCV_PMU_EVENT_HW_INSTRUCTIONS = 0x02, | |
| RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS = 0x10019, | |
| RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS = 0x1001B, | |
| RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021, | |
| }; | |
| /* used by tcg/tcg-cpu.c*/ | |
| void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en); | |
| bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset); | |
| void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext); | |
| bool riscv_cpu_is_vendor(Object *cpu_obj); | |
| typedef struct isa_ext_data { | |
| const char *name; | |
| const char *prop_name; | |
| int min_version; | |
| int ext_enable_offset; | |
| } RISCVIsaExtData; | |
| extern const RISCVIsaExtData isa_edata_arr[]; | |
| char *riscv_cpu_get_name(RISCVCPU *cpu); | |
| void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp); | |
| void riscv_add_satp_mode_properties(Object *obj); | |
| bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); | |
| void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); | |
| target_ulong riscv_new_csr_seed(target_ulong new_value, | |
| target_ulong write_mask); | |
| const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit); | |
| const char *priv_spec_to_str(int priv_version); | |
| #endif /* RISCV_CPU_H */ |