I have seen that, if I map physical memory exactly to virtual memory, my kernel successfully loads. And also I need to map the first 4mb of ram, otherwise my kernel crashes.
I'd want to load my kernel at 0x100000 (1mb) and map it at 0xC0000000 (3gb). Have I to use the linker script or can I do it in my kernel code?
My kernel's 'start' function (asm):
Code: Select all
[BITS 32]
[global start]
[extern _kmain]
start:
???mov esp, _sys_stack
???push ebx
???call _kmain
???jmp $
Code: Select all
void kmain(multiboot_info_t *boot_info)
{
???init_video();
???gdt_install();
???idt_install();
???isrs_install();
???irq_install();
???init_paging((boot_info->ext_mem + 1024) * 1024);
???init_multitasking();
???puts("Hello, World!\n");
???timer_install();
???keyboard_install();
???sti();
???idle();
}
Code: Select all
extern char _kernel_end[];
unsigned long *page_dir, *page_tbl;
unsigned long total_mempages, free_mempages;
void init_paging(uint32 total_ram)
{
???uint32 count = 0, t = 0;
???free_mempages = total_mempages = (total_ram / 4096);
???page_dir = (uint32 *)ALIGN_PAGE(_kernel_end);
???memset(page_dir, 0, 0x1000);
???memset(page_tbl, 0, 0x1000);
???page_tbl = page_dir + 0x1000;
???install_page_table(page_dir, 0, page_tbl, PG_PRESENT | PG_WRITABLE);
???page_tbl = page_dir + 0x2000;
???install_page_table(page_dir, 0x300, page_tbl, PG_PRESENT | PG_WRITABLE);
???for (count = 0; count < 256; count++)
??????map_page(page_dir, 0, count, count * 0x1000, PG_PRESENT | PG_WRITABLE);
???for (count = 256; count < 1024; count++)
??????map_page(page_dir, 0x300, count - 256, count * 0x1000, PG_PRESENT | PG_WRITABLE);
???__asm__ __volatile__ ("movl %%eax, %%cr3" :: "a" (page_dir));
???__asm__ __volatile__ ("movl %%cr0, %%eax" : "=a" (t));
???t |= 0x80000000;
???__asm__ __volatile__ ("movl %%eax, %%cr0" :: "a" (t));
}
void install_page_table(uint32 *pgdir, uint32 tbl_index, uint32 *pgtable, uint16 flags)
{
???pgdir[tbl_index] = ((uint32)(pgtable) & ~0x3FF) | (flags & 0x3FF);
}
uint32 *get_page_table(uint32 *pgdir, uint32 tbl_index)
{
???return (uint32 *)(pgdir[tbl_index] & ~0x3FF);
}
void map_page(uint32 *pgdir, uint32 pgtable, uint32 page, uint32 phys_mem, uint16 flags)
{
???uint32 *ptr = NULL;
???ptr = get_page_table(pgdir, pgtable);
???ptr[page] = (phys_mem & ~0x3FF) | (flags & 0x3FF);
}
I've seen that, if I map the first 1024 pages in the first page table, all goes very well. But I want my kernel at 0xC0000000.
I hope you can help me...