 Yeah, so I'm going to be able to change that last one. OK. So, recitation 11th. So that means our last recitation and discussing the assignments. So let's review what we've discussed in the previous recitation. We've presented the page table, and we said that the page table is basically a data structure that quickly maps the VPN to a page table entry. And we've said that each process should have its own page table. And all addresses within a virtual page should map to the same physical page. And so one of the requirements for that page table to be able to, or the functionality of that page table should be given a virtual address and an operation should first check if that virtual address is valid, which means it falls within one of the defined region. And then check if the operation matches the permissions for that page. And if all are valid, then get the physical address. And we refer for every entry in that page table as the page table entry. What should we keep? We've said that this depends on your data structure. So you might need to keep a virtual page number, but you need to keep physical page number and permission of that page and the state whether that page is on disk or in memory. And whether that page is valid, which means, so this basically means that you have a physical page allocated for that virtual page. And also, a reference of that page has been recently referenced or not. And some other, depending on what data structure you're using. We've presented the three table page table designs. We've said there is a flat page table design that you shouldn't use, but just to know that this page table, so if you use a flat page table, you're going to retrieve the PTE in order one or constant time. And most entry could be unused. So you're wasting space, but another design is the link list page table, where you have a list of PTEs, and each one of these refers to an actual physical page. But if you want to retrieve a page table entry, you need to search or go through the whole list. So order of time. We've also presented the two-level page table. We've said multi-level page tables basically are just like the three-like data structures mapping the VPN to PTE. So if we want to implement the two-level page table, then we need to break up the VPN into two parts, 10 bits each, and then each part maps to an entry into a separate level of the three. So valid entry in the first-level page table, we said that it should contain a pointer to the second-level page table, where the second-level page table can still be either a table of pointers or a table of PTE structures. And this should only be allocated as needed. That means there is no physical page allocated for that virtual page, or if the page is not valid, you shouldn't allocate a second-level page table for it. And it should be null in the first-level page table. So the three-time is, again, constant time. Usage is better than a flat page table and worse than the link list. We've also presented the address space. So the address space basically is a collection of virtual addresses that the operating system make them available for the user process. So what should we maintain in the address space structure? We've said that we need to maintain region information, start address size of that region, and the permission of that region, stack heap information, and also page table pointer. So you should implement all the interfaces for address space that are defined in address space.h. And you can find a usage example on load-elf how these interfaces are used in load-elf. So the last thing that we presented is the TLB. And we've said the TLB is basically a buffer that is used by the MMU to quickly map virtual address to physical address. And we have a fixed number of TLB entries per core, which is 64. And the size of each TLB entry is 64-bit divided as you can see. So we use the first 20 bits as the VPN. The rest are unused. This is from the first 32-bit and the second 32-bit. So the first 20 bits is the VPN or the physical page number. And then we have also 12 bits that are unused, except for the TLB load valid and the dirty. And we said the valid indicates if that translation in the TLB is valid or not. And the dirty tells that the permission of that page with that page is read-only or read-write. So we've said that we have three different VM faults. So either VM fault happens on a read for a missing TLB entry or on a write for a missing TLB entry or VM fault read-only. And that's where the dirty bit comes into play. So if VM fault happens on a read-only, that means I'm trying to write into an existing translation, but that page is a read-only page. We have helper functions that are defined for us to use with the TLB or defined in TLB.h. So the general VM fault is basically we check the fault address if that address is valid and falls within one of the defined region. And then we check the operation of that operation that we are trying to perform on that page, whether it matches the page permission or not. And then we check if it's a TLB fault, page fault, or both. And if it's a page fault, then we allocate physical page for it as needed. And then we update the TLB entry. So the operation could go through. So this is basically what we've discussed last time. Any question on last time? OK. So today we're going to, again, overview what left for us with the assigned three. Then we're going to discuss the physical page states, virtual page states, swapping, swapping out, and swapping in. So as you can see, we are at the first checkpoint, which is swapping. The next deadline is going to be not this Friday, the one after May 6. So let's start. So you might be familiar with this. We've discussed it before. But as we have physical page states, we have virtual page states. So we need to compare these two together. But now, since we have the swapping enabled, then we all need to consider all the states, even though maybe in OS 161 you really don't need, maybe, again, dirty and clean. But to better understand how you should implement swapping, you need to understand the full picture of a swapping and how does it function. So we have four states, basically, for the physical page state. The free, this is what we start with. So if the physical page is a free, you mark it as a free. It should be marked as a free. We have another state, which is fixed. And that, as we discussed that, we need to use this for the kernel pages, exception, core map, whatever page that you should not swap out out of memory, then you should put it as a fixed. So and this is what will happen with allocate pages. And because allocate pages just like allocate kernel pages for us. And then, so this is basically used with kernel pages. And then we have, on the other side, is the dirty and clean that is used with the user pages. So whenever we create or allocate a page for the user, then the first state that should get is dirty. Why? Because we have that page allocated in memory, but it has no copy on disk. Or we can also use that dirty state for if we have a page allocated. And it has a copy on disk. But the content of the page in memory and the content that is on disk is different. So with the clean state, we use it if we have the page allocated. And the content in memory and in disk are the same, are exactly the same. There is no difference. So as you can see here, then from page alloc, which allocates user pages for us, the first state we get in is the dirty state. And then once we flush or allocate or create a copy on disk, then that page state should be clean. And on VM fold, again, that page should be, if it's accessed and there is a right operation on it, then it should be, again, changed to dirty up until the time that, again, we flush it to disk. And that's also whenever we free a dirty page, then one of the steps is basically going into the clean state and then free it. So just make sure the content are the same and then you need to, the content in memory and on disk are the same and then you should free it. So these are the physical page states that we have any question on these. Okay, so as we said, as we have physical page states, we have a virtual page state. So for the virtual part, or for the virtual pages, we have the three states, unmapped, mapped, swapped. Unmapped, this is the initial state, which is for all the free pages or pages that are not yet, yes. Yes. Yeah, so that depends on your data structure. If you're using Linglist, I don't think you need these two states, what you need is the mapped and swapped. That's what you need with the Linglist. If you're using a two level page table, again, depends on how you're implementing the two level or three or four level page tables, how you're implementing them. So as we said, the last level page table is basically just like you have another table, okay, that is table of structures. So some people just like to find table of pointers. So if you have just like a table of structures and then you have all these structures defined and you only have one entry that has a valid physical page entry, then for the others you need to set the state as unmapped. So depending, this is the general idea, but depending on your data structure, how you're implementing the page tables, you need to figure out what states you really need for your page table. So yes, if you're doing the list, there is no need because having a node in the list, that means you basically have a physical page. So that doesn't make sense to have the unmapped and mapped, but what you need is a state that mapped or swapped. Is that page in memory or in disk? So unmapped basically physical page is not allocated. Map means the physical page is allocated and is in memory. Swap means the physical page is allocated and in disk. So it's not in memory. So yeah, as you can see unmapped on VM fault, you allocate the page and then it is mapped because once the VM fault happened, once you just allocate an entry in your page table, then you need to again allocate the physical page for it. So on VM fault you call the page alloc, you allocate the page and then you give it the mapped status. And once there is a VM fault happens with just like you're out of memory, then you swap out that page. And then once the VM fault again happened and you figure out that the VM fault is for a process that tries to access a page, a virtual page that is swapped out, then you need to swap in the page to the memory. When you swap it in. Okay, so the physical page is basically used. Right? Should be, so yeah, that's what I was saying. For OS 161, we're not really implementing that dirty clean mechanism, but it's good for you to know. So it should be clean because you just copied out the content and disk onto memory and those both content are the same, right? So it should be clean. And just like if you want to understand how, yeah. But then the data structure with the reference to this you'll be actually seeing that spot, right? Yes, that's what we're gonna discuss, so. Okay. Yeah, so if you swapped it in, then it should be the same copy, so it should be clean. So these are the states for the virtual page states. Any question on these? Okay. So now let's revisit the TLB entry format. So as we said, we have these flags, which is the TLBO dirty and valid and no cache. But what we really need to care about now here is the TLB low dirty. And what we've said about that flag is that we set that flag to zero if the page is read only and we set it to one if it's read write. But now that we have the swapping enabled, we can just like use that flag much better. But before I continue, just like let you know this is an advanced. So if you're done, so you're not required to really implement this, but you can just like implement it later on if you're done. But it's a good idea to have an idea of what now with the swapping enabled, the dirty bit you can better use it in much more ways other than just like read only or read write. So this dirty bit of flag, we can use it either to determine if a page is a read only page, which we set it to zero. As we said, all read write page which we set it to one. So let's say you're implementing copy on write page and that's what I told you for as copy that you can for example, when you're copying the pages, you can also as an additional feature implement copy on write, which means you basically don't copy that page but you refer to the parent page and whenever a write happens to that page then you duplicate the page and write to it. So if you're implementing that feature which is implement on write page, copy on write page then you can set that flag to zero as long as you don't read as long as you read from that page. Once you write to that page then or once VM fold read only happens then that means you are trying to write on an existing TLB translation that the dirty bit is set for it to zero. So what you're gonna do is duplicate that page first and then you set that dirty flag to one to allow the write operation happens to that page. So this is another use. A third use that you can use with the dirty bit flag is protect the clean pages. So what you can do is just like even though that page you can read and write to it but you can still set that dirty bit flag to zero. So what happens is that as long as you read from that page, as long as you read from that page that's fine. Once a VM fold read only happens on it that means you need to change the page state to dirty if it's a clean and then set the flag to one to allow the operation to continue, the dirty flag. So these are just like an advanced usage of the dirty bit flag, any questions on this. Okay. So now swapping. Swapping basically is the process of moving data back and forth from memory to disk and the main goal is just like to have to let your system just like have a view of the memory that is as large as the disk and as fast as the memory. So there are two main interfaces for the swapping which is swap out and swap in. So swap out if we run out of physical pages and allocate pages or page alloc. So allocate pages, allocate kernel page for us, page alloc allocate user pages for us then we should swap out. Swap in and VM fold, if a VM fold happens and we determine that there is a user process that trying to access a swapped virtual page then you need to swap in that page from disk and probably you need also to swap out against some other pages if you don't have enough free physical pages available. So this is the swapping. Now let's discuss the swap out. So to swap out from memory to disk there are several steps that you need to follow. First of all is synchronization. So you need to prevent access to this page. So the picture is a little like that. I just like decide a page should be swapped out. That page doesn't belong to me and it belongs to other process that might be running on other cores. So this why we need to prevent access to this page. First, once we get a look on that page we make sure that there is no access on this page then we can move forward with the swap out which is we need to remove the translation from the TLB if it exists and then we copy the content from the page content from memory to disk. And if you're implementing the dirty and clean states then this should only happen when the page is dirty. But if the page state is clean you basically just like free access to that physical page and you just like save an IO on the disk IO for that operation. Once you're done with this then you need to update the page table entry just like of that process to indicate that your page is now on disk and it's not on memory. So we have a few questions for you to consider. Where should we store the page? How should we notify the process and where do we find the page later on when we wanna swap it in? So the first thing is swap storage. So you only have one option. Previously it was mentioned that you have two options just like file or a swap disk but I just confirmed this today. The first option was wrong, it's not correct. So you only have one option which you need to use a dedicated swap disk that you can check the disk configuration in sys161. Come fix, so this is sys161.com file. So if we go down you'll have complete description of what is in that file. So as you can see we have two disk here and previously we could just like use the MEMUFS but that's not correct as I said. So you only need to use one of the disks here so you have two disks basically what you need to use is one of them. The other was just like for assignment four file system but that's not used. So and the size 32 meg should be enough for our OS161. And so this is the option that you have for the swap storage and how should you open a file, a row file and that disk is basically in VFS open you need to set the file name to LHD0 row and then the flag should be read write. So and that basically will just like opens a swap file for you so when should you initialize a swap file that should happen during the VM bootstrap and main.c or somewhere around this. So the second question is how should we notify the owner? So as we said once you choose a page to swap out you should find where this page was mapped to how should we do this? Now if you remember when we discussed the core map we said one of the fields that you need to have in a core map entry is owner information and we said that this is for swapping that's what you need now. What is the owner information basically is the address space have a pointer to the address space and the virtual address. So you should not once you get the owner of that page then you should notify the owner by updating its page table to indicate that this page is now on disk and it's not in memory. So this is for the second question and the third where is the page? Now how should we manipulate the swap file? What you need to do is just like to divide the swap file into slots or swap slots and each slot should be of size 4K because you're swapping pages. The page size is 4K then it's much better to divide the file into 4Ks and each slot would refer to a page. So and you need also to implement a new data structure that is let's call it slot table. Sorry. So we can call it a slot table and that table was basically is a data structure that maps address space given the key is the address space virtual address and the value is the swap slot. So you need to find a way to map once you get an address space and the virtual address you need to find a way to just like to retrieve the swap slot corresponding to that address space and virtual address. So the requirement basically is it should be able to allocate swap slot. So if for a given address space and virtual address there is no swap slot allocated then you need to allocate one and this is basically happens in swap out. Or for swap in then given an address space and virtual address you should be able to retrieve that swap slot or basically let's say if you wanna make it simple the offset in the file. So yeah. And also it should be able to reuse the existing swap slot. So let's say an address space and virtual address has a swap slot allocated for it. You swapped out some page and then you swapped in you shouldn't really free that one on the on the swap file but what you need to do is just like make it reusable. So later on if you need to swap out then you can again reuse that existing swap slot that is already allocated, yes. So I think the idea is like a thing. Okay. Should we be using all five of those like once? So yeah, as I said, so the size of that table basically should be how much what is the size of the disc, the swap disc? You divide it by 4K. Yeah. So. Yes. Is this a core map for? Yeah. Yeah, the same thing, yes. The same thing. So. But I don't think, yeah. But as I said, I think you need to use more you need to increase the size of the swap disc. So five. Can you use the old size for this? Yeah, yeah. So it's the same as the core map. The actual size is not known at the compile time. You need to just like figure it out after you put the, yes. And yeah, for the size of the swap disc, I think 32 meg. That's what you need to use. Yeah. So any question on swap him? Swap out, sorry. A question on POV. Okay. Yes. Oh no, one CPU. So wait, CPU has four cores. Okay. So CPU has four cores. I think 160 is one here. It should be, I think. Yes. Oh yeah, because you have. So the MMU is part of the CPU. Then you have only 64 entries. And then yes, I don't. You need to have a few in your format which says that this page is actually in this CPU's chosen. That would be like really more old. So let's say it's the number of CPUs that's 32. That would be really old. Yeah, they're much simpler than the CPUs. Okay. Yeah, I'm trying to make it up to 32. Yeah. So I think the way to solve this problem is just like you need to think of all the data structure implemented and each data structure is a private to which. Which CPU? Yeah, which CPU, or which CPU process. So yeah, you know. If you're reading over 32 CPUs with like 64 entries each, it's gonna be. Yeah. So I think this is one of the things that you need. Double check in the office hours. Yeah, just to see. Anyway, so any other questions on the swap out? Okay. So let's move on to swap in. So swap in happens on a VM fold. One, basically when a user program tries to access a swapped virtual page, then the first thing that you need to do here is you need to find a swap slot, to find the swap slot and the swap table that correspond to that swapped virtual page. So you're gonna be given again the address space and the virtual address. And from that you're gonna retrieve the swap slot and swap table. And then you need to allocate a physical page and that's what might need to also swap some other pages if there is no enough physical memory available. So once you allocate the physical page, then you copy the content of the page from disk to memory and you update the PTE or the page table entry for that process to indicate that page is now in memory. So it looks easier, but you still need to just like keep in mind that you have the synchronization that you need to deal with. So this is basically the swapping. Any questions on the swapping? Okay. So the last thing we have here is address space with swapping. So how does the swapping changes the as copy and as destroy? So previously what we've said that AS copy basically needs to create an exact copy of the past address space structure and also copy every page in memory. Now we need to not only copy every page in memory, but also if a page is in disk, then we need to copy it also. Just like by creating either bringing that page in memory or just like if the page is in disk, the best thing or the trivial thing is just like to create or allocate another swap slot for it and copy that content into the new swap slot in the swap file. This is for the AS copy and for AS destroy, we're gonna dispose as we said, an existing address space structure and the free every page. So previously we said in memory, now we say in memory and in a swap disk. So you free the page in memory and you also need to free the page in swap disk and just like set that slot into available. So you can use it later on. So basically this is how swapping changes your address space interfaces. Any questions on here? Okay, so this is basically what I have for today. Next week we'll probably have a final review. So thanks for coming and any questions? Good luck with checkpoint three and I'll see you next week.