General protection falt - paging (solved)
Posted: Fri Feb 02, 2007 10:55 pm
I'm trying to write a higher half kernel and so far I can't figure out why it keeps generating a general protection fault. The fault occurs right after paging is enabled and right before the next instruction is run.
edit: Please see the code in my second response to this thread. The code contained in this post has issues that were fixed in the second one.
Below is the debug output of bochs (its not letting me copy the text so i'm using a screenshot):
My linker script:
And my assembly:
Any ideas on what is going wrong?
edit: Please see the code in my second response to this thread. The code contained in this post has issues that were fixed in the second one.
Below is the debug output of bochs (its not letting me copy the text so i'm using a screenshot):
My linker script:
Code: Select all
ENTRY (entry)
SECTIONS{
. = 0xC0000000;
.text :AT(ADDR(.text) - 0xBFF00000){*(.text)}
.data :AT(ADDR(.data) - 0xBFF00000){*(.data)}
.bss :AT(ADDR(.bss) - 0xBFF00000){*(.bss)}
}
Code: Select all
/* multiboot header */
.int 0x1BADB002
.int 1<<0 | 1<<1
.int -(0x1BADB002 + 1<<0 | 1<<1)
.equ VIRTUAL_OFFSET, 0xBFF00000 /* 0xC0000000 (virtual location) - 1mb (physical location) */
.comm page_table, 0x2000, 0x1000 /* Page table for 4mbs (1024 (number of ints) * 8 bytes) = 0x2000 */
.comm page_directory, 0x8, 0x1000 /* Page directory for 1 entry (1 int = 8 bytes) */
.comm page_data, 0x8 /* temporary page data is put here then moved out to page_table */
.comm counter, 0x8 /* counter for which entry page_table needs to be filled out */
.global entry /* set up paging, must be postition independent */
.global higher_half /* first section to run in paging */
entry:
/* set counter to 0 and load it into ecx for use */
movl $0x0, (counter - VIRTUAL_OFFSET) /* set counter to 0 */
mov (counter - VIRTUAL_OFFSET), %ecx
fill_page_table: /* fill out page_table */
/* calculate data for page_table entry */
mov $0x1000, %eax /* 4k */
mul %ecx /* multiply counter (ecx) to 4k (eax) */
add $0xC0000003, %eax /* add 3 (flags) and 0xC0000000 (offset) to eax (counter * 4k) */
mov %eax, (page_data - VIRTUAL_OFFSET) /* move out data to page_data, so eax can be used */
/* calculate location of where to store the data in the page_table */
mov $0x20, %eax /* 32 to eax (size of page_table entry) */
mul %ecx /* 32 (size of page_table entry) * counter */
add $(page_table - VIRTUAL_OFFSET), %eax /* add page_table location to eax (offset) */
mov (page_data - VIRTUAL_OFFSET), %ecx /* move temporary page_data into ecx */
mov %ecx, (%eax) /* write data to offset */
/* increase counter */
mov (counter - VIRTUAL_OFFSET), %ecx /* move counter to ecx in order to increase it */
inc %ecx /* counter ++ */
mov %ecx, (counter - VIRTUAL_OFFSET) /* write counter */
/* continue? */
cmp $0x401, %ecx /* compare counter to see if we need to loop continue or not */
jne fill_page_table /* loop if not equal */
/* set (single) page directory entry */
mov $(page_table - VIRTUAL_OFFSET), %eax /* move location of page_table to eax */
add $0x3, %eax /* add 3 (flags) */
mov %eax, (page_directory - VIRTUAL_OFFSET) /* write entry */
/* set cr3 (PDBR) */
mov $(page_directory - VIRTUAL_OFFSET), %eax
mov %eax, %cr3
/* set cr0 */
mov %cr0, %eax
xor $0x80000000, %eax /* set PG bit */
mov %eax, %cr0
lea higher_half, %eax /* load address -- this is where the general protection falt occurs */
jmp *%eax /* long jump */
higher_half:
mov $0x1, %ecx /* set ecx to 1 in order to see if the code got this far */
jmp 0xFFFFFFF /* crash, in order to make sure no other random instructions run */