From 81df510743fc8f738d184bb565b90156b1d2ea72 Mon Sep 17 00:00:00 2001 From: stefan Date: Fri, 10 Sep 2010 22:18:55 +0000 Subject: [PATCH] - add comments - use readable macros instead of constants - use the same error number like newlib git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@156 315a16e6-25f9-4109-90ae-ca3045a26c18 --- arch/x86/include/asm/gdt.h | 72 ++++++++++++++++++++++++++++++++ arch/x86/include/asm/irq.h | 1 + arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/string.h | 26 ++++++++++++ arch/x86/include/asm/tasks.h | 2 +- arch/x86/include/asm/tss.h | 2 +- arch/x86/kernel/entry.asm | 2 +- arch/x86/kernel/gdt.c | 49 ++++------------------ arch/x86/kernel/irq.c | 1 - arch/x86/kernel/timer.c | 14 +++++-- include/metalsvm/tasks_types.h | 2 +- kernel/tasks.c | 59 ++++++++++++++++---------- 12 files changed, 160 insertions(+), 73 deletions(-) create mode 100644 arch/x86/include/asm/gdt.h diff --git a/arch/x86/include/asm/gdt.h b/arch/x86/include/asm/gdt.h new file mode 100644 index 00000000..cb6b2561 --- /dev/null +++ b/arch/x86/include/asm/gdt.h @@ -0,0 +1,72 @@ +/* + * Copyright 2010 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +#ifndef __ARCH_GDT_H__ +#define __ARCH_GDT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GDT_FLAG_DATASEG 0x02 +#define GDT_FLAG_CODESEG 0x0a +#define GDT_FLAG_TSS 0x09 +#define GDT_FLAG_TSS_BUSY 0x02 + +#define GDT_FLAG_SEGMENT 0x10 +#define GDT_FLAG_RING0 0x00 +#define GDT_FLAG_RING1 0x20 +#define GDT_FLAG_RING2 0x40 +#define GDT_FLAG_RING3 0x60 +#define GDT_FLAG_PRESENT 0x80 + +#define GDT_FLAG_4K_GRAN 0x80 +#define GDT_FLAG_32_BIT 0x40 + +/* Defines a GDT entry */ +typedef struct { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +} __attribute__ ((packed)) gdt_entry_t; + +typedef struct { + unsigned short limit; + unsigned int base; +} __attribute__ ((packed)) gdt_ptr_t; + +#define GDT_ENTRIES (5+MAX_TASKS) +#if GDT_ENTRIES > 8192 +#error Too many GDT entries! +#endif + +//extern gdt_entry_t gdt[GDT_ENTRIES]; + +void gdt_install(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 87bd69c1..46665ed8 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -21,6 +21,7 @@ #define __ARCH_IRQ_H__ #include +#include #ifdef __cplusplus extern "C" { diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index e0f821d7..4ae3af4f 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -21,6 +21,7 @@ #define __ARCH_PROCESSOR_H__ #include +#include #ifdef CONFIG_PCI #include #endif @@ -60,8 +61,6 @@ static inline uint64_t rdtsc(void) #define NOP4 asm volatile ("nop;nop;nop;nop") #define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") -void gdt_install(void); - inline static int system_init(void) { #ifdef CONFIG_ROCKCREEK diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index f31b6b60..156579bb 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -27,6 +27,7 @@ extern "C" { #endif #ifdef HAVE_ARCH_MEMCPY +#if 0 inline static void *memcpy(void *dest, const void *src, size_t count) { int32_t i, j, k; @@ -44,6 +45,31 @@ inline static void *memcpy(void *dest, const void *src, size_t count) return dest; } +#else +inline static void *memcpy(void *dest, const void *src, size_t count) +{ + int32_t h, i, j, k, l, m; + + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + + asm volatile ( + "cld;\n\t" + "1: cmpl $0, %%eax ; je 2f\n\t" + "movl (%%edi), %%edx\n\t" + "movl $8, %%ecx\n\t" + "rep ; movsl\n\t" + "dec %%eax ; jmp 1b\n\t" + "2: movl (%%edi), %%edx\n\t" + "movl %%ebx, %%ecx\n\t" + "andl $31, %%ecx\n\t" + "rep ; movsb\n\t" + : "=&a"(h), "=&D"(i), "=&S"(j), "=&b"(k), "=&c"(l), "=&d"(m) + : "0"(count/32), "1"(dest), "2"(src), "3"(count) : "memory"); + + return dest; +} +#endif #endif #ifdef HAVE_ARCH_MEMSET diff --git a/arch/x86/include/asm/tasks.h b/arch/x86/include/asm/tasks.h index 3353f182..f929e0dc 100644 --- a/arch/x86/include/asm/tasks.h +++ b/arch/x86/include/asm/tasks.h @@ -24,7 +24,7 @@ #include #include -int create_default_frame(task_t* task, entry_point_t ep, void* arg, int ring); +int create_default_frame(task_t* task, entry_point_t ep, void* arg, int user); int register_task(task_t* task); void reschedule(void); diff --git a/arch/x86/include/asm/tss.h b/arch/x86/include/asm/tss.h index 769a477e..bb54ecef 100644 --- a/arch/x86/include/asm/tss.h +++ b/arch/x86/include/asm/tss.h @@ -49,7 +49,7 @@ typedef struct { uint16_t trace, bitmap; } __attribute__ ((packed)) tss_t; -/*extern tss_t task_state_segments[MAX_TASKS];*/ +//extern tss_t task_state_segments[MAX_TASKS]; #ifdef __cplusplus } diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index 1d232933..b22ee610 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -14,7 +14,7 @@ ; See the License for the specific language governing permissions and ; limitations under the License. ; -; This file is part of metalsvm. +; This file is part of MetalSVM. ; This is the kernel's entry point. We could either call main here, ; or we can use this to setup the stack or other nice stuff, like diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 26457b71..cc559023 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -20,42 +20,9 @@ #include #include #include +#include #include -/* Defines a GDT entry */ -typedef struct { - unsigned short limit_low; - unsigned short base_low; - unsigned char base_middle; - unsigned char access; - unsigned char granularity; - unsigned char base_high; -} __attribute__ ((packed)) gdt_entry_t; - -typedef struct { - unsigned short limit; - unsigned int base; -} __attribute__ ((packed)) gdt_ptr_t; - -#define GDT_ENTRIES (5+MAX_TASKS) -#if GDT_ENTRIES > 8192 -#error Too many GDT entries! -#endif - -#define GDT_FLAG_DATASEG 0x02 -#define GDT_FLAG_CODESEG 0x0a -#define GDT_FLAG_TSS 0x09 - -#define GDT_FLAG_SEGMENT 0x10 -#define GDT_FLAG_RING0 0x00 -#define GDT_FLAG_RING1 0x20 -#define GDT_FLAG_RING2 0x40 -#define GDT_FLAG_RING3 0x60 -#define GDT_FLAG_PRESENT 0x80 - -#define GDT_FLAG_4K_GRAN 0x80 -#define GDT_FLAG_32_BIT 0x40 - gdt_ptr_t gp; static tss_t task_state_segments[MAX_TASKS]; static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; @@ -68,8 +35,7 @@ static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE]; extern void gdt_flush(void); int register_task(task_t* task) { - uint32_t id = task->id; - uint16_t sel = (id+5)*8; + uint16_t sel = (task->id+5) << 3; asm volatile ("mov %0, %%ax; ltr %%ax" : : "ir"(sel)); @@ -176,7 +142,7 @@ void gdt_install(void) * uses 32-bit opcodes, and is a Code Segment descriptor. */ gdt_set_gate(1, 0, 0xFFFFFFFF, - GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, + GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | GDT_FLAG_32_BIT); /* @@ -185,7 +151,7 @@ void gdt_install(void) * this entry's access byte says it's a Data Segment */ gdt_set_gate(2, 0, 0xFFFFFFFF, - GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, + GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | GDT_FLAG_32_BIT); /* @@ -203,14 +169,15 @@ void gdt_install(void) GDT_FLAG_4K_GRAN | GDT_FLAG_32_BIT); /* - * Create TSS for each task (we use these segments for task switching) - */ + * Create a TSS for each task (we use these segments for task switching) + */ for(i=0; i #include #include +#include +#include #include /* @@ -83,11 +85,15 @@ int timer_set_frequency(unsigned int freq) irq_disable(); /* set the timer frequency */ +#ifdef CONFIG_LAPICTIMER + /* Use LAPIC timer instead of 8254 PIT */ +#else outportb(0x43, 0x34); - udelay(10); - outportb(0x40, LATCH(freq) & 0xFF); /* low byte */ - udelay(10); - outportb(0x40, LATCH(freq) >> 8); /* high byte */ + udelay(10); + outportb(0x40, LATCH(freq) & 0xFF); /* low byte */ + udelay(10); + outportb(0x40, LATCH(freq) >> 8); /* high byte */ +#endif curr_timer_freq = freq; diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index bcdb6bc6..12b812e5 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -41,13 +41,13 @@ struct mailbox_int32; typedef struct { tid_t id; /* task id = position in the task table */ + uint32_t status; unsigned char* ustack; /* stack of an user level task */ size_t stack_size; /* only user level tasks * are able to specify its stack size */ atomic_int32_t mem_usage; /* in number of pages */ struct mailbox_int32* mbox[MAX_TASKS]; - uint32_t status; } __attribute__((packed)) task_t; #ifdef __cplusplus diff --git a/kernel/tasks.c b/kernel/tasks.c index 2b4ecb1f..2e5662e3 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,17 +29,24 @@ #include task_t* current_task = NULL; -static task_t task_table[MAX_TASKS]; +static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, 0, NULL, 0, ATOMIC_INIT(0)}}; static spinlock_t table_lock = SPINLOCK_INIT; int multitasking_init(void) { - memset(task_table, 0x00, sizeof(task_t)*MAX_TASKS); - - task_table[0].status = TASK_RUNNING; - current_task = task_table+0; - register_task(current_task); + unsigned int i; - return 0; + for(i=0; iid); - while(1) ; + while(1) { + NOP8; + } } void NORETURN sys_exit(int arg) @@ -104,11 +114,11 @@ void NORETURN abort(void) { static int create_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size, int user) { - int ret = -1; + int ret = -ENOMEM; unsigned int i; if (BUILTIN_EXPECT(!ep, 0)) - return -1; + return -EINVAL; if (user && !stack_size) stack_size = DEFAULT_STACK_SIZE; @@ -117,8 +127,9 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size for(i=0; istatus == TASK_FINISHED) current_task->status = TASK_INVALID; - for(i=1; i <= MAX_TASKS; i++) { + for(i=1; iid + i) % MAX_TASKS; if (task_table[new_id].status == TASK_READY) { @@ -271,14 +283,19 @@ void scheduler(void) } } - if (current_task->status == TASK_RUNNING) + if ((current_task->status == TASK_RUNNING) || (current_task->status == TASK_IDLE)) goto get_task_out; /* - * we switch to the idle task (id=0), if the current task terminates + * we switch to the idle task, if the current task terminates * and no other is ready */ - current_task = task_table+0; + for(i=0; i