[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 6/7] target/riscv: Add support to access ctrsource, ctrtarget,
From: |
Rajnesh Kanwal |
Subject: |
[PATCH v4 6/7] target/riscv: Add support to access ctrsource, ctrtarget, ctrdata regs. |
Date: |
Wed, 4 Dec 2024 17:56:44 +0500 |
CTR entries are accessed using ctrsource, ctrtarget and ctrdata
registers using smcsrind/sscsrind extension. This commits extends
the csrind extension to support CTR registers.
ctrsource is accessible through xireg CSR, ctrtarget is accessible
through xireg1 and ctrdata is accessible through xireg2 CSR.
CTR supports maximum depth of 256 entries which are accessed using
xiselect range 0x200 to 0x2ff.
This commits also adds properties to enable CTR extension. CTR can be
enabled using smctr=true and ssctr=true now.
Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
---
target/riscv/cpu.c | 26 +++++++-
target/riscv/csr.c | 150 ++++++++++++++++++++++++++++++++++++++++++++-
target/riscv/tcg/tcg-cpu.c | 11 ++++
3 files changed, 185 insertions(+), 2 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index
2a4f285a974ffc62e7f3e938691dbffe376a7e46..751029e924d4690aaa5de65456fd5a5ec25b916a
100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -199,6 +199,8 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, has_priv_1_12),
ISA_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, has_priv_1_12),
ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade),
+ ISA_EXT_DATA_ENTRY(smctr, PRIV_VERSION_1_12_0, ext_smctr),
+ ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr),
ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu),
ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
@@ -1481,6 +1483,8 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("smcdeleg", ext_smcdeleg, false),
MULTI_EXT_CFG_BOOL("sscsrind", ext_sscsrind, false),
MULTI_EXT_CFG_BOOL("ssccfg", ext_ssccfg, false),
+ MULTI_EXT_CFG_BOOL("smctr", ext_smctr, false),
+ MULTI_EXT_CFG_BOOL("ssctr", ext_ssctr, false),
MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
MULTI_EXT_CFG_BOOL("zicfilp", ext_zicfilp, false),
MULTI_EXT_CFG_BOOL("zicfiss", ext_zicfiss, false),
@@ -2656,6 +2660,26 @@ static RISCVCPUImpliedExtsRule SSCFG_IMPLIED = {
},
};
+static RISCVCPUImpliedExtsRule SMCTR_IMPLIED = {
+ .ext = CPU_CFG_OFFSET(ext_smctr),
+ .implied_misa_exts = RVS,
+ .implied_multi_exts = {
+ CPU_CFG_OFFSET(ext_sscsrind),
+
+ RISCV_IMPLIED_EXTS_RULE_END
+ },
+};
+
+static RISCVCPUImpliedExtsRule SSCTR_IMPLIED = {
+ .ext = CPU_CFG_OFFSET(ext_ssctr),
+ .implied_misa_exts = RVS,
+ .implied_multi_exts = {
+ CPU_CFG_OFFSET(ext_sscsrind),
+
+ RISCV_IMPLIED_EXTS_RULE_END
+ },
+};
+
RISCVCPUImpliedExtsRule *riscv_misa_ext_implied_rules[] = {
&RVA_IMPLIED, &RVD_IMPLIED, &RVF_IMPLIED,
&RVM_IMPLIED, &RVV_IMPLIED, NULL
@@ -2674,7 +2698,7 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[]
= {
&ZVFH_IMPLIED, &ZVFHMIN_IMPLIED, &ZVKN_IMPLIED,
&ZVKNC_IMPLIED, &ZVKNG_IMPLIED, &ZVKNHB_IMPLIED,
&ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SSCFG_IMPLIED,
- NULL
+ &SMCTR_IMPLIED, &SSCTR_IMPLIED, NULL
};
static Property riscv_cpu_properties[] = {
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index
7e03065d3dcd8713e2cadae3017ed355c9f9bf10..d80684a708891e062393deebe880650fb4df44ab
100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2401,6 +2401,13 @@ static bool xiselect_cd_range(target_ulong isel)
return (ISELECT_CD_FIRST <= isel && isel <= ISELECT_CD_LAST);
}
+static bool xiselect_ctr_range(int csrno, target_ulong isel)
+{
+ /* MIREG-MIREG6 for the range 0x200-0x2ff are not used by CTR. */
+ return CTR_ENTRIES_FIRST <= isel && isel <= CTR_ENTRIES_LAST &&
+ csrno < CSR_MIREG;
+}
+
static int rmw_iprio(target_ulong xlen,
target_ulong iselect, uint8_t *iprio,
target_ulong *val, target_ulong new_val,
@@ -2446,6 +2453,124 @@ static int rmw_iprio(target_ulong xlen,
return 0;
}
+static int rmw_ctrsource(CPURISCVState *env, int isel, target_ulong *val,
+ target_ulong new_val, target_ulong wr_mask)
+{
+ /*
+ * CTR arrays are treated as circular buffers and TOS always points to next
+ * empty slot, keeping TOS - 1 always pointing to latest entry. Given entry
+ * 0 is always the latest one, traversal is a bit different here. See the
+ * below example.
+ *
+ * Depth = 16.
+ *
+ * idx [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [A] [B] [C] [D] [E] [F]
+ * TOS H
+ * entry 6 5 4 3 2 1 0 F E D C B A 9 8 7
+ */
+ const uint64_t entry = isel - CTR_ENTRIES_FIRST;
+ const uint64_t depth = 16 << get_field(env->sctrdepth, SCTRDEPTH_MASK);
+ uint64_t idx;
+
+ /* Entry greater than depth-1 is read-only zero */
+ if (entry >= depth) {
+ if (val) {
+ *val = 0;
+ }
+ return 0;
+ }
+
+ idx = get_field(env->sctrstatus, SCTRSTATUS_WRPTR_MASK);
+ idx = (idx - entry - 1) & (depth - 1);
+
+ if (val) {
+ *val = env->ctr_src[idx];
+ }
+
+ env->ctr_src[idx] = (env->ctr_src[idx] & ~wr_mask) | (new_val & wr_mask);
+
+ return 0;
+}
+
+static int rmw_ctrtarget(CPURISCVState *env, int isel, target_ulong *val,
+ target_ulong new_val, target_ulong wr_mask)
+{
+ /*
+ * CTR arrays are treated as circular buffers and TOS always points to next
+ * empty slot, keeping TOS - 1 always pointing to latest entry. Given entry
+ * 0 is always the latest one, traversal is a bit different here. See the
+ * below example.
+ *
+ * Depth = 16.
+ *
+ * idx [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [A] [B] [C] [D] [E] [F]
+ * head H
+ * entry 6 5 4 3 2 1 0 F E D C B A 9 8 7
+ */
+ const uint64_t entry = isel - CTR_ENTRIES_FIRST;
+ const uint64_t depth = 16 << get_field(env->sctrdepth, SCTRDEPTH_MASK);
+ uint64_t idx;
+
+ /* Entry greater than depth-1 is read-only zero */
+ if (entry >= depth) {
+ if (val) {
+ *val = 0;
+ }
+ return 0;
+ }
+
+ idx = get_field(env->sctrstatus, SCTRSTATUS_WRPTR_MASK);
+ idx = (idx - entry - 1) & (depth - 1);
+
+ if (val) {
+ *val = env->ctr_dst[idx];
+ }
+
+ env->ctr_dst[idx] = (env->ctr_dst[idx] & ~wr_mask) | (new_val & wr_mask);
+
+ return 0;
+}
+
+static int rmw_ctrdata(CPURISCVState *env, int isel, target_ulong *val,
+ target_ulong new_val, target_ulong wr_mask)
+{
+ /*
+ * CTR arrays are treated as circular buffers and TOS always points to next
+ * empty slot, keeping TOS - 1 always pointing to latest entry. Given entry
+ * 0 is always the latest one, traversal is a bit different here. See the
+ * below example.
+ *
+ * Depth = 16.
+ *
+ * idx [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [A] [B] [C] [D] [E] [F]
+ * head H
+ * entry 6 5 4 3 2 1 0 F E D C B A 9 8 7
+ */
+ const uint64_t entry = isel - CTR_ENTRIES_FIRST;
+ const uint64_t mask = wr_mask & CTRDATA_MASK;
+ const uint64_t depth = 16 << get_field(env->sctrdepth, SCTRDEPTH_MASK);
+ uint64_t idx;
+
+ /* Entry greater than depth-1 is read-only zero */
+ if (entry >= depth) {
+ if (val) {
+ *val = 0;
+ }
+ return 0;
+ }
+
+ idx = get_field(env->sctrstatus, SCTRSTATUS_WRPTR_MASK);
+ idx = (idx - entry - 1) & (depth - 1);
+
+ if (val) {
+ *val = env->ctr_data[idx];
+ }
+
+ env->ctr_data[idx] = (env->ctr_data[idx] & ~mask) | (new_val & mask);
+
+ return 0;
+}
+
static RISCVException rmw_xireg_aia(CPURISCVState *env, int csrno,
target_ulong isel, target_ulong *val,
target_ulong new_val, target_ulong wr_mask)
@@ -2596,6 +2721,27 @@ done:
return ret;
}
+static int rmw_xireg_ctr(CPURISCVState *env, int csrno,
+ target_ulong isel, target_ulong *val,
+ target_ulong new_val, target_ulong wr_mask)
+{
+ if (!riscv_cpu_cfg(env)->ext_smctr && !riscv_cpu_cfg(env)->ext_ssctr) {
+ return -EINVAL;
+ }
+
+ if (csrno == CSR_SIREG || csrno == CSR_VSIREG) {
+ return rmw_ctrsource(env, isel, val, new_val, wr_mask);
+ } else if (csrno == CSR_SIREG2 || csrno == CSR_VSIREG2) {
+ return rmw_ctrtarget(env, isel, val, new_val, wr_mask);
+ } else if (csrno == CSR_SIREG3 || csrno == CSR_VSIREG3) {
+ return rmw_ctrdata(env, isel, val, new_val, wr_mask);
+ } else if (val) {
+ *val = 0;
+ }
+
+ return 0;
+}
+
/*
* rmw_xireg_csrind: Perform indirect access to xireg and xireg2-xireg6
*
@@ -2607,11 +2753,13 @@ static int rmw_xireg_csrind(CPURISCVState *env, int
csrno,
target_ulong isel, target_ulong *val,
target_ulong new_val, target_ulong wr_mask)
{
- int ret = -EINVAL;
bool virt = csrno == CSR_VSIREG ? true : false;
+ int ret = -EINVAL;
if (xiselect_cd_range(isel)) {
ret = rmw_xireg_cd(env, csrno, isel, val, new_val, wr_mask);
+ } else if (xiselect_ctr_range(csrno, isel)) {
+ ret = rmw_xireg_ctr(env, csrno, isel, val, new_val, wr_mask);
} else {
/*
* As per the specification, access to unimplented region is undefined
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index
2b57aa4d1704b176f314dbe0b120cfcc943bf4f8..575b5692c7f68a5f6d37edbc17269e41f496f682
100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -652,6 +652,17 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu,
Error **errp)
return;
}
+ if ((cpu->cfg.ext_smctr || cpu->cfg.ext_ssctr) &&
+ (!riscv_has_ext(env, RVS) || !cpu->cfg.ext_sscsrind)) {
+ if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_smctr)) ||
+ cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ssctr))) {
+ error_setg(errp, "Smctr and Ssctr require S-mode and Sscsrind");
+ return;
+ }
+ cpu->cfg.ext_smctr = false;
+ cpu->cfg.ext_ssctr = false;
+ }
+
/*
* Disable isa extensions based on priv spec after we
* validated and set everything we need.
--
2.34.1
- [PATCH v4 0/7] target/riscv: Add support for Control Transfer Records Ext., Rajnesh Kanwal, 2024/12/04
- [PATCH v4 1/7] target/riscv: Remove obsolete sfence.vm instruction, Rajnesh Kanwal, 2024/12/04
- [PATCH v4 2/7] target/riscv: Add Control Transfer Records CSR definitions., Rajnesh Kanwal, 2024/12/04
- [PATCH v4 3/7] target/riscv: Add support for Control Transfer Records extension CSRs., Rajnesh Kanwal, 2024/12/04
- [PATCH v4 5/7] target/riscv: Add CTR sctrclr instruction., Rajnesh Kanwal, 2024/12/04
- [PATCH v4 6/7] target/riscv: Add support to access ctrsource, ctrtarget, ctrdata regs.,
Rajnesh Kanwal <=
- [PATCH v4 7/7] target/riscv: machine: Add Control Transfer Record state description, Rajnesh Kanwal, 2024/12/04
- [PATCH v4 4/7] target/riscv: Add support to record CTR entries., Rajnesh Kanwal, 2024/12/04