@@ -388,7 +388,6 @@ Definition strict_regs : gset reg :=
388388 SP_EL1;
389389 SP_EL2;
390390 SP_EL3;
391- PSTATE;
392391 ELR_EL1;
393392 ELR_EL2;
394393 ELR_EL3;
@@ -709,8 +708,15 @@ Definition va_to_vpn {n : N} (va : bv 64) : bv n :=
709708 bv_extract 12 n va.
710709
711710Definition prefix_to_va {n : N} (is_upper : bool) (p : bv n) : bv 64 :=
712- let varange_bit := if is_upper then (bv_1 16) else (bv_0 16) in
713- bv_concat 64 varange_bit (bv_concat 48 p (bv_0 (48 - n))).
711+ let varange_bits : bv 16 := if is_upper then (-1)%bv else 0%bv in
712+ let padding := bv_0 (48 - n) in
713+ bv_concat 64 varange_bits (bv_concat 48 p padding).
714+
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.
714720
715721Definition level_prefix {n : N} (va : bv n) (lvl : Level) : prefix lvl :=
716722 bv_extract (12 + 9 * (3 - lvl)) (9 * (lvl + 1)) va.
@@ -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.
@@ -793,22 +801,19 @@ Module TLB.
793801 Definition t := {lvl : Level & NDCtxt.t lvl}.
794802 Definition lvl : t -> Level := projT1.
795803 Definition nd (ctxt : t) : NDCtxt.t (lvl ctxt) := projT2 ctxt.
804+ Definition is_upper (ctxt : t) : bool := NDCtxt.is_upper (nd ctxt).
796805 Definition va (ctxt : t) : prefix (lvl ctxt) := NDCtxt.va (nd ctxt).
797806 Definition asid (ctxt : t) : option (bv 16) := NDCtxt.asid (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,8 +823,8 @@ 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
@@ -828,8 +833,8 @@ Module TLB.
828833 Program Definition append {lvl clvl : Level}
829834 (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
@@ -1228,7 +1228,7 @@ Module TLB.
12281228 mret ((Entry.val_ttbr te), (vec_to_list (Entry.ptes te)), ti)
12291229 end .
12301230
1231- (** Get all the TLB entries and the corresponding TTBR value that
1231+ (** Get all the TLB entries (including the TTBR value) TTBR value that
12321232 could translate the given VA at the provided level
12331233 and in the provided ASID context.
12341234 Return each TLB entry as a list of descriptors [list val] with
@@ -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 48 bits 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,18 @@ 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+ (* We are only allowed to read registers that are never written during the translation *)
1539+ guard_or
1540+ ("The register should niether be relaxed nor strict: " ++ pretty reg)%string
1541+ $ (reg ∉ strict_regs ∧ reg ∉ relaxed_regs);;
15311542 othrow
15321543 ("Register " ++ pretty reg ++ " unmapped; cannot read")%string
15331544 $ TState.read_reg ts reg.
@@ -1588,18 +1599,14 @@ Definition run_mem_read (addr : address) (macc : mem_acc) (init : Memory.initial
15881599 iis ← mget PPState.iis;
15891600 let vaddr := iis.(IIS.strict) in
15901601 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
15941602 '(view, val) ←
15951603 Exec.liftSt (PPState.state ×× PPState.mem)
1596- $ read_mem_explicit loc vaddr invalidation macc init;
1604+ $ read_mem_explicit loc vaddr iis.(IIS.inv_time) macc init;
15971605 mset PPState.iis $ IIS.add view;;
15981606 mret val
15991607 else if is_ttw macc then
16001608 ts ← mget PPState.state;
1601- tres_option ← mget (IIS.trs ∘ PPState.iis);
1602- tres ← othrow "TTW read before translation start" tres_option;
1609+ tres ← othrow "TTW read before translation start" iis.(IIS.trs);
16031610 '(view, val) ←
16041611 read_pte vaddr (ts, tres)
16051612 |> Exec.lift_res_set_full
@@ -1828,27 +1835,29 @@ Definition run_trans_start (trans_start : TranslationStartInfo)
18281835 valid_entries ← mlift $ TLB.get_valid_entries_from_snapshots snapshots mem tid va asid;
18291836 invalid_entries ← mlift $
18301837 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 ←
1838+ (* update IIS with either a valid translation result or an invalid result *)
1839+ valid_res ←
18331840 for (val_ttbr, path, t, ti) in valid_entries do
18341841 val_ttbr ← othrow
18351842 "TTBR value type does not match with the value from the translation"
18361843 (val_to_regval ttbr val_ttbr);
18371844 let root := (Some (existT ttbr val_ttbr)) in
1838- mret $ IIS.TransRes.make (va_to_vpn va) t root path ti
1845+ let ti := if is_ifetch then None else ti in
1846+ mret $ (IIS.TransRes.make (va_to_vpn va) t root path, ti)
18391847 end ;
1840- invalid_trs ←
1848+ invalid_res ←
18411849 for (val_ttbr, path, t, ti) in invalid_entries do
18421850 val_ttbr ← othrow
18431851 "TTBR value type does not match with the value from the translation"
18441852 (val_to_regval ttbr val_ttbr);
18451853 let root := (Some (existT ttbr val_ttbr)) in
1846- mret $ IIS.TransRes.make (va_to_vpn va) t root path ti
1854+ mret $ ( IIS.TransRes.make (va_to_vpn va) t root path, ti)
18471855 end ;
1848- mchoosel (valid_trs ++ invalid_trs )
1856+ mchoosel (valid_res ++ invalid_res )
18491857 else
1850- mret $ IIS.TransRes.make (va_to_vpn va) vpre_t None [] None;
1851- mset PPState.iis $ IIS.set_trs trans_res.
1858+ mret $ (IIS.TransRes.make (va_to_vpn va) vpre_t None [], None);
1859+ mset PPState.iis $ IIS.set_trs trans_res.1;;
1860+ mset PPState.iis $ IIS.set_inv_time trans_res.2.
18521861
18531862Definition read_fault_vpre (is_acq : bool)
18541863 (trans_time : nat) : Exec.t (TState.t * IIS.t) string view :=
@@ -1876,7 +1885,7 @@ Definition run_trans_end (trans_end : trans_end) :
18761885 let trans_time := trs.(IIS.TransRes.time) in
18771886 let fault := trans_end.(AddressDescriptor_fault) in
18781887 if decide (fault.(FaultRecord_statuscode) = Fault_None) then
1879- mret ()
1888+ msetv (IIS.trs ∘ snd) None
18801889 else
18811890 is_ets3 ← mlift (ets3 ts);
18821891 if is_ets3 && (trans_time <? (ts.(TState.vrd) ⊔ ts.(TState.vwr)))
@@ -1893,20 +1902,19 @@ Definition run_trans_end (trans_end : trans_end) :
18931902 let is_write := fault.(FaultRecord_access).(AccessDescriptor_write) in
18941903 let is_rel := fault.(FaultRecord_access).(AccessDescriptor_relsc) in
18951904 write_view ← write_fault_vpre is_rel trans_time;
1896- mset snd $ IIS.add (view_if is_write write_view)
1905+ mset snd $ IIS.add (view_if is_write write_view);;
1906+ msetv (IIS.trs ∘ snd) None
18971907 else
18981908 mthrow "Translation ends with an empty translation".
18991909
1910+ (* TODO: check translation fault using `fault` and handle other cases *)
19001911Definition run_take_exception (fault : exn) (vmax_t : view) :
19011912 Exec.t (TState.t * IIS.t) string () :=
19021913 iis ← mget snd;
1903- if iis.(IIS.trs) is Some trans_res then
1904- match trans_res.(IIS.TransRes.invalidation) with
1905- | Some invalidation => run_cse invalidation
1906- | None => mret ()
1907- end
1908- else
1909- run_cse vmax_t.
1914+ match iis.(IIS.inv_time) with
1915+ | Some inv_time => run_cse inv_time
1916+ | None => run_cse vmax_t
1917+ end .
19101918
19111919(** Runs an outcome. *)
19121920Section RunOutcome.
@@ -1940,11 +1948,9 @@ Section RunOutcome.
19401948 addr ← othrow "Address not supported" $ Loc.from_addr addr;
19411949 viio ← mget (IIS.strict ∘ PPState.iis);
19421950 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
1951+ inv_time ← mget (IIS.inv_time ∘ PPState.iis);
19461952 vpre_opt ← Exec.liftSt (PPState.state ×× PPState.mem) $
1947- write_mem_xcl tid addr viio invalidation macc val;
1953+ write_mem_xcl tid addr viio inv_time macc val;
19481954 mret (Ok (), vpre_opt)
19491955 else mthrow "Unsupported non-explicit write"
19501956 | MemWrite _ _ _ => mthrow "Memory write of size other than 8, or with tags"
0 commit comments