Skip to content

Commit dfe8ec8

Browse files
committed
Make an incremental update on VATLB
1 parent a3b9f5e commit dfe8ec8

File tree

1 file changed

+56
-43
lines changed

1 file changed

+56
-43
lines changed

ArchSemArm/VMPromising.v

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)