Skip to content

Commit d91b0d7

Browse files
committed
CHERI riscv: optionally trap on PTE_{A,D,CD} clear
These are `#if 0`-ed out, but has proven useful in testing, as our FPGA cores trap rather than atomically update the PTE.
1 parent 12cfe2e commit d91b0d7

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

target/riscv/cpu_helper.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,17 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
362362
extern bool rvfi_debug_output;
363363
#endif
364364

365+
#ifndef RISCV_PTE_TRAPPY
366+
/*
367+
* The PTW logic below supports trapping on any subset of PTE_A, PTE_D, PTE_CD
368+
* being clear during an access that would have them be set. The RISC-V spec
369+
* says that PTE_A and PTE_D always go together, and it's probably most sensible
370+
* that PTE_CD implies PTE_A and PTE_D. So, sensible values for this constant
371+
* are 0, (PTE_A | PTE_D), or (PTE_A | PTE_D | PTE_CD).
372+
*/
373+
#define RISCV_PTE_TRAPPY 0
374+
#endif
375+
365376
/* get_physical_address - get the physical address for this virtual address
366377
*
367378
* Do a page table walk to obtain the physical address corresponding to a
@@ -618,6 +629,28 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
618629
} else if (access_type == MMU_DATA_CAP_STORE && !(pte & PTE_CW)) {
619630
/* CW inhibited */
620631
return TRANSLATE_CHERI_FAIL;
632+
#endif
633+
#if RISCV_PTE_TRAPPY & PTE_A
634+
} else if (!(pte & PTE_A)) {
635+
/* PTE not marked as accessed */
636+
return TRANSLATE_FAIL;
637+
#endif
638+
#if RISCV_PTE_TRAPPY & PTE_D
639+
} else if ((access_type == MMU_DATA_STORE) && !(pte & PTE_D)) {
640+
/* PTE not marked as dirty */
641+
return TRANSLATE_FAIL;
642+
#endif
643+
#if defined(TARGET_CHERI) && !defined(TARGET_RISCV32)
644+
#if RISCV_PTE_TRAPPY & PTE_D
645+
} else if (access_type == MMU_DATA_CAP_STORE && !(pte & PTE_D)) {
646+
/* PTE not marked as dirty for cap store */
647+
return TRANSLATE_FAIL;
648+
#endif
649+
#if RISCV_PTE_TRAPPY & PTE_CD
650+
} else if (access_type == MMU_DATA_CAP_STORE && !(pte & PTE_CD)) {
651+
/* CD clear; force the software trap handler to get involved */
652+
return TRANSLATE_CHERI_FAIL;
653+
#endif
621654
#endif
622655
} else {
623656
/* if necessary, set accessed and dirty bits. */

0 commit comments

Comments
 (0)