@@ -15,12 +15,29 @@ bitfield PTE_Bits : pteAttribs = {
15
15
16
16
/* Reserved PTE bits could be used by extensions on RV64. There are
17
17
* no such available bits on RV32, so these bits will be zeros on RV32.
18
+ *
19
+ * XXX Because these bits are 0 on RV32, do we want to use inverted polarity,
20
+ * so that 0 is the *enabled* form?
21
+ *
22
+ * The intended semantics for LoadCap* are:
23
+ *
24
+ * LC LC_Mod LC_CLG Action
25
+ * 0 0 0 Capability loads always strip tags
26
+ * 0 [other values] [Reserved]
27
+ *
28
+ * 1 0 0 Capability loads always succeed without tag stripping
29
+ * 1 0 1 Capability loads always trap
30
+ * 1 1 G Capability loads trap if G mismatches sccsr.gclg[su],
31
+ * where the compared bit is keyed off of this PTE's U.
32
+ *
18
33
*/
19
34
type extPte = bits(10)
20
35
21
36
bitfield Ext_PTE_Bits : extPte = {
22
37
LoadCap : 9,
23
38
StoreCap : 8,
39
+ LoadCap_Mod : 7,
40
+ LoadCap_CLG : 6,
24
41
}
25
42
26
43
function isPTEPtr(p : pteAttribs, ext : extPte) -> bool = {
@@ -41,6 +58,26 @@ union PTE_Check = {
41
58
function to_pte_check(b : bool) -> (bool, pte_check) =
42
59
(b, PTE_CAP_OK)
43
60
61
+ /*
62
+ * Assuming we're allowed to load from this page, modulate our cap response
63
+ */
64
+ val checkPTEPermission_LC : (PTE_Bits, Ext_PTE_Bits) -> pte_check effect {rreg}
65
+ function checkPTEPermission_LC(p, e) =
66
+ if e.LoadCap() == 0b0
67
+ then PTE_LOAD_CAP_CLR
68
+ else if e.LoadCap_Mod() == 0b0
69
+ then { /* With LoadCap_Mod off, CLG modulates the behavior directly */
70
+ if e.LoadCap_CLG() == 0b0
71
+ then PTE_CAP_OK
72
+ else PTE_LOAD_CAP_TRAP
73
+ }
74
+ else { /* With LoadCap_Mod on, use CLG as such */
75
+ let gclg : bits(1) = if p.U() == 0b1 then sccsr.gclgu() else sccsr.gclgs();
76
+ if e.LoadCap_CLG() == gclg
77
+ then PTE_CAP_OK
78
+ else PTE_LOAD_CAP_TRAP
79
+ }
80
+
44
81
function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege, mxr : bool, do_sum : bool, p : PTE_Bits, ext : extPte, ext_ptw : ext_ptw) -> PTE_Check = {
45
82
let (succ, pte_chk) : (bool, pte_check) =
46
83
match (ac, priv) {
@@ -58,12 +95,7 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
58
95
if p.U() == 0b1 & p.R() == 0b1
59
96
then {
60
97
let e = Mk_Ext_PTE_Bits(ext);
61
- if e.LoadCap() == 0b1
62
- then (true, PTE_CAP_OK)
63
- else {
64
- /* Allow the address translation to proceed, but mark for tag stripping */
65
- (true, PTE_LOAD_CAP_ERR)
66
- }
98
+ (true, checkPTEPermission_LC(p, e))
67
99
}
68
100
else (false, PTE_CAP_OK)
69
101
},
@@ -84,23 +116,22 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
84
116
(ReadWrite(Cap), User) => { if p.U() == 0b1 & p.R() == 0b1 & p.W() == 0b1
85
117
then {
86
118
let e = Mk_Ext_PTE_Bits(ext);
87
- if e.StoreCap() == 0b1 & e.LoadCap() == 0b1
119
+ let lcm = checkPTEPermission_LC(p, e);
120
+ if e.StoreCap() == 0b1 & lcm == PTE_CAP_OK
88
121
then (true, PTE_CAP_OK)
89
122
else if e.StoreCap() == 0b0
90
123
/* return a failure since we should cause an exception */
91
124
then (false, PTE_STORE_CAP_ERR)
92
125
/* return a success since the translation should proceed */
93
- else (true, PTE_LOAD_CAP_ERR )
126
+ else (true, lcm )
94
127
}
95
128
else (false, PTE_CAP_OK)
96
129
},
97
130
98
131
(Read(Cap), Supervisor) => { if (p.U() == 0b0 | do_sum) & p.R() == 0b1
99
132
then {
100
133
let e = Mk_Ext_PTE_Bits(ext);
101
- if e.LoadCap() == 0b1
102
- then (true, PTE_CAP_OK)
103
- else (true, PTE_LOAD_CAP_ERR)
134
+ (true, checkPTEPermission_LC(p, e))
104
135
}
105
136
else (false, PTE_CAP_OK)
106
137
},
@@ -118,13 +149,14 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
118
149
(ReadWrite(Cap), Supervisor) => { let e = Mk_Ext_PTE_Bits(ext);
119
150
if (p.U() == 0b0 | do_sum) & p.R() == 0b1 & p.W() == 0b1
120
151
then {
121
- if e.StoreCap() == 0b1 & e.LoadCap() == 0b1
152
+ let lcm = checkPTEPermission_LC(p, e);
153
+ if e.StoreCap() == 0b1 & lcm == PTE_CAP_OK
122
154
then (true, PTE_CAP_OK)
123
155
else if e.StoreCap() == 0b0
124
156
/* return a failure since we should cause an exception */
125
157
then (false, PTE_STORE_CAP_ERR)
126
158
/* return a success since the translation should proceed */
127
- else (true, PTE_LOAD_CAP_ERR )
159
+ else (true, lcm )
128
160
}
129
161
else (false, PTE_CAP_OK)
130
162
},
0 commit comments