@@ -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