Skip to content

Commit 3eb695b

Browse files
ShaleXIONGShale Xiong
authored andcommitted
Add missing fault label in all RMW related instruction.
The LxSx has to label both the generated load and store instructions. Also the fault check for those two instructions should be composited disjectively.
1 parent 7ae32c6 commit 3eb695b

6 files changed

Lines changed: 169 additions & 73 deletions

File tree

gen/AArch64Compile_gen.ml

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,18 +1723,30 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
17231723

17241724
let get_tagged_loc e = add_tag (as_data e.C.loc) e.C.tag
17251725

1726-
let add_label_to_instructions e cs =
1726+
let add_label_to_last_instructions e cs =
17271727
match e.C.check_fault with
17281728
| Some (label_name, _) ->
1729-
(* Always label the last instruction,
1730-
which should be the actual load or store. *)
17311729
let rec do_rec = function
17321730
| [] -> assert false (* the `cs` should not be empty *)
17331731
| [instr] -> [Label(label_name, instr)]
17341732
| instr::rem -> instr::do_rec rem in
17351733
do_rec cs
17361734
| None -> cs
17371735

1736+
let add_label_to_first_instructions e cs =
1737+
match e.C.check_fault with
1738+
| Some (label_name, _) ->
1739+
(* find the first non-label instruction *)
1740+
let rec do_rec cs = match cs with
1741+
| [] -> assert false (* the `cs` should not be empty *)
1742+
| instr::rem -> begin match instr with
1743+
(* skip label or instruction that is already labelled *)
1744+
| Label(_) -> instr::do_rec rem
1745+
|_ -> Label(label_name, instr)::rem
1746+
end in
1747+
do_rec cs
1748+
| None -> cs
1749+
17381750
let emit_access st p init e =
17391751
(* collapse the value `v` in event `e` to integer *)
17401752
let value = Code.value_to_int e.C.v in
@@ -1745,7 +1757,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
17451757
| R,Some (Instr, None) ->
17461758
let r,init,cs,st = LDR.emit_fetch st p init lab in
17471759
Some r,init,cs,st
1748-
(* Plain read from an instruction label is currently not supported,
1760+
(* Plain read from an instruction label is currently not supported,
17491761
but will be implemented in a future patch
17501762
| R, None ->
17511763
let r,init,cs,st = LDR.emit_load st p init lab in
@@ -1940,7 +1952,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
19401952
| W,Some (Neon _,Some _) -> assert false
19411953
end in
19421954
(* Add a label to instructions `cs`, when a fault check is required. *)
1943-
let cs = add_label_to_instructions e cs in
1955+
let cs = add_label_to_last_instructions e cs in
19441956
regs,inits,cs,st
19451957
(* END of emit_access *)
19461958

@@ -1960,6 +1972,15 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
19601972
check_cu (not (A64.do_cu || same_sz szr szw)) ;
19611973
ar,aw
19621974

1975+
let add_label_to_pair er ew cs=
1976+
(* Add the label to the read event,
1977+
which should be the first non-labelled instruction *)
1978+
cs |> add_label_to_first_instructions er
1979+
(* After the first read event being labelled,
1980+
add the label to the write event which should now
1981+
be the first non-labelled instruction *)
1982+
|> add_label_to_first_instructions ew
1983+
19631984

19641985
let emit_addr_simple st p init er =
19651986
let rA,init,st = U.next_init st p init (get_tagged_loc er) in
@@ -1971,6 +1992,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
19711992
let rW,init,csi,st = U.emit_mov st p init (Code.value_to_int ew.C.v) in
19721993
let arw = check_arw_lxsx er ew in
19731994
let init,cs,st = XSingle.emit_pair arw p st init rR rW rA ew in
1995+
let cs = add_label_to_pair er ew cs in
19741996
rR,init,csi@caddr@cs,st
19751997

19761998
let emit_exch1 = do_emit_exch1 emit_addr_simple
@@ -1983,6 +2005,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
19832005
let arw = check_arw_lxsx er ew in
19842006
let init,cs,st =
19852007
XPair.emit_pair arw p st init (rR1,rR2) (rW1,rW2) rA ew in
2008+
let cs = add_label_to_pair er ew cs in
19862009
rR1,init,csi@caddr@cs,st
19872010

19882011
let emit_exch22 = do_emit_exch22 emit_addr_simple
@@ -1995,6 +2018,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
19952018
let module X = ExclusivePair(XLoadPair)(XStore) in
19962019
let init,cs,st =
19972020
X.emit_pair arw p st init (rR1,rR2) rW rA ew in
2021+
let cs = add_label_to_pair er ew cs in
19982022
rR1,init,csi@caddr@cs,st
19992023

20002024
let emit_exch21 = do_emit_exch21 emit_addr_simple
@@ -2008,6 +2032,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
20082032
let module X = ExclusivePair(XLoad)(XStorePair) in
20092033
let init,cs,st =
20102034
X.emit_pair arw p st init rR (rW1,rW2) rA ew in
2035+
let cs = add_label_to_pair er ew cs in
20112036
rR,init,csi@caddr@cs,st
20122037

20132038
let emit_exch12 = do_emit_exch12 emit_addr_simple
@@ -2068,8 +2093,9 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
20682093
| Some (sz,o) ->
20692094
let rA,cs,st = sumi_addr st rA o in
20702095
cs@[ins_mixed sz a rW rR rA],st in
2096+
let cs = add_label_to_last_instructions er (pseudo cs) in
20712097
let cs2 = emit_ldr_addon opt rR in
2072-
rR,init,csi@csi2@pseudo (cs@cs2),st
2098+
rR,init,(csi@csi2@cs@pseudo cs2),st
20732099

20742100
let do_emit_ldop ins ins_mixed st p init er ew =
20752101
let rA,init,st =
@@ -2094,8 +2120,9 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
20942120
| Some (sz,o) ->
20952121
let rA,cs,st = sumi_addr st rA o in
20962122
cs@[cas_mixed sz a rS rT rA],st in
2123+
let cs = add_label_to_last_instructions er (pseudo cs) in
20972124
let cs2 = emit_ldr_addon opt rS in
2098-
rS,init,csS@csS2@csT@csT2@pseudo (cs@cs2),st
2125+
rS,init,csS@csS2@csT@csT2@cs@pseudo cs2,st
20992126

21002127
let emit_cas st p init er ew =
21012128
let rA,init,st =
@@ -2118,7 +2145,8 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
21182145
| Some (sz,o) ->
21192146
let rA,cs,st = sumi_addr st rA o in
21202147
cs@[stop_mixed op sz a rW rA],st in
2121-
None,init,csi@pseudo cs,st
2148+
let cs = add_label_to_last_instructions er (pseudo cs) in
2149+
None,init,csi@cs,st
21222150

21232151
let emit_stop op st p init er ew =
21242152
let rA,init,st =
@@ -2235,7 +2263,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
22352263
assert (Misc.is_none m) ;
22362264
Some (a,Some (MachSize.S128,0))
22372265
| _ -> Some (a,m) end in
2238-
begin match d,atom with
2266+
let regs,inits,cs,st = begin match d,atom with
22392267
| R,None ->
22402268
let r,init,cs,st =
22412269
LDR.emit_load_idx_var vloc vdep st p init loc r2 in
@@ -2449,8 +2477,10 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
24492477
None,init,pseudo cs0@cs,st
24502478
| W,Some (Neon _,Some _) -> assert false
24512479
| _,Some (Plain _,None) -> assert false
2452-
end
2453-
| _,Code _ -> Warn.fatal "No dependency to code location"
2480+
end in
2481+
(* Add a label to instructions `cs`, when a fault check is required. *)
2482+
regs,inits,(add_label_to_last_instructions e cs),st
2483+
| _,Code _ -> Warn.fatal "No dependency to code location"
24542484
(* END of emit_access_dep_addr *)
24552485

24562486
let emit_addr_dep csel vdep st p init loc rd =
@@ -2512,7 +2542,7 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
25122542
| _ -> Some (a,m) end in
25132543
(* collapse the value `v` in event `e` to integer *)
25142544
let value = Code.value_to_int e.C.v in
2515-
match e.C.dir,e.C.loc with
2545+
let regs,inits,cs,st = match e.C.dir,e.C.loc with
25162546
| None,_ -> Warn.fatal "TODO"
25172547
| Some R,_ -> Warn.fatal "data dependency to load"
25182548
| Some W,Data loc ->
@@ -2660,8 +2690,10 @@ module Make(Cfg:Config) : XXXCompile_gen.S =
26602690
None,init,cs2@cs,st
26612691
| Some (Pair _,Some _) -> assert false
26622692
end
2663-
| _,Code _ -> Warn.fatal "Not Yet (%s,dep_data)" (C.debug_evt e)
2664-
(* END of emit_access_dep_data *)
2693+
(* END of `Some W` *)
2694+
| _,Code _ -> Warn.fatal "Not Yet (%s,dep_data)" (C.debug_evt e) in
2695+
regs,inits,(add_label_to_last_instructions e cs),st
2696+
(* END of emit_access_dep_data *)
26652697

26662698
let is_ctrlisync = function
26672699
| D.CTRLISYNC -> true

gen/CCompile_gen.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ module Make(O:Config) : Builder.S
826826
F.run evts m
827827
| Cycle -> F.check f
828828
| Observe -> F.observe f in
829-
(add_args env c,f (F.FaultSet.empty,F.FaultSet.empty)),
829+
(add_args env c,f ([],[])),
830830
(U.compile_prefetch_ios (List.length obsc) ios,
831831
U.compile_coms splitted),
832832
env

gen/cycle.ml

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ let int_com e = match e.E.edge with
493493
| _ -> false
494494

495495

496-
497496
(* Coherence definition *)
498497

499498
module CoSt = struct
@@ -565,10 +564,34 @@ module CoSt = struct
565564

566565
let get_check_value st = st.check_value
567566

567+
let _set_check_fault st = {st with check_fault = true }
568+
568569
(* read the check_fault flag, and reset/clean it *)
569570
let read_and_unset_check_fault st =
570571
st.check_fault, {st with check_fault = false }
571572

573+
(* Check if `pte_val` might fault *)
574+
let label_fault pte_val = Some ((Label.next_label "L"), (PteVal.can_fault pte_val))
575+
576+
(* Helper function returns a fresh label and a boolean for if it should fault,
577+
if a fault check is need. Otherwise return `None` *)
578+
let fault_update st =
579+
let check_fault, st = read_and_unset_check_fault st in
580+
let pte_val = get_pte_value st in
581+
let fault =
582+
if check_fault then
583+
if do_kvm then label_fault pte_val
584+
(* While `memory tag` mode, any memory tag write to a variable
585+
invalidates the tag, hence leads to fault. However, due to
586+
potential weak memory behaviour, the final postcondition checks
587+
if memory load to the variable can still observe the default,
588+
and valid memory tag. Therefore we take a short cut here by
589+
always inject a negtive check once a tag to the variable changes.*)
590+
else if do_memtag then begin Some ((Label.next_label "L"), false) end
591+
else None
592+
else None in
593+
fault, st
594+
572595
let set_tcell st e = match e.bank with
573596
| Tag ->
574597
{e with tcell=[| e.v; |];},st
@@ -596,9 +619,6 @@ let pte_val_init loc = match loc with
596619
| Code.Data loc when do_kvm -> PteVal.default loc
597620
| _ -> pte_default
598621

599-
(* Check if `pte_val` might fault *)
600-
let label_fault pte_val = Some ((Label.next_label "L"), (PteVal.can_fault pte_val))
601-
602622
(****************************)
603623
(* Add events in edge cycle *)
604624
(****************************)
@@ -914,20 +934,19 @@ let set_same_loc st n0 =
914934
| Some W ->
915935
begin
916936
let check_value = Some (CoSt.get_check_value st) in
937+
(* No need to add fault check in read modify write
938+
situation, as the label will be assigned in read *)
939+
let fault_update_without_rmw st =
940+
if n.evt.rmw && E.is_one_rmw_instruction n.edge
941+
then None,st else CoSt.fault_update st in
917942
match n.evt.loc with
918943
| Data _ ->
919-
(* Helper function returns a fresh label and a boolean for if it should fault,
920-
if a fault check is need. Otherwise return `None` *)
921-
let fault_update st =
922-
let check_fault, st = CoSt.read_and_unset_check_fault st in
923-
let pte_val = CoSt.get_pte_value st in
924-
(if do_kvm && check_fault then label_fault pte_val else None), st in
925944
let bank = n.evt.bank in
926945
begin match bank with
927946
| Instr -> Warn.fatal "instruction annotation to data bank not possible?"
928947
| Ord ->
929948
let st = set_write_val_ord st n in
930-
let check_fault, st = fault_update st in
949+
let check_fault, st = fault_update_without_rmw st in
931950
n.evt <- { n.evt with check_fault; check_value; };
932951
(next_x_ok, st)
933952
| Pair ->
@@ -938,7 +957,7 @@ let set_same_loc st n0 =
938957
assert (Array.length cell>=2) ;
939958
let st = CoSt.next_co st Ord in (* Pre-increment *)
940959
let st = set_write_val_ord st n in
941-
let check_fault, st = fault_update st in
960+
let check_fault, st = fault_update_without_rmw st in
942961
n.evt <- { n.evt with check_fault; check_value; };
943962
(next_x_ok, st)
944963
| Tag|CapaTag|CapaSeal ->
@@ -1118,28 +1137,30 @@ let do_set_read_v init =
11181137
let check_value = Some (CoSt.get_check_value st) in
11191138
begin match bank with
11201139
| Ord | Instr->
1121-
set_read_individual_v n cell check_value
1140+
set_read_individual_v n cell check_value;
1141+
let check_fault, st = CoSt.fault_update st in
1142+
n.evt <- { n.evt with check_fault };
1143+
st
11221144
| Pair ->
1123-
set_read_pair_v n cell check_value
1145+
set_read_pair_v n cell check_value;
1146+
let check_fault, st = CoSt.fault_update st in
1147+
n.evt <- { n.evt with check_fault };
1148+
st
11241149
| VecReg a ->
11251150
let cell = Array.map Code.value_to_int cell in
11261151
let v = E.SIMD.read a cell
11271152
|> E.SIMD.reduce
11281153
|> Code.value_of_int in
1129-
n.evt <- { n.evt with v=v ; vecreg=[]; bank=Ord; check_value; }
1154+
let check_fault, st = CoSt.fault_update st in
1155+
n.evt <- { n.evt with v=v ; vecreg=[]; bank=Ord; check_value; check_fault ; };
1156+
st
11301157
| Tag|CapaTag|CapaSeal ->
1131-
n.evt <- { n.evt with v = CoSt.get_co st bank; check_value; }
1158+
n.evt <- { n.evt with v = CoSt.get_co st bank; check_value; };
1159+
st
11321160
| Pte ->
1133-
n.evt <- { n.evt with pte = CoSt.get_pte_value st; }
1134-
end ;
1135-
(* Update if this memory load might fault *)
1136-
let fault_update st =
1137-
let check_fault, st = CoSt.read_and_unset_check_fault st in
1138-
let pte_val = CoSt.get_pte_value st in
1139-
(if do_kvm && check_fault then label_fault pte_val else None), st in
1140-
let fault, st = fault_update st in
1141-
n.evt <- { n.evt with check_fault = fault };
1142-
st
1161+
n.evt <- { n.evt with pte = CoSt.get_pte_value st; };
1162+
st
1163+
end
11431164
(* Update `st`, `cell` and `pte_cell` for future read events *)
11441165
| Some W ->
11451166
let st =

gen/edge.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ module type S = sig
7272

7373
type edge = { edge: tedge; a1:atom option; a2: atom option; }
7474

75+
val is_one_rmw_instruction : edge -> bool
76+
7577
val plain_edge : tedge -> edge
7678

7779
val fold_atomo : (atom option -> 'a -> 'a) -> 'a -> 'a
@@ -458,6 +460,10 @@ let fold_tedges f r =
458460
let ok_rmw rmw a1 a2 =
459461
not (F.is_one_instruction rmw) || same_access_atoms a1 a2
460462

463+
let is_one_rmw_instruction e = match e.edge with
464+
| Rmw rmw -> F.is_one_instruction rmw
465+
| _ -> false
466+
461467
let ok_non_rmw e a1 a2 =
462468
do_is_diff e || do_disjoint ||
463469
(overlap_atoms a1 a2 &&

0 commit comments

Comments
 (0)