You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| 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
-
3483
3483
(*******************************)
3484
3484
(* Pointer Authentication Code *)
3485
3485
(*******************************)
@@ -4379,10 +4379,10 @@ Arguments:
4379
4379
begin
4380
4380
match lbl with
4381
4381
| Some lbl ->
4382
-
let v = ii.A.addr2v lbl in
4382
+
let v = ii.A.addr2v ii.A.proc lbl in
4383
4383
write_reg_dest r v ii >>= nextSet r
4384
4384
| None ->
4385
-
(* Delay error, only a poor fix.
4385
+
(* Delay error, only a poor fix.
4386
4386
A complete possible fix would be
4387
4387
having code addresses as values *)
4388
4388
M.failT
@@ -4649,20 +4649,81 @@ Arguments:
4649
4649
| _ -> k)
4650
4650
test.Test_herd.init_state []
4651
4651
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
+
4652
4670
let lift_fetch rA (* Base address register *)
4653
4671
dir updatedb
4654
4672
mop
4655
4673
perms ma mv an ii =
4656
4674
do_lift_memop rA dir updatedb false mop perms ma mv an ii Fun.id
4657
4675
4658
-
4659
4676
(* Test all possible instructions, when appropriate *)
4660
-
let mk_fetch_mphy test ii =
4677
+
let mk_mop_fetch exposed_page exposed_label test ii =
4661
4678
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
4662
4723
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
4666
4727
in
4667
4728
(* Shadow default control sequencing operator *)
4668
4729
let(>>*=) = M.bind_control_set_data_input_first in
@@ -4688,37 +4749,63 @@ Arguments:
4688
4749
>>*= fun () -> m_fault >>| set_elr_el1 lbl_v ii
4689
4750
>>! B.Fault (false,[AArch64Base.elr_el1, lbl_v])
4690
4751
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
4694
4754
M.bind_ctrldata ma (mop ac)
4695
-
end else begin
4696
-
assert (not kvm && self);
4755
+
else
4697
4756
ma >>= mop ac
4698
-
end
4699
4757
)
4700
4758
4701
4759
(* Test all possible instructions, when appropriate *)
4702
4760
let check_self test ii =
4703
4761
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
4706
4781
Label.Set.exists
4707
4782
(fun lbl ->
4708
4783
Label.Full.Set.exists
4709
4784
(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
0 commit comments