i have read some stuff on virtual memory and paging and so far i understand it except for the virtual memory addresses. just what ARE the addresses? like 0000 0000 - FFFF FFFF?
When virtual memory is not enabled (CR0:Bit 31) memory addresses heading from the CPU to RAM are pretty much direct and unaltered. A address of
0x82736212 hits the RAM or circuit right before the RAM with the address of
0x82736212.
[CPU]->[TLB]->[RAM]
When virtual memory is enabled all addresses pass through a extra stage. If I am not mistaken this is generally the TLB. The TLB will decode the address of
0x82736212 into another address using a set of tables. This set of tables reside in RAM (which were loaded earlier).
Code: Select all
struct PageTable{
unsigned long entry[1024];
};
struct PageDirectory{
unsigned long table[1024];
}
Each table governs 4MB of memory and its offset it relevant to it's index in the page directory. To govern 4MB of memory each table maps 1024 pages.
(1024 * 4096 = 4MB).
The page directory in total can govern 4GB of memory.
(1024 * 4096 * 1024 = 4GB).
This entire structure, all tables associated with the directory and the directory it's self, is loaded into a cache which I am guessing is located on or right beside the TLB (circuit/chip/unit). To decode a address the TLB uses a algorithm. The below is the algorithm in a manner that you would use and can understand, but the concept is exactly the same! Just that the implementation may differ and most likely does in the TLB.
Let vaddress equal the virtual address.
Let paddress equal the physical address.
paddress = ((unsigned long*)(pd[vaddress >> 22] & ~0xFFF))[vaddress << 10 >> 22] & ~0xFFF
This is done for each address that needs to be decoded. The
vaddress is the address to decode and the
paddress is the decoded address. The TLB is decoding virtual addresses(
vaddress) into physical addresses(
paddress).
paddress = ((unsigned long*)(pd[vaddress >> 22] & ~0xFFF))[vaddress << 10 >> 22] & ~0xFFF
The 'pd' variable is a pointer to the page directory.
If we turn the equation around we can map physical address to virtual ones.
((unsigned long*)(pd[vaddress >> 22] & ~0xFFF))[vaddress << 10 >> 22] = paddress
If
vaddress equals 0x8273000, and
paddress equals 0x27000. Then the virtual address 0x8273000 would always decode into 0x27000 when going through the TLB.
((unsigned long*)(pd[0x8273000 >> 22] & ~0xFFF))[0x8273000 << 10 >> 22] = 0x27000
To make a 1:1 mapping which is where virtual addresses equal physical address you could do:
Code: Select all
for(unsigned int x = 0; x < (1024 * 1024); ++x)
{
((unsigned long*)(pd[(x << 12) >> 22] & ~0xFFF))[(x << 12) << 10 >> 22] = x << 12;
}
[10BITS:1024][10BITS:1024][12BITS:.... ]
Of course there are special flags used in the lower twelve bits. These flags are _very_ important and having them all zeroed will result in CPU fault.
#define V_PRESENT 0x1
#define V_WRITE 0x2
#define V_USER 0x4
((unsigned long*)(pd[0x8273000 >> 22] & ~0xFFF))[0x8273000 << 10 >> 22] = 0x27000 | V_PRESENT | V_WRITE | V_USER
Also the actual tables need there flags set.