How to map more than 4MB?

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
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:

How to map more than 4MB?

Post by pcmattman »

I have this setup for paging, from the tutorial on osdever.net. It's not the best tutorial in the world, because it only really teaches how to map the first 4MB.

I've got this:

Code: Select all

// initializes paging
void InitPaging()
{
	// necessary variables
	ulong_t address = 0;
	uint_t i;
	
	// map the first 4 MB, first 4K not available
	pagetab[0] = address | 2; // not present
	address += 4096;
	for( i = 1; i < 1024; i++ )
	{
		pagetab[i] = address | 3; // supervisor, r/w, present
		address += 4096; // 4 KB
	}
	
	// fill first entry of the page directory
	pagedir[0] = (unsigned int) pagetab;
	pagedir[0] = pagedir[0] | 3; // supervisor, r/w, present

	// null out the rest
	for( i = 1; i < 1024; i++ )
		pagedir[i] = 0 | 2; // not present

	// fill CR3 and CR0
	write_cr3( (unsigned int) pagedir ); // put page directory address into cr3
	write_cr0( read_cr0() | 0x80000000 ); // set paging bit to 1
}
The question is, how do I map the other entries in the page directory?
DarkJarek
Posts: 3
Joined: Thu Apr 26, 2007 12:24 am

Post by DarkJarek »

it's simple, you just must have another page table

Code: Select all

   pagetab1[0] = address | 2; // not present
   address = 0x400000;
   for( i = 0; i < 1024; i++ )
   {
      pagetab1[i] = address | 3; // supervisor, r/w, present
      address += 4096; // 4 KB
   }
   
   // fill first entry of the page directory
   pagedir[1] = (unsigned int) pagetab1;
   pagedir[1] = pagedir[1] | 3; // supervisor, r/w, present 
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 »

What's the address of the second page table? 1024 higher than the first?
DarkJarek
Posts: 3
Joined: Thu Apr 26, 2007 12:24 am

Post by DarkJarek »

this's physical address of memory, in this case we start at 4MB, in your code should be

Code: Select all

pagetab[0] = address | 2; // not present
   address = 0;
   for( i = 1; i < 1024; i++ )
   {
      pagetab[i] = address | 3; // supervisor, r/w, present
      address += 4096; // 4 KB
   } 
not

Code: Select all

pagetab[0] = address | 2; // not present
   address += 4096;
   for( i = 1; i < 1024; i++ )
   {
      pagetab[i] = address | 3; // supervisor, r/w, present
      address += 4096; // 4 KB
   } 
of course if you start at begin of ram
Last edited by DarkJarek on Mon May 07, 2007 5:21 am, edited 1 time in total.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

pcmattman wrote:What's the address of the second page table? 1024 higher than the first?
The second entry in the page directory is the physical address (+ flags etc) of the page table which provides page mappings for the second 4MB of virtual memory. Each page table is 4kB in length, and 4kB aligned. The way I do it is to get the physical memory for my page tables from my physical memory allocator, and then just write the value I get into the page directory. This means that the page tables can exist anywhere in physical memory, and are not necessarily contiguous.

Regards,
John.
Post Reply