Skip to content

Commit 354ea58

Browse files
committed
CHERI riscv: cap-load generation support
This makes [ms]ccsr writable, but only the GCLG bits are updated.
1 parent 9d9e283 commit 354ea58

File tree

4 files changed

+48
-11
lines changed

4 files changed

+48
-11
lines changed

target/riscv/cpu.h

+4
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ struct CPURISCVState {
180180
target_ulong mbadaddr;
181181
target_ulong medeleg;
182182

183+
#if defined(TARGET_CHERI) && !defined(TARGET_RISCV32)
184+
target_ulong sccsr;
185+
#endif
186+
183187
#ifdef TARGET_CHERI
184188
// XXX: not implemented properly
185189
cap_register_t UTCC; // SCR 4 User trap code cap. (UTCC)

target/riscv/cpu_bits.h

+5
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@
348348
#define CSR_UCCSR 0x8C0
349349
#define CSR_SCCSR 0x9C0
350350
#define CSR_MCCSR 0xBC0
351+
352+
#define CCSR_ENABLE 0x1
353+
#define CCSR_DIRTY 0x2
354+
#define CCSR_GCLGS 0x4 /* Global Capability Load Generation, Super */
355+
#define CCSR_GCLGU 0x8 /* Global Capability Load Generation, User */
351356
#endif
352357

353358
/* mstatus CSR bits */

target/riscv/cpu_helper.c

+11
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,17 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
712712
} else {
713713
*prot |= PAGE_LC_TRAP;
714714
}
715+
} else {
716+
if (pte & PTE_LCM) {
717+
// Cap-loads checked against GCLG in CCSR using PTE_U
718+
719+
target_ulong gclgmask =
720+
(pte & PTE_U) ? CCSR_GCLGU : CCSR_GCLGS;
721+
722+
if (!(env->sccsr & gclgmask) != !(pte & PTE_LCG)) {
723+
*prot |= PAGE_LC_TRAP;
724+
}
725+
}
715726
}
716727
#endif
717728
return TRANSLATE_SUCCESS;

target/riscv/csr.c

+28-11
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,8 @@ static int write_pmpaddr(CPURISCVState *env, int csrno, target_ulong val)
12271227
#endif
12281228

12291229
#ifdef TARGET_CHERI
1230-
12311230
// See Capability Control and Status Registers (CCSRs) in CHERI ISA spec
1232-
// The e “enable” bit tells whether capability extensions are enabled or disabled.
1233-
#define CCSR_ENABLE 0x1
1234-
// The d “dirty” bit tells whether a capability register has been written.
1235-
#define CCSR_DIRTY 0x2
1231+
12361232
// We used to report cause and capcause here, but those have moved to xTVAL
12371233

12381234
static int read_ccsr(CPURISCVState *env, int csrno, target_ulong *val)
@@ -1241,24 +1237,44 @@ static int read_ccsr(CPURISCVState *env, int csrno, target_ulong *val)
12411237
// The capability cause has moved to xTVAL so we don't report it here.
12421238
RISCVCPU *cpu = env_archcpu(env);
12431239
target_ulong ccsr = 0;
1240+
1241+
// The e “enable” bit tells whether capability extensions are enabled or disabled.
12441242
ccsr = set_field(ccsr, CCSR_ENABLE, cpu->cfg.ext_cheri);
1243+
1244+
// The d “dirty” bit tells whether a capability register has been written.
12451245
ccsr = set_field(ccsr, CCSR_DIRTY, 1); /* Always report dirty */
1246+
12461247
// For backwards compat we also report cap cause and cap index
12471248
// However, this is the last value and is not separated by privilege mode!
12481249
// TODO: remove when CheriBSD has been updated to read xTVAL
12491250
ccsr |= env->cap_cause << 5;
12501251
ccsr |= env->cap_index << 10;
1252+
1253+
/* Expose state bits (GCLG) only above U mode */
1254+
if (env->priv != PRV_U)
1255+
ccsr |= env->sccsr;
1256+
12511257
qemu_log_mask(CPU_LOG_INT, "Reading xCCSR(%#x): %x\n", csrno, (int)ccsr);
12521258
*val = ccsr;
12531259
return 0;
12541260
}
12551261

12561262
static int write_ccsr(CPURISCVState *env, int csrno, target_ulong val)
12571263
{
1258-
error_report("Attempting to write " TARGET_FMT_lx
1259-
"to xCCSR(%#x), this is not supported (yet?).",
1260-
val, csrno);
1261-
return -1;
1264+
static const target_ulong gclgmask = (CCSR_GCLGS | CCSR_GCLGU);
1265+
1266+
/* U mode writes refused */
1267+
if (env->priv == PRV_U) {
1268+
error_report("Attempting to write " TARGET_FMT_lx
1269+
"to xCCSR(%#x), this is not supported (yet?).",
1270+
val, csrno);
1271+
return -1;
1272+
}
1273+
1274+
/* Take the GCLG bits from the store and update state bits */
1275+
env->sccsr = set_field(env->sccsr, gclgmask, get_field(val, gclgmask));
1276+
1277+
return 0;
12621278
}
12631279

12641280
static inline bool csr_needs_asr(CPURISCVState *env, int csrno) {
@@ -1571,8 +1587,9 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
15711587
[CSR_MTINST] = CSR_OP_RW(hmode, mtinst),
15721588

15731589
#ifdef TARGET_CHERI
1574-
// CHERI CSRs: For now we alway report the same values and don't allow
1575-
// turning off any of the bits
1590+
// CHERI CSRs: For now we always report enabled and dirty and don't support
1591+
// turning off CHERI. The global capability load generation bits in here
1592+
// can be written by S or higher.
15761593
[CSR_UCCSR] = CSR_OP_FN_RW(umode, read_ccsr, write_ccsr, "uccsr"),
15771594
[CSR_SCCSR] = CSR_OP_FN_RW(smode, read_ccsr, write_ccsr, "sccsr"),
15781595
[CSR_MCCSR] = CSR_OP_FN_RW(any, read_ccsr, write_ccsr, "mccsr"),

0 commit comments

Comments
 (0)