Page 1 of 1
higher half tutorial question
Posted: Sat Feb 28, 2009 10:42 am
by yemista
I have a question about this part of the code
Code: Select all
BootPageDirectory:
; This page directory entry identity-maps the first 4MB of the 32-bit physical address space.
; All bits are clear except the following:
; bit 7: PS The kernel page is 4MB.
; bit 1: RW The kernel page is read/write.
; bit 0: P The kernel page is present.
; This entry must be here -- otherwise the kernel will crash immediately after paging is
; enabled because it can't fetch the next instruction! It's ok to unmap this page later.
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages before kernel space.
; This page directory entry defines a 4MB page containing the kernel.
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages after the kernel image.
Why is bit 7 set? Isnt that a reserved bit? Also, why in this tutorial are page tables not setup? It just sets up a directory entry and loads it, but does not map those tables to any addresses.
Re: higher half tutorial question
Posted: Sat Feb 28, 2009 11:04 am
by Hery
Bit 7 of page directory entry determines if the size of pages is 4kB or 4MB. (Volume 3A 3.7.6 of Intel manuals)
In this example bit 7 is set, so there are 4MB pages (what is mentioned in the comments above). It is also the reason why no page tables are set. They are not used when size of a page is 4MB (Volume 3A 3.7.2 of Intel manuals).
Re: higher half tutorial question
Posted: Sun Mar 01, 2009 7:15 pm
by yemista
I copied the code exactly from there, and only modified a bit for my bootloader, and I get
(physical address not available) from bochs. the only thing different is my linker script, but shouldnt it be equivalent to the one on the wiki?
Code: Select all
SECTIONS
{
.textA 0x00000000 : { cr0.o(.cr0_text) }
.textB (0x00100000 + SIZEOF (.textA)) :
AT ( ADDR (.textA) + SIZEOF (.textA))
{ cr1.o(.cr1_text) }
.dataB ALIGN (0x1000)
: AT ( ADDR (.textA) + SIZEOF (.textA) + SIZEOF(.textB))
{ cr1.o(.cr1_data) }
.textC (0xC0100000 + SIZEOF (.textA) + SIZEOF (.textB) + SIZEOF (.dataB)) :
AT (ADDR (.textA) + SIZEOF (.textA) + SIZEOF (.textB) + SIZEOF (.dataB))
{ *(.text) }
.rodata : { *(.ro) }
.data : { *(.data) }
.bss : { *(.bss) }
}
Re: higher half tutorial question
Posted: Mon Mar 02, 2009 7:38 am
by yemista
This kind of script did work before I was trying to map my kernel to the higher half. I know it doesnt look very clean, but I need to do it this way because when cr0 runs, the offsets in the gdt are 0x00100000, and cr0 resets them to 0 and jumps to cr1, which is and thinks it is running at 0x00100000, and then that part is supposed to setup the kernel in the higher half, which is why the rest of the code is linked to run at 0xC0100000 + the size of the previous sections. I dont know why it wont work. I double checked the math and it seems fine. I have also tried using peoples code who use 4MB pages, and who use 4KB pages, with the same error, so I dont think its because my version of bochs does not support 4MB pages. I get an error right after paging is enabled.
Oh yes, I forgot to mention, I found out why it doesnt work. My tables are all screwed up. Not in the way I designed them, but in they way they got assembled. Im not sure whats going on, and my best guess is that I dont really understand how align works. I will post some code as soon as I get a chance
Re: higher half tutorial question
Posted: Mon Mar 02, 2009 6:44 pm
by yemista
Ok, here is the problem as I find it.
first, here is the code in question
Code: Select all
[section .cr1_data]
; Page table to map the first 4MB of physical memory
boot_page_directory:
dd (0x00000003 + boot_page_table)
times (KERNEL_DIR_NUMBER - 1) dd 0 ; Pages before kernel space.
; This page directory entry defines a 4MB page containing the kernel.
dd (0x00000003 + boot_page_table)
times (1024 - KERNEL_DIR_NUMBER - 1) dd 0 ; Pages after the kernel image.
boot_page_table:
%assign i 0
%rep 1024
dd (0x00000003 + (i * 4096))
%assign i (i+1)
%endrep
next, the relevant section of the linker script
Code: Select all
.dataB ALIGN (0x1000)
: AT ( ADDR (.textA) + SIZEOF (.textA) + SIZEOF(.textB))
{ cr1.o(.cr1_data) }
finally, heres what bochs displays as the contents of memory where both these data structures should be stored.
Code: Select all
<bochs:3> x /10 0x00101000
[bochs]:
0x00101000 <bogus+ 0>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00101010 <bogus+ 16>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00101020 <bogus+ 32>: 0x00000000 0x00000000
<bochs:4> x /10 0x00102000
[bochs]:
0x00102000 <bogus+ 0>: 0x0003003d 0x1003003e 0x2003003e 0x3003003e
0x00102010 <bogus+ 16>: 0x4003003e 0x5003003e 0x6003003e 0x7003003e
0x00102020 <bogus+ 32>: 0x8003003e 0x9003003e
So I figured out its failing because my tables are junk, but I dont know why they are turning out like this and it appears to be the data is not aligned properly and is overwriting itself. I also tried in the nasm code to put in align 8, but this still will not produce the same results. Shouldnt align 8 make it so that every 8 bytes it will start over again? I also tried align 4 for fun and no results. Is it the align directive in the linker code changing things? This appears like a simple answer, but Im not too sure how align really works or whats going on, because the way I understood it does not appear to be correct
Re: higher half tutorial question
Posted: Fri Mar 06, 2009 11:55 am
by yemista
Does anyone have any ideas on this? I have no idea why all the entries for boot_page_directory are coming up 0, or where all the 3e's are comming from for
the boot_page_table. I am very reluctant to continue development on my kernel
because I do not want to constrict user apps by address space, and unless they
have some kernel code mapped in, they are pretty useless without system calls.
Re: higher half tutorial question
Posted: Fri Mar 06, 2009 2:31 pm
by yemista
Well results are results so Ill take a look at it, but I cant see why this wouldnt compile as it should. What doesnt make any sense is that the boot_page_table is mostly correct. The entries are as they should be except for all those "3e"'s, but the way it is coded is pretty much equivalent to the boot_page_directory, except that ends up as all zeros, and that does not make any sense.