Paging (Help!)
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
No, you shouldn't. These are the physical mappings. If you read what you said before the code:Lprogster wrote:Thanks guys...
Ive hit a problem now.
This is the origional code (from the tutorial) that works fine:
If Im correct (and I probably arent!) I should be able to change the starting value of 'address' to change where pages are positioned. But when I change 'address' to something else Bochs simply restarts .Code: Select all
unsigned long address=0; // holds the physical address of where a page is unsigned int i; // map the first 4MB of memory for(i=0; i<1024; i++) { page_table[i] = address | 3; // attribute set to: supervisor level, read/write, present(011 in binary) address = address + 4096; // 4096 = 4kb };
What's up with that?
Thankyou both
Lster
In other words, the address has 4K added to it each time, for a total of 1024 times, which is 4MB.map the first 4MB of memory
I'm not 100% sure how to get the virtual mapping. You'll have to look around. Try this link: http://www.acm.uiuc.edu/sigops/roll_you ... 86/vm.html... With your system you can then, with any page table and a logical address, do this:
Code: Select all
unsigned int *getPageEntry(unsigned int address)
{
unsigned int *pageTable = (unsigned int *) 0xffc00000;
/* 0xffc00000 is the valid address if the page directory was mapped
into the last entry of itself
*/
return &pageTable[address >> 12];
}
Edit: also, make sure CR3 is the correct value, that could be the cause of your troubles.
Ok, so here we again confuse pages and frames. The "address" is actually the address of the physical pages, which in older (and academic) literature is known as a frame. It's better get used to everyone speaking about pages all the time though, because that's how it goes, and you just have to figure out by the context whether it's a physical page (frame) or a virtual page.Lprogster wrote:Thanks guys...
Ive hit a problem now.
This is the origional code (from the tutorial) that works fine:
If Im correct (and I probably arent!) I should be able to change the starting value of 'address' to change where pages are positioned. But when I change 'address' to something else Bochs simply restarts .Code: Select all
unsigned long address=0; // holds the physical address of where a page is unsigned int i; // map the first 4MB of memory for(i=0; i<1024; i++) { page_table[i] = address | 3; // attribute set to: supervisor level, read/write, present(011 in binary) address = address + 4096; // 4096 = 4kb };
What's up with that?
Thankyou both
Lster
So the addresses you are storing into the tables are physical address. Isn't that great?
So if you change the addresses, the end result is that you map different physical addresses at the same virtual addresses. This means that once you enable paging, you'll start accessing some other random memory (well not so random, it's the memory you put there, but it's probably not what you want anyway), and stuff is going to blow up.
It turns out that when you enable paging, you need to have at least the code (and for simplicity at least your stack as well) identity mapped, that is, you need the virtual and physical locations to be the same. Otherwise unpredictable things will happen.
So normally when you are setting up paging, you map the first 4MB of virtual addresses to the same 4MB of physical addresses. Once you've got paging up and running, you can then move stuff around, (say, if you wanted to have your kernel at some high virtual address). But you must do this after you've enabled paging, such that you can safely land in the paged-world at the same place where you were in the physical world.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
Btw, it might be good idea to leave the first 4k of virtual memory in "not present" state. That way you'll get page fault if you ever try to follow a NULL pointer in your kernel. I've catched at least two nasty bugs this way, and I'm pretty good at avoiding NULL pointers.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
CR2 not set = no page fault = good thing. Good to hear you got it working, now I also understand paging a whole lot moreLprogster wrote:My page directory is at 0x9C000.
When I change the value of 'address' back to 0 (and it runs normally) these are the results:
Lster00079100000i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x00000000
00079100000i[CPU0 ] | CR3=0x0009c000 CR4=0x00000000
im now at the stage where im trying to wrap my head around memory management.
after reading multiple tutorials, and scouring the forums im getting even more confused
all i have gathered is a page table somehow maps between physical and virtual memory.
as for the page directory, each entry in the page directory maps to the start of a page table?
so in most tutorials we set up a page directory with 1024 entries, but only map to a single page table, so we have only mapped 4mb (but could potentially map up to 4gb if each page in the directory was mapped)
somehow we map between physical/virtual memory using the page table, im not sure if the address in these pages of the page table are physical or virtual addresses.
also the process of swapping these pages in and out and what needs to happen to the page table is not clear to me. All i know is when a page fault occurs, i get a virtual address and i need to swap in the page in to physical memory somwhere and update the page table.
more info and or corrections to my thoughts very welcome
after reading multiple tutorials, and scouring the forums im getting even more confused
all i have gathered is a page table somehow maps between physical and virtual memory.
as for the page directory, each entry in the page directory maps to the start of a page table?
so in most tutorials we set up a page directory with 1024 entries, but only map to a single page table, so we have only mapped 4mb (but could potentially map up to 4gb if each page in the directory was mapped)
somehow we map between physical/virtual memory using the page table, im not sure if the address in these pages of the page table are physical or virtual addresses.
also the process of swapping these pages in and out and what needs to happen to the page table is not clear to me. All i know is when a page fault occurs, i get a virtual address and i need to swap in the page in to physical memory somwhere and update the page table.
more info and or corrections to my thoughts very welcome
Okay for starters, all of the addresses in the page tables and the page directory are physical addresses. Each entry in a page table maps one page or 4096 bytes normally. You use the page tables to map 'virtual addresses' to 'physical addresses'. When paging in enabled all of the address that you give it are virtual and will have to be translated into physical addresses by the processor. In order to find the page table entry for a certain page the processor does something like this
The code above first gets a pointer to the page directory. Then it figures out which page table the correct mapping would be in. Then it gets the physical address of the page table. Then it figures out which page table entry contains the correct mapping and stores the physical address of the page in physical_address. Note that this code will not work unless there is a one to one mapping of the address space, because the values stored in the page directory are physical addresses. If you want code that will successfully set a mapping in a page directory then just ask.
Code: Select all
// get a pointer to the page directory
unsigned int *page_directory = page_directory_address;
// Get the page number
unsigned int page_number = virtual_address >> 12;
// Get the page table number
unsigned int page_table_number = ( ( page_number & 0xFFC00 ) >> 10 );
// move to the correct page directory entry
page_directory += ( virtual_address >> 12 );
// get the page table start
unsigned int *page_table = *page_directory 0xFFFFF000;
// move to the right page table entry
page_table += page_number & 0x3FF;
// get the physical address
unsigned physical_address = *page_table & 0xFFFFF000;