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