Skip to content

Commit f41a95a

Browse files
committed
Initial support for page annotations and appropriate ifetch semantics
1 parent a816622 commit f41a95a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+856
-278
lines changed

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,18 @@ test.vmsa+mte:
693693
$(REGRESSION_TEST_MODE)
694694
@ echo "herd7 AArch64 VMSA+MTE instructions tests: OK"
695695

696+
test:: test.vmsa+ifetch
697+
test-local:: test.vmsa+ifetch
698+
test.vmsa+ifetch:
699+
@ echo
700+
$(HERD_REGRESSION_TEST) \
701+
-herd-path $(HERD) \
702+
-libdir-path ./herd/libdir \
703+
-litmus-dir ./herd/tests/instructions/AArch64.vmsa+ifetch \
704+
-conf ./herd/tests/instructions/AArch64.vmsa+ifetch/vmsa+ifetch.cfg \
705+
$(REGRESSION_TEST_MODE)
706+
@ echo "herd7 AArch64 VMSA+ifetch instructions tests: OK"
707+
696708
test:: diy-test diymicro-test
697709
test-local:: diy-test diymicro-test
698710

diymicro/compile.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,9 @@ let rec dump_pseudo = function
260260
| A.Macro (m, args) :: rem ->
261261
Printf.sprintf "%s(%s)" m (String.concat "," (List.map A.pp_reg args))
262262
:: dump_pseudo rem
263-
| A.Align _ :: _ ->
264-
Warn.fatal "Page alignment not available in diymicro"
263+
| A.Pagealign :: _ -> Warn.fatal "Page alignment not available in diymicro"
264+
| A.Skip _ :: _ ->
265+
Warn.fatal "Page alignment placeholders not available in diymicro"
265266

266267
let fmt_cols =
267268
let rec fmt_col p k = function

gen/top_gen.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,8 @@ let rec dump_pseudo = function
947947
(String.concat ","
948948
(List.map A.pp_reg args))::
949949
dump_pseudo rem
950-
| A.Align _::_ -> assert false (* support for .p2align not implemented yet*)
950+
| A.Pagealign::_ -> assert false (* support for .pagealign not implemented yet*)
951+
| A.Skip _::_ -> assert false (* used internally in herd7 only *)
951952

952953
let fmt_cols =
953954
let rec fmt_col p k = function

herd/AArch64Sem.ml

Lines changed: 166 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,56 @@ module Make
13181318
| Some ws -> M.unitT (B.Next ((rd,v) :: ws))
13191319
end
13201320

1321+
1322+
(************)
1323+
(* Branches *)
1324+
(************)
1325+
1326+
let v2tgt =
1327+
let open Constant in
1328+
function
1329+
| M.A.V.Val (Symbolic (Virtual {name=Symbol.Label (_, lbl); _})) -> Some (B.Lbl lbl)
1330+
| M.A.V.Val (Concrete i) -> Some (B.Addr (M.A.V.Cst.Scalar.to_int i))
1331+
| _ -> None
1332+
1333+
let do_indirect_jump test bds i ii v =
1334+
match v2tgt v with
1335+
| Some tgt ->
1336+
commit_bcc ii
1337+
>>= fun () -> M.unitT (B.Jump (tgt,bds))
1338+
| None ->
1339+
match v with
1340+
| M.A.V.Var(_) as v ->
1341+
let lbls = get_exported_labels test in
1342+
if Label.Full.Set.is_empty lbls then begin
1343+
if C.variant Variant.Telechat then M.unitT () >>! B.Exit
1344+
else
1345+
Warn.fatal "Could find no potential target for indirect branch %s \
1346+
(potential targets are statically known labels)" (AArch64.dump_instruction i)
1347+
end
1348+
else
1349+
commit_bcc ii
1350+
>>= fun () -> B.indirectBranchT v lbls bds
1351+
| _ -> Warn.fatal
1352+
"illegal argument for the indirect branch instruction %s \
1353+
(must be a label)" (AArch64.dump_instruction i)
1354+
1355+
let get_link_addr test ii =
1356+
let lbl =
1357+
let a = ii.A.addr + 4 in
1358+
let lbls = test.Test_herd.entry_points a in
1359+
Label.norm lbls in
1360+
match lbl with
1361+
| Some l -> ii.A.addr2v ii.A.proc l
1362+
| None -> V.intToV (ii.A.addr + 4)
1363+
1364+
let get_instr_addr proc ii =
1365+
match Label.norm ii.A.labels with
1366+
| Some hd -> ii.A.addr2v proc hd
1367+
| None -> V.intToV ii.A.addr
1368+
1369+
let get_instr_label ii = get_instr_addr ii.A.proc ii
1370+
13211371
(***************************)
13221372
(* Various lift functions. *)
13231373
(***************************)
@@ -1331,10 +1381,6 @@ module Make
13311381
*)
13321382

13331383
(* memtag faults *)
1334-
let get_instr_label ii =
1335-
match Label.norm ii.A.labels with
1336-
| Some hd -> ii.A.addr2v hd
1337-
| None -> V.intToV ii.A.addr
13381384

13391385
let set_elr_el1 v ii =
13401386
write_reg AArch64Base.elr_el1 v ii
@@ -1409,7 +1455,7 @@ module Make
14091455
and mno mpte_t =
14101456
let ma = M.para_bind_output_right mpte_t (fun _ -> mpte_d) in
14111457
let ft = Some FaultType.AArch64.TagCheck in
1412-
let mm ma =
1458+
let mm ma =
14131459
let branch = fun m -> m >>= M.ignore >>= B.next1T in
14141460
ma |> branch in
14151461
let fault = lift_fault_memtag
@@ -1547,9 +1593,8 @@ module Make
15471593
lift_pac_virt mop ma dir an ii
15481594
else if checked then
15491595
lift_memtag_virt mop ma dir an ii branch
1550-
else(
1596+
else
15511597
mop Access.VIR ma |> branch
1552-
)
15531598

15541599
(*
15551600
Arguments:
@@ -3432,54 +3477,9 @@ Arguments:
34323477
(* Instruction fetch *)
34333478
(*********************)
34343479

3435-
let make_label_value proc lbl_str =
3436-
A.V.cstToV (Constant.mk_sym_virtual_label proc lbl_str)
3437-
34383480
let read_loc_instr a ac ii =
34393481
M.read_loc Port.No (mk_fetch Annot.N ac) a ii
34403482

3441-
(************)
3442-
(* Branches *)
3443-
(************)
3444-
3445-
let v2tgt =
3446-
let open Constant in
3447-
function
3448-
| M.A.V.Val (Symbolic (Virtual {name=Symbol.Label (_, lbl); _})) -> Some (B.Lbl lbl)
3449-
| M.A.V.Val (Concrete i) -> Some (B.Addr (M.A.V.Cst.Scalar.to_int i))
3450-
| _ -> None
3451-
3452-
let do_indirect_jump test bds i ii v =
3453-
match v2tgt v with
3454-
| Some tgt ->
3455-
commit_bcc ii
3456-
>>= fun () -> M.unitT (B.Jump (tgt,bds))
3457-
| None ->
3458-
match v with
3459-
| M.A.V.Var(_) as v ->
3460-
let lbls = get_exported_labels test in
3461-
if Label.Full.Set.is_empty lbls then begin
3462-
if C.variant Variant.Telechat then M.unitT () >>! B.Exit
3463-
else
3464-
Warn.fatal "Could find no potential target for indirect branch %s \
3465-
(potential targets are statically known labels)" (AArch64.dump_instruction i)
3466-
end
3467-
else
3468-
commit_bcc ii
3469-
>>= fun () -> B.indirectBranchT v lbls bds
3470-
| _ -> Warn.fatal
3471-
"illegal argument for the indirect branch instruction %s \
3472-
(must be a label)" (AArch64.dump_instruction i)
3473-
3474-
let get_link_addr test ii =
3475-
let lbl =
3476-
let a = ii.A.addr + 4 in
3477-
let lbls = test.Test_herd.entry_points a in
3478-
Label.norm lbls in
3479-
match lbl with
3480-
| Some l -> ii.A.addr2v l
3481-
| None -> V.intToV (ii.A.addr + 4)
3482-
34833483
(*******************************)
34843484
(* Pointer Authentication Code *)
34853485
(*******************************)
@@ -4379,10 +4379,10 @@ Arguments:
43794379
begin
43804380
match lbl with
43814381
| Some lbl ->
4382-
let v = ii.A.addr2v lbl in
4382+
let v = ii.A.addr2v ii.A.proc lbl in
43834383
write_reg_dest r v ii >>= nextSet r
43844384
| None ->
4385-
(* Delay error, only a poor fix.
4385+
(* Delay error, only a poor fix.
43864386
A complete possible fix would be
43874387
having code addresses as values *)
43884388
M.failT
@@ -4649,20 +4649,81 @@ Arguments:
46494649
| _ -> k)
46504650
test.Test_herd.init_state []
46514651

4652+
let get_instr_ptevals test =
4653+
let open Constant in
4654+
let open AArch64PteVal in
4655+
AArch64.state_fold
4656+
(fun _ v k ->
4657+
match v with
4658+
| V.Val (PteVal pte_v) -> begin
4659+
let lbl_opt =
4660+
pte_v.oa
4661+
|> OutputAddress.as_physical
4662+
|> fun o -> Option.bind o Misc.str_as_label in
4663+
match lbl_opt with
4664+
| Some lbl -> lbl::k
4665+
| None -> k
4666+
end
4667+
| _ -> k)
4668+
test.Test_herd.init_state []
4669+
46524670
let lift_fetch rA (* Base address register *)
46534671
dir updatedb
46544672
mop
46554673
perms ma mv an ii =
46564674
do_lift_memop rA dir updatedb false mop perms ma mv an ii Fun.id
46574675

4658-
46594676
(* Test all possible instructions, when appropriate *)
4660-
let mk_fetch_mphy test ii =
4677+
let mk_mop_fetch exposed_page exposed_label test ii =
46614678
let module InstrSet = AArch64.V.Cst.Instr.Set in
4679+
let relevant_pagelbls = get_instr_ptevals test in
4680+
4681+
let default_cands =
4682+
InstrSet.empty
4683+
|> InstrSet.add ii.A.inst
4684+
in
4685+
let exposed_page_cands =
4686+
(* When an address can get remapped, consider the possibility of
4687+
* fetching instructions from other relevant pages *)
4688+
if exposed_page then
4689+
let offset = (ii.A.addr mod Pseudo.proc_size) mod Pseudo.page_size in
4690+
relevant_pagelbls
4691+
|> List.map (fun (_,lbl) ->
4692+
let base = Label.Map.find lbl test.Test_herd.program in
4693+
let cand_a = base + offset in
4694+
let cand_i = match IntMap.find cand_a test.Test_herd.code_segment with
4695+
| (_,(_,i)::_) -> i
4696+
| _ -> Warn.user_error "Instruction not found by the address %d" cand_a (* this case means that we have found a relevant page, but it does not have an instruction -- it may make sense to use NOP here rather than throw an error *)
4697+
in
4698+
cand_i)
4699+
|> InstrSet.of_list
4700+
else InstrSet.empty
4701+
in
4702+
let potentially_exposed_label =
4703+
(* When an address can get remapped, check if the possible remapped
4704+
* addresses needs the ifetch logic *)
4705+
let no_remap_case = exposed_label ii.A.addr in
4706+
if exposed_page then
4707+
let offset = (ii.A.addr mod Pseudo.proc_size) mod Pseudo.page_size in
4708+
relevant_pagelbls
4709+
|> List.map (fun (_,lbl) ->
4710+
let base = Label.Map.find lbl test.Test_herd.program in
4711+
let cand_a = base + offset in
4712+
exposed_label cand_a)
4713+
|> List.fold_left (fun acc a -> acc || a) no_remap_case
4714+
else no_remap_case
4715+
in
4716+
let exposed_label_cands =
4717+
(if potentially_exposed_label then
4718+
get_overwriting_instrs test
4719+
|> InstrSet.of_list (* optimization to consider only possible instruction overwrites *)
4720+
|> InstrSet.filter AArch64.can_overwrite (* for testing purposes *)
4721+
else InstrSet.empty)
4722+
in
46624723
let cands =
4663-
InstrSet.of_list (get_overwriting_instrs test) (* optimization to consider only possible instruction overwrites *)
4664-
|> InstrSet.filter AArch64.can_overwrite (* for testing purposes *)
4665-
|> InstrSet.add ii.A.inst (* instruction to fetch by default *)
4724+
default_cands
4725+
|> InstrSet.union exposed_page_cands
4726+
|> InstrSet.union exposed_label_cands
46664727
in
46674728
(* Shadow default control sequencing operator *)
46684729
let(>>*=) = M.bind_control_set_data_input_first in
@@ -4688,37 +4749,63 @@ Arguments:
46884749
>>*= fun () -> m_fault >>| set_elr_el1 lbl_v ii
46894750
>>! B.Fault (false,[AArch64Base.elr_el1, lbl_v])
46904751
end in
4691-
fun ac ma _ -> ( (* value fake here *)
4692-
if Access.is_physical ac then begin
4693-
assert (kvm && self);
4752+
fun ac ma _ -> (
4753+
if Access.is_physical ac then
46944754
M.bind_ctrldata ma (mop ac)
4695-
end else begin
4696-
assert (not kvm && self);
4755+
else
46974756
ma >>= mop ac
4698-
end
46994757
)
47004758

47014759
(* Test all possible instructions, when appropriate *)
47024760
let check_self test ii =
47034761
let module InstrSet = AArch64.V.Cst.Instr.Set in
4704-
let lbls = get_exported_labels test in
4705-
let is_exported =
4762+
let exp_pages = get_exposed_codepages test in
4763+
let is_on_exported_page =
4764+
match ii.A.rel_addr with
4765+
| Some (A.V.Val c) -> begin
4766+
let this_lbl = c in
4767+
List.exists
4768+
(fun ttd_lbl ->
4769+
let this_triple = Constant.unmk_sym_virtual_label_with_offset this_lbl in
4770+
let ttd_triple = Constant.unmk_sym_virtual_label_with_offset ttd_lbl in
4771+
match (this_triple,ttd_triple) with
4772+
| (p1,s1,_),(p2,s2,_) ->
4773+
(Misc.int_eq p1 p2) && (Misc.string_eq s1 s2)
4774+
) exp_pages
4775+
end
4776+
| _ -> false
4777+
in
4778+
4779+
let lbl_exposed addr =
4780+
let labels = test.Test_herd.entry_points addr in
47064781
Label.Set.exists
47074782
(fun lbl ->
47084783
Label.Full.Set.exists
47094784
(fun (_,lbl0) -> Misc.string_eq lbl lbl0)
4710-
lbls)
4711-
ii.A.labels in
4712-
if is_exported then
4713-
match Label.norm ii.A.labels with
4714-
| None -> assert false
4715-
| Some hd ->
4716-
let mop_fetch = mk_fetch_mphy test ii in
4717-
let a_v = make_label_value ii.A.fetch_proc hd in
4718-
lift_fetch AArch64.ZR Dir.R true
4719-
mop_fetch
4720-
(to_perms "r" MachSize.Word)
4721-
(M.unitT a_v) mzero Annot.N ii
4785+
(get_exported_labels test))
4786+
labels in
4787+
4788+
let needs_vmsa_for_ifetch =
4789+
kvm && self && is_on_exported_page in
4790+
let needs_ifetch = (lbl_exposed ii.A.addr) && self in
4791+
if needs_ifetch || needs_vmsa_for_ifetch then
4792+
try (
4793+
let mop_fetch = mk_mop_fetch is_on_exported_page lbl_exposed test ii in
4794+
let a_v =
4795+
if needs_vmsa_for_ifetch then begin
4796+
Option.get ii.A.rel_addr
4797+
end else get_instr_addr ii.A.fetch_proc ii
4798+
in
4799+
lift_fetch AArch64.ZR Dir.R true
4800+
mop_fetch
4801+
(to_perms "r" MachSize.Word)
4802+
(M.unitT a_v) mzero Annot.N ii
4803+
) with
4804+
| Not_found -> begin
4805+
Warn.warn_always "Not_found error\n";
4806+
do_build_semantics test ii.A.inst ii
4807+
end
4808+
| Invalid_argument _ -> Warn.user_error "Invalid argument error\n"
47224809
else
47234810
do_build_semantics test ii.A.inst ii
47244811

herd/RISCVSem.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ module
274274
fun v -> M.op (tr_opi op) v (V.intToV k) >>=
275275
fun v -> write_reg r1 v ii >>= B.next1T
276276
| RISCV.OpA (RISCV.LA,r1,lbl) ->
277-
let v = ii.A.addr2v lbl in
277+
let v = ii.A.addr2v ii.A.proc lbl in
278278
write_reg r1 v ii >>= B.next1T
279279
| RISCV.OpIW (op,r1,r2,k) ->
280280
read_reg_ord r2 ii >>=

0 commit comments

Comments
 (0)