@@ -15,12 +15,34 @@ 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
+ * XXX For initial implementation, only LoadCap and StoreCap are expected to
23
+ * be implemented. The LC_Mod and LC_LCLG bits are for Revocation 3's benefit
24
+ * and will be first brought up in emulation.
25
+ *
26
+ * The intended semantics for LoadCap* are:
27
+ *
28
+ * LC LC_Mod LC_LCLG Action
29
+ * 0 0 0 Capability loads strip tags
30
+ * 0 1 0 Capability loads trap (on set tag)
31
+ * 0 X 1 [Reserved]
32
+ *
33
+ * 1 0 0 Capability loads succeed: no traps or tag clearing
34
+ * 1 0 1 [Reserved]
35
+ * 1 1 G Capability loads trap if G mismatches sccsr.gclg[su],
36
+ * where the compared bit is keyed off of this PTE's U.
37
+ *
18
38
*/
19
39
type extPte = bits(10)
20
40
21
41
bitfield Ext_PTE_Bits : extPte = {
22
- LoadCap : 9,
23
- StoreCap : 8,
42
+ LoadCap : 9, /* Permit capability loads */
43
+ StoreCap : 8, /* Permit capability stores */
44
+ LoadCap_Mod : 7, /* Modify capability load behavior; see above table */
45
+ LoadCap_LCLG : 6, /* When cap. load gens. are in use, the "local" CLG */
24
46
}
25
47
26
48
function isPTEPtr(p : pteAttribs, ext : extPte) -> bool = {
@@ -41,6 +63,29 @@ union PTE_Check = {
41
63
function to_pte_check(b : bool) -> (bool, pte_check) =
42
64
(b, PTE_CAP_OK)
43
65
66
+ /*
67
+ * Assuming we're allowed to load from this page, modulate our cap response
68
+ */
69
+ val checkPTEPermission_LC : (PTE_Bits, Ext_PTE_Bits) -> pte_check effect {rreg}
70
+ function checkPTEPermission_LC(p, e) =
71
+ if e.LoadCap() == 0b0
72
+ then match (e.LoadCap_LCLG(), e.LoadCap_Mod()) {
73
+ (0b1, _) => not_implemented("Reserved PTE extension bits: !LC but LCLG"),
74
+ (_, 0b0) => PTE_LOAD_CAP_CLR /* Clear tag for "unmodified" no-LC case */,
75
+ (_, 0b1) => PTE_LOAD_CAP_TRAP /* Trap on tag load for "modified" no-LC case */
76
+ }
77
+ else if e.LoadCap_Mod() == 0b0
78
+ then { if e.LoadCap_LCLG() == 0b0
79
+ then PTE_CAP_OK /* Unmodified LC case: go ahead */
80
+ else not_implemented("Reserved PTE extension bits: LC, !LC_Mod but LCLG")
81
+ }
82
+ else { /* With LoadCap_Mod on with LC, use LCLG */
83
+ let gclg : bits(1) = if p.U() == 0b1 then sccsr.gclgu() else sccsr.gclgs();
84
+ if e.LoadCap_LCLG() == gclg
85
+ then PTE_CAP_OK
86
+ else PTE_LOAD_CAP_TRAP
87
+ }
88
+
44
89
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
90
let (succ, pte_chk) : (bool, pte_check) =
46
91
match (ac, priv) {
@@ -58,12 +103,7 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
58
103
if p.U() == 0b1 & p.R() == 0b1
59
104
then {
60
105
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
- }
106
+ (true, checkPTEPermission_LC(p, e))
67
107
}
68
108
else (false, PTE_CAP_OK)
69
109
},
@@ -84,23 +124,22 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
84
124
(ReadWrite(Cap), User) => { if p.U() == 0b1 & p.R() == 0b1 & p.W() == 0b1
85
125
then {
86
126
let e = Mk_Ext_PTE_Bits(ext);
87
- if e.StoreCap() == 0b1 & e.LoadCap() == 0b1
127
+ let lcm = checkPTEPermission_LC(p, e);
128
+ if e.StoreCap() == 0b1 & lcm == PTE_CAP_OK
88
129
then (true, PTE_CAP_OK)
89
130
else if e.StoreCap() == 0b0
90
131
/* return a failure since we should cause an exception */
91
132
then (false, PTE_STORE_CAP_ERR)
92
133
/* return a success since the translation should proceed */
93
- else (true, PTE_LOAD_CAP_ERR )
134
+ else (true, lcm )
94
135
}
95
136
else (false, PTE_CAP_OK)
96
137
},
97
138
98
139
(Read(Cap), Supervisor) => { if (p.U() == 0b0 | do_sum) & p.R() == 0b1
99
140
then {
100
141
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)
142
+ (true, checkPTEPermission_LC(p, e))
104
143
}
105
144
else (false, PTE_CAP_OK)
106
145
},
@@ -118,13 +157,14 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
118
157
(ReadWrite(Cap), Supervisor) => { let e = Mk_Ext_PTE_Bits(ext);
119
158
if (p.U() == 0b0 | do_sum) & p.R() == 0b1 & p.W() == 0b1
120
159
then {
121
- if e.StoreCap() == 0b1 & e.LoadCap() == 0b1
160
+ let lcm = checkPTEPermission_LC(p, e);
161
+ if e.StoreCap() == 0b1 & lcm == PTE_CAP_OK
122
162
then (true, PTE_CAP_OK)
123
163
else if e.StoreCap() == 0b0
124
164
/* return a failure since we should cause an exception */
125
165
then (false, PTE_STORE_CAP_ERR)
126
166
/* return a success since the translation should proceed */
127
- else (true, PTE_LOAD_CAP_ERR )
167
+ else (true, lcm )
128
168
}
129
169
else (false, PTE_CAP_OK)
130
170
},
0 commit comments