Paging (Help!)

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.
pcmattman
Member
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:

Post by pcmattman »

I just added some stuff in while you were posting :D.

Also: Page Global Enable (PGE) is a bit in the CR4 register. Just thought I might add that. However, it seems your best be is in CR2 and CR3...
pcmattman
Member
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:

Post by pcmattman »

Lprogster wrote:Thanks guys...

Ive hit a problem now.

This is the origional code (from the tutorial) that works fine:

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
};
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 :(.

What's up with that?

Thankyou both :)
Lster
No, you shouldn't. These are the physical mappings. If you read what you said before the code:
map the first 4MB of memory
In other words, the address has 4K added to it each time, for a total of 1024 times, which is 4MB.

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];
}
Good luck, and if you get it please tell us how you did it because I'd like very much to implement paging myself :D.

Edit: also, make sure CR3 is the correct value, that could be the cause of your troubles.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

...
Last edited by Lprogster on Tue Oct 23, 2007 11:25 am, edited 1 time in total.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Lprogster wrote:Thanks guys...

Ive hit a problem now.

This is the origional code (from the tutorial) that works fine:

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
};
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 :(.

What's up with that?

Thankyou both :)
Lster
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.

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.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

Thankyou soooooooooooooo much. That is great explanation.

I think that clears everything up 8). Brilliant!

Again, thanks everyone who helped,
Lster
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

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.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

Wow, paging rocks :D!

THANKYOU,
Lster
Last edited by Lprogster on Tue Oct 23, 2007 11:25 am, edited 1 time in total.
pcmattman
Member
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:

Post by pcmattman »

Lprogster 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:
00079100000i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x00000000
00079100000i[CPU0 ] | CR3=0x0009c000 CR4=0x00000000
Lster
CR2 not set = no page fault = good thing. Good to hear you got it working, now I also understand paging a whole lot more :D
supagu
Member
Member
Posts: 46
Joined: Sat Apr 07, 2007 1:24 am

Post by supagu »

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

:roll:

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 :)
supagu
Member
Member
Posts: 46
Joined: Sat Apr 07, 2007 1:24 am

Post by supagu »

*bump* sorry this thread was lost even though i responded to it
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

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

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;
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.
Post Reply