-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support of Smepmp #601
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,14 @@ function pmpAddrRange(cfg: Pmpcfg_ent, pmpaddr: xlenbits, prev_pmpaddr: xlenbits | |
} | ||
} | ||
} | ||
// helper function to check if the access type is execute | ||
val isExecute: AccessType(ext_access_type) -> bool | ||
function isExecute(acc: AccessType(ext_access_type)) -> bool = | ||
match acc { | ||
Execute(_) => true, | ||
_ => false, | ||
} | ||
|
||
|
||
/* permission checks */ | ||
|
||
|
@@ -47,6 +55,34 @@ function pmpCheckRWX(ent, acc) = | |
Execute() => ent[X] == 0b1, | ||
} | ||
|
||
/* this needs to be called with the effective current privilege */ | ||
val pmpCheckPerms: (Pmpcfg_ent, AccessType(ext_access_type), Privilege) -> bool | ||
function pmpCheckPerms(ent, acc, priv) = { | ||
if mseccfg[MML] == 0b1 | ||
then { | ||
match (ent[L], ent[R], ent[W], ent[X]) { | ||
(0b1, 0b0, 0b1, _) => | ||
match acc { | ||
Execute(_) => true, | ||
Read(_) => priv == Machine & ent[X] == 0b1, | ||
_ => false | ||
}, | ||
(0b0, 0b0, 0b1, _) => | ||
match acc { | ||
Read(_) => true, | ||
Write(_) => priv == Machine | ent[X] == 0b1, | ||
_ => false | ||
}, | ||
(0b1, 0b1, 0b1, 0b1) => | ||
match acc { | ||
Read(_) => true, | ||
_ => false | ||
}, | ||
(L, _, _, _) => ((priv == Machine) == (L == 0b1)) & pmpCheckRWX(ent, acc) | ||
} | ||
} | ||
else (priv == Machine & not(pmpLocked(ent))) | pmpCheckRWX(ent, acc) | ||
} | ||
|
||
/* matching logic */ | ||
|
||
|
@@ -84,7 +120,7 @@ function pmpMatchEntry(addr: physaddr, width: xlenbits, acc: AccessType(ext_acce | |
match pmpMatchAddr(addr, width, rng) { | ||
PMP_NoMatch => PMP_Continue, | ||
PMP_PartialMatch => PMP_Fail, | ||
PMP_Match => if pmpCheckRWX(ent, acc) | (priv == Machine & not(pmpLocked(ent))) | ||
PMP_Match => if pmpCheckPerms(ent, acc, priv) | ||
then PMP_Success | ||
else PMP_Fail | ||
} | ||
|
@@ -112,7 +148,12 @@ function pmpCheck forall 'n, 'n > 0. (addr: physaddr, width: int('n), acc: Acces | |
PMP_Continue => (), | ||
} | ||
}; | ||
if priv == Machine then None() else Some(accessToFault(acc)) | ||
/* Make Read, Write and execute denied by default, if mseccfg[MMWP] == 0b1 for M mode | ||
* Make execute denied, if mseccfg[MML] == 0b1 for M mode | ||
*/ | ||
if priv == Machine & mseccfg[MMWP] == 0b0 & (mseccfg[MML] == 0b0 | not(isExecute(acc))) | ||
then None() | ||
else Some(accessToFault(acc)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this could be a lot simpler:
(add |
||
} | ||
|
||
function reset_pmp() -> unit = { | ||
|
@@ -121,6 +162,8 @@ function reset_pmp() -> unit = { | |
"sys_pmp_count() must be 0, 16, or 64" | ||
); | ||
|
||
mseccfg = [mseccfg with MML = 0b0, MMWP = 0b0, RLB = 0b0]; | ||
|
||
foreach (i from 0 to 63) { | ||
// On reset the PMP register's A and L bits are set to 0 unless the plaform | ||
// mandates a different value. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,6 +107,11 @@ val sys_pmp_grain = pure "sys_pmp_grain" : unit -> range(0, 63) | |
/* Which HPM counters are supported (as a bit mask). Bits [2 .. 0] are ignored. */ | ||
val sys_writable_hpm_counters = pure "sys_writable_hpm_counters" : unit -> bits(32) | ||
|
||
/* Enable Smepmp */ | ||
val sys_enable_smepmp = pure "sys_enable_smepmp" : unit -> bool | ||
/* TODO: for extension smmpm and zkr to enable */ | ||
function sys_has_mseccfg() -> bool = sys_enable_smepmp() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can implement
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean we need to add an extra command line parameter to act as an extra switch to control the presence of mseccfg to make sure that even if we don't implement extensions that use this register, we can still implement this register, right ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah exactly. I don't think we need to actually bother hooking it up to a CLI arguments at the moment - we can wait until Alasdair's new config system exists and then it will be a whole lot less tedious. But we can just have a function that returns |
||
|
||
/* whether misa.v was enabled at boot */ | ||
val sys_enable_vext = pure "sys_enable_vext" : unit -> bool | ||
|
||
|
@@ -409,6 +414,47 @@ function is_fiom_active() -> bool = { | |
} | ||
} | ||
|
||
bitfield Mseccfg_ent : bits(64) = { | ||
RLB : 2, /* Rule Locking Bypass */ | ||
MMWP : 1, /* Machine Mode Whitelist Policy */ | ||
MML : 0 /* Machine Mode Lockdown */ | ||
} | ||
|
||
register mseccfg : Mseccfg_ent | ||
|
||
val checkPmpNcfgL : range(0, 63) -> bits(1) | ||
|
||
function mseccfgWrite(reg: Mseccfg_ent, v: bits(64)) -> Mseccfg_ent = { | ||
let legal_v : Mseccfg_ent = Mk_Mseccfg_ent(zero_extend(v[2 .. 0])); | ||
let reg : Mseccfg_ent = match (reg[RLB], legal_v[RLB], checkPmpNcfgL(63)) { | ||
// to set RLB, need to check PMPCFG_L | ||
(0b0, 0b1, 0b1) => reg, | ||
(_, _, _) => [reg with RLB = legal_v[RLB]], | ||
}; | ||
let reg : Mseccfg_ent = match (reg[MML], reg[MMWP]) { | ||
// Implements stickiness of MML bit, if once set remains set | ||
(0b0, 0b0) => [reg with MMWP = legal_v[MMWP], MML = legal_v[MML]], | ||
(0b0, 0b1) => [reg with MML = legal_v[MML]], | ||
(0b1, 0b0) => [reg with MMWP = legal_v[MMWP]], | ||
(0b1, 0b1) => reg | ||
}; | ||
reg | ||
} | ||
|
||
mapping clause csr_name_map = 0x747 <-> "mseccfg" | ||
mapping clause csr_name_map = 0x757 <-> "mseccfgh" | ||
|
||
function clause is_CSR_defined(0x747) = sys_has_mseccfg() | ||
function clause is_CSR_defined(0x757) = sys_has_mseccfg() & xlen == 32 | ||
|
||
function clause read_CSR(0x747) = mseccfg.bits[xlen - 1 .. 0] | ||
function clause read_CSR(0x757 if xlen == 32) = mseccfg.bits[63 .. 32] | ||
|
||
// Keep a consistent writing style, as it may be necessary to integrate the ifs process into the writeCSR function body in the future | ||
function clause write_CSR((0x747, value) if xlen == 64) = { mseccfg = mseccfgWrite(mseccfg, value); mseccfg.bits } | ||
function clause write_CSR((0x747, value) if xlen == 32) = { mseccfg = mseccfgWrite(mseccfg, mseccfg.bits[63 .. 32] @ value); mseccfg.bits[xlen - 1 .. 0] } | ||
function clause write_CSR((0x757, value) if xlen == 32) = { mseccfg = mseccfgWrite(mseccfg, value @ mseccfg.bits[31 .. 0]); mseccfg.bits[63 .. 32] } | ||
|
||
/* interrupt processing state */ | ||
|
||
bitfield Minterrupts : xlenbits = { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//
style comments are nicer IMO. I don't see why we would change them back?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the part that was changed by @HamzaKh01, I didn't check this as I was too focused on the code implementation part, we can change it back if needed, but there are many one line comments like
/* ... */
in Sail, we might need to declare it better in the codestyle after some discussion?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there is an experimental auto-formatter in the Sail compiler but I don't know what state it got to and I'd guess it doesn't change this sort of thing.