From c282cd481a69a1bb7cd6015bab232b2f0fd258ee Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Mon, 26 May 2008 06:10:53 +0000 Subject: [PATCH] more x86_64 work. started to put the mmu bits together in the (former) stage2 loader. Need to get the kernel pseudo building to put together the elf loader next. git-svn-id: svn+ssh://newos.org/var/svn/newos/newos@1246 c25cc9d1-44fa-0310-b259-ad778cb1d433 --- boot/pc/x86_64/heap.c | 20 +++ boot/pc/x86_64/inflate.c | 1 - boot/pc/x86_64/makefile | 13 +- boot/pc/x86_64/mmu.c | 104 ++++++++++++++++ boot/pc/x86_64/multiboot.c | 55 ++++++++ boot/pc/x86_64/multiboot.h | 51 ++++++++ boot/pc/x86_64/stage1.c | 242 +++++------------------------------- boot/pc/x86_64/stage1.h | 17 --- boot/pc/x86_64/stage1_entry.S | 14 +-- boot/pc/x86_64/stage2.c | 196 +++++++---------------------- boot/pc/x86_64/stage2_asm.S | 4 + boot/pc/x86_64/stage2_priv.h | 11 +- include/boot/arch/x86_64/stage2.h | 6 +- include/kernel/arch/x86_64/kernel.h | 14 +-- 14 files changed, 342 insertions(+), 406 deletions(-) create mode 100755 boot/pc/x86_64/heap.c create mode 100755 boot/pc/x86_64/mmu.c create mode 100755 boot/pc/x86_64/multiboot.c create mode 100755 boot/pc/x86_64/multiboot.h rewrite boot/pc/x86_64/stage1.c (86%) delete mode 100644 boot/pc/x86_64/stage1.h diff --git a/boot/pc/x86_64/heap.c b/boot/pc/x86_64/heap.c new file mode 100755 index 0000000..2c8b253 --- /dev/null +++ b/boot/pc/x86_64/heap.c @@ -0,0 +1,20 @@ +/* +** Copyright 2001-2008, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include "stage2_priv.h" + +static unsigned char *heap_ptr = (unsigned char *)0x01000000; // 16MB + +void *kmalloc(unsigned int size) +{ +// dprintf("kmalloc: size %d, ptr %p\n", size, heap_ptr - size); + + return (heap_ptr -= size); +} + +void kfree(void *ptr) +{ +} + diff --git a/boot/pc/x86_64/inflate.c b/boot/pc/x86_64/inflate.c index 6ff2cf6..e627ffe 100644 --- a/boot/pc/x86_64/inflate.c +++ b/boot/pc/x86_64/inflate.c @@ -103,7 +103,6 @@ static char rcsid[] = "$Id$"; #include #include #include -#include "stage1.h" #include "inflate.h" typedef unsigned char uch; diff --git a/boot/pc/x86_64/makefile b/boot/pc/x86_64/makefile index 704d59b..db0471f 100644 --- a/boot/pc/x86_64/makefile +++ b/boot/pc/x86_64/makefile @@ -19,15 +19,18 @@ MY_TARGET := $(LOADER) MY_SRCS := \ stage1_entry.S \ stage1.c \ - inflate.c + inflate.c \ + stage2.c \ + mmu.c \ + heap.c \ + multiboot.c \ + stage2_asm.S -# stage2.c \ - stage2_asm.S \ - smp_boot.c \ +# smp_boot.c \ smp_trampoline.S MY_INCLUDES := $(STDINCLUDE) -MY_CFLAGS := $(KERNEL_CFLAGS) +MY_CFLAGS := $(KERNEL_CFLAGS) -mno-sse MY_LDFLAGS := -dN MY_LIBS := $(LIBS_BUILD_DIR)/libc.a MY_LIBPATHS := diff --git a/boot/pc/x86_64/mmu.c b/boot/pc/x86_64/mmu.c new file mode 100755 index 0000000..66f753b --- /dev/null +++ b/boot/pc/x86_64/mmu.c @@ -0,0 +1,104 @@ +/* +** Copyright 2008, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include "stage2_priv.h" + +// working pagedir and pagetables +static unsigned long *pgtable0 = 0; +static unsigned long *pgtable1 = 0; +static unsigned long *pgtable2 = 0; + +static unsigned long *pgtables_user = 0; + +static void setup_identity_map(void) +{ + // build a set of page tables to keep the low identity map + // the kernel will blow this away shortly + pgtables_user = (unsigned long *)0x11000; // use this random spot + + // clear out all of these page tables + memset(pgtables_user, 0, PAGE_SIZE * 2); + + // point the top level page directory at it + pgtable0[0] = (addr_t)pgtables_user | DEFAULT_PAGE_FLAGS; + + // second level table points to the next + pgtables_user[0] = ((addr_t)pgtables_user + PAGE_SIZE) | DEFAULT_PAGE_FLAGS; + + // third level page table identity maps 1GB using 2MB pages + int i; + for (i=0; i < 512; i++) + pgtables_user[512 + i] = (i * 0x200000) | (1<<7) | DEFAULT_PAGE_FLAGS; +} + +static unsigned long *alloc_pagetable(kernel_args *ka, addr_t *next_paddr) +{ + int i; + unsigned long *table; + + table = (unsigned long *)*next_paddr; + (*next_paddr) += PAGE_SIZE; + ka->arch_args.pgtables[ka->arch_args.num_pgtables++] = (addr_t)table; + + // clear it out + for(i = 0; i < 512; i++) + table[i] = 0; + + return table; +} + +// allocate enough page tables to allow mapping of kernel and identity mapping of user space +// +// kernel maps at 0xffffffff00000000 (top of 64bit - 4GB) +int mmu_init(kernel_args *ka, addr_t *next_paddr) +{ + ka->arch_args.num_pgtables = 0; + + // allocate a new top level pgdir + pgtable0 = alloc_pagetable(ka, next_paddr); + + // set up the identity map of low ram + setup_identity_map(); + + // set up the kernel's 2nd level page table + pgtable1 = alloc_pagetable(ka, next_paddr); + + // point the top level page table at it + pgtable0[511] = (addr_t)pgtable1 | DEFAULT_PAGE_FLAGS; + + // create a 3rd level kernel pagetable + pgtable2 = alloc_pagetable(ka, next_paddr); + + // point the 3nd level at 0xffffff00000000 + pgtable1[512 - 4] = (addr_t)pgtable2 | DEFAULT_PAGE_FLAGS; + + dprintf("switching page dirs: new one at %p\n", pgtable0); + + // switch to the new pgdir + asm("mov %0, %%rax;" + "mov %%rax, %%cr3;" :: "m" (pgtable0) : "rax"); + + dprintf("done switching page dirs\n"); + + return 0; +} + +// can only map the 4 meg region right after KERNEL_BASE, may fix this later +// if need arises. +void mmu_map_page(addr_t vaddr, addr_t paddr) +{ + dprintf("mmu_map_page: vaddr 0x%lx, paddr 0x%lx\n", vaddr, paddr); + +#if 0 + if(vaddr < KERNEL_BASE || vaddr >= (KERNEL_BASE + 4096*1024)) { + dprintf("mmu_map_page: asked to map invalid page!\n"); + for(;;); + } + paddr &= ~(PAGE_SIZE-1); +// dprintf("paddr 0x%x @ index %d\n", paddr, (vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE); + pgtable[(vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE] = paddr | DEFAULT_PAGE_FLAGS; +#endif +} + diff --git a/boot/pc/x86_64/multiboot.c b/boot/pc/x86_64/multiboot.c new file mode 100755 index 0000000..12fc7e5 --- /dev/null +++ b/boot/pc/x86_64/multiboot.c @@ -0,0 +1,55 @@ +#include +#include "stage2_priv.h" +#include "multiboot.h" + +static uint32 read32(const void *ptr, unsigned int offset) +{ + return *(const uint32 *)((const char *)ptr + offset); +} + +static void dump_multiboot_mmap(const void *mmap_base, uint32 len) +{ + unsigned int index = 0; + struct multiboot_mmap *mmap = (struct multiboot_mmap *)mmap_base; + + while (index < (len / sizeof(struct multiboot_mmap))) { +// dprintf("\t\tsize 0x%x\n", mmap[index].size); + uint64 addr = ((uint64)mmap[index].base_addr_high << 32) | mmap[index].base_addr_low; + dprintf("\t\taddr 0x%Lx, ", addr); + uint64 length = ((uint64)mmap[index].len_high << 32) | mmap[index].len_low; + dprintf("len 0x%Lx, ", length); + dprintf("type 0x%x\n", mmap[index].type); + + index++; + } +} + +void dump_multiboot(const void *multiboot) +{ + uint32 flags = read32(multiboot, 0); + + dprintf("multiboot struct at %p\n", multiboot); + dprintf("\tflags 0x%x\n", flags); + + if (flags & (1<<0)) { + dprintf("\tmem_lower 0x%x\n", read32(multiboot, 4)); + dprintf("\tmem_upper 0x%x\n", read32(multiboot, 8)); + } + if (flags & (1<<1)) { + dprintf("\tboot_device 0x%x\n", read32(multiboot, 12)); + } + if (flags & (1<<2)) { + dprintf("\tcmdline 0x%x\n", read32(multiboot, 16)); + } + if (flags & (1<<3)) { + dprintf("\tmods_count 0x%x\n", read32(multiboot, 20)); + dprintf("\tmods_addr 0x%x\n", read32(multiboot, 24)); + } + if (flags & (1<<6)) { + dprintf("\tmmap_length 0x%x\n", read32(multiboot, 44)); + dprintf("\tmmap_addr 0x%x\n", read32(multiboot, 48)); + + dump_multiboot_mmap((void *)(unsigned long)read32(multiboot, 48), read32(multiboot, 44)); + } +} + diff --git a/boot/pc/x86_64/multiboot.h b/boot/pc/x86_64/multiboot.h new file mode 100755 index 0000000..1762837 --- /dev/null +++ b/boot/pc/x86_64/multiboot.h @@ -0,0 +1,51 @@ +#ifndef __MULTIBOOT_H +#define __MULTIBOOT_H + +struct multiboot_info { + uint32 flags; + + uint32 mem_lower; + uint32 mem_upper; + + uint32 boot_device; + + uint32 cmdline; + + uint32 mods_count; + uint32 mods_addr; + + uint32 syms[4]; + + uint32 mmap_length; + uint32 mmap_addr; + + uint32 drives_length; + uint32 drives_addr; + + uint32 config_table; + + uint32 boot_loader_name; + + uint32 apm_table; + + uint32 vbe_control_info; + uint32 vbe_mode_info; + uint32 vbe_mode; + uint32 vbe_interface_seg; + uint32 vbe_interface_off; + uint32 vbe_interface_len; +}; + +struct multiboot_mmap { + uint32 size; + uint32 base_addr_low; + uint32 base_addr_high; + uint32 len_low; + uint32 len_high; + uint32 type; +}; + +void dump_multiboot(const void *multiboot); + +#endif + diff --git a/boot/pc/x86_64/stage1.c b/boot/pc/x86_64/stage1.c dissimilarity index 86% index 0ccb199..c5007ae 100644 --- a/boot/pc/x86_64/stage1.c +++ b/boot/pc/x86_64/stage1.c @@ -1,211 +1,31 @@ -/* -** Copyright 2001-2006, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#include -#include -#include -#include -#include -#include "stage1.h" -#include "inflate.h" - -// needed for console stuff -static unsigned short *kScreenBase = (unsigned short*) 0xb8000; -static unsigned screenOffset = 0; -static unsigned int line = 0; - -#define SCREEN_WIDTH 80 -#define SCREEN_HEIGHT 25 -#define PAGE_SIZE 4096 - -static unsigned char *heap_ptr = (unsigned char *)0x01000000; // 16MB - -extern void *_payload_start; -extern void *_payload_end; -#define TARGET ((void *)0x400000) // 4MB - -struct multiboot_info { - uint32 flags; - - uint32 mem_lower; - uint32 mem_upper; - - uint32 boot_device; - - uint32 cmdline; - - uint32 mods_count; - uint32 mods_addr; - - uint32 syms[4]; - - uint32 mmap_length; - uint32 mmap_addr; - - uint32 drives_length; - uint32 drives_addr; - - uint32 config_table; - - uint32 boot_loader_name; - - uint32 apm_table; - - uint32 vbe_control_info; - uint32 vbe_mode_info; - uint32 vbe_mode; - uint32 vbe_interface_seg; - uint32 vbe_interface_off; - uint32 vbe_interface_len; -}; - -void stage1_main(void *multiboot_info); - -static uint32 read32(const void *ptr, unsigned int offset) -{ - return *(const uint32 *)((const char *)ptr + offset); -} - -static void dump_multiboot(const void *multiboot) -{ - uint32 flags = read32(multiboot, 0); - - dprintf("flags 0x%x\n", flags); - - if (flags & (1<<0)) { - dprintf("mem_lower 0x%x\n", read32(multiboot, 4)); - dprintf("mem_upper 0x%x\n", read32(multiboot, 8)); - } - if (flags & (1<<1)) { - dprintf("boot_device 0x%x\n", read32(multiboot, 12)); - } - if (flags & (1<<2)) { - dprintf("cmdline 0x%x\n", read32(multiboot, 16)); - } - if (flags & (1<<3)) { - dprintf("mods_count 0x%x\n", read32(multiboot, 20)); - dprintf("mods_addr 0x%x\n", read32(multiboot, 24)); - } - if (flags & (1<<6)) { - dprintf("mmap_length 0x%x\n", read32(multiboot, 44)); - dprintf("mmap_addr 0x%x\n", read32(multiboot, 48)); - } - -} - -//void stage1_main(void *ext_mem_block, int ext_mem_count, int in_vesa, unsigned long vesa_ptr) -void stage1_main(void *multiboot_info) -{ - unsigned long len; - boot_dir *bootdir = TARGET; - void (*stage2_entry)(void *ext_mem_block, int ext_mem_count, int in_vesa, unsigned int vesa_ptr, int console_ptr); - - clearscreen(); - - dprintf("stage1 boot\n"); - dprintf("multiboot info %p\n", multiboot_info); - dump_multiboot(multiboot_info); - - dprintf("%lld\n", 0x123456789abcdefLL); - - dprintf("decompressing system, payload at %p...\n", &_payload_start); - - len = gunzip((unsigned char const *)&_payload_start, TARGET, kmalloc(32*1024)); - dprintf("done, len %d\n", len); - - -#if 1 - dprintf("finding stage2..."); - stage2_entry = (void*)((char *)bootdir + bootdir->bd_entry[1].be_offset * PAGE_SIZE + bootdir->bd_entry[1].be_code_ventr); - dprintf("entry at %p\n", stage2_entry); - - // jump into stage2 - stage2_entry(0,0,0,0,0); -#endif -} - -void *kmalloc(unsigned int size) -{ - dprintf("kmalloc: size %d, ptr %p\n", size, heap_ptr - size); - - return (heap_ptr -= size); -} - -void kfree(void *ptr) -{ -} - -void clearscreen() -{ - int i; - - for(i=0; i< SCREEN_WIDTH*SCREEN_HEIGHT*2; i++) { - kScreenBase[i] = 0xf20; - } -} - -static void scrup() -{ - int i; - memcpy(kScreenBase, kScreenBase + SCREEN_WIDTH, - SCREEN_WIDTH * SCREEN_HEIGHT * 2 - SCREEN_WIDTH * 2); - screenOffset = (SCREEN_HEIGHT - 1) * SCREEN_WIDTH; - for(i=0; i SCREEN_HEIGHT - 1) - scrup(); - else - screenOffset += SCREEN_WIDTH - (screenOffset % 80); - } else { - kScreenBase[screenOffset++] = 0xf00 | *str; - } - if (screenOffset >= SCREEN_WIDTH * SCREEN_HEIGHT) - scrup(); - - str++; - } - return 0; -} - -int dprintf(const char *fmt, ...) -{ - int ret; - va_list args; - char temp[256]; - - va_start(args, fmt); - ret = vsprintf(temp,fmt,args); - va_end(args); - - puts(temp); - return ret; -} - -int panic(const char *fmt, ...) -{ - int ret; - va_list args; - char temp[256]; - - va_start(args, fmt); - ret = vsprintf(temp,fmt,args); - va_end(args); - - puts("STAGE1 PANIC: "); - puts(temp); - puts("\n"); - - puts("spinning forever..."); - for(;;); - return ret; -} - +/* +** Copyright 2001-2008, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include +#include +#include +#include "stage2_priv.h" +#include "inflate.h" + +extern void *_payload_start; +extern void *_payload_end; +#define TARGET ((void *)0x400000) // 4MB + +void stage1_main(void *multiboot_info); + +void stage1_main(void *multiboot_info) +{ + unsigned long len; + + clearscreen(); + + dprintf("stage1 boot\n"); + + dprintf("decompressing system, payload at %p...\n", &_payload_start); + len = gunzip((unsigned char const *)&_payload_start, TARGET, kmalloc(32*1024)); + + stage2_main(multiboot_info, 0, 0, 0); +} + diff --git a/boot/pc/x86_64/stage1.h b/boot/pc/x86_64/stage1.h deleted file mode 100644 index 70c81f6..0000000 --- a/boot/pc/x86_64/stage1.h +++ /dev/null @@ -1,17 +0,0 @@ -/* -** Copyright 2001-2006, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef _STAGE1_H -#define _STAGE1_H - - -extern void clearscreen(void); -extern int dprintf(const char *fmt, ...); -extern void *kmalloc(unsigned int size); -extern void kfree(void *ptr); -extern int panic(const char *fmt, ...); - - -#endif - diff --git a/boot/pc/x86_64/stage1_entry.S b/boot/pc/x86_64/stage1_entry.S index 11e63d7..8206727 100644 --- a/boot/pc/x86_64/stage1_entry.S +++ b/boot/pc/x86_64/stage1_entry.S @@ -39,19 +39,19 @@ _enter64: // 2MB pages to identity map the first 16MB ram mov $(0 | (1<<7) | 3), %eax mov %eax, (PGTABLE_BASE + 0x2000) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2008) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2010) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2018) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2020) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2028) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2030) - add $0x2000, %eax + add $0x200000, %eax mov %eax, (PGTABLE_BASE + 0x2038) // set the page table base diff --git a/boot/pc/x86_64/stage2.c b/boot/pc/x86_64/stage2.c index 233faa5..7ab133e 100644 --- a/boot/pc/x86_64/stage2.c +++ b/boot/pc/x86_64/stage2.c @@ -7,6 +7,7 @@ #include "stage2_priv.h" #include "vesa.h" #include "int86.h" +#include "multiboot.h" #include #include @@ -33,17 +34,10 @@ unsigned int cv_factor = 0; // size of bootdir in pages static unsigned int bootdir_pages = 0; -// working pagedir and pagetable -static unsigned int *pgdir = 0; -static unsigned int *pgtable = 0; - // function decls for this module static void calculate_cpu_conversion_factor(void); static void load_elf_image(void *data, unsigned int *next_paddr, addr_range *ar0, addr_range *ar1, unsigned int *start_addr, addr_range *dynamic_section); -static int mmu_init(kernel_args *ka, unsigned int *next_paddr); -static void mmu_map_page(unsigned int vaddr, unsigned int paddr); -static int check_cpu(kernel_args *ka); static void sort_addr_range(addr_range *range, int count); // memory structure returned by int 0x15, ax 0xe820 @@ -56,52 +50,28 @@ struct emem_struct { // called by the stage1 bootloader. // State: -// 32-bit -// mmu disabled +// long mode (64bit) +// mmu enabled, first 16MB identity mapped // stack somewhere below 1 MB // supervisor mode -void _start(unsigned int memsize, void *extended_mem_block, unsigned int extended_mem_count, int in_vesa, unsigned int vesa_ptr, unsigned int console_ptr) +void stage2_main(void *multiboot_info, unsigned int memsize, void *extended_mem_block, unsigned int extended_mem_count) { unsigned int *idt; unsigned int *gdt; - unsigned int next_vaddr; - unsigned int next_paddr; + addr_t next_vaddr; + addr_t next_paddr; unsigned int i; unsigned int kernel_entry; asm("cld"); // Ain't nothing but a GCC thang. asm("fninit"); // initialize floating point unit - screenOffset = console_ptr; dprintf("stage2 bootloader entry.\n"); - dprintf("args: memsize 0x%x, emem_block %p, emem_count %d, in_vesa %d\n", - memsize, extended_mem_block, extended_mem_count, in_vesa); - - for (;;); - - // verify we can run on this cpu - if(check_cpu(ka) < 0) { - dprintf("\nSorry, this computer appears to be lacking some of the features\n"); - dprintf("needed by NewOS.\n"); - dprintf("\nPlease reset your computer to continue."); - - for(;;); - } - if(extended_mem_count > 0) { - struct emem_struct *buf = (struct emem_struct *)extended_mem_block; - unsigned int i; - - dprintf("extended memory info (from 0xe820):\n"); - for(i=0; iarch_args.supports_rdtsc) - calculate_cpu_conversion_factor(); + calculate_cpu_conversion_factor(); // calculate how big the bootdir is so we know where we can start grabbing pages { @@ -113,7 +83,7 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende bootdir_pages += bootdir[entry].be_size; } -// nmessage("bootdir is ", bootdir_pages, " pages long\n"); + dprintf("bootdir is %d pages long\n", bootdir_pages); } ka->bootdir_addr.start = (unsigned long)bootdir; @@ -121,6 +91,7 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende next_paddr = BOOTDIR_ADDR + bootdir_pages * PAGE_SIZE; +#if 0 if(in_vesa) { //struct VBEInfoBlock *info = (struct VBEInfoBlock *)vesa_ptr; struct VBEModeInfoBlock *mode_info = (struct VBEModeInfoBlock *)(vesa_ptr + 0x200); @@ -143,9 +114,12 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende } else { ka->fb.enabled = 0; } +#endif mmu_init(ka, &next_paddr); + for (;;); + // load the kernel (3rd entry in the bootdir) load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR_ADDR), &next_paddr, &ka->kernel_seg0_addr, &ka->kernel_seg1_addr, &kernel_entry, &ka->kernel_dynamic_section_addr); @@ -273,6 +247,7 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende // nmessage("idt at virtual address ", next_vpage, "\n"); } +#if 0 // Map the pg_dir into kernel space at 0xffc00000-0xffffffff // this enables a mmu trick where the 4 MB region that this pgdir entry // represents now maps the 4MB of potential pagetables that the pgdir @@ -283,6 +258,7 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende mmu_map_page(next_vaddr, (unsigned int)pgdir); ka->arch_args.vir_pgdir = next_vaddr; next_vaddr += PAGE_SIZE; +#endif // mark memory that we know is used ka->phys_alloc_range[0].start = BOOTDIR_ADDR; @@ -399,6 +375,9 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende ka->cons_line = screenOffset / SCREEN_WIDTH; + for(;;); + +#if 0 asm("movl %0, %%eax; " // move stack out of way "movl %%eax, %%esp; " : : "m" (ka->cpu_kstack[0].start + ka->cpu_kstack[0].size)); @@ -408,6 +387,7 @@ void _start(unsigned int memsize, void *extended_mem_block, unsigned int extende "pushl %1; " // this is the start address "ret; " // jump. : : "g" (ka), "g" (kernel_entry)); +#endif } static void load_elf_image(void *data, unsigned int *next_paddr, addr_range *ar0, addr_range *ar1, unsigned int *start_addr, addr_range *dynamic_section) @@ -481,118 +461,6 @@ static void load_elf_image(void *data, unsigned int *next_paddr, addr_range *ar0 *start_addr = imageHeader->e_entry; } -// allocate a page directory and page table to facilitate mapping -// pages to the 0x80000000 - 0x80400000 region. -// also identity maps the first 8MB of memory -static int mmu_init(kernel_args *ka, unsigned int *next_paddr) -{ - int i; - - // allocate a new pgdir - pgdir = (unsigned int *)*next_paddr; - (*next_paddr) += PAGE_SIZE; - ka->arch_args.phys_pgdir = (unsigned int)pgdir; - - // clear out the pgdir - for(i = 0; i < 1024; i++) - pgdir[i] = 0; - - // make a pagetable at this random spot - pgtable = (unsigned int *)0x11000; - - for (i = 0; i < 1024; i++) { - pgtable[i] = (i * 0x1000) | DEFAULT_PAGE_FLAGS; - } - - pgdir[0] = (unsigned int)pgtable | DEFAULT_PAGE_FLAGS; - - // make another pagetable at this random spot - pgtable = (unsigned int *)0x12000; - - for (i = 0; i < 1024; i++) { - pgtable[i] = (i * 0x1000 + 0x400000) | DEFAULT_PAGE_FLAGS; - } - - pgdir[1] = (unsigned int)pgtable | DEFAULT_PAGE_FLAGS; - - // Get new page table and clear it out - pgtable = (unsigned int *)*next_paddr; - ka->arch_args.pgtables[0] = (unsigned int)pgtable; - ka->arch_args.num_pgtables = 1; - - (*next_paddr) += PAGE_SIZE; - for (i = 0; i < 1024; i++) - pgtable[i] = 0; - - // put the new page table into the page directory - // this maps the kernel at KERNEL_BASE - pgdir[KERNEL_BASE/(4*1024*1024)] = (unsigned int)pgtable | DEFAULT_PAGE_FLAGS; - - // switch to the new pgdir - asm("movl %0, %%eax;" - "movl %%eax, %%cr3;" :: "m" (pgdir) : "eax"); - // Important. Make sure supervisor threads can fault on read only pages... - asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); - // pkx: moved the paging turn-on to here. - - return 0; -} - -// can only map the 4 meg region right after KERNEL_BASE, may fix this later -// if need arises. -static void mmu_map_page(unsigned int vaddr, unsigned int paddr) -{ -// dprintf("mmu_map_page: vaddr 0x%x, paddr 0x%x\n", vaddr, paddr); - if(vaddr < KERNEL_BASE || vaddr >= (KERNEL_BASE + 4096*1024)) { - dprintf("mmu_map_page: asked to map invalid page!\n"); - for(;;); - } - paddr &= ~(PAGE_SIZE-1); -// dprintf("paddr 0x%x @ index %d\n", paddr, (vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE); - pgtable[(vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE] = paddr | DEFAULT_PAGE_FLAGS; -} - -static int check_cpu(kernel_args *ka) -{ - unsigned int data[4]; - char str[17]; - - // check the eflags register to see if the cpuid instruction exists - if((get_eflags() & 1<<21) == 0) { - set_eflags(get_eflags() | 1<<21); - if((get_eflags() & 1<<21) == 0) { - // we couldn't set the ID bit of the eflags register, this cpu is old - return -1; - } - } - - // we can safely call cpuid - - // print some fun data - cpuid(0, data); - - // build the vendor string - memset(str, 0, sizeof(str)); - *(unsigned int *)&str[0] = data[1]; - *(unsigned int *)&str[4] = data[3]; - *(unsigned int *)&str[8] = data[2]; - - // get the family, model, stepping - cpuid(1, data); - dprintf("CPU: family %d model %d stepping %d, string '%s'\n", - (data[0] >> 8) & 0xf, (data[0] >> 4) & 0xf, data[0] & 0xf, str); - - // check for bits we need - cpuid(1, data); - if(data[3] & 1<<4) { - ka->arch_args.supports_rdtsc = true; - } else { - ka->arch_args.supports_rdtsc = false; - dprintf("CPU: does not support RDTSC, disabling high resolution timer\n"); - } - - return 0; -} void sleep(uint64 time) { @@ -642,7 +510,6 @@ static void calculate_cpu_conversion_factor(void) uint64 p1, p2, p3; double r1, r2, r3; - outb(0x34, 0x43); /* program the timer to count down mode */ outb(0xff, 0x40); /* low and then high */ outb(0xff, 0x40); @@ -664,7 +531,6 @@ quick_sample: p1= t2-t1; r1= (double)(p1)/(double)(((s_high<<8)|s_low) - ((high<<8)|low)); - /* not so quick sample */ not_so_quick_sample: do { @@ -850,3 +716,27 @@ int dprintf(const char *fmt, ...) return ret; } +int panic(const char *fmt, ...) +{ + int ret; + va_list args; + char temp[256]; + + va_start(args, fmt); + ret = vsprintf(temp,fmt,args); + va_end(args); + + puts("PANIC: "); + puts(temp); + puts("\n"); + + puts("spinning forever..."); + for(;;); + return ret; +} + +uint64 system_time(void) +{ + return 0; +} + diff --git a/boot/pc/x86_64/stage2_asm.S b/boot/pc/x86_64/stage2_asm.S index 2efcf7a..fe8215a 100644 --- a/boot/pc/x86_64/stage2_asm.S +++ b/boot/pc/x86_64/stage2_asm.S @@ -8,6 +8,8 @@ /* uint64 rdtsc() */ FUNCTION(rdtsc): rdtsc + shl $32,%rdx + or %rdx,%rax ret FUNCTION(execute_n_instructions): @@ -33,6 +35,7 @@ FUNCTION(execute_n_instructions): loop .again ret +#if 0 FUNCTION(system_time): /* load 64-bit factor into %eax (low), %edx (high) */ /* hand-assemble rdtsc -- read time stamp counter */ @@ -75,4 +78,5 @@ FUNCTION(set_eflags): pushl 4(%esp) popfl ret +#endif diff --git a/boot/pc/x86_64/stage2_priv.h b/boot/pc/x86_64/stage2_priv.h index 932fb51..3940b87 100644 --- a/boot/pc/x86_64/stage2_priv.h +++ b/boot/pc/x86_64/stage2_priv.h @@ -8,7 +8,7 @@ #include #include -extern void _start(unsigned int mem, void *extended_mem_block, unsigned int extended_mem_count, int in_vesa, unsigned int vesa_ptr, unsigned int console_ptr); +extern void stage2_main(void *multiboot_info, unsigned int mem, void *extended_mem_block, unsigned int extended_mem_count); extern void clearscreen(void); extern int dprintf(const char *fmt, ...); extern void sleep(uint64 time); @@ -20,6 +20,15 @@ unsigned int get_eflags(void); void set_eflags(unsigned int val); void cpuid(unsigned int selector, unsigned int *data); +extern void clearscreen(void); +extern int dprintf(const char *fmt, ...); +extern void *kmalloc(unsigned int size); +extern void kfree(void *ptr); +extern int panic(const char *fmt, ...); + +int mmu_init(kernel_args *ka, addr_t *next_paddr); +void mmu_map_page(addr_t vaddr, addr_t paddr); + //void put_uint_dec(unsigned int a); //void put_uint_hex(unsigned int a); //void nmessage(const char *str1, unsigned int a, const char *str2); diff --git a/include/boot/arch/x86_64/stage2.h b/include/boot/arch/x86_64/stage2.h index c4bd8dc..c5af9de 100644 --- a/include/boot/arch/x86_64/stage2.h +++ b/include/boot/arch/x86_64/stage2.h @@ -8,7 +8,7 @@ #include #include -#define MAX_BOOT_PTABLES 4 +#define MAX_BOOT_PTABLES 16 #define IDT_LIMIT 0x800 #define GDT_LIMIT 0x800 @@ -22,12 +22,10 @@ struct gdt_idt_descr { // kernel args typedef struct { // architecture specific - int supports_rdtsc; unsigned int system_time_cv_factor; addr_t phys_pgdir; - addr_t vir_pgdir; unsigned int num_pgtables; - unsigned int pgtables[MAX_BOOT_PTABLES]; + addr_t pgtables[MAX_BOOT_PTABLES]; addr_t phys_idt; addr_t vir_idt; addr_t phys_gdt; diff --git a/include/kernel/arch/x86_64/kernel.h b/include/kernel/arch/x86_64/kernel.h index e706933..c2caf04 100644 --- a/include/kernel/arch/x86_64/kernel.h +++ b/include/kernel/arch/x86_64/kernel.h @@ -1,16 +1,16 @@ /* -** Copyright 2004, Travis Geiselbrecht. All rights reserved. +** Copyright 2004-2008, Travis Geiselbrecht. All rights reserved. ** Distributed under the terms of the NewOS License. */ #ifndef _NEWOS_KERNEL_ARCH_X86_64_KERNEL_H #define _NEWOS_KERNEL_ARCH_X86_64_KERNEL_H // memory layout -#define KERNEL_BASE 0x80000000 -#define KERNEL_SIZE 0x80000000 +#define KERNEL_BASE (0xffff800000000000UL) +#define KERNEL_SIZE (0x00007fffffffffffUL) #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) -#define KERNEL_ADDR_MASK 0x80000000 +#define KERNEL_ADDR_MASK (0x8000000000000000UL) // a macro to test if a pointer is inside kernel space #define is_kernel_address(x) (((addr_t)(x)) & KERNEL_ADDR_MASK) @@ -23,9 +23,9 @@ ** region wont be placed there. The 64kb region assures a user space thread cannot pass ** a buffer into the kernel as part of a syscall that would cross into kernel space. */ -#define USER_BASE 0x100000 -#define USER_SIZE (0x80000000 - (0x10000 + 0x100000)) -#define USER_TOP (USER_BASE + (USER_SIZE - 1)) +#define USER_BASE (0x100000UL) +#define USER_TOP (0x00007fffffffffffUL) +#define USER_SIZE (USER_TOP - USER_BASE) // a macro to test if a pointer is inside user space #define is_user_address(x) (((addr_t)(x)) >= USER_BASE && ((addr_t)(x)) <= USER_TOP) -- 2.11.4.GIT