Skip to content

Commit bc15a8d

Browse files
loiclefortMichael Tokarev
authored andcommitted
target/riscv: pmp: fix checks on writes to pmpcfg in Smepmp MML mode
With Machine Mode Lockdown (mseccfg.MML) set and RLB not set, checks on pmpcfg writes would match the wrong cases of Smepmp truth table. The existing code allows writes for the following cases: - L=1, X=0: cases 8, 10, 12, 14 - L=0, RWX!=WX: cases 0-2, 4-6 This leaves cases 3, 7, 9, 11, 13, 15 for which writes are ignored. From the Smepmp specification: "Adding a rule with executable privileges that either is M-mode-only or a locked Shared-Region is not possible (...)" This description matches cases 9-11, 13 of the truth table. This commit implements an explicit check for these cases by using pmp_get_epmp_operation to convert between PMP configuration and Smepmp truth table cases. Signed-off-by: Loïc Lefort <[email protected]> Reviewed-by: Daniel Henrique Barboza <[email protected]> Reviewed-by: LIU Zhiwei <[email protected]> Message-ID: <[email protected]> Signed-off-by: Alistair Francis <[email protected]> Cc: [email protected] (cherry picked from commit 19cf1a7) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 504dcda commit bc15a8d

File tree

1 file changed

+43
-36
lines changed

1 file changed

+43
-36
lines changed

target/riscv/pmp.c

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,44 @@ static int pmp_is_readonly(CPURISCVState *env, uint32_t pmp_index)
7575
return pmp_is_locked(env, pmp_index) && !MSECCFG_RLB_ISSET(env);
7676
}
7777

78+
/*
79+
* Check whether `val` is an invalid Smepmp config value
80+
*/
81+
static int pmp_is_invalid_smepmp_cfg(CPURISCVState *env, uint8_t val)
82+
{
83+
/* No check if mseccfg.MML is not set or if mseccfg.RLB is set */
84+
if (!MSECCFG_MML_ISSET(env) || MSECCFG_RLB_ISSET(env)) {
85+
return 0;
86+
}
87+
88+
/*
89+
* Adding a rule with executable privileges that either is M-mode-only
90+
* or a locked Shared-Region is not possible
91+
*/
92+
switch (pmp_get_smepmp_operation(val)) {
93+
case 0:
94+
case 1:
95+
case 2:
96+
case 3:
97+
case 4:
98+
case 5:
99+
case 6:
100+
case 7:
101+
case 8:
102+
case 12:
103+
case 14:
104+
case 15:
105+
return 0;
106+
case 9:
107+
case 10:
108+
case 11:
109+
case 13:
110+
return 1;
111+
default:
112+
g_assert_not_reached();
113+
}
114+
}
115+
78116
/*
79117
* Count the number of active rules.
80118
*/
@@ -103,44 +141,13 @@ static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
103141
static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
104142
{
105143
if (pmp_index < MAX_RISCV_PMPS) {
106-
bool readonly = true;
107-
108-
if (riscv_cpu_cfg(env)->ext_smepmp) {
109-
/* mseccfg.RLB is set */
110-
if (MSECCFG_RLB_ISSET(env)) {
111-
readonly = false;
112-
}
113-
114-
/* mseccfg.MML is not set */
115-
if (!MSECCFG_MML_ISSET(env) && !pmp_is_readonly(env, pmp_index)) {
116-
readonly = false;
117-
}
118-
119-
/* mseccfg.MML is set */
120-
if (MSECCFG_MML_ISSET(env)) {
121-
/* not adding execute bit */
122-
if ((val & PMP_LOCK) != 0 && (val & PMP_EXEC) != PMP_EXEC) {
123-
readonly = false;
124-
}
125-
/* shared region and not adding X bit */
126-
if ((val & PMP_LOCK) != PMP_LOCK &&
127-
(val & 0x7) != (PMP_WRITE | PMP_EXEC)) {
128-
readonly = false;
129-
}
130-
}
131-
} else {
132-
readonly = pmp_is_readonly(env, pmp_index);
133-
}
134-
135-
if (readonly) {
144+
if (pmp_is_readonly(env, pmp_index)) {
136145
qemu_log_mask(LOG_GUEST_ERROR,
137146
"ignoring pmpcfg write - read only\n");
138-
} else if (env->pmp_state.pmp[pmp_index].cfg_reg != val) {
139-
/* If !mseccfg.MML then ignore writes with encoding RW=01 */
140-
if ((val & PMP_WRITE) && !(val & PMP_READ) &&
141-
!MSECCFG_MML_ISSET(env)) {
142-
return false;
143-
}
147+
} else if (pmp_is_invalid_smepmp_cfg(env, val)) {
148+
qemu_log_mask(LOG_GUEST_ERROR,
149+
"ignoring pmpcfg write - invalid\n");
150+
} else {
144151
env->pmp_state.pmp[pmp_index].cfg_reg = val;
145152
pmp_update_rule_addr(env, pmp_index);
146153
return true;

0 commit comments

Comments
 (0)