Going crazy with my higher half kernel initialization.
Posted: Fri Jul 01, 2016 11:52 am
I'm trying to map my kernel to virtual higher half memory.
My linker script is:
As you can see in the linker script, i've tackled the whole virtual/physical linker relocation issues with special sections
for initializations only.
I'm using GRUB as my bootloader, my entry point is in the
Printing a character to the screen using VGA works before calling , but after is called, the function never returns, and my kernel goes crazy.
Here are my identitiy maps of the lower 1M memory and my kernel memory:
'map_identitiy' identity maps the lower 1M(bios, bootloader, etc..) and the init and table sections, which are right after the 1M.
'map_kernel_memory' maps the higher half kernel to physical addresses.
I didn't find anything odd in my code, and i'm already in a bloody debugging session for more than 5 hours.
Any ideas, suggestions..? Thank you.
EDIT:
I have found the problematic instruction that makes my kernel reboot, all of the addresses are correct and aligned to 4K, CR3 does contain the address of my page directory, but AFTER these instructions are executed:
the system reboots constantly.
EDIT:
Solved...
The problem was that i didn't load the GDT, although GRUB has loaded one, weird. maybe one of the segments wasn't mapped.
My linker script is:
Code: Select all
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
KERNEL_VIRTUAL_OFFSET = 0xC0000000;
SECTIONS
{
. = 1M;
kernel_start = .;
start_init = .;
.init ALIGN(4K) :
{ *(.multiboot);
*(.init);
*(.tables);
}
end_init = .;
init_size = end_init - start_init ;
. += KERNEL_VIRTUAL_OFFSET;
kernel_high_half_start = .;
/****** KERNEL *******/
.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_VIRTUAL_OFFSET)
{*(.text) }
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_VIRTUAL_OFFSET)
{ *(.data) }
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_VIRTUAL_OFFSET)
{ *(.bss) }
/****** KERNEL *******/
kernel_high_half_end = .;
kernel_end = . - KERNEL_VIRTUAL_OFFSET;
}
for initializations only.
I'm using GRUB as my bootloader, my entry point is in the
section:.init
Code: Select all
bits 32
section .multiboot
;grub bootloader header
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
global start
extern kmain
extern paging_init
section .init
start:
cli ;block interrupts
mov esp, init_stack
call paging_init
; Now high half kernel is mapped to the page directory
mov esp, stack_space ;set stack pointer
push ebx ; grub boot info
call kmain
loop:
hlt ;halt the CPU
jmp loop
resb 4096; 4KB small stack for my init section.
init_stack:
section .bss
resb 8192 ;8KB for stack
stack_space:
Code: Select all
paging_init
Code: Select all
paging_init
Here are my identitiy maps of the lower 1M memory and my kernel memory:
Code: Select all
typedef int page_table_t;
typedef int page_pointer_t;
page_table_t kernel_page_directory[PAGE_DIR_SIZE]
__attribute__((aligned(PAGE_SIZE))) __attribute__((section(".tables")));
page_pointer_t kernel_page_tables[PAGE_TABLE_SIZE]
__attribute__((aligned(PAGE_SIZE))) __attribute__((section(".tables")));
page_pointer_t identity_page_table[PAGE_TABLE_SIZE]
__attribute__((aligned(PAGE_SIZE))) __attribute__((section(".tables")));
/* Identity map the low 1M
* In early boot stage.
*/
static void __attribute__((section(".init"))) map_identity()
{
//memset(0, identity_page_table, PAGE_TABLE_SIZE);
unsigned int current_page = 0;
for(int i = 0; i < BIOS_PAGE_TABLE_ENTRIES; i++, current_page += PAGE_SIZE)
identity_page_table[i] = (current_page) | 0x3;
current_page = 0x100000;
for(int i = BIOS_PAGE_TABLE_ENTRIES + 1;
i < (BIOS_PAGE_TABLE_ENTRIES + 1) + (INIT_SIZE / PAGE_SIZE);
i++, current_page += PAGE_SIZE)
{
identity_page_table[i] = (current_page) | 0x3;
}
kernel_page_directory[0] = ((unsigned long)(identity_page_table)) | 0x3;
}
/* Map the kernel memory to its page directory,
* **in early boot stage.
* We don't need to map the init section, we don't need it anymore.
*/
__attribute__((section(".init"))) static void map_kernel_memory()
{
//Identity map the init section
//Start at 1MB i.e. its page aligned.
unsigned int start_index = (INIT_SIZE / PAGE_SIZE) - 1;
unsigned long current_page = KERNEL_VIRTUAL_START - KERNEL_VIRTUAL_OFFSET;
for(int i = start_index;
i < (start_index + (KERNEL_VIRTUAL_SIZE / PAGE_SIZE));
i++, current_page += PAGE_SIZE)
{
kernel_page_tables[i] = current_page | 0x3;
}
kernel_page_directory[KERNEL_DIRECTORY_ENTRY] = (unsigned long)kernel_page_tables | 0x3;
}
__attribute__((section(".init"))) static inline void enable_paging()
{
asm("mov eax, kernel_page_directory");
asm("mov cr3, eax");
asm("mov eax, cr0");
//Turn on paging bit
asm("or eax, 0x80000000");
asm("mov cr0, eax");
}
__attribute__((section(".init"))) void paging_init()
{
map_identity();
map_kernel_memory();
enable_paging();
}
'map_kernel_memory' maps the higher half kernel to physical addresses.
I didn't find anything odd in my code, and i'm already in a bloody debugging session for more than 5 hours.
Any ideas, suggestions..? Thank you.
EDIT:
I have found the problematic instruction that makes my kernel reboot, all of the addresses are correct and aligned to 4K, CR3 does contain the address of my page directory, but AFTER these instructions are executed:
Code: Select all
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
EDIT:
Solved...
The problem was that i didn't load the GDT, although GRUB has loaded one, weird. maybe one of the segments wasn't mapped.