Memory Management Unit: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
(Moved it into the global namespace, going to remove the one in my namespace. Should be a pretty useful article ^_^)
 
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(8 intermediate revisions by 7 users not shown)
Line 1:
The '''MMU''', or '''Memory Management Unit''', is a component of many computers that handles memory translation, memory protection, and other purposes specific to each architecture.
 
== Translation ==
The MMU's main service to the computer is memory translation. Memory translation is a process by which virtual addresses are converted to physical addresses. We can say that the virtual addresses are ''mapped'' to the physical address. This gives us the ability to create a memory model in our own fashion. That is, we can rearrange how the memory ''seems'' to be ordered.
 
For instance, this technique is used when creating a [[Higher Half Kernel]]. The kernel is loaded at location x, but when [[paging]] is initialized the MMU is told to map location x to 0xC0000000. This then creates the effect that the kernel actually '''is''' at 0xC0000000.
 
== Protection ==
Because we can make memory seem however we want, we can make each process appear that it is the only process on the machine. Moreover, because the process can only see memory that it has, it cannot modify or copy any other application's memory. This means that if an application is to fail, ''it'' will fail, but nothing else.
 
== Discourse on Memory Management Units and Virtual Memory systems in contemporary architectures ==
 
Line 7 ⟶ 17:
As a rule, a chipset (motherboard) would tend to have N bytes of physical memory. Physical memory is "real" memory which should be globally visible to all processors. Under normal operation, or rather, when the CPU is operating without its Paged [[Memory Management Unit]] turned on, any address the CPU encounters will bypass the (P)MMU and go directly out onto the address bus.
 
I'd like to move directly into the idea of a [[TLB]], and how "paging" works, etc. Many processor architectures of the day specify a set of behaviours that the processor will exhibit when the OS software activates the processor's PMMU. But what *is* a Memory Management Unit? A Memory Management Unit is a cache of translation information. When a processor allows multiple "virtual", independent address spaces to be used on a machine such that the CPU sees one stretch of "virtual" memory which can be mapped to any physical page, there must be some form of tabling, or other record-keeping of which physical frame each virtual page should cause the processor to eventually access on the address bus.
 
To clarify: A processor with a MMU that provides virtual memory has an on-chip cache of "translations". Each "translation record/entry" tells the CPU the mapping of one virtual address to one physical address. Let us imaging this on-chip cache as a big lookup array of entries that are of this form:
 
<sourcesyntaxhighlight lang="C">
// Abstract model of a TLB.
 
typedef ubit32uintptr_t vaddr_t;
typedef ubit32uintptr_t paddr_t;
 
// Flag to mark an entry in the modelled hardware TLB as having been set for use as a valid translation.
Line 24 ⟶ 34:
vaddr_t entry_virtual_address;
paddr_t relevant_physical_address;
ubit16uint16_t permissions;
};
 
// Instance of a hardware Translation Lookaside Buffer.
struct tlb_cache_record_t hw_tlb[CPU_MODEL_MAX_TLB_ENTRIES];
</syntaxhighlight>
</source>
 
Your processor's TLB is essentially a hash lookup table of entries that tell what physical address each page refers to. When you enable paging, every address reference is sent out to the TLB for lookup. The CPU does something like this internally:
 
<sourcesyntaxhighlight lang="C">
// Model routine for a TLB lookup.
 
Line 48 ⟶ 58:
return 0;
}
</syntaxhighlight>
</source>
 
If the TLB contains an entry for that virtual address, that virtual address's recorded physical address is returned. The CPU *does not* care about the actual state of the REAL translation in memory! *You* are responsible for ensuring that the information in the processor's TLB is correct. Let us pretend that our processor's TLB has an entry in it that records the virtual address 0xC0103000 as pointing to the physical address 0x11807000. Assume that your kernel has changed this information in the page tables in RAM; Your writing to physical RAM does not affect the on-chip TLB. UNLESS you tell the processor to flush that TLB entry for 0xC0103000 from its TLB, the next time 0xC0103000 is referenced, the CPU will look into the TLB, and go right on ahead to send out the physical address 0x11807000 that the TLB *says* the address corresponds to.
 
A processor architecture would normally, then provide an instruction to invalidate TLB entries, either en massmasse, or one by one, or however the CPU designers decided. Let's try to model a TLB flush. In our model CPU architecture, there is an instruction that software can issue which will invalidate one virtual address. It is called: TLBFLSH. An OS would invoke this on our model architecture by doing something like this:
 
<sourcesyntaxhighlight lang="C">
asm volatile ("TLBFLSH %0\n\t"::"r" (virtual_address));
</syntaxhighlight>
</source>
 
And on to our model:
<sourcesyntaxhighlight lang="C">
// Modelled function for a flush of the TLB modelled earlier on.
 
Line 73 ⟶ 83:
};
}
</syntaxhighlight>
</source>
 
Now please understand that a CPU will, as long as you enable its MMU, *always* use the TLB before sending an address out onto the address bus. That is, once you enable the MMU, until you take it off, you have essentially "trapped" yourself in a virtual address space. Unless you can edit that virtual address space by editing the page tables, and invalidating the TLB entries for virtual addresses, you have no means of changing where your kernel can read from/write to in RAM. Enabling paging means that ALL of your data and instruction fetch addresses will pass through the TLB first.
Line 132 ⟶ 142:
<li>The CPU takes the virtual address, 0x00200xxx and splits it up, 10 bits, 10 bits, and 12 bits.</li>
<li>The CPU now knows that it must index into entry 0x0 of the page directory pointed to by CR3, and then index into entry 0x200 (512) of the page table pointed to by the page directory in CR3.</li>
<li>CPU begins page table walk. The OS has written 0x12345xxx into CR3. The CPU assumes that this is the address of a valid page directory and sends out (0x12345000 + 0x0 * sizeof(pdir_entry_t)) onto the address bus as a dworduint32_t fetch. That computes to the physical address 0x12345000 being sent out on the address bus.</li>
<li>CPU gets the 4 bytes from the memory controller on the data bus, and interprets the 4bytes it just got from our page directory index 0 as a page directory entry.</li>
<li>CPU sees that this page directory entry is 0x12344xxx, as in our example above. 'xxx' are the permission bits. The CPU checks these, and since we're just gansta like that, they're correct, and the entry is PRESENT.</li>
Line 151 ⟶ 161:
<li>The CPU takes the virtual address, 0xFFFFFxxx and splits it up, 10 bits, 10 bits, and 12 bits.</li>
<li>The CPU now knows that it must index into entry 0x3FF (1023) of the page directory pointed to by CR3, and then index into entry 0x3FF (1023) of the page table pointed to by the page directory in CR3.</li>
<li>CPU begins page table walk. The OS has written 0x12345xxx into CR3. The CPU assumes that this is the address of a valid page directory and sends out (0x12345000 + 0x3FF * sizeof(pdir_entry_t)) onto the address bus as a dworduint32_t fetch. That computes to the physical address 0x12345FFC being sent out on the address bus.</li>
<li>CPU gets the 4 bytes from the memory controller on the data bus, and correctly interprets the 4bytes it just got from our page directory index 1023 as a page directory entry.</li>
<li>CPU sees that this page directory entry is 0x12345xxx, as in our example above: this entry references itself! But the CPU does not check that; it simply checks the permissions, and gets ready to interpret that address in the page directory entry as a page table's physical address. 'xxx' are the permission bits. The CPU checks these, and since we're just gansta like that, they're correct, and the entry is PRESENT.</li>
Line 165 ⟶ 175:
 
And now that we understand how the self-referencing page table trick can be used to read from and write to the current page directory, we'll examine how to read from and write to the page tables in the current process next. A note: 0xFFFFF000 is a valid address to any program unless you map it as SUPERVISOR, or in other words, you leave the USER bit unset. Otherwise programs in userspace will be able to edit their own page tables. Imagine a program deciding to start mapping pages in its address space to the kernel at physical address 0x100000? It could very well now decide to zero out the kernel in RAM.
 
==See Also==
* [[Paging]]
* [[Segmentation]]
=== External Links ===
*[http://en.wikipedia.org/wiki/Memory_management_unit Memory Management Unit] on Wikipedia
 
 
[[Category:Memory management]]
[[Category:Physical Memory]]
[[Category:Virtual Memory]]