@@ -881,6 +881,10 @@ Module TLB.
881881 (entries : gset (Entry.t (Ctxt.lvl ctxt))) (vatlb : t) : t :=
882882 hset (Ctxt.lvl ctxt) {[(Ctxt.nd ctxt) := entries]} vatlb.
883883
884+ Definition add (ctxt : Ctxt.t) (entry : Entry.t (Ctxt.lvl ctxt)) (vatlb : t) : t :=
885+ let entries := get ctxt vatlb in
886+ hset (Ctxt.lvl ctxt) {[(Ctxt.nd ctxt) := entries ∪ {[ entry ]}]} vatlb.
887+
884888 #[global] Instance empty : Empty t := VATLB.init.
885889 #[global] Instance union : Union t := fun x y => hmap2 (fun _ => (∪ₘ)) x y.
886890 End VATLB.
@@ -926,31 +930,35 @@ Module TLB.
926930 - If entry is a table, builds a root context with ASID from TTBR
927931 and inserts it into VATLB.
928932 - Otherwise returns empty VATLB. *)
929- Definition va_fill_root (ts : TState.t)
933+ Definition va_fill_root (vatlb : VATLB.t) ( ts : TState.t)
930934 (init : Memory.initial)
931935 (mem : Memory.t)
932936 (time : nat)
933937 (va : prefix root_lvl)
934- (ttbr : reg) : result string VATLB.t :=
938+ (ttbr : reg) : result string ( VATLB.t * bool) :=
935939 sregs ← othrow "TTBR should exist in initial state"
936940 $ TState.read_sreg_at ts ttbr time;
937- vatlbs ←
938- for sreg in sregs do
939- val_ttbr ← othrow "TTBR should be a 64 bit value"
941+ fold_left (λ prev sreg,
942+ '(vatlb, is_changed) ← prev;
943+ val_ttbr ← othrow "TTBR should be a 64 bit value"
940944 $ regval_to_val ttbr sreg.1;
941- let entry_addr := next_entry_addr val_ttbr va in
942- let loc := Loc.from_addr_in entry_addr in
943- if (Memory.read_at loc init mem time) is Some (memval, _) then
944- if decide (is_table memval) then
945- let asid := bv_extract 48 16 val_ttbr in
946- let ndctxt := NDCtxt.make va (Some asid) in
947- Ok $ VATLB.singleton (existT root_lvl ndctxt) [#memval]
948- else
949- Ok VATLB.init
945+ let entry_addr := next_entry_addr val_ttbr va in
946+ let loc := Loc.from_addr_in entry_addr in
947+ if (Memory.read_at loc init mem time) is Some (memval, _) then
948+ if decide (is_table memval) then
949+ let asid := bv_extract 48 16 val_ttbr in
950+ let ndctxt := NDCtxt.make va (Some asid) in
951+ let ctxt := existT root_lvl ndctxt in
952+ let entry : Entry.t (Ctxt.lvl ctxt) := [#memval] in
953+ (* add the entry to vatlb only when it is not in the original vatlb *)
954+ if decide (entry ∉ (VATLB.get ctxt vatlb)) then
955+ Ok (VATLB.add ctxt entry vatlb, true)
956+ else Ok (vatlb, is_changed)
950957 else
951- Ok VATLB.init
952- end ;
953- Ok (union_list vatlbs).
958+ Ok (vatlb, is_changed)
959+ else
960+ Ok (vatlb, is_changed)
961+ ) sregs (mret (vatlb, false)).
954962
955963 (** Extend one level down from a parent table entry [te].
956964 - Requires [te] ∈ [vatlb] and ASID active for [ttbr].
@@ -964,13 +972,13 @@ Module TLB.
964972 (ctxt : Ctxt.t)
965973 (te : Entry.t (Ctxt.lvl ctxt))
966974 (index : bv 9)
967- (ttbr : reg) : result string VATLB.t :=
975+ (ttbr : reg) : result string ( VATLB.t * bool) :=
968976 guard_or "ASID is not active"
969977 $ is_active_asid ts (Ctxt.asid ctxt) ttbr time;;
970978 guard_or "The translation entry is not in the TLB"
971979 (te ∈ VATLB.get ctxt vatlb);;
972980
973- if decide (¬is_table (Entry.pte te)) then Ok VATLB.init
981+ if decide (¬is_table (Entry.pte te)) then Ok (vatlb, false)
974982 else
975983 let entry_addr := next_entry_addr (Entry.pte te) index in
976984 let loc := Loc.from_addr_in entry_addr in
@@ -983,12 +991,16 @@ Module TLB.
983991 let asid := if bool_decide (is_global clvl next_pte) then None
984992 else Ctxt.asid ctxt in
985993 let ndctxt := NDCtxt.make va asid in
986- let new_te := Entry.append te next_pte (child_lvl_add_one _ _ e) in
987- Ok $ VATLB.singleton (existT clvl ndctxt) new_te
994+ let ctxt := existT clvl ndctxt in
995+ let entry := Entry.append te next_pte (child_lvl_add_one _ _ e) in
996+ (* add the entry to vatlb only when it is not in the original vatlb *)
997+ if decide (entry ∉ (VATLB.get ctxt vatlb)) then
998+ Ok (VATLB.add ctxt entry vatlb, true)
999+ else Ok (vatlb, false)
9881000 | None eq:_ => mthrow "An intermediate level should have a child level"
9891001 end
9901002 else
991- Ok VATLB.init .
1003+ Ok (vatlb, false) .
9921004
9931005 (** Make [tlb] containing entries for [va] at [lvl].
9941006 - At root: call [va_fill_root].
@@ -1001,31 +1013,32 @@ Module TLB.
10011013 (lvl : Level)
10021014 (va : bv 64)
10031015 (ttbr : reg) : result string (t * bool) :=
1004- vatlb_new ←
1016+ '( vatlb_new, is_changed) ←
10051017 match parent_lvl lvl with
10061018 | None =>
1007- va_fill_root ts init mem time (level_index va root_lvl) ttbr
1019+ va_fill_root tlb.(vatlb) ts init mem time (level_index va root_lvl) ttbr
10081020 | Some plvl =>
10091021 let pva := level_prefix va plvl in
10101022 let index := level_index va lvl in
10111023 sregs ← othrow "TTBR should exist in initial state"
10121024 $ TState.read_sreg_at ts ttbr time;
1013- active_vatlbs ←
1014- for sreg in sregs do
1015- val_ttbr ← othrow "TTBR should be a 64 bit value"
1016- $ regval_to_val ttbr sreg.1;
1017- let asid := bv_extract 48 16 val_ttbr in
1018- let ndctxt := NDCtxt.make pva (Some asid) in
1019- let ctxt := existT plvl ndctxt in
1020- vatlbs ←
1021- for te in elements (VATLB.get ctxt tlb.(vatlb)) do
1022- va_fill_lvl tlb.(vatlb) ts init mem time ctxt te index ttbr
1023- end ;
1024- Ok (union_list vatlbs)
1025- end ;
1026- Ok $ (union_list active_vatlbs)
1025+ fold_left (λ prev sreg,
1026+ val_ttbr ← othrow "TTBR should be a 64 bit value"
1027+ $ regval_to_val ttbr sreg.1;
1028+ let asid := bv_extract 48 16 val_ttbr in
1029+ let ndctxt := NDCtxt.make pva (Some asid) in
1030+ let ctxt := existT plvl ndctxt in
1031+ (* parent entries should be from the original TLB (in the parent level) *)
1032+ let tes := elements (VATLB.get ctxt tlb.(vatlb)) in
1033+ fold_left (λ prev te,
1034+ '(vatlb_prev, is_changed_prev) ← prev;
1035+ '(vatlb_lvl, is_changed_lvl) ←
1036+ va_fill_lvl vatlb_prev ts init mem time ctxt te index ttbr;
1037+ mret (vatlb_lvl, is_changed_lvl || is_changed_prev)
1038+ ) tes prev
1039+ ) sregs (mret (tlb.(vatlb), false))
10271040 end ;
1028- mret $ (TLB.make ( vatlb_new ∪ tlb.(vatlb)), negb(vatlb_new =? ∅) ).
1041+ mret $ (TLB.make vatlb_new, is_changed ).
10291042
10301043 (** Fill TLB entries for [va] through all levels 0–3.
10311044 - Sequentially calls [va_fill] at each level.
@@ -1037,7 +1050,6 @@ Module TLB.
10371050 (time : nat)
10381051 (va : bv 64)
10391052 (ttbr : reg) : result string (t * bool) :=
1040- (* make an incremental update *)
10411053 fold_left (λ prev lvl,
10421054 '(tlb_prev, is_changed_prev) ← prev;
10431055 '(tlb_new, is_changed) ← va_fill tlb_prev ts init mem time lvl va ttbr;
@@ -1111,10 +1123,11 @@ Module TLB.
11111123 match mem !! time_cur with
11121124 | Some ev =>
11131125 (* always true if tlbi is applied *)
1114- let tlb_inv :=
1115- if ev is Ev.Tlbi tlbi then tlbi_apply tlbi tlb_prev else tlb_prev
1126+ let ( tlb_inv, is_changed_by_tlbi) :=
1127+ if ev is Ev.Tlbi tlbi then ( tlbi_apply tlbi tlb_prev, true) else ( tlb_prev, false)
11161128 in
1117- update tlb_inv ts mem_init mem time_cur va ttbr
1129+ '(tlb, is_changed) ← update tlb_inv ts mem_init mem time_cur va ttbr;
1130+ mret (tlb, is_changed || is_changed_by_tlbi)
11181131 | None => mret (init, false)
11191132 end ;
11201133 let acc :=
0 commit comments