Skip to content

Commit 30886e7

Browse files
committed
[herd] Global count of necessary spurious updates
When TTHM=HA or TTHM=HD are active, HW update of the AF flag is performed. This include the so-called "spurious" updates that are performed independently of test code. For efficiency reason we limit the number of such spurious updates to what is necessary. We do so by a global scan of the execution candidates counting the writes that may unset the AF flag in the final set of effects. Notice that we also consider the initial writes in this scan. We perform one optimisation: by exception, when a write effect value is the same as the value read by the same instruction from the same location, there is no need to add a supplementary spurious update as the (potential) update associated to the write that stored the value has already been counted and is sufficient.
1 parent 6911b0d commit 30886e7

29 files changed

+213
-155
lines changed

herd/AArch64ASLSem.ml

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
8787

8888
module Mixed (SZ : ByteSize.S) : sig
8989
val build_semantics : test -> A.inst_instance_id -> (proc * branch) M.t
90+
val can_unset_af_loc : event -> V.v option
9091
val spurious_setaf : V.v -> unit M.t
9192
end = struct
9293
module AArch64Mixed = AArch64S.Mixed (SZ)
@@ -1392,36 +1393,7 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
13921393

13931394
let tr_cnstrnts cs = List.fold_left tr_cnstrnt [] cs
13941395

1395-
1396-
let dirty =
1397-
match TopConf.dirty with
1398-
| None -> DirtyBit.soft
1399-
| Some d -> d
1400-
1401-
let check_spurious ii =
1402-
(*
1403-
* Explicit loads or stores yield a potential spurious update of
1404-
* the AF flag. When the hardware feature is active, of course.
1405-
*)
1406-
if dirty.DirtyBit.ha ii.A.proc then
1407-
let dir_ok =
1408-
let open Dir in
1409-
if TopConf.C.variant Variant.PhantomOnLoad then
1410-
(function R -> true | W -> false)
1411-
else
1412-
(function W -> true | R -> false) in
1413-
fun act ->
1414-
match act with
1415-
| Act.Access
1416-
(dir,A.Location_global loc,_,_,
1417-
AArch64Explicit.Exp,_,Access.(PHY_PTE|PTE DISide.Data))
1418-
when dir_ok dir
1419-
->
1420-
Some loc
1421-
| _ -> None
1422-
else fun _ -> None
1423-
1424-
let event_to_monad ii check_spurious is_bcc get_port event =
1396+
let event_to_monad ii is_bcc get_port event =
14251397
let { ASLE.action; ASLE.iiid; _ } = event in
14261398
let () =
14271399
if _dbg then
@@ -1446,8 +1418,7 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
14461418
|> M.as_port (get_port event)
14471419
|> M.force_once
14481420
in
1449-
let check_af = check_spurious action' in
1450-
Some (event, (check_af,m))
1421+
Some (event,m)
14511422

14521423
let rel_to_monad event_to_monad_map comb rel =
14531424
let one_pair (e1, e2) =
@@ -1497,17 +1468,10 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
14971468
fun e -> ASLE.EventSet.mem e bcc in
14981469
let () = if _dbg then Printf.eprintf "\t- events: " in
14991470
let event_list = List.of_seq events in
1500-
let check_spurious = check_spurious ii in
1501-
let spurious_locs,event_to_monad_map =
1471+
let event_to_monad_map =
15021472
let seq =
1503-
Seq.filter_map (event_to_monad ii check_spurious is_bcc get_port) events in
1504-
let locs =
1505-
Seq.filter_map (fun (_,(loc,_)) -> loc) seq
1506-
|> List.of_seq
1507-
and map =
1508-
Seq.map (fun (e,(_,m)) -> (e,m)) seq
1509-
|> EMap.of_seq in
1510-
locs,map
1473+
Seq.filter_map (event_to_monad ii is_bcc get_port) events in
1474+
EMap.of_seq seq
15111475
in
15121476
let events_m =
15131477
let folder _e1 m1 acc = m1 ||| acc in
@@ -1604,18 +1568,8 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
16041568
M.restrict (tr_cnstrnts cs)
16051569
in
16061570
let () = if _dbg then Printf.eprintf "\n" in
1607-
let m_spurious =
1608-
(*
1609-
* At most one spurious setaf operation per relevant location
1610-
* is probably sufficient. Anyway, it is unlikely that a given
1611-
* value appears more than once in the spurious_locs list.
1612-
*)
1613-
List.fold_left
1614-
(fun m loc ->
1615-
M.altT (AArch64Mixed.spurious_setaf loc) (M.unitT ()) ||| m)
1616-
(M.unitT ()) @@ List.sort_uniq A.V.compare spurious_locs in
16171571
let* () =
1618-
m_spurious ||| events_m ||| iico_data ||| iico_ctrl
1572+
events_m ||| iico_data ||| iico_ctrl
16191573
||| iico_order ||| constraints ||| M.restrict eqs_test
16201574
in
16211575
M.addT (A.next_po_index ii.A.program_order_index) (return branch)
@@ -1777,6 +1731,7 @@ module Make (TopConf : AArch64Sig.Config) (V : Value.AArch64ASL) :
17771731
AArch64Mixed.build_semantics test ii
17781732
| _ -> asl_build_semantics test ii
17791733

1734+
let can_unset_af_loc e = AArch64Mixed.can_unset_af_loc e
17801735
let spurious_setaf v = AArch64Mixed.spurious_setaf v
17811736
end
17821737
end

herd/AArch64Sem.ml

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ module Make
105105
(* Semantics proper *)
106106
module Mixed(SZ:ByteSize.S) : sig
107107
val build_semantics : test -> A.inst_instance_id -> (proc * branch) M.t
108+
val can_unset_af_loc : event -> V.v option
108109
val spurious_setaf : V.v -> unit M.t
109110
end = struct
110111

@@ -1120,14 +1121,15 @@ module Make
11201121
check_cond cond)
11211122
end in
11221123
if pte2 then mvirt
1123-
else
1124-
M.op1 Op.IsVirtual a_virt >>= fun cond ->
1125-
M.choiceT cond mvirt
1124+
else begin
1125+
let mdirect =
11261126
(* Non-virtual accesses are disallowed from EL0.
11271127
For instance, user code cannot access the page table. *)
1128-
(if is_el0 then mk_pte_fault a_virt ma dir an ii domain
1129-
else mdirect)
1130-
1128+
if is_el0 then mk_pte_fault a_virt ma dir an ii domain
1129+
else mdirect in
1130+
M.op1 Op.IsVirtual a_virt >>= fun cond ->
1131+
M.choiceT cond mvirt mdirect
1132+
end
11311133
(* Read memory, return value read *)
11321134
let do_read_mem_ret sz an anexp ac a ii =
11331135
let m a =
@@ -1444,25 +1446,22 @@ module Make
14441446

14451447
(* KVM mode *)
14461448

1447-
let some_ha = dirty.DirtyBit.some_ha || dirty.DirtyBit.some_hd
1449+
let can_be_pt v =
1450+
match V.as_constant v with
1451+
| None -> true
1452+
| Some c -> Constant.is_pt c
14481453

1449-
let fire_spurious_af dir a m domain =
1450-
if
1451-
some_ha &&
1452-
(let v = C.variant Variant.PhantomOnLoad in
1453-
match dir with Dir.W -> not v | Dir.R -> v)
1454-
then
1455-
(m >>|
1456-
M.altT (test_and_set_af_succeeds a E.IdSpurious domain) (M.unitT ())) >>=
1457-
fun (r,_) -> M.unitT r
1458-
else m
1454+
let can_af0 v =
1455+
(match V.as_constant v with
1456+
| Some (Constant.PteVal p) ->
1457+
p.AArch64PteVal.valid <> 0 && p.AArch64PteVal.af = 0
1458+
| _ -> true)
14591459

1460-
let lift_kvm dir updatedb mop ma an ii mphy branch domain =
1460+
let lift_kvm _tag dir updatedb mop ma an ii mphy branch domain =
14611461
let mfault ma a ft = emit_fault a ma dir an ft None ii in
14621462
let maccess a ma =
14631463
check_ptw ii.AArch64.proc dir updatedb false a ma an ii
1464-
((let m = mop (Access.PTE domain) ma in
1465-
fire_spurious_af dir a m domain) |> branch)
1464+
(mop (Access.PTE domain) ma |> branch)
14661465
mphy
14671466
mfault
14681467
domain in
@@ -1515,8 +1514,7 @@ module Make
15151514
(* tag checks only apply to data *)
15161515
let domain = DISide.Data in
15171516
let mdirect =
1518-
let m = mop (Access.PTE domain) ma in
1519-
fire_spurious_af dir a m domain >>= M.ignore >>= B.next1T in
1517+
mop (Access.PTE domain) ma >>= M.ignore >>= B.next1T in
15201518
check_ptw ii.AArch64.proc Dir.R false true a ma an ii
15211519
mdirect
15221520
cond_check_tag
@@ -1617,7 +1615,7 @@ Arguments:
16171615
when translating for instruction fetches.
16181616
- domain: Whether the translation is for data or instruction access.
16191617
*)
1620-
let do_lift_memop rA (* Base address register *)
1618+
let do_lift_memop ?tag rA (* Base address register *)
16211619
dir updatedb checked mop perms ma mv an ii branch domain =
16221620
if morello then
16231621
lift_morello mop perms ma mv dir an ii branch
@@ -1630,15 +1628,15 @@ Arguments:
16301628
M.op1 Op.IsVirtual a_virt >>= fun c ->
16311629
M.choiceT c
16321630
(mop Access.PHY ma)
1633-
(fire_spurious_af dir a_virt (mop Access.PHY_PTE ma) domain) |> branch
1631+
(mop Access.PHY_PTE ma)
1632+
|> branch
16341633
else
1635-
mop Access.PHY ma
1636-
|> branch in
1634+
mop Access.PHY ma |> branch in
16371635
let mphy =
16381636
if checked then lift_memtag_phy dir mop ma an ii mphy
16391637
else mphy
16401638
in
1641-
let m = lift_kvm dir updatedb mop ma an ii mphy branch domain in
1639+
let m = lift_kvm tag dir updatedb mop ma an ii mphy branch domain in
16421640
(* M.short will add an iico_data only if memtag is enabled *)
16431641
M.short (is_this_reg rA) (E.is_pred_txt (Some "color")) m
16441642
else if pac then
@@ -1648,10 +1646,10 @@ Arguments:
16481646
else
16491647
mop Access.VIR ma |> branch
16501648

1651-
let lift_memop rA (* Base address register *)
1649+
let lift_memop ?(tag = "") rA (* Base address register *)
16521650
dir updatedb checked mop perms ma mv an ii =
16531651
let domain = DISide.Data in
1654-
do_lift_memop rA dir updatedb checked mop perms ma mv an ii
1652+
do_lift_memop ~tag rA dir updatedb checked mop perms ma mv an ii
16551653
(fun a -> a >>= M.ignore >>= B.next1T) domain
16561654

16571655
(* Address translation instruction *)
@@ -1679,8 +1677,7 @@ Arguments:
16791677
let domain = DISide.Data in
16801678
let maccess a ma =
16811679
check_ptw ii.AArch64.proc dir false false a ma Annot.N ii
1682-
((let m = mop (Access.PTE domain) ma in
1683-
fire_spurious_af dir a m domain) >>= M.ignore >>= B.next1T)
1680+
(mop (Access.PTE domain) ma >>= M.ignore >>= B.next1T)
16841681
mphy
16851682
mfault
16861683
domain in
@@ -1694,7 +1691,7 @@ Arguments:
16941691
if memtag && C.mte_store_only then
16951692
ma >>= fun a -> loc_extract a
16961693
else ma in
1697-
lift_memop rA Dir.R false checked
1694+
lift_memop ~tag:"LD" rA Dir.R false checked
16981695
(fun ac ma _mv -> (* value fake here *)
16991696
let open Precision in
17001697
let memtag_sync =
@@ -1709,7 +1706,7 @@ Arguments:
17091706

17101707
(* Generic store *)
17111708
let do_str rA mop sz an ma mv ii =
1712-
lift_memop rA Dir.W true memtag
1709+
lift_memop ~tag:"ST" rA Dir.W true memtag
17131710
(fun ac ma mv ->
17141711
let open Precision in
17151712
let memtag_sync = memtag && C.mte_precision = Synchronous in
@@ -1994,12 +1991,12 @@ Arguments:
19941991

19951992
let str_simple sz rs rd m_ea ii =
19961993
do_str rd
1997-
(fun ac a _ ii ->
1998-
M.data_input_next
1999-
(read_reg_data_sz sz rs ii)
2000-
(fun v -> do_write_mem sz Annot.N aexp ac a v ii))
1994+
(fun ac a v ii ->
1995+
M.data_input_next
1996+
(M.unitT v)
1997+
(fun v -> do_write_mem sz Annot.N aexp ac a v ii))
20011998
sz Annot.N
2002-
m_ea (M.unitT V.zero) ii
1999+
m_ea (read_reg_data_sz sz rs ii) ii
20032000

20042001
let str sz rs rd e ii =
20052002
let open AArch64Base in
@@ -2013,14 +2010,14 @@ Arguments:
20132010
(read_reg_addr rd ii)
20142011
(fun a_virt ma ->
20152012
do_str rd
2016-
(fun ac a _ ii ->
2013+
(fun ac a v ii ->
20172014
M.add a_virt (V.intToV k) >>= fun b -> write_reg rd b ii
20182015
>>|
20192016
M.data_input_next
2020-
(read_reg_data_sz sz rs ii)
2017+
(M.unitT v)
20212018
(fun v -> do_write_mem sz Annot.N aexp ac a v ii))
20222019
sz Annot.N
2023-
ma (M.unitT V.zero) ii) in
2020+
ma (read_reg_data_sz sz rs ii) ii) in
20242021
if kvm then M.upOneRW (is_this_reg rd) m
20252022
else m
20262023
| Imm (k,PreIdx) ->
@@ -2117,9 +2114,9 @@ Arguments:
21172114
(write_reg ResAddr V.zero ii)
21182115
(fun v -> write_reg rr v ii)
21192116
(mw an ac))
2120-
(to_perms "w" sz)
2121-
(read_reg_addr rd ii)
2122-
ms an ii
2117+
(to_perms "w" sz)
2118+
(read_reg_addr rd ii)
2119+
ms an ii
21232120

21242121
let stxr sz t rr rs rd ii =
21252122
do_stxr
@@ -2193,7 +2190,7 @@ Arguments:
21932190
(* Dir.W would force check for dbm bit: *)
21942191
(* - if set then either update or not db bit per R_TXGHB *)
21952192
(* - if unset raise Permission fault *)
2196-
lift_memop rn Dir.W updatedb checked mop (to_perms "rw" sz) ma mv an ii
2193+
lift_memop ~tag:"FAIL" rn Dir.W updatedb checked mop (to_perms "rw" sz) ma mv an ii
21972194
in
21982195
if do_wb then
21992196
do_action true checked ma
@@ -2234,7 +2231,7 @@ Arguments:
22342231
M.altT (
22352232
(* CAS succeeds and generates an Explicit Write Effect *)
22362233
(* there must be an update to the dirty bit of the TTD *)
2237-
lift_memop rn Dir.W true memtag mop_success (to_perms "rw" sz) ma mv an ii
2234+
lift_memop ~tag:"CAS" rn Dir.W true memtag mop_success (to_perms "rw" sz) ma mv an ii
22382235
)( (* CAS fails *)
22392236
M.altT (
22402237
(* CAS generates an Explicit Write Effect *)
@@ -4881,6 +4878,19 @@ Arguments:
48814878
else do_build_semantics test ii.A.inst ii
48824879
end
48834880

4881+
let can_unset_af_loc e =
4882+
match E.access_of e with
4883+
| Some Access.(PTE _|PHY_PTE)
4884+
->
4885+
begin
4886+
match E.location_of e,E.written_of e with
4887+
| Some (A.Location_global loc),Some v ->
4888+
if E.is_explicit e && can_be_pt loc && can_af0 v then Some loc
4889+
else None
4890+
| _ -> None
4891+
end
4892+
| _ -> None
4893+
48844894
let spurious_setaf v =
48854895
test_and_set_af_succeeds v E.IdSpurious DISide.Data
48864896

herd/ARMSem.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ module
514514

515515
end
516516

517-
let spurious_setaf _ = assert false
517+
include NoAF
518518

519519
end
520520

herd/ASLAction.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ module Make (C: Config) (A : S) = struct
112112
(**************************************)
113113
(* Access to sub_components of events *)
114114
(**************************************)
115+
let access_of = function
116+
| Access (_,_,_,_,(_,_,a)) -> Some a
117+
| Fault _|Barrier _|Branching _|CutOff _|NoAction
118+
-> None
115119

116120
let value_of =
117121
function

herd/ASLSem.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ module Make (Conf : Config) = struct
152152
let atomic_pair_allowed _ _ = true
153153
module Mixed (SZ : ByteSize.S) : sig
154154
val build_semantics : test -> A.inst_instance_id -> (proc * branch) M.t
155+
val can_unset_af_loc : event -> A.V.v option
155156
val spurious_setaf : A.V.v -> unit M.t
156157
end = struct
157158
module Mixed = M.Mixed (SZ)
@@ -931,6 +932,7 @@ module Make (Conf : Config) = struct
931932
assert (V.equal i V.zero);
932933
M.addT !(snd ii_env) B.nextT
933934

934-
let spurious_setaf _ = assert false
935+
include NoAF
936+
935937
end
936938
end

herd/BPFSem.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ struct
246246
>>= fun v -> commit ii >>= fun () -> B.bccT v lbl)
247247
;;
248248

249-
let spurious_setaf _ = assert false
249+
include NoAF
250+
250251
end
251252
end

herd/BellAction.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ end = struct
8181
| CutOff msg -> "CutOff:" ^ msg
8282

8383
(* Utility functions to pick out components *)
84+
85+
let access_of _ = None
86+
8487
let value_of a = match a with
8588
| Access (_,_ ,v,_,_,_) -> Some v
8689
| _ -> None

0 commit comments

Comments
 (0)