From 8646b56a630b64a5e29e7c768ad96d6523d3a6cf Mon Sep 17 00:00:00 2001 From: stefan Date: Wed, 5 Jan 2011 10:16:53 +0000 Subject: [PATCH] - minor changes to support APIC (currently, we got page fault by entering apic_calibration) - first steps to realize a loader git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@365 315a16e6-25f9-4109-90ae-ca3045a26c18 --- arch/x86/include/asm/page.h | 5 ++ arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/apic.c | 37 +++++---- arch/x86/mm/page.c | 12 +-- include/metalsvm/elf.h | 125 +++++++++++++++++++------------ include/metalsvm/tasks.h | 2 +- kernel/main.c | 4 +- kernel/tasks.c | 44 ++++++++++- kernel/tests.c | 28 ++----- 9 files changed, 162 insertions(+), 97 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index ae521db1..b8d57ad3 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -105,4 +105,9 @@ int arch_paging_init(void); */ int get_kernel_pgd(task_t* task); +/* + * Create a new page directory for a new user-level task + */ +page_dir_t* create_pgd(void); + #endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a50b7c14..d6cdfd2e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -139,7 +139,7 @@ inline static int system_init(void) scc_init(); #endif gdt_install(); - //apic_init(); + apic_init(); #ifdef CONFIG_PCI pci_init(); #endif diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index ef9c06ff..8583bc61 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -54,7 +55,7 @@ static volatile ioapic_t* ioapic = NULL; static uint32_t ncores = 1; static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}; #if MAX_CORES > 1 -static uint8_t boot_code[] = {0xE9, 0x1F, 0x00, 0x90, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x04, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x37, 0x00, 0x01, 0x00, 0x08, 0x00, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0xB8, 0x02, 0xD0, 0xBA, 0x02, 0x31, 0xDB, 0xEA, 0x00, 0x10, 0x10, 0x00, 0x08, 0x00}; +static uint8_t boot_code[] = {0xE9, 0x1E, 0x00, 0x17, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x03, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0xFA, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0x0F, 0x20, 0xC0, 0x25, 0xFF, 0xFF, 0xFF, 0x9F, 0x0D, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x22, 0xC0, 0x31, 0xC0, 0x0F, 0x22, 0xD8, 0xBC, 0xEF, 0xBE, 0xAD, 0xDE, 0x31, 0xC0, 0x31, 0xDB, 0xEA, 0xDE, 0xC0, 0xAD, 0xDE, 0x08, 0x00}; #endif static uint8_t initialized = 0; static atomic_int32_t cpu_online = ATOMIC_INIT(1); @@ -68,10 +69,10 @@ static inline uint32_t lapic_read(uint32_t addr) static inline void lapic_write(uint32_t addr, uint32_t value) { /* - * to avoid ap entium bug, we have to read a apic register before - * before we write value to this register + * to avoid a pentium bug, we have to read a apic register + * before we write a value to this register */ - asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(addr+lapic), "b"(value) : "%edx"); + asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); //*((volatile uint32_t*) (lapic+addr)) = value; } @@ -167,20 +168,16 @@ static int wakeup_all_aps(uint32_t start_eip) } #endif -int smp_main(void) -{ #if MAX_CORES > 1 +static void smp_main(void) +{ vga_puts("JJAJAJAJAJAJA\n"); lowlevel_init(); atomic_int32_inc(&cpu_online); kputs("JAJAJAJ\n"); - while(1) - - ; -#endif - - return 0; + while(1) ; } +#endif #ifndef CONFIG_MULTIBOOT static unsigned int* search_apic(unsigned int base, unsigned int limit) { @@ -201,6 +198,7 @@ static unsigned int* search_apic(unsigned int base, unsigned int limit) { int smp_init(void) { uint32_t i; + size_t bootaddr; int err; if (ncores <= 1) @@ -210,12 +208,19 @@ int smp_init(void) * dirty hack: Copy 16bit startup code (see tools/smp_setup.asm) * to a 16bit address. Wakeup the other cores via IPI. They start * at this address in real mode, switch to protected and finally - * they jump to 0x101000 (see smp_start in entry.asm) + * they jump to smp_main. */ - memcpy((void*)0x10000, boot_code, sizeof(boot_code)); + bootaddr = 0x10000; + map_region(per_core(current_task), bootaddr, get_pages(1), 1, MAP_KERNEL_SPACE); + for(i=0; ipgd->entries[index1] & 0xFFFFF000)) goto out; - pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000); + pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000); if (!pgt || !(pgt->entries[index2])) goto out; @@ -167,14 +167,14 @@ size_t map_region(task_t* task, size_t viraddr, size_t phyaddr, uint32_t npages, // clear the page table if (paging_enabled) - memset((void*) (KERNEL_SPACE - 1024*PAGE_SIZE + index*4), 0, PAGE_SIZE); + memset((void*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000), 0, PAGE_SIZE); else memset(pgt, 0, PAGE_SIZE); } else pgt = (page_table_t*) (task->pgd->entries[index] & 0xFFFFF000); /* convert physical address to virtual */ if (paging_enabled) - pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*4) & 0xFFFFF000); + pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000); index = (viraddr >> 12) & 0x3FF; if (BUILTIN_EXPECT(pgt->entries[index], 0)) { @@ -225,7 +225,7 @@ size_t vm_alloc(task_t* task, uint32_t npages, uint32_t flags) index1 = i >> 22; index2 = (i >> 12) & 0x3FF; - pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000); + pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000); if (!pgt || !(pgt->entries[index2])) { i+=PAGE_SIZE; j++; @@ -257,7 +257,7 @@ int vm_free(task_t* task, size_t viraddr, uint32_t npages) index1 = viraddr >> 22; index2 = (viraddr >> 12) & 0x3FF; - pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000); + pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000); if (!pgt) continue; pgt->entries[index2] = 0; @@ -289,7 +289,7 @@ int print_paging_tree(size_t viraddr) /* convert physical address to virtual */ if (paging_enabled && pgt) - pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*4); + pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE); kprintf("\tPage table entry %u: ", index2); if (pgt) diff --git a/include/metalsvm/elf.h b/include/metalsvm/elf.h index f1fc773b..62dd4e96 100644 --- a/include/metalsvm/elf.h +++ b/include/metalsvm/elf.h @@ -29,59 +29,92 @@ extern "C" { #define ELF_MAGIC 0x464C457F +#define ELF_ET_NONE 0x0000 // no type +#define ELF_ET_REL 0x0001 // relocatable +#define ELF_ET_EXEC 0x0002 // executeable +#define ELF_ET_DYN 0x0003 // Shared-Object-File +#define ELF_ET_CORE 0x0004 // Corefile +#define ELF_ET_LOPROC 0xFF00 // Processor-specific +#define ELF_ET_HIPROC 0x00FF // Processor-specific + +#define ELF_EM_NONE 0x0000 // no type +#define ELF_EM_M32 0x0001 // AT&T WE 32100 +#define ELF_EM_SPARC 0x0002 // SPARC +#define ELF_EM_386 0x0003 // Intel 80386 +#define ELF_EM_68K 0x0004 // Motorola 68000 +#define ELF_EM_88K 0x0005 // Motorola 88000 +#define ELF_EM_860 0x0007 // Intel 80860 +#define ELF_EM_MIPS 0x0008 // MIPS RS3000 + +#define ELF_CLASS_NONE 0x0000 +#define ELF_CLASS_32 0x0001 // 32bit file +#define ELF_CLASS_64 0x0002 // 64bit file + +#define ELF_DATA_NONE 0x0000 +#define ELF_DATA_2LSB 0x0001 +#define ELF_DATA_2MSB 0x002 + /* Legal values for p_type (segment type). */ -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local storage segment */ -#define PT_NUM 8 /* Number of defined types */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ -#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ -#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ +#define ELF_PT_NULL 0 /* Program header table entry unused */ +#define ELF_PT_LOAD 1 /* Loadable program segment */ +#define ELF_PT_DYNAMIC 2 /* Dynamic linking information */ +#define ELF_PT_INTERP 3 /* Program interpreter */ +#define ELF_PT_NOTE 4 /* Auxiliary information */ +#define ELF_PT_SHLIB 5 +#define ELF_PT_PHDR 6 /* Entry for header table itself */ +#define ELF_PT_TLS 7 /* Thread-local storage segment */ +#define ELF_PT_NUM 8 /* Number of defined types */ +#define ELF_PT_LOOS 0x60000000 /* Start of OS-specific */ +#define ELF_PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define ELF_PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define ELF_PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define ELF_PT_LOSUNW 0x6ffffffa +#define ELF_PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define ELF_PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define ELF_PT_HISUNW 0x6fffffff +#define ELF_PT_HIOS 0x6fffffff /* End of OS-specific */ +#define ELF_PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define ELF_PT_HIPROC 0x7fffffff /* End of processor-specific */ typedef struct { - uint32_t magic; - uint32_t version; - uint64_t reserved; - uint64_t version2; - uint32_t entry; - uint32_t ph_offset; - uint32_t sh_offset; - uint32_t flags; - uint16_t header_size; - uint16_t ph_entry_size; - uint16_t ph_entry_count; - uint16_t sh_entry_size; - uint16_t sh_entry_count; - uint16_t sh_str_table_index; -} __attribute__((packed)) elf_header_t; - + uint32_t magic; + uint8_t _class; + uint8_t data; + uint8_t version; + uint8_t pad[8]; + uint8_t nident; +} __attribute__ ((packed)) elf_ident_t; + typedef struct { - uint32_t type; - uint32_t offset; - uint32_t virt_addr; - uint32_t phys_addr; - uint32_t file_size; - uint32_t mem_size; - uint32_t flags; - uint32_t alignment; -} __attribute__((packed)) elf_program_header_t; + elf_ident_t ident; + uint16_t type; + uint16_t machine; + uint32_t version; + uint32_t entry; + uint32_t ph_offset; + uint32_t sh_offset; + uint32_t flags; + uint16_t header_size; + uint16_t ph_entry_size; + uint16_t ph_entry_count; + uint16_t sh_entry_size; + uint16_t sh_entry_count; + uint16_t sh_str_table_index; +} __attribute__ ((packed)) elf_header_t; + +typedef struct { + uint32_t type; + uint32_t offset; + uint32_t virt_addr; + uint32_t phys_addr; + uint32_t file_size; + uint32_t mem_size; + uint32_t flags; + uint32_t alignment; +} __attribute__ ((packed)) elf_program_header_t; #ifdef __cplusplus } #endif - #endif diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index e528aeec..1aae59d4 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -38,7 +38,7 @@ int multitasking_init(void); int create_kernel_task(tid_t*, entry_point_t, void*); /* create a user level task. if sz is zero, the task with the default stack size will be created */ -int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t sz); +int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv); /* until the task id is runnint, the current task is block */ int join_task(tid_t id, int* result); diff --git a/kernel/main.c b/kernel/main.c index a3631e06..dcad1ab9 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -97,7 +97,7 @@ int main(void) kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end); system_calibration(); - network_init(); + //network_init(); kprintf("Processor frequency: %u MHz\n", get_cpu_frequency()); kprintf("Total memory: %u MBytes\n", atomic_int32_read(&total_pages)/((1024*1024)/PAGE_SIZE)); @@ -105,7 +105,7 @@ int main(void) kprintf("Current available memory: %u MBytes\n", atomic_int32_read(&total_available_pages)/((1024*1024)/PAGE_SIZE)); sleep(5); - list_root(); + //list_root(); test_init(); per_core(current_task)->status = TASK_IDLE; diff --git a/kernel/tasks.c b/kernel/tasks.c index 0ee5ab1b..714a3528 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include DEFINE_PER_CORE(task_t*, current_task, NULL); static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, 0, ATOMIC_INIT(0), NULL, NULL}}; @@ -173,10 +175,48 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg) return create_task(id, ep, arg, 0, 0); } -int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size) +int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv) +{ + vfs_node_t* node; + elf_header_t header; + page_dir_t* pgd; + + node = findnode_fs(filename); + if (node && (node->type == FS_FILE)) { + kprintf("Found application %s at node %p\n", filename, node); + + read_fs(node, (uint8_t*)&header, sizeof(elf_header_t), 0); + if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0)) + return -EINVAL; + + if (BUILTIN_EXPECT(header.type != ELF_ET_EXEC, 0)) + return -EINVAL; + + if (BUILTIN_EXPECT(header.machine != ELF_EM_386, 0)) + return -EINVAL; + + if (BUILTIN_EXPECT(header.ident._class != ELF_CLASS_32, 0)) + return -EINVAL; + + if (BUILTIN_EXPECT(header.ident.data != ELF_DATA_2LSB, 0)) + return -EINVAL; + + kprintf("entry point at 0x%x\n", header.entry); + + pgd = create_pgd(); + if (!pgd) + return -ENOMEM; + + return 0; + } + + return -EINVAL; +} + +/*int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size) { return create_task(id, ep, arg, stack_size, 1); -} +}*/ int join_task(tid_t id, int* result) { diff --git a/kernel/tests.c b/kernel/tests.c index ae74dc4d..b256c385 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -83,25 +83,6 @@ static int STDCALL foo(void* arg) return 42; } -static int STDCALL userfoo(void* arg) -{ - int i; - - if (!arg) - return 0; - - for (i = 0; i < 5; i++) - SYSCALL3(__NR_write, 0, (char*)arg, strlen((char*)arg)); - - // demo of a general protection fault - //kprintf("test user\n"); - - /* task exit */ - SYSCALL1(__NR_exit, 0); - - return 0; -} - static int STDCALL join_test(void* arg) { tid_t id; @@ -118,16 +99,17 @@ static int STDCALL join_test(void* arg) int test_init(void) { tid_t id1, id2, id3, id4, id5; + char* argv[1] = {"/bin/hello"}; sem_init(&producing, 1); sem_init(&consuming, 0); mailbox_int32_init(&mbox); - create_kernel_task(&id1, foo, "Hello from foo1\n"); + //create_kernel_task(&id1, foo, "Hello from foo1\n"); //create_kernel_task(&id2, join_test, NULL); - create_kernel_task(&id3, producer, NULL); - create_kernel_task(&id4, consumer, NULL); - //create_user_task(&id5, userfoo, "Hello from user process foo\n", 0); + //create_kernel_task(&id3, producer, NULL); + //create_kernel_task(&id4, consumer, NULL); + create_user_task(&id5, 8192, "/bin/hello", 1, argv); return 0; }