Page 2 of 2

Posted: Thu Apr 26, 2007 4:08 am
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...

Posted: Thu Apr 26, 2007 4:16 am
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.

Posted: Thu Apr 26, 2007 4:18 am
by Lprogster
...

Posted: Thu Apr 26, 2007 4:41 am
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.

Posted: Thu Apr 26, 2007 4:52 am
by Lprogster
Thankyou soooooooooooooo much. That is great explanation.

I think that clears everything up 8). Brilliant!

Again, thanks everyone who helped,
Lster

Posted: Thu Apr 26, 2007 5:32 am
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. ;)

Posted: Thu Apr 26, 2007 6:54 am
by Lprogster
Wow, paging rocks :D!

THANKYOU,
Lster

Posted: Thu Apr 26, 2007 3:49 pm
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

Posted: Sat May 05, 2007 8:10 am
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 :)

Posted: Sat May 05, 2007 6:23 pm
by supagu
*bump* sorry this thread was lost even though i responded to it

Posted: Sun May 06, 2007 8:46 am
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.