@@ -712,6 +712,12 @@ Definition prefix_to_va {n : N} (is_upper : bool) (p : bv n) : bv 64 :=
712712 let varange_bit := if is_upper then (bv_1 16) else (bv_0 16) in
713713 bv_concat 64 varange_bit (bv_concat 48 p (bv_0 (48 - n))).
714714
715+ Definition is_upper_va (va : bv 64) : option bool :=
716+ let top_bits := bv_extract 48 16 va in
717+ if top_bits =? (-1)%bv then Some true
718+ else if top_bits =? 0%bv then Some false
719+ else None.
720+
715721Definition level_prefix {n : N} (va : bv n) (lvl : Level) : prefix lvl :=
716722 bv_extract (12 + 9 * (3 - lvl)) (9 * (lvl + 1)) va.
717723
@@ -768,10 +774,12 @@ Module TLB.
768774 Module NDCtxt.
769775 Record t (lvl : Level) :=
770776 make {
777+ is_upper : bool;
771778 va : prefix lvl;
772779 asid : option (bv 16);
773780 }.
774781 Arguments make {_} _ _.
782+ Arguments is_upper {_}.
775783 Arguments va {_}.
776784 Arguments asid {_}.
777785
@@ -783,8 +791,8 @@ Module TLB.
783791
784792 #[global] Instance count lvl : Countable (t lvl).
785793 Proof .
786- eapply (inj_countable' (fun ndc => (va ndc, asid ndc))
787- (fun x => make x.1 x.2)).
794+ eapply (inj_countable' (fun ndc => (is_upper ndc, va ndc, asid ndc))
795+ (fun x => make x.1.1 x.1.2 x.2)).
788796 abstract sauto.
789797 Defined .
790798 End NDCtxt.
@@ -795,20 +803,17 @@ Module TLB.
795803 Definition nd (ctxt : t) : NDCtxt.t (lvl ctxt) := projT2 ctxt.
796804 Definition va (ctxt : t) : prefix (lvl ctxt) := NDCtxt.va (nd ctxt).
797805 Definition asid (ctxt : t) : option (bv 16) := NDCtxt.asid (nd ctxt).
806+ Definition is_upper (ctxt : t) : bool := NDCtxt.is_upper (nd ctxt).
798807 End Ctxt.
799808 #[export] Typeclasses Transparent Ctxt.t.
800809
801810 Module Entry.
802- Record t ( lvl : Level) :=
811+ Record t { lvl : Level} :=
803812 make {
804- is_upper : bool;
805813 val_ttbr : val;
806814 ptes : vec val (S lvl);
807815 }.
808- Arguments make {_} _ _ _.
809- Arguments is_upper {_}.
810- Arguments val_ttbr {_}.
811- Arguments ptes {_}.
816+ Arguments t : clear implicits.
812817
813818 #[global] Instance eq_dec lvl : EqDecision (t lvl).
814819 Proof . solve_decision. Defined .
@@ -818,18 +823,18 @@ Module TLB.
818823
819824 #[global] Instance count lvl : Countable (t lvl).
820825 Proof .
821- eapply (inj_countable' (fun ent => (is_upper ent, val_ttbr ent, ptes ent))
822- (fun x => make x.1.1 x.1.2 x.2)).
826+ eapply (inj_countable' (fun ent => (val_ttbr ent, ptes ent))
827+ (fun x => make lvl x.1 x.2)).
823828 abstract sauto.
824829 Defined .
825830
826831 Definition pte {lvl} (tlbe : t lvl) := Vector.last tlbe.(ptes).
827832
828833 Program Definition append {lvl clvl : Level}
829- (tlbe : t lvl)
834+ (tlbe : @ t lvl)
830835 (pte : val)
831- (CHILD : lvl + 1 = clvl) : t clvl :=
832- make tlbe.(is_upper) tlbe.(val_ttbr) (ctrans _ (tlbe.(ptes) +++ [#pte])).
836+ (CHILD : lvl + 1 = clvl) : @ t clvl :=
837+ make _ tlbe.(val_ttbr) (ctrans _ (tlbe.(ptes) +++ [#pte])).
833838 Solve All Obligations with lia.
834839 End Entry.
835840 Export (hints) Entry.
@@ -971,10 +976,10 @@ Module TLB.
971976 if (Memory.read_at loc init mem time) is Some (memval, _) then
972977 if decide (is_table memval) then
973978 let asid := bv_extract 48 16 val_ttbr in
974- let ndctxt := NDCtxt.make va (Some asid) in
979+ let ndctxt := NDCtxt.make is_upper va (Some asid) in
975980 let ctxt := existT root_lvl ndctxt in
976981 let entry : Entry.t (Ctxt.lvl ctxt) :=
977- Entry.make is_upper val_ttbr ([#memval] : vec val (S root_lvl)) in
982+ Entry.make _ val_ttbr ([#memval] : vec val (S root_lvl)) in
978983 (* add the entry to vatlb only when it is not in the original vatlb *)
979984 if decide (entry ∉ (VATLB.get ctxt vatlb)) then
980985 Ok (VATLB.insert ctxt entry vatlb, true)
@@ -998,11 +1003,6 @@ Module TLB.
9981003 (te : Entry.t (Ctxt.lvl ctxt))
9991004 (index : bv 9)
10001005 (ttbr : reg) : result string (VATLB.t * bool) :=
1001- (* guard_or "ASID is not active"
1002- $ is_active_asid ts (Ctxt.asid ctxt) ttbr time;; *)
1003- guard_or "The translation entry is not in the TLB"
1004- (te ∈ VATLB.get ctxt vatlb);;
1005-
10061006 if decide (¬is_table (Entry.pte te)) then Ok (vatlb, false)
10071007 else
10081008 let entry_addr := next_entry_addr (Entry.pte te) index in
@@ -1015,7 +1015,7 @@ Module TLB.
10151015 let va := next_va ctxt index (child_lvl_add_one _ _ e) in
10161016 let asid := if bool_decide (is_global clvl next_pte) then None
10171017 else Ctxt.asid ctxt in
1018- let ndctxt := NDCtxt.make va asid in
1018+ let ndctxt := NDCtxt.make (Ctxt.is_upper ctxt) va asid in
10191019 let ctxt := existT clvl ndctxt in
10201020 let entry := Entry.append te next_pte (child_lvl_add_one _ _ e) in
10211021 (* add the entry to vatlb only when it is not in the original vatlb *)
@@ -1047,11 +1047,12 @@ Module TLB.
10471047 let index := level_index va lvl in
10481048 sregs ← othrow "TTBR should exist in initial state"
10491049 $ TState.read_sreg_at ts ttbr time;
1050+ is_upper ← othrow "The register is not TTBR" (is_upper_ttbr ttbr);
10501051 foldlM (λ prev sreg,
10511052 val_ttbr ← othrow "TTBR should be a 64 bit value"
10521053 $ regval_to_val ttbr sreg.1;
10531054 let asid := bv_extract 48 16 val_ttbr in
1054- let ndctxt := NDCtxt.make pva (Some asid) in
1055+ let ndctxt := NDCtxt.make is_upper pva (Some asid) in
10551056 let ctxt := existT plvl ndctxt in
10561057 (* parent entries should be from the original TLB (in the parent level) *)
10571058 let tes := elements (VATLB.get ctxt tlb.(vatlb)) in
@@ -1194,7 +1195,6 @@ Module TLB.
11941195 | (ev, t) :: tl =>
11951196 match ev with
11961197 | Ev.Tlbi tlbi =>
1197- let va := prefix_to_va (Entry.is_upper te) (Ctxt.va ctxt) in
11981198 if decide (is_te_invalidated_by_tlbi tlbi tid ctxt te) then
11991199 mret (Some t)
12001200 else
@@ -1239,8 +1239,10 @@ Module TLB.
12391239 (lvl : Level)
12401240 (va : bv 64) (asid : bv 16) :
12411241 result string (list (val * list val * (option nat))) :=
1242- let ndctxt_asid := NDCtxt.make (level_prefix va lvl) (Some asid) in
1243- let ndctxt_global := NDCtxt.make (level_prefix va lvl) None in
1242+ is_upper ← othrow ("VA is not in the range: " ++ (pretty va))%string
1243+ (is_upper_va va);
1244+ let ndctxt_asid := NDCtxt.make is_upper (level_prefix va lvl) (Some asid) in
1245+ let ndctxt_global := NDCtxt.make is_upper (level_prefix va lvl) None in
12441246 candidates_asid ←
12451247 get_leaf_ptes_with_inv_time_by_ctxt mem tid tlb trans_time lvl ndctxt_asid;
12461248 candidates_global ←
@@ -1277,7 +1279,9 @@ Module TLB.
12771279 (ttbr : reg) :
12781280 result string (list (val * list val * (option nat))) :=
12791281 if parent_lvl lvl is Some parent_lvl then
1280- let ndctxt := NDCtxt.make (level_prefix va parent_lvl) asid in
1282+ is_upper ← othrow ("VA is not in the range: " ++ (pretty va))%string
1283+ (is_upper_va va);
1284+ let ndctxt := NDCtxt.make is_upper (level_prefix va parent_lvl) asid in
12811285 let ctxt := existT parent_lvl ndctxt in
12821286 let tes := VATLB.get ctxt tlb.(TLB.vatlb) in
12831287 let tes := filter (λ te, is_table (TLB.Entry.pte te)) tes in
@@ -1376,7 +1380,7 @@ Module TLB.
13761380 candidates ← TLB.lookup mem tid tlb trans_time va asid;
13771381 let new :=
13781382 omap (λ '(val_ttbr, path, ti_opt),
1379- if ( is_new_entry val_ttbr path ti_opt entries) then
1383+ if is_new_entry val_ttbr path ti_opt entries then
13801384 Some (val_ttbr, path, trans_time, ti_opt)
13811385 else None
13821386 ) candidates in
@@ -1397,7 +1401,7 @@ Module TLB.
13971401 candidates ← TLB.get_invalid_ptes_with_inv_time ts init mem tid tlb trans_time va asid ttbr;
13981402 let new :=
13991403 omap (λ '(val_ttbr, path, ti_opt),
1400- if decide ( is_new_entry val_ttbr path ti_opt entries) then
1404+ if is_new_entry val_ttbr path ti_opt entries then
14011405 Some (val_ttbr, path, trans_time, ti_opt)
14021406 else None
14031407 ) candidates in
@@ -1420,8 +1424,7 @@ Module IIS.
14201424 va : bv 36;
14211425 time : nat;
14221426 root : option {ttbr : reg & reg_type ttbr};
1423- remaining : list (bv 64);
1424- invalidation : option nat
1427+ remaining : list (bv 64)
14251428 }.
14261429
14271430 Definition pop : Exec.t t string (bv 64) :=
@@ -1436,10 +1439,11 @@ Module IIS.
14361439 make {
14371440 strict : view;
14381441 (* The translations results of the latest translation *)
1439- trs : option TransRes.t
1442+ trs : option TransRes.t;
1443+ inv_time : option nat
14401444 }.
14411445
1442- Definition init : t := make 0 None.
1446+ Definition init : t := make 0 None None .
14431447
14441448 (** Add a new view to the IIS *)
14451449 Definition add (v : view) (iis : t) : t :=
@@ -1448,6 +1452,9 @@ Module IIS.
14481452 Definition set_trs (tres : TransRes.t) :=
14491453 setv trs (Some tres).
14501454
1455+ Definition set_inv_time (ti_opt : option nat) :=
1456+ setv inv_time ti_opt.
1457+
14511458End IIS.
14521459
14531460Import UMPromising(view_if, read_fwd_view).
@@ -1520,14 +1527,17 @@ Definition run_reg_general_read (reg : reg) (racc : reg_acc) :
15201527Definition run_reg_trans_read (reg : reg) (racc : reg_acc)
15211528 (trs : IIS.TransRes.t) :
15221529 Exec.t TState.t string (reg_type reg * view) :=
1523- guard_or "Translation read during the translation should be implicit"
1530+ guard_or "Register read during the translation should be implicit"
15241531 (¬ (is_Some racc));;
15251532 root ← othrow "Could not find the translation root: error in translation assumptions"
15261533 (trs.(IIS.TransRes.root));
1527- if decide (projT1 root = reg) is left eq then
1528- mret (ctrans eq (projT2 root) , 0%nat)
1534+ if decide (root.T1 = reg) is left eq then
1535+ mret (ctrans eq root.T2 , 0%nat)
15291536 else
15301537 ts ← mGet;
1538+ guard_or
1539+ ("The register should niether be relaxed nor strict: " ++ pretty reg)%string
1540+ $ (reg ∉ strict_regs ∨ reg ∉ relaxed_regs);;
15311541 othrow
15321542 ("Register " ++ pretty reg ++ " unmapped; cannot read")%string
15331543 $ TState.read_reg ts reg.
@@ -1588,18 +1598,14 @@ Definition run_mem_read (addr : address) (macc : mem_acc) (init : Memory.initial
15881598 iis ← mget PPState.iis;
15891599 let vaddr := iis.(IIS.strict) in
15901600 if is_explicit macc then
1591- tres_opt ← mget (IIS.trs ∘ PPState.iis);
1592- trans_res ← othrow "Explicit access before translation" tres_opt;
1593- let invalidation := trans_res.(IIS.TransRes.invalidation) in
15941601 '(view, val) ←
15951602 Exec.liftSt (PPState.state ×× PPState.mem)
1596- $ read_mem_explicit loc vaddr invalidation macc init;
1603+ $ read_mem_explicit loc vaddr iis.(IIS.inv_time) macc init;
15971604 mset PPState.iis $ IIS.add view;;
15981605 mret val
15991606 else if is_ttw macc then
16001607 ts ← mget PPState.state;
1601- tres_option ← mget (IIS.trs ∘ PPState.iis);
1602- tres ← othrow "TTW read before translation start" tres_option;
1608+ tres ← othrow "TTW read before translation start" iis.(IIS.trs);
16031609 '(view, val) ←
16041610 read_pte vaddr (ts, tres)
16051611 |> Exec.lift_res_set_full
@@ -1828,27 +1834,28 @@ Definition run_trans_start (trans_start : TranslationStartInfo)
18281834 valid_entries ← mlift $ TLB.get_valid_entries_from_snapshots snapshots mem tid va asid;
18291835 invalid_entries ← mlift $
18301836 TLB.get_invalid_entries_from_snapshots snapshots ts init mem tid is_ets2 va asid ttbr;
1831- (* update IIS with either a valid translation result or a fault *)
1832- valid_trs ←
1837+ (* update IIS with either a valid translation result or an invalid result *)
1838+ valid_res ←
18331839 for (val_ttbr, path, t, ti) in valid_entries do
18341840 val_ttbr ← othrow
18351841 "TTBR value type does not match with the value from the translation"
18361842 (val_to_regval ttbr val_ttbr);
18371843 let root := (Some (existT ttbr val_ttbr)) in
1838- mret $ IIS.TransRes.make (va_to_vpn va) t root path ti
1844+ mret $ ( IIS.TransRes.make (va_to_vpn va) t root path, ti)
18391845 end ;
1840- invalid_trs ←
1846+ invalid_res ←
18411847 for (val_ttbr, path, t, ti) in invalid_entries do
18421848 val_ttbr ← othrow
18431849 "TTBR value type does not match with the value from the translation"
18441850 (val_to_regval ttbr val_ttbr);
18451851 let root := (Some (existT ttbr val_ttbr)) in
1846- mret $ IIS.TransRes.make (va_to_vpn va) t root path ti
1852+ mret $ ( IIS.TransRes.make (va_to_vpn va) t root path, ti)
18471853 end ;
1848- mchoosel (valid_trs ++ invalid_trs )
1854+ mchoosel (valid_res ++ invalid_res )
18491855 else
1850- mret $ IIS.TransRes.make (va_to_vpn va) vpre_t None [] None;
1851- mset PPState.iis $ IIS.set_trs trans_res.
1856+ mret $ (IIS.TransRes.make (va_to_vpn va) vpre_t None [], None);
1857+ mset PPState.iis $ IIS.set_trs trans_res.1;;
1858+ mset PPState.iis $ IIS.set_inv_time trans_res.2.
18521859
18531860Definition read_fault_vpre (is_acq : bool)
18541861 (trans_time : nat) : Exec.t (TState.t * IIS.t) string view :=
@@ -1876,7 +1883,7 @@ Definition run_trans_end (trans_end : trans_end) :
18761883 let trans_time := trs.(IIS.TransRes.time) in
18771884 let fault := trans_end.(AddressDescriptor_fault) in
18781885 if decide (fault.(FaultRecord_statuscode) = Fault_None) then
1879- mret ()
1886+ mset snd $ setv IIS.trs None
18801887 else
18811888 is_ets3 ← mlift (ets3 ts);
18821889 if is_ets3 && (trans_time <? (ts.(TState.vrd) ⊔ ts.(TState.vwr)))
@@ -1893,16 +1900,18 @@ Definition run_trans_end (trans_end : trans_end) :
18931900 let is_write := fault.(FaultRecord_access).(AccessDescriptor_write) in
18941901 let is_rel := fault.(FaultRecord_access).(AccessDescriptor_relsc) in
18951902 write_view ← write_fault_vpre is_rel trans_time;
1896- mset snd $ IIS.add (view_if is_write write_view)
1903+ mset snd $ IIS.add (view_if is_write write_view);;
1904+ mset snd $ setv IIS.trs None
18971905 else
18981906 mthrow "Translation ends with an empty translation".
18991907
1908+ (* TODO: check translation fault using `fault` and handle other cases *)
19001909Definition run_take_exception (fault : exn) (vmax_t : view) :
19011910 Exec.t (TState.t * IIS.t) string () :=
19021911 iis ← mget snd;
19031912 if iis.(IIS.trs) is Some trans_res then
1904- match trans_res .(IIS.TransRes.invalidation ) with
1905- | Some invalidation => run_cse invalidation
1913+ match iis .(IIS.inv_time ) with
1914+ | Some inv_time => run_cse inv_time
19061915 | None => mret ()
19071916 end
19081917 else
@@ -1940,11 +1949,9 @@ Section RunOutcome.
19401949 addr ← othrow "Address not supported" $ Loc.from_addr addr;
19411950 viio ← mget (IIS.strict ∘ PPState.iis);
19421951 if is_explicit macc then
1943- tres_opt ← mget (IIS.trs ∘ PPState.iis);
1944- trans_res ← othrow "Explicit access before translation" tres_opt;
1945- let invalidation := trans_res.(IIS.TransRes.invalidation) in
1952+ inv_time ← mget (IIS.inv_time ∘ PPState.iis);
19461953 vpre_opt ← Exec.liftSt (PPState.state ×× PPState.mem) $
1947- write_mem_xcl tid addr viio invalidation macc val;
1954+ write_mem_xcl tid addr viio inv_time macc val;
19481955 mret (Ok (), vpre_opt)
19491956 else mthrow "Unsupported non-explicit write"
19501957 | MemWrite _ _ _ => mthrow "Memory write of size other than 8, or with tags"
0 commit comments