Page 1 of 2
Initializing paging not working, what have I forgotten?
Posted: Fri Jan 23, 2004 2:14 pm
by frank
I've been trying to enable paging for a while,
but my cpu keeps crashing.
The code I have:
Code: Select all
mem = (unsigned int *) 0x300000; /* Page Directory Entry */
mem[0] = (0x300000 + 0x1000) | 3;
mem = (unsigned int *) 0x301000 ; /* Page Table Entry */
mem[0] = (0x302000) | 3;
asm("movl $0x300000,%eax"); /* Put the Page-Directory Base address in eax */
asm("movl %eax,%cr3"); /* Set the pointer to the 1st Page-Directory Base in CR3 (Controll Register 3 / PDBR) */
asm("movl %cr0,%eax");
asm("addl $2147483648,%eax");
asm("movl %eax,%cr0"); /* Set bit 31 of CR0 (Controll Register 0, paging bit) */
asm("jmp $0x08,$pagingdone");
asm("pagingdone:");
I'm wondering what I have forgotten or not done?
I've read the intel manual and k.j. tutorial btw.
Thanks in advance,
Frank
Re:Initializing paging not working, what have I forgotten?
Posted: Fri Jan 23, 2004 2:55 pm
by Phil
I'm fairly new to this, but I'll give it a shot...
1) I think you need to fill in all the other entries in the Page Directory and set them to "Not Present" if you don't want to actually initialize them.
2) Same thing for the Page Table entries.
3) It appears that you are mapping physical address 0x302000 to be linear address 0x00000000. Are all your segments and currently running code designed to work that way? And are they located starting at physical address 0x302000?
Like I said, I'm new to this stuff. I could be way off. Good luck either way.
Phil
Re:Initializing paging not working, what have I forgotten?
Posted: Fri Jan 23, 2004 2:57 pm
by Phil
One more thought - check out this web page for an EXCELLENT example of getting paging going.
http://osdev.neopages.net/tutorials/pag ... ?the_id=43
Re:Initializing paging not working, what have I forgotten?
Posted: Fri Jan 23, 2004 4:02 pm
by frank
1) I think you need to fill in all the other entries in the Page Directory and set them to "Not Present" if you don't want to actually initialize them.
2) Same thing for the Page Table entries.
Ok, I changed that. The cpu crashes though.
3) It appears that you are mapping physical address 0x302000 to be linear address 0x00000000. Are all your segments and currently running code designed to work that way? And are they located starting at physical address 0x302000?
Should I set the linear address of the page in 0x302000?
That would make the size of a page not 4096 bytes.. right?
I haven't set up the segments/code to work that way.
How can I do this?
My code is running at 0x100000.
Re:Initializing paging not working, what have I forgotten?
Posted: Fri Jan 23, 2004 9:34 pm
by Neo
are you linking your kernel to run at whatever virtual address you plan to use? (i think thats 0x302000) is your linker script right?
Re:Initializing paging not working, what have I forgotten?
Posted: Sat Jan 24, 2004 4:13 am
by frank
are you linking your kernel to run at whatever virtual address you plan to use? (i think thats 0x302000) is your linker script right?
It currently uses 0x100000, should I change it?
The entry is defined as -e main in my Makefile btw.
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY(entry)
Virtual = 0x100000;
Physical = 0x100000;
SECTIONS
{
.text Virtual : AT(Physical)
{
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(Physical + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(Physical + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
_end = .;
}
Re:Initializing paging not working, what have I forgotten?
Posted: Sun Jan 25, 2004 2:54 pm
by frank
Correct me if I'm wrong about this:
To initialize paging:
[sup]
1. The cpu needs 1024 Page Directory Entries. Each should point to a physical address of a Page Table Entry. (4k aligned)
2. It needs 1024 Page Table Entries, each pointing to the physical address of the Page Table. (4k aligned)
3. It needs the physical address of the first Page Directory in cr3 (Page Directory Base Address)
4. After that set bit 31 of cr0 (enable paging) and paging is initialized
[/sup]
Re:Initializing paging not working, what have I forgotten?
Posted: Sun Jan 25, 2004 3:36 pm
by Tim
2a. At least the page containing the code that enables paging must be mapped. It's easy to map the entire bottom 4MB.
Re:Initializing paging not working, what have I forgotten?
Posted: Sun Jan 25, 2004 4:40 pm
by Curufir
frank wrote:
[sup]
1. The cpu needs 1024 Page Directory Entries. Each should point to a physical address of a Page Table Entry. (4k aligned)
[/sup]
Just for the sake of precision

.
In the page directory only the entries for page tables that are marked as present actually need to contain an address. Any entires that are marked as not-present can use the top 31 bits in any way you see fit. For example you might keep some virtual memory information there.
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 5:16 am
by frank
2a. At least the page containing the code that enables paging must be mapped. It's easy to map the entire bottom 4MB.
Would it be ok if my page directory would start at 0xFE000, my page table at 0xFF000 and my kernel at 0x100000?
Should the paging intialize code start at 0x100000?
I don't know what goes wrong (apart that it crashes at mov cr0,eax) 'cause I'm using vmware. (I can not use bochs)
The code I have now
Code: Select all
unsigned int * mem;
unsigned int i = 0;
mem = (unsigned int *) 0xFE000; /* Page Directory start */
for (i=1; i<1024; i++) /* Make 1024 Page Directory Entries */
{
mem[i] = 0;
mem[i] = mem[i] | 2;
}
mem[0] = (unsigned int) 0xFF000;
mem[0] = mem[0] | 3;
mem = (unsigned int *) 0xFF000; /* Page Table start */
for (i=0; i<1024; i++) /* Make 1024 Page Table Entries */
{
mem[i] = (unsigned int*) ((unsigned int) (0xFF000 + (i*4096)) );
mem[i] = mem[i] | 3;
}
asm("movl $0xFE000,%eax"); /* Put the Page-Directory Base address in eax */
asm("movl %eax,%cr3"); /* Set the pointer to the 1st Page-Directory Base in CR3 (Controll Register 3 / PDBR) */
asm("movl %cr0,%eax");
asm("addl $0x80000000,%eax");
asm("movl %eax,%cr0"); /* Set bit 31 of CR0 (Controll Register 0, paging bit) */
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 5:58 am
by Candy
frank wrote:
2a. At least the page containing the code that enables paging must be mapped. It's easy to map the entire bottom 4MB.
Would it be ok if my page directory would start at 0xFE000, my page table at 0xFF000 and my kernel at 0x100000?
Should the paging intialize code start at 0x100000?
I am quite happy you didn't try this on a real computer. 0xA0000-0xFFFFF is the SYSTEM HARDWARE area (or some name similar), and it is ROM. That means, it is NOT memory, and you can NOT use it as such. Place it somewhere else(hint: try int15/ax=e820).
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 6:15 am
by frank
I moved it to 0x100000, the cpu crashes.
I have not a clue why though..
Code: Select all
void VM_Pages()
{
unsigned int * mem;
unsigned int i = 0;
mem = (unsigned int *) 0x100000; /* Page Directory start */
for (i=1; i<1024; i++) /* Make 1024 Page Directory Entries */
{
mem[i] = 0;
mem[i] = mem[i] | 2;
}
mem[0] = (unsigned int) 0x101000;
mem[0] = mem[0] | 3;
mem = (unsigned int *) 0x101000; /* Page Table start */
for (i=0; i<1024; i++) /* Make 1024 Page Table Entries */
{
mem[i] = (unsigned int*) ((unsigned int) (0x102000 + (i*4096)) );
mem[i] = mem[i] | 3;
}
asm("movl $0x100000,%eax"); /* Put the Page-Directory Base address in eax */
asm("movl %eax,%cr3"); /* Set the pointer to the 1st Page-Directory Base in CR3 (Controll Register 3 / PDBR) */
asm("movl %cr0,%eax");
asm("addl $0x80000000,%eax");
asm("movl %eax,%cr0"); /* Set bit 31 of CR0 (Controll Register 0, paging bit) */
}
I also changed my linker script
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY(entry)
Virtual = 0x102000;
Physical = 0x102000;
SECTIONS
{
.text Virtual : AT(Physical)
{
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(Physical + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(Physical + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
_end = .;
}
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 6:22 am
by Pype.Clicker
what about trying it in
bochs ?? it could give you more informations about what crashed and why ... it could provide you register states at crash time, the trace of last executed instructions etc.
Think in the bochs ...
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 6:33 am
by Pype.Clicker
Code: Select all
asm("movl $0x100000,%eax");
asm("movl %eax,%cr3");
asm("movl %cr0,%eax");
asm("addl $0x80000000,%eax");
asm("movl %eax,%cr0");
There are some things i dislike in these ASM statements (and that the compiler might dislike aswell:
- you're refering to registers with a simple '%eax', which is their AS name, but you should double-quote the '%' and thus refer registers as %%eax and %%cr0
- you didn't said your instruction were volatile (so the compiler could optimize them by not issuing them as it doesn't see how they help generating correct C function)
- there's nothing that prevents the compiler from modifying the content of the EAX register between "asm(mov 0x10000,eax); and asm(mov eax,cr3) instruction. If you don't want the compiler to mess with your asm instructions, either write them in asm (in a separate file, i mean) or as a single asm("mov 0x10000,eax ; mov eax,cr3") command ...
imho, giving a look at the code generated for your inline asm would worth the effort (objdump -drS vm.o may help)
Re:Initializing paging not working, what have I forgotten?
Posted: Tue Jan 27, 2004 7:13 am
by frank
Ok, I changed it, but the cpu crashes..
Bochs would make it a lot easier, but..
what about trying it in bochs ?? it could give you more informations about what crashed and why ... it could provide you register states at crash time, the trace of last executed instructions etc.
the problem with trying it in bochs is that I don't have a floppy drive and I'm using grub.
afaik it's impossible to let bochs boot from /dev/hda
- you're refering to registers with a simple '%eax', which is their AS name, but you should double-quote the '%' and thus refer registers as %%eax and %%cr0
If I give them the names %%eax and so I get the error:
"Error: Bad Register name `%%eax'"
- you didn't said your instruction were volatile (so the compiler could optimize them by not issuing them as it doesn't see how they help generating correct C function)
- there's nothing that prevents the compiler from modifying the content of the EAX register between "asm(mov 0x10000,eax); and asm(mov eax,cr3) instruction. If you don't want the compiler to mess with your asm instructions, either write them in asm (in a separate file, i mean) or as a single asm("mov 0x10000,eax ; mov eax,cr3") command ...
imho, giving a look at the code generated for your inline asm would worth the effort (objdump -drS vm.o may help)
Ok, I changed it
Code: Select all
asm volatile("movl $0x100000,%%eax;" \
"movl %eax,%cr3;" \
"movl %cr0,%eax;" \
"addl $0x80000000,%eax;" \
"movl %eax,%cr0");
objdump gives me the output:
Code: Select all
c7: 81 fa ff 03 00 00 cmp $0x3ff,%edx
cd: 76 e5 jbe b4 <VM_Pages+0x30>
cf: b8 00 00 10 00 mov $0x100000,%eax
d4: 0f 22 d8 mov %eax,%cr3
d7: 0f 20 c0 mov %cr0,%eax
da: 05 00 00 00 80 add $0x80000000,%eax
df: 0f 22 c0 mov %eax,%cr0
e2: c9 leave
e3: c3 ret