virtual memory addresses?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
com1
Member
Member
Posts: 105
Joined: Sat Apr 28, 2007 11:57 am
Location: TN

virtual memory addresses?

Post by com1 »

hey,


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?
oh microsoft, microsoft, what souls you have dismayed
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

A virtual memory address is just a 32-bit (in x86) address. That address gets run through the MMU (memory management unit) and the paging/segmentation mappings are applied, resulting in a physical address.
User avatar
jerryleecooper
Member
Member
Posts: 233
Joined: Mon Aug 06, 2007 6:32 pm
Location: Canada

Post by jerryleecooper »

But you shouldn't allocate address 0x00000000, no? Or yes? :cry: :x
Doesn't the null segment descriptor prevent the use of address 0 paged?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

There is nothing preventing you from using address 0. The first dword of the realmode IDT is at physical address 0 at boot time, and it works just fine. It is just conventional to make 0 an illegal address in software. So it's more that you would just screw up the error-checking in 10 million C programs if you make 0 a legal variable address (but you can always make that the beginning of the virtial code-space for an app if you want).
urxae
Member
Member
Posts: 149
Joined: Sun Jul 30, 2006 8:16 am
Location: The Netherlands

Post by urxae »

If you put the beginning of the code at address 0, how would you check for an illegal function pointer? :)
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

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.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

Thanks for that, Kevin. I needed to see it again. I think you forgot to mention that you still need to copy the bottom 12 bits of the vaddress into the paddress after doing the translation: | (vaddress & 0xFFF)

And urxae is right, of course. You can put 4k of _init code into virtual address 0 if you want to, but after it is run, you need to set the Page Table entry for address 0 to prevent any access to that 1st 4k page. This gives you instant hardware detection of any attempts by software to access any NULL pointers.
Post Reply