@@ -31,22 +31,39 @@ bitfield PTE_Bits : pteAttribs = {
31
31
* state cached and then observe a CW=1 CD=1 PTE, no PTE write is necessary.
32
32
* On the other hand, if CW=0 is observed, the store operation must trap.
33
33
*
34
+ * The intended semantics for capability loads are as follows.
35
+ *
36
+ * CR CR_Mod CR_Gen Action
37
+ *
38
+ * 0 0 0 Capability loads strip tags
39
+ * 0 1 0 Capability loads trap (on set tag)
40
+ * 0 X 1 [Reserved]
41
+ *
42
+ * 1 0 0 Capability loads succeed: no traps or tag clearing
43
+ * 1 0 1 [Reserved]
44
+ * 1 1 G Capability loads trap if G mismatches sccsr.[su]gclg,
45
+ * where the compared bit is keyed off of this PTE's U.
46
+ *
34
47
* SV32: There are no extension bits available, so we hard-code the result to
35
- * CW=1 CR=1 CD=1.
48
+ * CW=1 CR=1 CD=1 CR_Mod=0 CR_Gen=0
36
49
*/
37
50
type extPte = bits(10)
38
51
39
52
bitfield Ext_PTE_Bits : extPte = {
40
53
CapWrite : 9, /* Permit capability stores */
41
54
CapRead : 8, /* Permit capability loads */
42
55
CapDirty : 7, /* Capability Dirty flag */
56
+ CapRead_Mod : 6, /* Modify capability load prohibition; see above table */
57
+ CapRead_Gen : 5, /* When load-cap gens. are in use, the "local" gen. bit */
43
58
}
44
59
45
60
/*
46
61
* CapWrite = 1,
47
62
* CapRead = 1,
48
63
* CapDirty = 1,
49
- * bits 0 .. 6 = 0
64
+ * CapRead_Mod = 0,
65
+ * CapRead_Gen = 0,
66
+ * bits 0 .. 4 = 0
50
67
*/
51
68
let default_sv32_ext_pte : extPte = 0b1110000000
52
69
@@ -57,7 +74,10 @@ function isPTEPtr(p : pteAttribs, ext : extPte) -> bool = {
57
74
58
75
function isInvalidPTE(p : pteAttribs, ext : extPte) -> bool = {
59
76
let a = Mk_PTE_Bits(p);
60
- a.V() == 0b0 | (a.W() == 0b1 & a.R() == 0b0)
77
+ let e = Mk_Ext_PTE_Bits(ext);
78
+ a.V() == 0b0 | (a.W() == 0b1 & a.R() == 0b0) |
79
+ (e.CapRead() == 0b0 & e.CapRead_Gen() == 0b1) |
80
+ (e.CapRead() == 0b1 & e.CapRead_Gen() == 0b1 & e.CapRead_Mod() == 0b0)
61
81
}
62
82
63
83
union PTE_Check = {
@@ -73,6 +93,25 @@ function checkPTEPermission_SC(e, ext_ptw) = {
73
93
else PTE_Check_Failure(ext_ptw, EPTWF_CAP_ERR)
74
94
}
75
95
96
+ /*
97
+ * Assuming we're allowed to load from this page, modulate our cap response
98
+ */
99
+ val checkPTEPermission_LC : (PTE_Bits, Ext_PTE_Bits, ext_ptw) -> PTE_Check effect { escape, rreg }
100
+ function checkPTEPermission_LC(p, e, ext_ptw) =
101
+ match (e.CapRead(), e.CapRead_Mod(), e.CapRead_Gen()) {
102
+ (0b0, 0b0, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_CLEAR)), /* Clear tag for "unmodified" no-LC case */
103
+ (0b0, 0b1, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_TRAP)), /* Trap on tag load for "modified" no-LC case */
104
+ (0b0, _ , 0b1) => internal_error("Bad PTE not caught by isInvalidPTE"),
105
+ (0b1, 0b0, 0b0) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, PTW_LC_OK)), /* Unmodified LC case: go ahead */
106
+ (0b1, 0b0, 0b1) => internal_error("Bad PTE not caught by isInvalidPTE"),
107
+ (0b1, 0b1, lclg) => {
108
+ /* Compare local CLG against the pte.U-selected, not mode-selected, global CLG bit */
109
+ let gclg : bits(1) = if p.U() == 0b1 then sccsr.ugclg() else sccsr.sgclg();
110
+ let ptwl = if lclg == gclg then PTW_LC_OK else PTW_LC_TRAP;
111
+ PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptwl))
112
+ }
113
+ }
114
+
76
115
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 = {
77
116
/*
78
117
* Although in many cases MXR doesn't make sense for capabilities, we honour
@@ -123,7 +162,6 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
123
162
};
124
163
125
164
/* Load side */
126
- let ptw_lc = if e.CapRead() == 0b1 then PTW_LC_OK else PTW_LC_CLEAR;
127
165
let res : PTE_Check = match res {
128
166
PTE_Check_Failure(_, _) => res,
129
167
PTE_Check_Success(ext_ptw) => match ac {
@@ -132,8 +170,8 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
132
170
Write(_) => res,
133
171
ReadWrite(Data, _) => res,
134
172
135
- Read(Cap) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptw_lc) ),
136
- ReadWrite(Cap, _) => PTE_Check_Success(ext_ptw_lc_join(ext_ptw, ptw_lc) )
173
+ Read(Cap) => checkPTEPermission_LC(p, e, ext_ptw ),
174
+ ReadWrite(Cap, _) => checkPTEPermission_LC(p, e, ext_ptw )
137
175
}
138
176
};
139
177
0 commit comments