PS: When enabling paging, do I have to start from physical address 0x0 or from the end of kernel (would make more sense to me).
As Solar stated the design of your addressspace is up to you, but
you have to start from 0x0 anyway by the means of mapping theses pages. Again you got to distinguish between physical locations of pages and their actual virtual mapping.
The memory starting from 0x0 definetely needs to be mapped at a place where you want it to be in your addressspace. As you will lateron need to access device registers etc. It doesn't matter though if you identity map it - accessing it at the same addresses virtual as their physical pendant or use a higher half scheme - all up to you.
The same for the kernel, those pages that hold it need to be mapped in, otherwise you will get a pagefault resulting in a double fault at once when activating paging (as the interrupt handler can't be reached though and that's another page fault). Therefore you need to map all the memory in you use till now, where you map it is totally up to you.
And then, how can I map any physical page to a virtual address?
Have a look at how a virtual address is structured. eg. 0x100000 (1 mb)
Code: Select all
[0000000000] [0100000000] [000000000000]
PDE(10bits) PTE(10bits) OFFSET(12bits)
That would be the address in binary. Now look at how it is split -
10 bit - 10 bit - 12 bit. Think of the maximum values these patterns can hold. 2^10 = 1024 / 2^12 = 4096.
Now if the MMU needs to translate the 0x100000 virtual to the appropriate physical address it does the following.
CR3 holds the physical address of the page that contains the page directory entries. These entries (PDE) are 4 byte in size.
Now back to our address - the PDE part was 10 bit, therefore it can address every PDE that is in a page directory. (the page dir) 4096 / 4 bytes per PDE = 1024 PDEs per page directory).
Code: Select all
PDE:[bit 31 ...page frame ... 12][11 ... attributes ...0]
Natively a 32bit cpu can address 4 gb of memory.
If you calculate how much pages that are (2^32 / 4096) you will get 1048576 pages. The PDEs page frame part is 20 bits.
Now calculate 2^20 and guess what's the page frame part of the PDE for. You will see that this part can address any page of the 1048576. The attributes are for managing access rights and stuff like that.
Now think of the PDE's page frame part as the physical address of a page that is used as a page table. A page table consists of page table entries (PTEs) which got the same format like PDEs.
Therefore there are again 1024 PTEs per page table. And again do these have a page frame part that can address any page of those 1048576 that could be there.
Now back to the virtual address - look at the PTE part - it's 10 bit wide - similiar purpose it's indexing the appropriate PTE.
Using the page frame address of that indexed PTE the MMU now knows the base address of the page that is addressed by that virtual address. Now the last part is the offset part of the virtual address. This is just the offset into this page. 2^12 = 4096 therefore every byte of the page that was pointed to before by the PTE, can be accessed.
As this whole construct works on the physical addresses of pages the virtual addressing is realized through simply putting the physical page that is addressed by 0x100000 in another PTE than that which gets accessed by this mechanism if you access the virtual address 0x100000.
Just as a small calculation example to demonstrate this:
Again the 0x100000 virtual address in binary
Code: Select all
[0000000000] [0100000000] [000000000000]
The MMU then would look up the very first PDE as the index is zero. Then it would take the 256th PTE [0100000000] of that page table.
Now if this would be identity mapping this PTE would contain
Code: Select all
[00000000000100000000][attributes]
Which would access the physical page that is addressed at 1 mb.
But as it's totally up to at which virtual address you map which physical page you could also map the page that has 1 gb as physical address here to be accessed at 1 mb virtual.
The other way round is therefore also possible as you can map the 0x100000 phys to be accessed at 1 gb virtual.
Then you would need to calculate which page table and the appropriate index for insertion.
Code: Select all
PDE = ([page aligned virt addr] / 4096) / 1024
PTE = ([page aligned virt addr] / 4096) % 1024
I hope you get the point and I didn't tell crap.