@@ -93,22 +93,39 @@ bitfield PTE_Bits : pteAttribs = {
93
93
* state cached and then observe a CW=1 CD=1 PTE, no PTE write is necessary.
94
94
* On the other hand, if CW=0 is observed, the store operation must trap.
95
95
*
96
- * SV32: There are no extension bits available, so we hard-code the result to
97
- * CW=1 CR=1 CD=1.
96
+ * The intended semantics for capability loads are as follows.
97
+ *
98
+ * CR CR_Trap CR_Gen Action
99
+ *
100
+ * 0 0 0 Capability loads strip tags
101
+ * 0 1 0 Capability loads trap (on set tag)
102
+ * 0 X 1 [Reserved]
103
+ *
104
+ * 1 0 0 Capability loads succeed: no traps or tag clearing
105
+ * 1 0 1 [Reserved]
106
+ * 1 1 G Capability loads trap if G mismatches sccsr.[su]gclg,
107
+ * where the compared bit is keyed off of this PTE's U.
108
+ *
109
+ * Sv32: There are no extension bits available, so we hard-code the result to
110
+ * CW=1 CR=1 CD=1 CR_Trap=0 CR_Gen=0
98
111
*/
99
112
type extPte = bits(10)
100
113
101
114
bitfield Ext_PTE_Bits : extPte = {
102
115
CapWrite : 9, /* Permit capability stores */
103
116
CapRead : 8, /* Permit capability loads */
104
117
CapDirty : 7, /* Capability Dirty flag */
118
+ CapRead_Trap : 6, /* Trap on capability loads; see above table */
119
+ CapRead_Gen : 5, /* When load-cap gens. are in use, the "local" gen. bit */
105
120
}
106
121
107
122
/*
108
123
* CapWrite = 1,
109
124
* CapRead = 1,
110
125
* CapDirty = 1,
111
- * bits 0 .. 6 = 0
126
+ * CapRead_Trap = 0,
127
+ * CapRead_Gen = 0,
128
+ * bits 0 .. 4 = 0
112
129
*/
113
130
let default_sv32_ext_pte : extPte = 0b1110000000
114
131
@@ -119,7 +136,10 @@ function isPTEPtr(p : pteAttribs, ext : extPte) -> bool = {
119
136
120
137
function isInvalidPTE(p : pteAttribs, ext : extPte) -> bool = {
121
138
let a = Mk_PTE_Bits(p);
122
- a.V() == 0b0 | (a.W() == 0b1 & a.R() == 0b0)
139
+ let e = Mk_Ext_PTE_Bits(ext);
140
+ a.V() == 0b0 | (a.W() == 0b1 & a.R() == 0b0) |
141
+ (e.CapRead() == 0b0 & e.CapRead_Gen() == 0b1) |
142
+ (e.CapRead() == 0b1 & e.CapRead_Gen() == 0b1 & e.CapRead_Trap() == 0b0)
123
143
}
124
144
125
145
union PTE_Check = {
@@ -135,6 +155,25 @@ function checkPTEPermission_SC(e, ext_ptw) = {
135
155
else PTE_Check_Failure(ext_ptw, EPTWF_CAP_ERR)
136
156
}
137
157
158
+ /*
159
+ * Assuming we're allowed to load from this page, modulate our cap response
160
+ */
161
+ val checkPTEPermission_LC : (PTE_Bits, Ext_PTE_Bits, ext_ptw) -> PTE_Check effect { escape, rreg }
162
+ function checkPTEPermission_LC(p, e, ext_ptw) =
163
+ match (e.CapRead(), e.CapRead_Trap(), e.CapRead_Gen()) {
164
+ (0b0, 0b0, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_CLEAR)), /* Clear tag for "unmodified" no-LC case */
165
+ (0b0, 0b1, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_TRAP)), /* Trap on tag load for "modified" no-LC case */
166
+ (0b0, _ , 0b1) => internal_error("Bad PTE not caught by isInvalidPTE"),
167
+ (0b1, 0b0, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_OK)), /* Unmodified LC case: go ahead */
168
+ (0b1, 0b0, 0b1) => internal_error("Bad PTE not caught by isInvalidPTE"),
169
+ (0b1, 0b1, lclg) => {
170
+ /* Compare local CLG against the pte.U-selected, not mode-selected, global CLG bit */
171
+ let gclg : bits(1) = if p.U() == 0b1 then sccsr.ugclg() else sccsr.sgclg();
172
+ let ptwl = if lclg == gclg then PTW_LC_OK else PTW_LC_TRAP;
173
+ PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptwl))
174
+ }
175
+ }
176
+
138
177
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 = {
139
178
/*
140
179
* Although in many cases MXR doesn't make sense for capabilities, we honour
@@ -185,7 +224,6 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
185
224
};
186
225
187
226
/* Load side */
188
- let ptw_lc = if e.CapRead() == 0b1 then PTW_LC_OK else PTW_LC_CLEAR;
189
227
let res : PTE_Check = match res {
190
228
PTE_Check_Failure(_, _) => res,
191
229
PTE_Check_Success(ext_ptw) => match ac {
@@ -194,8 +232,8 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
194
232
Write(_) => res,
195
233
ReadWrite(Data, _) => res,
196
234
197
- Read(Cap) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptw_lc) ),
198
- ReadWrite(Cap, _) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptw_lc) )
235
+ Read(Cap) => checkPTEPermission_LC(p, e, ext_ptw ),
236
+ ReadWrite(Cap, _) => checkPTEPermission_LC(p, e, ext_ptw )
199
237
}
200
238
};
201
239
0 commit comments