1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
function clause currentlyEnabled(
Ext_Zicbom) =
hartSupports(
Ext_Zicbom)
function cbo_clean_flush_enabled(
p :
Privilege) ->
bool =
feature_enabled_for_priv(
p,
menvcfg[
CBCFE][
0],
senvcfg[
CBCFE][
0])
union clause instruction =
ZICBOM : (
cbop_zicbom,
regidx)
mapping encdec_cbop :
cbop_zicbom <->
bits(
12) = {
CBO_CLEAN <->
0b000000000001,
CBO_FLUSH <->
0b000000000010,
CBO_INVAL <->
0b000000000000,
}
mapping clause encdec =
ZICBOM(
cbop,
rs1)
<->
encdec_cbop(
cbop) @
encdec_reg(
rs1) @
0b010 @
0b00000 @
0b0001111
when currentlyEnabled(
Ext_Zicbom)
mapping cbop_mnemonic :
cbop_zicbom <->
string = {
CBO_CLEAN <->
"cbo.clean",
CBO_FLUSH <->
"cbo.flush",
CBO_INVAL <->
"cbo.inval"
}
mapping clause assembly =
ZICBOM(
cbop,
rs1)
<->
cbop_mnemonic(
cbop)
^ spc()
^ "(" ^ opt_spc()
^ reg_name(
rs1)
^ opt_spc()
^ ")"
enum cbie = {
CBIE_ILLEGAL,
CBIE_EXEC_FLUSH,
CBIE_EXEC_INVAL}
mapping encdec_cbie :
cbie <->
bits(
2) = {
CBIE_ILLEGAL <->
0b00,
CBIE_EXEC_FLUSH <->
0b01,
CBIE_EXEC_INVAL <->
0b11,
backwards 0b10 =>
internal_error(
__FILE__,
__LINE__,
"reserved CBIE"),
}
enum checked_cbop = {
CBOP_ILLEGAL,
CBOP_ILLEGAL_VIRTUAL,
CBOP_INVAL_FLUSH,
CBOP_INVAL_INVAL}
function cbop_priv_check(
p:
Privilege) ->
checked_cbop = {
let mCBIE :
cbie =
encdec_cbie(
menvcfg[
CBIE]);
let sCBIE :
cbie =
if currentlyEnabled(
Ext_S)
then encdec_cbie(
senvcfg[
CBIE])
else encdec_cbie(
menvcfg[
CBIE]);
match (
p,
mCBIE,
sCBIE) {
(
VirtualUser, _, _) =>
internal_error(
__FILE__,
__LINE__,
"Hypervisor extension not supported"),
(
VirtualSupervisor, _, _) =>
internal_error(
__FILE__,
__LINE__,
"Hypervisor extension not supported"),
(
Machine, _, _ ) =>
CBOP_INVAL_INVAL,
(_,
CBIE_ILLEGAL, _ ) =>
CBOP_ILLEGAL, (
User, _,
CBIE_ILLEGAL ) =>
CBOP_ILLEGAL, (_,
CBIE_EXEC_FLUSH, _ ) =>
CBOP_INVAL_FLUSH, (
User, _,
CBIE_EXEC_FLUSH) =>
CBOP_INVAL_FLUSH, _ =>
CBOP_INVAL_INVAL,
}
}
val process_clean_inval : (
regidx,
cbop_zicbom) ->
ExecutionResult
function process_clean_inval(
rs1,
cbop) = {
let rs1_val =
X(
rs1);
let cache_block_size = 2 ^
plat_cache_block_size_exp;
let negative_offset = (
rs1_val & ~(
zero_extend(
ones(
plat_cache_block_size_exp))))
- rs1_val;
match ext_data_get_addr(
rs1,
negative_offset,
Read(
Data),
cache_block_size) {
Ext_DataAddr_Error(
e) =>
Ext_DataAddr_Check_Failure(
e),
Ext_DataAddr_OK(
vaddr) => {
let res :
option(
ExceptionType) =
match translateAddr(
vaddr,
Read(
Data)) {
Ok(
paddr, _) => {
let ep =
effectivePrivilege(
Read(
Data),
mstatus,
cur_privilege);
let exc_read =
phys_access_check(
Read(
Data),
ep,
paddr,
cache_block_size);
let exc_write =
phys_access_check(
Write(
Data),
ep,
paddr,
cache_block_size);
match (
exc_read,
exc_write) {
(
Some(
exc_read),
Some(
exc_write)) =>
Some(
exc_write),
_ =>
None(),
}
},
Err(
e, _) =>
Some(
e)
};
match res {
None() =>
RETIRE_SUCCESS,
Some(
e) => {
let e :
ExceptionType =
match e {
E_Load_Access_Fault() =>
E_SAMO_Access_Fault(),
E_SAMO_Access_Fault() =>
E_SAMO_Access_Fault(),
E_Load_Page_Fault() =>
E_SAMO_Page_Fault(),
E_SAMO_Page_Fault() =>
E_SAMO_Page_Fault(),
_ =>
internal_error(
__FILE__,
__LINE__,
"unexpected exception for cmo.clean/inval"),
};
Memory_Exception(
vaddr - negative_offset,
e)
}
}
}
}
}
function clause execute(
ZICBOM(
CBO_CLEAN,
rs1)) =
if cbo_clean_flush_enabled(
cur_privilege)
then process_clean_inval(
rs1,
CBO_CLEAN)
else Illegal_Instruction()
function clause execute(
ZICBOM(
CBO_FLUSH,
rs1)) =
if cbo_clean_flush_enabled(
cur_privilege)
then process_clean_inval(
rs1,
CBO_FLUSH)
else Illegal_Instruction()
function clause execute(
ZICBOM(
CBO_INVAL,
rs1)) =
match cbop_priv_check(
cur_privilege) {
CBOP_ILLEGAL =>
Illegal_Instruction(),
CBOP_ILLEGAL_VIRTUAL =>
internal_error(
__FILE__,
__LINE__,
"unimplemented"),
CBOP_INVAL_INVAL =>
process_clean_inval(
rs1,
CBO_INVAL),
CBOP_INVAL_FLUSH =>
process_clean_inval(
rs1,
CBO_FLUSH),
}