 So these are, I will put these up on piazza as well, but these are the midterm statistics. So we will hand, made a small change, we'll hand back your exams today after class. So come up to, well, now let's do them upstairs. So come up to 301B or that vicinity, and I'll give you your grades back, and maybe Aditya and Zehe will be there to help me. But yeah, I don't know. I mean, I don't know what to say about these numbers other than they exist. So again, I'll put these up on piazza so you can kind of compare. Looks like, let's see here, I guess a chance he's my laser pointer. Oh. Yeah, question five seemed very, so these include some statistics from the alternate midterm that other people took, which were different questions, right? But there's not too much mixing in. So this seemed like an easy question. I don't remember which question that was, but it was popular. Most people got the multiple choice. Anyway, I mean, these are what they are. But we'll put these up on piazza, and you guys can pick up your exams later today after class. Cool. All right, so today we are going to talk about, we're going to go back a little bit to Monday and maybe go over some of that again because I just had one of those lectures Monday where I just didn't feel like I nailed it Monday. So we'll go back and we'll try it again. So and then we're going to talk a little bit about, now that we have this nice idea of using pages as a fixed size segment to translate addresses, how does the kernel, so we're going to talk about the interaction between hardware and software, talk a little bit more about hardware and what hardware does, but there's this other question of how does the kernel store these mappings, right? And how does the kernel look up them efficiently when the kernel needs to? And then we'll talk a little bit, if we're assuming we get to this today about ways that the kernel can reuse, underutilize memory by moving its contents to disk, right? And when we might do that and why that might be a good idea. And then what happens if a program tries to use memory that I've moved to disk behind its back, right? All right, so right midterms after class, come up to the 301B 303 area. I also just wanted to mention this because this is a time in the semester where perhaps you guys have started to actually work on some of the homework assignments. So if you're having troubles with your partner, please come talk to us. Please be proactive about doing this, right? The earlier you guys come to us and talk about struggles you're having with your partner, the sooner we can intervene, right? If that's an issue, right? The partner difficulties are really up to you guys to define, right? So you guys at some point hopefully will graduate from this wonderful institution and go off into the world to do, you know, let's be honest, probably less exciting but more profitable things. And in that context, you will have to work with other people and you will find many of those other people to be a challenge to work with, or at least some of them. And so you guys, the partner portion of this class is designed to give you guys a little bit of preparation for this type of environment. But if your expectation of your partnership is that you and your partner are going to each do exactly 50% of the work, that's probably maybe a little bit unrealistic, right? On the other hand, if you find yourself doing 95% of the work and are really excited about it because it's really awesome, then maybe don't come talk to us, right? So this is, again, this is really up to you guys to define, right? And this is also a time when it's okay not to use piazza. Although, I don't know, if you wanna post funny things about your partner problems on piazza, I guess that would be okay. Maybe use the anonymous student feature, right? Okay, any questions about this stuff? Okay, here's these numbers again. They are there. Uh-oh. Clicker confused by slides. Uh-oh, slides confused by slides. Like this doesn't. All right, so any questions about paging? About pages, fixed size segments. It simplify the process of address translation and reduce internal fragmentation. So we're gonna do a little bit of review here. So we had this, we've been talking about this all along without really stating this explicitly, but we've been playing, we've been using a trick here, a common systems trick that's used to make something slow look faster. What is that, what is that trick, Nick? Nick rhymes with trick and caching, right? So we're gonna throw a cache in front of something. So the typical approach is, when you have something big that is slow, you put something smaller that is faster in front of it. So again, the L1 cache on your machine is very fast. Well registers are very fast, but there's only a few of them. The L1 cache is bigger, right? But it's a little bit slower. The L2 cache is even bigger and then potentially more slower. Memory is much bigger but slower and then your disk is huge and really slow, right? So you can think about operating systems as essentially managing a series of hardware caches, right? So what is the thing, but let's be more explicit. What is the thing here that is slow and what is the cache that I'm putting in front of it? What's the process here that's slow, Manish? When we're talking about virtual memory, what's the slow process that I'm trying to make faster? Okay, so that load and store is what causes me to have to do this, but AJ, what load and store causes the system to have to do what? Right, translate an address, right? So we talked about, and this would be equippling difficult to because you can't imagine how slow your system would be if every address translation had to be done by the kernel, right? So the kernel is too slow. So what's the cache that I put in front of it? Sean, Paul. Yeah, TLB or really this memory management unit in general that we've been talking about, kind of this vaguely defined MMU, right? The idea is that the kernel wants to be able to tell the MMU how to do the translations and allow the MMU to perform most of the translations by itself, right? So what's slow here is the kernel's process of manually translating addresses and the cache I'm gonna put in front of it is this MMU. So I'm gonna tell the MMU about some address translations and I want the MMU to be able to do them going forward, right? And we just talked about this, right? Or we use this translation look aside buffer and that's the particular part of the MMU that's going to, we're gonna talk about caching these translations, right? So you think about the MMU as a component that not only includes this cache but also is able to process those virtual addresses, right? So the CPU sends a virtual address to the MMU and the MMU sends a physical address back, right? Or punts and says I need help, right? But we hope that that doesn't happen too often. How do entries get into the TLB? Where did the TLB entries come from? We can, it's good I'm a lip reader because I can't hear you but I think that you said the right thing. The operating system tells the TLB what to do, right? So again, this is classic case of separation of mechanism and policy, right? The mechanism here is the TLB and the MMU translating addresses. The policy is dictated by the kernel. That's how we want it, right? We want the kernel to decide how addresses get translated and allow hardware to translate them quickly, okay? So we talked a little bit about how hardware could translate base and bounds type addresses and segmentations and segments, right? Using segmentation. But then we found ourselves having this problem, right? Which is that as segment size has changed that would cause problems for the operating system in managing the memory on the system, right? Specifically the potential for both external and internal fragmentation, right? Internal fragmentation in terms of unused pockets within the segments themselves. And external fragmentation in terms of as segment size has changed trying to reallocate segments in different parts of physical memory, right? So what we did is we said, let's make things simpler for ourselves. We're gonna choose a fixed size for the segment, right? And we're gonna call these new fixed size segments pages. And there was this trade-off here, right? So as the page, so what happens when the page size gets really small? Let's say I had very, very small pages. What undesirable thing starts to happen? So I'm gonna argue that that is actually what happens when the pages get big. What happens when they get small? Dan, we tried the same answer twice and it was still not right the second time, yeah. Why? Okay, we're getting closer, right? So Bart, you wanna take us the rest of the way? As the segment size gets smaller, I'm gonna have to tell the MMU about more translations but why is that? Yeah, so the cache in the MMU is a fixed size, right? So you think about it, the amount of memory that the MMU can translate without asking the kernel for help is the size of the MMU's translation cache times the amount of memory that each translation covers, right? As page sizes get smaller, the amount of memory that's cached by the MMU, the amount of memory it can translate without asking for kernel help goes down, right? Does that make sense, everybody? As pages get bigger, it goes up, right? However, as several people pointed out, as pages get bigger, what's the problem? Dan, internal fragmentation, right? Why? Because a page is some big bundle of content, right? And the pages we're gonna talk about either has to be in memory or not in memory, right? So here's another question. Hopefully you guys are developing some intuition about this. Why can't, so let's say I had like a 32K page. Why can't I move half of the page contents to disk, right? Or why can't I only have, you know, say, oh, why? You know, why not? Why can't I have 16K of the page that's in memory and 16K of the page that's in memory? Jeremy. Well, but again, I'm gonna say, let's say I'm gonna create this new concept called a page fragment, right? Which is 4K and my pages are now 64K, right? And I'm claiming I'm getting the best of both worlds. I can move around these little pieces of the page, but why can't I actually do this? I don't know, we're getting warmer, right? So again, I'm claiming I don't have to move the whole thing, but what's the problem here, right? So let's say that I'm trying to implement this idea. I have my big 64K page, right? And the page is in memory because the process has used it, right? And there's a translation that is cached in the MMU, right? Oop, sorry. So the MMU is caching a translation for this page. So while, so here's a question. While the MMU is caching a translation for the page, does the operating system, does the operating system know whether or not, does the operating system know anything about what parts of the page the application is using? I see shaking of heads, why not? Tim, I tell the MMU, this is how to map this 64K of virtual address to physical addresses, right? What doesn't happen for the rest of the time that that translation is in the MMU? What don't we want to happen? Why did we tell the MMU about the translation in the first place? Sumit. Yeah, we don't want the kernel to know, right? The MMU is sitting there translating all these virtual to physical translations behind our back and the kernel has no clue, right? So because of this, there's no, so for example, if I wanted to take a piece of that page and move it somewhere else or take it out of memory, there's no way to stop the process from using it, right? Because the, so essentially what's happening here is my protection granularity is also a page size, right? And this is actually true when we go back to thinking about how we grant and enforce and revoke memory, right? It's all now done on a page size granularity, right? I cannot give a, I cannot give a process, if I have a 4K page, I cannot give a process permission to only access 1K of memory. It's impossible, right? Because I give it a mapping for 4K and it can use any of that 4K, right? Without me having any idea, right? So this is something to keep in mind. If I have 1K of physical memory that I want a process to use, there is no way to do that with 4K pages, right? I have to give it access to the 4K that includes that 1K. Does this make sense, everybody? Nod your heads vigorously. Head banging sort of thing. Okay. So pages, besides setting our protection boundaries, right? Pages also dictate the size of these kernel data structures we're gonna talk about today that are associated with memory mint, right? So as page sizes get big, the other nice thing in the kernel is I don't have to keep as much state around, because fundamentally there are fewer translations to translate a fixed amount of memory, right? So if I take a fixed amount of physical memory, the way I allow a process to use it is I cover it with pages, right? So as the pages size gets bigger, I have to use fewer pages to cover the same amount of physical memory. As it gets smaller, I have to use more. And we talked a little bit about address and execution locality, right? And how this helps us, right? So we talked about the fact that if we look at the memory addresses that are actually used by a process at runtime, they are temporarily clustered within the process's address space, right? So I'm fetching a bunch of instructions from this one part of memory, right? And maybe I'm also using another page over here for data or something, right? And I do that for a while and then I jump over here to do something else because you clicked a different button or whatever, right? But there's a lot of locality, which means that a small cache of address translations on the MMU, right? So a small TLB actually goes a long way, right? So small, and you guys will find this when you do assignment three, right? Because the TLB on your system is not very big, but you'll find that when you start a process running fairly quickly, especially for the processes on your system because they're really, really small, right? So it's very, very easy to cache all the translations that one of your processes needs in a TLB with fairly limited size, right? Okay, so we talked about 4K, which is the kind of the common page size. There's some larger systems that allow, you know, I think some of the new x86 architectures have these huge pages, which could be like 64K, right? But we can think of in this class as pages being a specific size, finish. Yeah, I mean, we think of the MMU as a part of the system that performs virtual to physical address translation, right? One of the things that it uses to do that is a cache of address translations, right? But there's also circuitry involved in just doing the translation itself. So when we talk about the process of taking a page, a virtual page, or translating it to a physical page, part of that is looking up the virtual to physical page number mapping in this cache, but there's other parts of that, right? And all that circuitry is all kind of wound up in what we call the MMU, right? And we'll talk today a little bit at the end if we have time and if not on Friday about other things that x86 MMUs do in particular, right? So x86 MMUs are a little bit more sophisticated because x86 MMUs will actually use kernel data structures to look up translations, right? Behind the kernels back, right? Which further limits the amount of work that the kernel has to do, but it also ends up having to impact on the amount of control that the kernel potentially has, right? So again, we think of pages as fixed size segments, right? Pages are like what? Fixed size segments, right? Review slide follows material fairly quick, right? And again, all the virtual addresses on a single virtual page map to the same physical page, right? These are fixed size segments. So when we talk, and that's why we can split pages into this page number, right? Which identifies the virtual page and an offset, right? The offset is like a segment. It's to both the virtual page and the physical page. And again, if I load a translation for a page, all the addresses are gonna map to the same physical page of memory and there's no way to protect anything within that page boundary, right? So I can't protect 32 bytes of memory with 4K pages. I can't even protect two kilobytes of memory with a 4K page, right? So when we do page translation, we split the page, we split the address like we do with the segment, right? Into two parts. There's a part that identifies the page number and there's a part that identifies the offset within the page, right? And the nice thing about doing this is we can essentially take the virtual page number, replace it with a physical page number and that's how we perform the translation, right? So for 4K pages, it turns out again that we can do some nice bit masking here, which again, you guys will do this for assignment three, right? You take the top 20 bits, that's your page number. You take the bottom 12 bits, that's your offset. You map the virtual page number to a physical page number. We'll start talking about how we do that today and data structures that the kernel uses. And if a virtual to physical page translation exists, we simply replace the virtual page number with the physical page number and we're done. Does this make sense? This is essentially segmentation and because we're using a power of two, right? We can do these bitmap operations. You could have a thousand byte pages. You could, and then you would be a mathematician instead of a computer scientist, right? Because then you would have to do real math, right? So let's say you had a thousand byte page just for fun. How would you, what would the page number be for a thousand byte page? How would you determine the page number? Anybody wanna guess? Tim, front row, Tim. So let's say I have a thousand byte pages and I have a virtual address of 10,000. What page number, oh yeah, someone said, oh, that's easy now, right? Gave you powers of 10, right? I have virtual address 10,000. My pages are 1,000 bytes. So what's my virtual page number for a virtual address of 10,000? 10, right? It's 10,000 divided by 1,000. What if I had the virtual address 20,072? What would my virtual page number be? Powers of 10 math. Looked at 20, right? I'm essentially taking the virtual address and I'm dividing by the page number and I'm taking that offset part that's within the page that's ignoring. Let's do some examples of these, right? Okay, here's my TLB, right? So my memory map, these are virtual to physical page number translations that the operating system has told the MMU about. So these are the virtual to physical page number translations and now we will use hex because it's kind of easy to do this, right? So if I'm using 4K pages, right? This is a hex address. Every nibble, which is actually what they're called in the hex address corresponds to how many bits? Who's good with their hex? Four bits. Four bits, four bits per nibble, right? So who can identify the virtual page number for this address? Bethany. 4K pages means the top 20 bits are the virtual page number. The bottom 12 bits are the offset. Four bits per nibble, 12 bits per offset. I just like saying nibble. I'm gonna keep saying that again. Oh, you guys are gonna like how easy this is. Boom! Bottom 12 bits, right? Bottom 12 bits, four, eight, 12. This is my offset. Top other bits, right? I mean, if this was really a 32-bit address, I'd have a bunch of zeros out there, right? These are my page number, right? Does this make sense? Top 20 bits for a 4K page, virtual page number. Bottom 12 bits, offset, right? So you can literally do this. Just tear the hex address apart, okay? So where does this map to in the TOB? It is easy, right now. Yeah, so remember how my TOB works. I'm searching all these entries in parallel, right? This is content-adjustable memory. It's very efficient, right? And I get a hit, boom, right here, right? I look up and this is easy, right? We just didn't do this example yet, so that's okay, right? Now, how do I finish this translation, right? So I've identified the virtual page number for this physical page number. What physical address does this map to? Guru, who wants to tweak you? So, and what do I get? Oh, okay, so this is interesting. Do I add them together? What do you think, Paul? I replace the virtual page number with the physical page number, right? This is that the process of doing this is, we're doing it differently than we did segments. Yeah, great. So, okay, let's walk through this more slowly, right? The first thing I do when I translate a virtual page is I need to identify the page number, right? Because remember, the offset is the same in both the physical page and the virtual page, right? So here, right, this is my virtual page number, right? Hex 800, basically, right? This is my offset, right? The offset is gonna be the same in both the virtual and the physical page. So, I look this up in my TLB, I find that virtual page number 800 translates to physical page number 306, I replace the virtual page number with the physical page number, right? So I don't add the offset in, right? I'm actually doing that, right? I actually am adding the offset in, but I'm doing it using this trick by splitting the hex number into parts and replacing the top 20 bits, right? So now what I've done is I've taken my virtual page number and I've translated it to physical page number and this translation is complete, right? I wish I had an example here. You could do this with our old friend, the segment, right? So you could look this up in a segmentation table. All the segments would be the same size, right? You would remove the offset from the segment, right? Which is 346. You would translate the segment and then you could add the offset back in, right? It would work the same way, but because we're doing powers of two and because we're removing 12 bits, right? We can do this nicely here, right? Does this make sense? Let's walk through another example, right? How does, so how do I translate this address to a physical address? Let's step one. Yasha's. What's that? So what's, okay, what's my virtual page number? One zero, virtual page number 10, right? And what's my offset? Three 36. What physical page number does this virtual page number translate to? 50 and so what is the final address that this page translates to? Correct. Zero five zero three three six. How many people does this make sense to? Good. You guys are giving me these confused looks. It's like confused Wednesday or something and nobody told me, okay. So, okay, we talked about this, okay. So we talked about where entries in the TLB come from, right? So the operating system is gonna tell the MMU, here's an entry to put in your cache, right? This is very, very similar to segmentation and base and bounds, right? But what happens if a process tries to access an address that is not in the TLB, right? So a process tries to translate a virtual address and the TLB does not have a virtual physical page number mapping for that address. What happens, Alyssa? What can it do? What must it do? What, okay, so I have a better question. What can't it do? If there's no mapping, it can't do what? It can't access the address, right? It can't translate the address, right? And this is a load operation, right? Is there like a raise exception with this? Like is this Java, right? Could I throw an exception to the program? No, like this address either has to do what? It has to translate or it has to what? It can't complete, right? There's no way to complete this, right? So what does the TLB have to do? There were hands over here. Yeah, great. Ask the kernel. How do I, and how does the TL, how do you think the TLB asks, asks is the kernel for help is? Remo. It raises an exception, right? So this is our old friend, the exception, right? When there's a missing entry in the TLB, and this is now, I just wanna point this out, this is specific to a certain type of TLB architecture, but this is the one you guys are gonna be using for assignment three, so it's a good one to talk about. When there's a missing entry in the cache, the MMU calls for help, right? It says to the kernel, I don't know anything about this address, right? And then the kernel has to do, what does the kernel have to do at this point? The kernel has a couple of choices. What's one choice? Okay. I could terminate the process, right? What's a, what else might this result in? We might just call it a new, so. Okay, so if it's not, right, I'm gonna do this check, and if it's not a valid address, I'm gonna terminate the process. If it, let's say it is a valid address, then what do I need to do at that point? Frank. Yeah, I need to tell the MMU how to translate it, right? So I need to tell the MMU here's a page mapping, right, for this. So again, this is, these are, you can think about these as fixed size segments, right? Is the address in a segment? No, ask the kernel. Kernel says either there is no segment for that, as I never told the process it had permission to use it, I'm gonna kill that process, or it tells the MMU here's how to translate 4K worth of virtual addresses, right? So remember we talked about segments, we said that there was this trade-off. Each exception that the MMU caused allowed it to learn how to translate a certain number of addresses. So how many addresses does the MMU learn about at a time with pages? Tam. Four, or you were moving in the right direction with that answer and then there was a missing, Andrew? 4K, right? Four, I mean four would be kind of terrible, right? But at least this way, one exception and hopefully I've told the MMU, like I have, I've told the MMU how to translate 4,000 bytes, right? That's nice, right? Okay. So one of the nice things about pages is that as somebody was asking about before, frequently kernels still think about address spaces as being composed of segments, right? But all the MMU knows about are page translations, right? So what I can do is I can take a segment and I can basically break it into pages, okay? The segment, the ideas behind segmentation in terms of a segment having a logical purpose, right? And a segment having permissions that are associated with it, I can still just push those down to pages, right? So for example, if a segment is marked as read-write by the kernel, what does that mean about all the page translations that are inside that segment? Sarah, they're marked read-write, right? Page is just inherent, the permissions of the segment. But segments are kind of a nice way for the kernel to think about the virtual addresses, right? This is why again, when you guys mess up and see, I almost said a bad word. If you mess up and see, you still get a segmentation violation, right? What really happened is that there was a page translation missing for your process and it was killed by the kernel, right? But what the kernel tells you is you violated segmentation, right? So I can still do this, so I can still organize and protect regions of memory appropriately by just kind of inheriting these ideas from segments, right? This is even a better fit for address, better fit for address spaces, right? So I have less internal fragmentation than segmentation, because my allocation size is small, right? So I give the process permission to use 4K of memory and while that translation is loaded, it's allowed to use that 4K, right? But remember in a segment, I might have told the MMU, I might have to have a gigabyte of memory resident because I've told the MMU how to translate all those addresses, but the process might be only using a teeny, teeny piece of it, right? So this protrudes the internal fragmentation and also again, fixed allocation size means no external fragmentation, right? And this is fantastic, right? The kernel can never, the kernel will never not be able to allocate a page if it has memory available because if it has memory available, it has memory available in sizes of what? A page, right? Like I broke up memory into pages and I give out pages and all I get are allocations of one, two, three pages and again, the nice thing is, so what's also true? Let's say I have three pages, let's say I have four pages in the address space of a process that have been allocated, right? That are contiguous and the process asks for a fifth page. Do I have to allocate those five pages contiguously in physical memory or not? No, right? So I just find a page anywhere, right? If there's a page available, I can satisfy that request, right? So remember which segments those segments had to be contiguous. Every page is contiguous, but multiple page requests can go anywhere, right? I can map those page requests anywhere I want, okay? One of the problems with pages though is that I'm only telling the hardware how to translate 4,000 virtual addresses at a time, right? Whereas with segments, I could potentially tell it how to translate a million virtual addresses at a time, right? The other problem here, which we'll talk about on Friday is that this requires per page state within the operating system. And so there are all these tricks that the operating system is gonna start to play to try to make this state small, right? If the kernel had to save information about every page in the processes address space, that would be potentially bad, right? But what we want is we want a way to save only information about valid pages in the address space. All right, so the ideas with page state are, I have two goals, so on Friday what we're gonna talk about is how does, when the kernel gets involved, right? So we've talked essentially, we're pretty much done talking about hardware, we'll talk a little bit more about some hardware features on Friday that are different than what we've talked about, but we're pretty much done talking about the MMU. Now what we're gonna talk about is what does the kernel do when the MMU calls for help, right? And how does the kernel make this part of it as fast as possible, right? So when the MMU doesn't have a translation available, it's gonna ask the kernel to load one. The kernel has to keep all this state about the translations that are valid for each process, and so on Friday, we will talk about how, oh gosh, it's like 940. Well, maybe let's talk about it a little bit more. I'm sorry, my unit of time is off today, so I thought we were almost done. Somebody's peeking in the door. Okay, so let's talk a little bit about some of the state and then on Friday we can sort of wrap things up, right? I like this stuff, so maybe time's just going rapidly. All right, so again, now we're in the kernel, right? And then we have to think about what state, so when the MMU asks for help, right, what does the kernel have to be able to tell it? So first of all, what is the MMU going to tell the kernel, right? When the MMU raises an exception, what state does the kernel have to, what does the kernel have to know, Sam? Okay, it needs the virtual address or the virtual page number, potentially that it was trying to translate, and then what else might I need, Jeremy? Oh, yes, very good. Why do I need the process? Why do I need to know what process was running? Sumit. Well, but this is a separate thing, so I also need to know, so I need to know the virtual address that it was trying to translate. I need to know what happened, right? Was it a load, was it a store, was it a fetch, right? Was it trying to execute from this instruction? Why do I need to know the process? This is a great review question, because the virtual address has no meaning outside of a process context, right? It is, if I tell you translate virtual address 10,000, you cannot answer that question, right? Is it impossible? It means nothing, okay? Now, in actuality, the MMU doesn't have to tell the kernel what process is running normally. Why not? Well, okay, you can do a one-word substitution and that answer and it'll be correct. Who knows what process is running? Yeah? Yeah, the kernel scheduled the process, right? So the kernel knows, right? The kernel knows that, oh, yeah, okay, you know, like, yeah, that process is running, right? It's on the running queue I assigned it to the CPU. Now there's an exception that emerges from that CPU, so the kernel knows this, right? Typically, actually, the hardware doesn't really know about processes that much, right? The kernel has an ID and other things, so the idea is that the exception occurs in the context of some process executing, right? And the kernel needs to know that, okay? Okay, so I need to know what process was running. I need to know the virtual address that it tried to translate and I need to know something about what it was trying to do, right? What information do I need to tell the MMU when I'm finished? Well, I need to complete the translation, right? But specifically, now we're talking about pages, so we're using page language. What do I need to tell? What do I need to tell? Harish. I might need to tell it to permissions, right? Sometimes the hardware is gonna help me in enforcing read-only or read-write or read-write execute, right? But what's the most important thing? I'm ignoring you, Greg. Yeah, I was calling on yawn. Okay, right, so the location of physical memory, what do we call that? What's that? A physical page number. A physical page number, right? So the request comes in, it says, I don't know how to translate a load to virtual page number X, right? The process is aha, the kernel says aha, this was the process who was trying to translate this. And if that address is valid, right? That's the first thing I need to determine. If it's valid, I need to tell the MMU this virtual page number maps to this physical page number, right? So this is the transaction that has to go on, right? The data structure that's used to store a single entry, right, a single virtual physical page number mapping is usually referred to as a page table entry, right? Or we colloquially refer to them as PTEs, right? And we'll talk about why they're called page table entries, you know, in a slide or two, right? But a page table entry is designed to incorporate all of the information about this translation. And on modern systems, right, so first of all, there's gonna be a lot of these, right? The kernel will have a lot of these floating around, okay? How many page table entries, conservatively, will the kernel have to keep track of? By a five processes, each process, you know, just explain how to do the math one way. Okay, page table entries, sorry, not page tables, right? So one for, I definitely, it definitely scales with the number of processes, but what else does it scale with? It's positive. The amount of virtual, it turns out the amount of virtual memory that the process has allocated, right? So if I have five processes, if I have a system that is half gigabyte of physical memory, but I have five processes that are each allocated a gigabyte each of virtual memory, then I need to have page table entries for all of that virtual memory, right? Because it turns out that this page table entry is also gonna contain information about where the page is, even if the page contents are not in memory, right? So the page table entry is designed so the kernel can find out information about this specific page, right? It could be that that page table entry contains information about where it is in memory, but it also could be that it contains information about the fact that it might not be in memory at all, that its contents may have been moved, okay? So modern systems play a lot of games with these to make them small, right? So if you look at Linux and Windows, they have all of these bit masking things and bit packing stuff, right? This is not a structure that you just like allocate and allow it to sprawl over like 64 bytes, right? Like they try to jam this stuff together, right? So it's like, if the first bit is one, then I interpret the next eight bits as the whatever, and if the first bit is zero, then I interpret the next six bits as something, right? There's a lot of messy stuff that goes into trying to cram. It's much information. Ideally, you try to get these into like four bytes, right? Because usually like four bytes is an allocation size, but you try to make these as small as possible, okay? And there we go, right? So here's our goal, right? Jam everything into one 32-bit machine word, right? So some information about the location, right? That could be a virtual page number. If it's on disk, right? If I've moved the contents to disk, which we'll talk about next week, then I need to also, like wherever the page contents are, this location has to allow me to find, right? You know, the permissions, valid bits usually tell the kernel, is this page actually resident in memory or has it been moved? And then for, and we'll talk about this again more next week, for tracking the access to pages, I usually have some state in the page demo entry that helps me determine whether this page has been used, right, or how frequently it's been used. And this is something that's gonna concern us more next week, Jeremy, yeah. Yeah, yeah, that is, if you've set up a Linux system before and you've allocated space on your hard disk for swap, right? And swapping, which we will talk about next week, that's where pages go when they're not in memory, right? That's one of the places that the kernel will put them, right? It turns out that you should have, you have more than an academic interest in the format of these page table entries because you guessed it, for assignment three, you get to format these entries yourself, right? You will get to design your own page table entries and implement them and you will have to use them to figure out where things are, right? So again, usually the location, again, my location, if it's a 32-bit address with a 4K page is 20 bits, right? So frequently I can use four bits for read write, execute permissions, I might have one bit for valid and then one bit and look, you know, I still have a, I still have six bits left for fun, you know, to store, to store little messages I'm sending to the page, you know? I don't know, whatever. So yeah, there's tricks that people play to try to get all this stuff into a very, very small package. I think on modern systems I'm guessing that a lot of times now these are 64-bit structures, right? I should look on Linux and see how well they've done, right? I think at some point when machines started to have more memory, these structures kind of spilled over 32 bits, right? And then once you pass 32, might as well go to 64. All right, so let's talk about how this works, right? So the process is going to tell the MMU store to address 10,000, right? The MMU is gonna say, I have no idea where this address is, right? And it's gonna ask the kernel for help, right? What happens now? Just, this is a review from five minutes ago. Who, how does hardware get the kernel's attention? Throws an exception, yeah. We like to say raises, right? Once you say throws, then I feel like I'm worried you're talking about Java or something, right? Like it raises an exception, right? Of course you can be talking about Python if you say raises, right? But the point is that there's a electronic signal that is sent to the kernel by means of changing the logic value on a line that's connected to a port on the kernel, right? So yes, it raises an exception, right? So now we have this challenge, right? Because now, think about this, right? We want memory translation to be fast, okay? And the MMU is in general fast, but as soon as the MMU gets into the kernel and asks the kernel for help, what is already true about this translation? What do we want to happen? For most cases of virtual to physical translation, what do we want to happen? Wembley. Yeah, so once we get to the kernel, things are already going wrong, right? Not wrong in the global sense. This is a normal part of process operation, right? But wrong in the performance sense where we're already slow, right? Like this is already taking forever, right? And now if the kernel is like super disorganized and takes like all this time to find the translation, now it's just getting worse and worse, right? So if you think about it, you're already on a very, very sort of hot code path, right? And you're already taking like thousand times longer than you want to, right? So don't add, you know, misery to something that's already miserable, right? So the requirements for how we locate this information, there's two of them, right? And these two requirements are completely, this is another case where we have an interesting design trade-off that we're gonna talk more about. Because these two requirements are completely at odds with each other, right? The first requirement is speed, right? Again, we're on a hot path here. This happens a lot, right? And actually it usually happens a lot at a time where the process is already running slowly for some reason, right? So the process is already throwing these exceptions and I'm gonna slow it down more, right? So I wanna be able to do, I wanna be able to find my page table entry as fast as possible. The other thing is, if the data structures that the kernel uses to store these translations take up 90% of the memory on the system, then it doesn't matter how fast they are, right? Because now I'm forcing processes to use so little memory that they might not, I'm limiting the effectiveness of the system. Oh, yeah, great question. Where do these data structures live? They live in memory, right? And so if I see where you're going with this, can I have a page fault or can I have a case where the data structures that are necessary to translate a page address are themselves not resonant in memory? And the case is, yes, you can and we don't talk about that and you don't have to implement that for assignment three because it gets, you can if you want to, right? Mark Zuckerberg's partner in this class when he was a TA for the course declared that he was going to get this to work. For OS 161, which you can do, as far as I know, he never did, but it is possible we don't encourage people to try it, right? So it can be that and we'll talk next week about what happens when things get moved to disk, but on modern systems it can be the case that these data structures themselves can be moved to disk, right? So imagine that I'm in the process of trying to translate an address, right? And the kernel now uses a virtual address that itself needs to be translated, right? So now I have what's called a recursive exception, right? And the process of generating, of trying to address a page fault that was generated or sorry, a virtual memory exception that was generated by a process, the kernel itself can cause other exceptions with which it has to handle, right? So this can get very, very complicated. Okay, so it's a good question. You guys can start packing up. I don't wanna get into too much detail about this, but the reason why the kernel would use virtual addresses, especially for storing this type of information is the same reason that processes would, because if I have a virtual address, I can move it, right? If the kernel uses a physical address for its, so when you guys implement this for the VM portion of this class, we will tell you to put all of your kernel data structures for address translation in physical memory, right? And you will use addresses that are hardwired to physical memory. If you do that, there's no way that they can ever move, right? Once you use them that way, if you wanted to move them to disk, right, to free up memory for some other purpose, it's impossible to do it, right? So the reason why the kernel uses virtual addresses is the same reason that the process is, right? And that's why on your system, for example, there's a portion of the kernel address space that will translate, right? That requires translation by the MMU. All right, so on Friday we'll talk more about how to do this efficiently and fast, and if you want your midterm, come upstairs.