Lab 2 Extra Reflection
BUAA OS 2023 Spring
Due to misunderstanding of some concepts and the meaning of some functions, I failed on lab 2 extra. So much thanks to the TA who helped me understand these stuffs. Thus, a reflection here, I have.
To be honest, the problem is not that difficult, but if you’re not clear with related concepts, you may get into much trouble. So, here I just want to demonstrate some key points of it.
Here is the original problem description, you can expand it optionally.
Problem
To get a better understanding of this article, you can refer to my previous post here:
Traverse Page Table Entries
In this problem, to swap in or out a page need a complete traverse of the page table of current process. But why? Why not just a single page? Well, you know, multiple virtual page could be mapped to the same physical address, so we have to make sure all these pages are correctly marked. Therefore, a complete traverse is needed.
Then, you may ask again, there are so many page table entries, won’t it take too long? Emm… some page directories are not valid, so the page table entries will be skipped.
So, how do we traverse page table entries?
1 | // Traverse page table entries. |
Flush TLB
Another point that is difficult to understand is the action to clear old TLB entry. The structure of TLB entry is as follows.
VPN is virtual page number, if we takes it out and make low 12 bits zero, it will be the start virtual address of a virtual page. The same goes with PFN, which is Page Frame number, a.k.a. Physical Page number (PPN).
To invalidate a page directory entry, we actually flush the VPN it mapped to. Yeah, the VPN it mapped to, but how to get it? In pgdir_walk()
function, we create or get a page table entry of the given va
, which is exactly what we want here. So, again, what does pgdir_walk()
really mean?
pgdir_walk()
I found that I didn’t understand this function before. Here is the definition of this tricky function.
1 | /* |
Depending on the value of create
, we can get the page table entry mapped to virtual address va
, or create the missing page table. (Since we use two-level page table, where the second level won’t be created until needed.) And what we used here is the so called VPN, which could be further explained as PDX and PTX. Again, here is a picture of it.
Get it? Are we getting it? (By Steve Jobs on iPhone’s release conference.)
The va
here is exactly what we use later in tlb_invalidate()
. What? You still don’t know what va
is? Just take some time to read the previous post Page Directory Self Mapping.
So the purpose of pgdir_walk()
is just to get the corresponding page table entry of the virtual address va
, or create it if not allocated before.
tlb_invalidate()
Here is the definition of related functions. Now you should know what’s the correct va
to pass.
1 | // Invalidate the TLB entry with specified 'asid' and virtual address 'va'. |
In tlb_invalidate()
, we called tlb_out()
function, which is written in MIPS. To access TLB in MIPS, we use EntryHi
and EntryLo
registers. EntryHi
as key and EntryLo
as value. So, here, to flush the entry, we need the key to specify which entry to flush, and the key is what we call entryhi
. As a parameter and the first parameter, it will be passed as $a0
in MIPS.
1 | LEAF(tlb_out) |
“The even page entries in the TLB (such as PFN0) come from
CP0.EntryLo0
. Similarly, odd page entries come fromCP0.EntryLo1
.” From MD00090-2B-MIPS32PRA-AFP-06.02, Page 32.However, we use MIPS 3000, which doesn’t have such feature. It only has
CP0.EntryLo0
.
Here are some explanation to TLB related instructions.
tlbr
(read): Using the value inCP0.Index
to read the corresponding entry toCP0.EntryHi
andCP0.EntryLo
.
tlbwi
(write): Using the value inCP0.Index
to write the value ofCP0.EntryHi
andCP0.EntryLo
to corresponding TLB entry.
tlbwr
(write random): WriteCP0.EntryHi
andCP0.EntryLo
to a random TLB entry. Here, a register with random value is used, which is in fact a counter.
tlbp
(probe): Using the value inCP0.EntryHi
as key (including VPN and ASID) to find corresponding entry in TLB. If there is such an entry, the index of it will be stored atCP0.Index
. Other wise, the highest bit ofCP0.Index
will be set to 1 to make it a negative number, indicating a failure.
So, let get back to the problem one last time. Now, everything is clear. We traverse the page table entries, and get the legal ones. Then, do the … things.
As we know, “Talk is cheap, show me the code.” So, just show the code. ;)
Code
To make it shorter, I removed some blank lines. We’re really sorry about this. :(
1 | // Interface for 'Passive Swap Out' |
1 | // Interfaces for 'Active Swap In' |