aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/cpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/cpu.h')
-rw-r--r--target/riscv/cpu.h741
1 files changed, 529 insertions, 212 deletions
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5896aca346..3b1a02b944 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -22,40 +22,41 @@
#include "hw/core/cpu.h"
#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
#include "exec/cpu-defs.h"
-#include "fpu/softfloat-types.h"
+#include "exec/gdbstub.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"
-#define TCG_GUEST_DEFAULT_MO 0
-
-#define TYPE_RISCV_CPU "riscv-cpu"
+typedef struct CPUArchState CPURISCVState;
-#define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
-#define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
#define CPU_RESOLVING_TYPE TYPE_RISCV_CPU
-#define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
-#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
-#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
-#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
-#define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
-#define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
-#define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
-#define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
-#define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34")
-#define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54")
-
#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
-#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
-#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
+#define TCG_GUEST_DEFAULT_MO 0
+
+/*
+ * RISC-V-specific extra insn start words:
+ * 1: Original instruction opcode
+ */
+#define TARGET_INSN_START_EXTRA_WORDS 1
#define RV(x) ((target_ulong)1 << (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')
@@ -67,24 +68,46 @@
#define RVS RV('S')
#define RVU RV('U')
#define RVH RV('H')
+#define RVJ RV('J')
+#define RVG RV('G')
#define RVB RV('B')
-/* S extension denotes that Supervisor mode exists, however it is possible
- to have a core that support S mode but does not have an MMU and there
- is currently no bit in misa to indicate whether an MMU exists or not
- so a cpu features bitfield is required, likewise for optional PMP support */
+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)
+
+typedef struct riscv_cpu_profile {
+ struct riscv_cpu_profile *parent;
+ const char *name;
+ uint32_t misa_ext;
+ bool enabled;
+ 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[];
+
+/* 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"
enum {
- RISCV_FEATURE_MMU,
- RISCV_FEATURE_PMP,
- RISCV_FEATURE_EPMP,
- RISCV_FEATURE_MISA
-};
+ PRIV_VERSION_1_10_0 = 0,
+ PRIV_VERSION_1_11_0,
+ PRIV_VERSION_1_12_0,
-#define PRIV_VERSION_1_10_0 0x00011000
-#define PRIV_VERSION_1_11_0 0x00011100
+ PRIV_VERSION_LATEST = PRIV_VERSION_1_12_0,
+};
-#define BEXT_VERSION_0_93_0 0x00009300
-#define VEXT_VERSION_0_07_1 0x00000701
+#define VEXT_VERSION_1_00_0 0x00010000
+#define VEXT_VER_1_00_0_STR "v1.0"
enum {
TRANSLATE_SUCCESS,
@@ -93,27 +116,51 @@ enum {
TRANSLATE_G_STAGE_FAIL
};
+/* Extension context status */
+typedef enum {
+ EXT_STATUS_DISABLED = 0,
+ EXT_STATUS_INITIAL,
+ EXT_STATUS_CLEAN,
+ EXT_STATUS_DIRTY,
+} RISCVExtStatus;
+
#define MMU_USER_IDX 3
#define MAX_RISCV_PMPS (16)
-typedef struct CPURISCVState CPURISCVState;
-
#if !defined(CONFIG_USER_ONLY)
#include "pmp.h"
+#include "debug.h"
#endif
-#define RV_VLEN_MAX 256
-
-FIELD(VTYPE, VLMUL, 0, 2)
-FIELD(VTYPE, VSEW, 2, 3)
-FIELD(VTYPE, VEDIV, 5, 2)
-FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9)
-FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
-
-struct CPURISCVState {
+#define RV_VLEN_MAX 1024
+#define RV_MAX_MHPMEVENTS 32
+#define RV_MAX_MHPMCOUNTERS 32
+
+FIELD(VTYPE, VLMUL, 0, 3)
+FIELD(VTYPE, VSEW, 3, 3)
+FIELD(VTYPE, VTA, 6, 1)
+FIELD(VTYPE, VMA, 7, 1)
+FIELD(VTYPE, VEDIV, 8, 2)
+FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
+
+typedef struct PMUCTRState {
+ /* Current value of a counter */
+ target_ulong mhpmcounter_val;
+ /* Current value of a counter in RV32 */
+ target_ulong mhpmcounterh_val;
+ /* Snapshot values of counter */
+ target_ulong mhpmcounter_prev;
+ /* Snapshort value of a counter in RV32 */
+ target_ulong mhpmcounterh_prev;
+ bool started;
+ /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
+ target_ulong irq_overflow_left;
+} PMUCTRState;
+
+struct CPUArchState {
target_ulong gpr[32];
- uint64_t fpr[32]; /* assume both F and D extensions */
+ target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
/* vector coprocessor state. */
uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16);
@@ -122,23 +169,35 @@ struct CPURISCVState {
target_ulong vl;
target_ulong vstart;
target_ulong vtype;
+ bool vill;
target_ulong pc;
target_ulong load_res;
target_ulong load_val;
+ /* Floating-Point state */
+ uint64_t fpr[32]; /* assume both F and D extensions */
target_ulong frm;
+ float_status fp_status;
target_ulong badaddr;
+ target_ulong bins;
+
target_ulong guest_phys_fault_addr;
target_ulong priv_ver;
- target_ulong bext_ver;
target_ulong vext_ver;
- target_ulong misa;
- target_ulong misa_mask;
- uint32_t features;
+ /* 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 */
+ target_ulong retxh;
+
+ target_ulong jvt;
#ifdef CONFIG_USER_ONLY
uint32_t elf_flags;
@@ -147,8 +206,9 @@ struct CPURISCVState {
#ifndef CONFIG_USER_ONLY
target_ulong priv;
/* This contains QEMU specific information about the virt state. */
- target_ulong virt;
- target_ulong resetvec;
+ bool virt_enabled;
+ target_ulong geilen;
+ uint64_t resetvec;
target_ulong mhartid;
/*
@@ -157,12 +217,32 @@ struct CPURISCVState {
*/
uint64_t mstatus;
- target_ulong mip;
+ 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;
- uint32_t miclaim;
+ uint64_t miclaim;
- target_ulong mie;
- target_ulong mideleg;
+ 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;
target_ulong satp; /* since: priv-1.10.0 */
target_ulong stval;
@@ -177,15 +257,43 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
+ /* Machine and Supervisor interrupt priorities */
+ uint8_t miprio[64];
+ uint8_t siprio[64];
+
+ /* AIA CSRs */
+ target_ulong miselect;
+ target_ulong siselect;
+ uint64_t mvien;
+ uint64_t mvip;
+
/* Hypervisor CSRs */
target_ulong hstatus;
target_ulong hedeleg;
- target_ulong hideleg;
- target_ulong hcounteren;
+ uint64_t hideleg;
+ uint32_t hcounteren;
target_ulong htval;
target_ulong htinst;
target_ulong hgatp;
+ target_ulong hgeie;
+ target_ulong 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 */
+ target_ulong hvictl;
+ uint8_t hviprio[64];
+
+ /* Upper 64-bits of 128-bit CSRs */
+ uint64_t mscratchh;
+ uint64_t sscratchh;
/* Virtual CSRs */
/*
@@ -200,6 +308,9 @@ struct CPURISCVState {
target_ulong vstval;
target_ulong vsatp;
+ /* AIA VS-mode CSRs */
+ target_ulong vsiselect;
+
target_ulong mtval2;
target_ulong mtinst;
@@ -212,248 +323,393 @@ struct CPURISCVState {
target_ulong satp_hs;
uint64_t mstatus_hs;
- /* Signals whether the current exception occurred with two-stage address
- translation active. */
+ /*
+ * 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 mcountinhibit;
+
+ /* PMU counter state */
+ PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
- target_ulong scounteren;
- target_ulong mcounteren;
+ /* PMU event selector configured values. First three are unused */
+ target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
+
+ /* PMU event selector configured values for RV32 */
+ target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];
target_ulong sscratch;
target_ulong mscratch;
- /* temporary htif regs */
- uint64_t mfromhost;
- uint64_t mtohost;
- uint64_t timecmp;
+ /* Sstc CSRs */
+ uint64_t stimecmp;
+
+ uint64_t vstimecmp;
/* physical memory protection */
pmp_table_t pmp_state;
target_ulong mseccfg;
+ /* trigger module */
+ target_ulong trigger_cur;
+ target_ulong tdata1[RV_MAX_TRIGGERS];
+ target_ulong tdata2[RV_MAX_TRIGGERS];
+ target_ulong tdata3[RV_MAX_TRIGGERS];
+ target_ulong mcontext;
+ struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS];
+ struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS];
+ QEMUTimer *itrigger_timer[RV_MAX_TRIGGERS];
+ int64_t last_icount;
+ bool itrigger_enabled;
+
/* machine specific rdtime callback */
- uint64_t (*rdtime_fn)(uint32_t);
- uint32_t rdtime_fn_arg;
+ uint64_t (*rdtime_fn)(void *);
+ void *rdtime_fn_arg;
+
+ /* machine specific AIA ireg read-modify-write callback */
+#define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
+ ((((__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)
+ int (*aia_ireg_rmw_fn[4])(void *arg, target_ulong reg,
+ target_ulong *val, target_ulong new_val, target_ulong write_mask);
+ void *aia_ireg_rmw_fn_arg[4];
/* True if in debugger mode. */
bool debugger;
-#endif
- float_status fp_status;
+ /*
+ * CSRs for PointerMasking extension
+ */
+ target_ulong mmte;
+ target_ulong mpmmask;
+ target_ulong mpmbase;
+ target_ulong spmmask;
+ target_ulong spmbase;
+ target_ulong upmmask;
+ target_ulong upmbase;
+
+ /* CSRs for execution environment configuration */
+ uint64_t menvcfg;
+ uint64_t mstateen[SMSTATEEN_MAX_COUNT];
+ uint64_t hstateen[SMSTATEEN_MAX_COUNT];
+ uint64_t sstateen[SMSTATEEN_MAX_COUNT];
+ target_ulong senvcfg;
+ uint64_t henvcfg;
+#endif
+ target_ulong cur_pmmask;
+ target_ulong cur_pmbase;
/* Fields from here on are preserved across CPU reset. */
- QEMUTimer *timer; /* Internal timer */
+ 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 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;
+#endif /* CONFIG_KVM */
};
-OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
- RISCV_CPU)
-
-/**
- * RISCVCPUClass:
- * @parent_realize: The parent class' realize handler.
- * @parent_reset: The parent class' reset handler.
- *
- * A RISCV CPU model.
- */
-struct RISCVCPUClass {
- /*< private >*/
- CPUClass parent_class;
- /*< public >*/
- DeviceRealize parent_realize;
- DeviceReset parent_reset;
-};
-
-/**
+/*
* RISCVCPU:
* @env: #CPURISCVState
*
* A RISCV CPU.
*/
-struct RISCVCPU {
- /*< private >*/
+struct ArchCPU {
CPUState parent_obj;
- /*< public >*/
- CPUNegativeOffsetState neg;
+
CPURISCVState env;
- char *dyn_csr_xml;
+ GDBFeature dyn_csr_feature;
+ GDBFeature dyn_vreg_feature;
/* Configuration Settings */
- struct {
- bool ext_i;
- bool ext_e;
- bool ext_g;
- bool ext_m;
- bool ext_a;
- bool ext_f;
- bool ext_d;
- bool ext_c;
- bool ext_b;
- bool ext_s;
- bool ext_u;
- bool ext_h;
- bool ext_v;
- bool ext_counters;
- bool ext_ifencei;
- bool ext_icsr;
-
- char *priv_spec;
- char *user_spec;
- char *bext_spec;
- char *vext_spec;
- uint16_t vlen;
- uint16_t elen;
- bool mmu;
- bool pmp;
- bool epmp;
- uint64_t resetvec;
- } cfg;
+ RISCVCPUConfig cfg;
+
+ QEMUTimer *pmu_timer;
+ /* A bitmask of Available programmable counters */
+ uint32_t pmu_avail_ctrs;
+ /* Mapping of events to counters */
+ GHashTable *pmu_event_ctr_map;
};
-static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
-{
- return (env->misa & ext) != 0;
-}
+/**
+ * RISCVCPUClass:
+ * @parent_realize: The parent class' realize handler.
+ * @parent_phases: The parent class' reset phase handlers.
+ *
+ * A RISCV CPU model.
+ */
+struct RISCVCPUClass {
+ CPUClass parent_class;
-static inline bool riscv_feature(CPURISCVState *env, int feature)
+ DeviceRealize parent_realize;
+ ResettablePhases parent_phases;
+ uint32_t misa_mxl_max; /* max mxl for this cpu */
+};
+
+static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
{
- return env->features & (1ULL << feature);
+ return (env->misa_ext & ext) != 0;
}
#include "cpu_user.h"
-#include "cpu_bits.h"
extern const char * const riscv_int_regnames[];
+extern const char * const riscv_int_regnamesh[];
extern const char * const riscv_fpr_regnames[];
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
void riscv_cpu_do_interrupt(CPUState *cpu);
int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque);
+ int cpuid, DumpState *s);
int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque);
+ 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);
bool riscv_cpu_fp_enabled(CPURISCVState *env);
-bool riscv_cpu_virt_enabled(CPURISCVState *env);
+target_ulong riscv_cpu_get_geilen(CPURISCVState *env);
+void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
+bool riscv_cpu_vector_enabled(CPURISCVState *env);
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
-bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
-void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
-bool riscv_cpu_two_stage_lookup(int mmu_idx);
-int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
-hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
- MMUAccessType access_type, int mmu_idx,
- uintptr_t retaddr) QEMU_NORETURN;
+int riscv_env_mmu_index(CPURISCVState *env, bool ifetch);
+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(const char *optname);
+
+#ifndef CONFIG_USER_ONLY
+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);
-char *riscv_isa_string(RISCVCPU *cpu);
-void riscv_cpu_list(void);
-
-#define cpu_list riscv_cpu_list
-#define cpu_mmu_index riscv_cpu_mmu_index
-
-#ifndef CONFIG_USER_ONLY
+hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
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, uint32_t interrupts);
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
+uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
+ uint64_t value);
+void riscv_cpu_interrupt(CPURISCVState *env);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
- uint32_t arg);
+void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
+ void *arg);
+void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
+ int (*rmw_fn)(void *arg,
+ target_ulong reg,
+ target_ulong *val,
+ target_ulong new_val,
+ target_ulong write_mask),
+ void *rmw_fn_arg);
+
+RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
#endif
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
void riscv_translate_init(void);
-void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
- uint32_t exception, uintptr_t pc);
+G_NORETURN void riscv_raise_exception(CPURISCVState *env,
+ uint32_t exception, uintptr_t pc);
target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
-#define TB_FLAGS_MMU_MASK 7
-#define TB_FLAGS_PRIV_MMU_MASK 3
-#define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2)
-#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
-
-typedef CPURISCVState CPUArchState;
-typedef RISCVCPU ArchCPU;
#include "exec/cpu-all.h"
-FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1)
-FIELD(TB_FLAGS, LMUL, 3, 2)
-FIELD(TB_FLAGS, SEW, 5, 3)
-FIELD(TB_FLAGS, VILL, 8, 1)
-/* Is a Hypervisor instruction load/store allowed? */
-FIELD(TB_FLAGS, HLSX, 9, 1)
+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, 20, 1)
+FIELD(TB_FLAGS, VMA, 21, 1)
+/* Native debug itrigger */
+FIELD(TB_FLAGS, ITRIGGER, 22, 1)
+/* Virtual mode enabled */
+FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
+FIELD(TB_FLAGS, PRIV, 24, 2)
+FIELD(TB_FLAGS, AXL, 26, 2)
+
+#ifdef TARGET_RISCV32
+#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
+#else
+static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
+{
+ return env->misa_mxl;
+}
+#endif
+#define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env)))
-bool riscv_cpu_is_32bit(CPURISCVState *env);
+static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
+{
+ return &env_archcpu(env)->cfg;
+}
-/*
- * A simplification for VLMAX
- * = (1 << LMUL) * VLEN / (8 * (1 << SEW))
- * = (VLEN << LMUL) / (8 << SEW)
- * = (VLEN << LMUL) >> (SEW + 3)
- * = VLEN >> (SEW + 3 - LMUL)
- */
-static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
+#if !defined(CONFIG_USER_ONLY)
+static inline int cpu_address_mode(CPURISCVState *env)
{
- uint8_t sew, lmul;
+ int mode = env->priv;
- sew = FIELD_EX64(vtype, VTYPE, VSEW);
- lmul = FIELD_EX64(vtype, VTYPE, VLMUL);
- return cpu->cfg.vlen >> (sew + 3 - lmul);
+ if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
+ mode = get_field(env->mstatus, MSTATUS_MPP);
+ }
+ return mode;
}
-static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
- target_ulong *cs_base, uint32_t *pflags)
+static inline RISCVMXL cpu_get_xl(CPURISCVState *env, target_ulong mode)
{
- uint32_t flags = 0;
-
- *pc = env->pc;
- *cs_base = 0;
-
- if (riscv_has_ext(env, RVV)) {
- uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
- bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
- flags = FIELD_DP32(flags, TB_FLAGS, VILL,
- FIELD_EX64(env->vtype, VTYPE, VILL));
- flags = FIELD_DP32(flags, TB_FLAGS, SEW,
- FIELD_EX64(env->vtype, VTYPE, VSEW));
- flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
- FIELD_EX64(env->vtype, VTYPE, VLMUL));
- flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
- } else {
- flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
+ 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
- flags |= TB_FLAGS_MSTATUS_FS;
+ return env->xl;
#else
- flags |= cpu_mmu_index(env, 0);
- if (riscv_cpu_fp_enabled(env)) {
- flags |= env->mstatus & MSTATUS_FS;
- }
+ int mode = cpu_address_mode(env);
- if (riscv_has_ext(env, RVH)) {
- if (env->priv == PRV_M ||
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
- get_field(env->hstatus, HSTATUS_HU))) {
- flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
- }
- }
+ return cpu_get_xl(env, mode);
+#endif
+}
#endif
- *pflags = flags;
+static inline int 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
+ return get_field(env->mstatus, MSTATUS64_SXL);
+#endif
+}
+#endif
+
+/*
+ * 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);
+}
+
+void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
+ uint64_t *cs_base, uint32_t *pflags);
+
+void riscv_cpu_update_mask(CPURISCVState *env);
+bool riscv_cpu_is_32bit(RISCVCPU *cpu);
+
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
@@ -486,12 +742,25 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
target_ulong new_value,
target_ulong write_mask);
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+ Int128 *ret_value,
+ Int128 new_value, Int128 write_mask);
+
+typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
+ Int128 *ret_value);
+typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
+ Int128 new_value);
+
typedef struct {
const char *name;
riscv_csr_predicate_fn predicate;
riscv_csr_read_fn read;
riscv_csr_write_fn write;
riscv_csr_op_fn op;
+ riscv_csr_read128_fn read128;
+ riscv_csr_write128_fn write128;
+ /* The default priv spec version should be PRIV_VERSION_1_10_0 (i.e 0) */
+ uint32_t min_priv_ver;
} riscv_csr_operations;
/* CSR function table constants */
@@ -499,12 +768,60 @@ enum {
CSR_TABLE_SIZE = 0x1000
};
+/*
+ * 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 RISCVCPUMultiExtConfig {
+ const char *name;
+ uint32_t offset;
+ bool enabled;
+} RISCVCPUMultiExtConfig;
+
+extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[];
+
+typedef struct isa_ext_data {
+ const char *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);
+
/* CSR function table */
extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
+extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
+
void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
+uint8_t satp_mode_max_from_map(uint32_t map);
+const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
+
#endif /* RISCV_CPU_H */