diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/Makefrag.am | 2 | ||||
-rw-r--r-- | arch/x86/machine/boot.c | 1 | ||||
-rw-r--r-- | arch/x86/machine/tcb.c | 109 | ||||
-rw-r--r-- | arch/x86/machine/tcb.h | 58 | ||||
-rw-r--r-- | arch/x86/machine/trap.h | 7 | ||||
-rw-r--r-- | arch/x86/machine/trap_asm.S | 16 |
6 files changed, 191 insertions, 2 deletions
diff --git a/arch/x86/Makefrag.am b/arch/x86/Makefrag.am index b61ab9e9..a6baf70d 100644 --- a/arch/x86/Makefrag.am +++ b/arch/x86/Makefrag.am @@ -26,6 +26,8 @@ x86_FILES = \ arch/x86/machine/pit.h \ arch/x86/machine/pmap.c \ arch/x86/machine/pmap.h \ + arch/x86/machine/tcb.c \ + arch/x86/machine/tcb.h \ arch/x86/machine/trap_asm.S \ arch/x86/machine/trap.c \ arch/x86/machine/trap.h \ diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c index 331d44ea..5a5148f0 100644 --- a/arch/x86/machine/boot.c +++ b/arch/x86/machine/boot.c @@ -280,7 +280,6 @@ boot_main(void) vm_phys_info(); pic_setup(); pit_setup(); - cpu_mp_setup(); kernel_main(); /* Never reached */ diff --git a/arch/x86/machine/tcb.c b/arch/x86/machine/tcb.c new file mode 100644 index 00000000..ee1cb4fe --- /dev/null +++ b/arch/x86/machine/tcb.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <kern/error.h> +#include <kern/init.h> +#include <kern/kmem.h> +#include <kern/param.h> +#include <kern/stddef.h> +#include <kern/string.h> +#include <kern/thread.h> +#include <machine/cpu.h> +#include <machine/tcb.h> +#include <machine/trap.h> + +static struct kmem_cache tcb_cache; + +void __init +tcb_setup(void) +{ + kmem_cache_init(&tcb_cache, "tcb", sizeof(struct tcb), + 0, NULL, NULL, NULL, 0); +} + +#ifdef __LP64__ + +static void +tcb_init_stack(struct tcb *tcb, void *stack, const struct thread *thread) +{ + struct trap_frame *frame; + + frame = (struct trap_frame *)(stack + STACK_SIZE) - 1; + memset(frame, 0, sizeof(*frame)); + frame->rdi = (unsigned long)thread; + frame->rip = (unsigned long)thread_main; + frame->cs = CPU_GDT_SEL_CODE; + frame->rflags = CPU_EFL_IF | CPU_EFL_ONE; + frame->rsp = (unsigned long)(stack + STACK_SIZE); + frame->ss = CPU_GDT_SEL_DATA; + tcb->frame = frame; +} + +#else /* __LP64__ */ + +static void +tcb_init_stack(struct tcb *tcb, void *stack, const struct thread *thread) +{ + struct trap_frame *frame; + const struct thread **arg; + const void **ret_addr; + void *ptr; + size_t size; + + /* Fake a function call (return address and argument) */ + ptr = stack + STACK_SIZE - (2 * sizeof(long)); + ret_addr = ptr; + *ret_addr = 0; + arg = ptr + sizeof(long); + *arg = thread; + + /* Exclude user space stack registers */ + size = sizeof(*frame) - (2 * sizeof(long)); + frame = ptr - size; + memset(frame, 0, size); + frame->ds = CPU_GDT_SEL_DATA; + frame->es = CPU_GDT_SEL_DATA; + frame->fs = CPU_GDT_SEL_CPU; + frame->gs = CPU_GDT_SEL_NULL; + frame->eip = (unsigned long)thread_main; + frame->cs = CPU_GDT_SEL_CODE; + frame->eflags = CPU_EFL_IF | CPU_EFL_ONE; + tcb->frame = frame; +} + +#endif /* __LP64__ */ + +int +tcb_create(struct tcb **tcbp, void *stack, const struct thread *thread) +{ + struct tcb *tcb; + + tcb = kmem_cache_alloc(&tcb_cache); + + if (tcb == NULL) + return ERROR_NOMEM; + + tcb_init_stack(tcb, stack, thread); + *tcbp = tcb; + return 0; +} + +void +tcb_load(struct tcb *tcb) +{ + trap_load(tcb->frame); +} diff --git a/arch/x86/machine/tcb.h b/arch/x86/machine/tcb.h new file mode 100644 index 00000000..96ac66a7 --- /dev/null +++ b/arch/x86/machine/tcb.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * Thread control block. + */ + +#ifndef _X86_TCB_H +#define _X86_TCB_H + +#include <kern/macros.h> +#include <machine/trap.h> + +/* + * Forward declaration. + */ +struct thread; + +/* + * Architecture specific thread data. + */ +struct tcb { + struct trap_frame *frame; +}; + +/* + * Set up the tcb module. + */ +void tcb_setup(void); + +/* + * Create a TCB. + * + * Prepare the given stack for execution. + */ +int tcb_create(struct tcb **tcbp, void *stack, const struct thread *thread); + +/* + * Load a TCB. + * + * The caller context is lost. + */ +void __noreturn tcb_load(struct tcb *tcb); + +#endif /* _X86_TCB_H */ diff --git a/arch/x86/machine/trap.h b/arch/x86/machine/trap.h index f25c5893..06275c4a 100644 --- a/arch/x86/machine/trap.h +++ b/arch/x86/machine/trap.h @@ -126,6 +126,13 @@ void trap_main(struct trap_frame *frame); */ void trap_frame_show(struct trap_frame *frame); +/* + * Load a context saved in a trap frame. + * + * The caller context is lost. + */ +void __noreturn trap_load(struct trap_frame *frame); + #endif /* __ASSEMBLER__ */ #endif /* _X86_TRAP_H */ diff --git a/arch/x86/machine/trap_asm.S b/arch/x86/machine/trap_asm.S index 29c12f41..55ac669f 100644 --- a/arch/x86/machine/trap_asm.S +++ b/arch/x86/machine/trap_asm.S @@ -77,6 +77,13 @@ ASM_ENTRY(trap_isr_ ## name) \ iretq; \ ASM_END(trap_isr_ ## name) +ASM_ENTRY(trap_load) + movq %rdi, %rsp + TRAP_POP_REGISTERS + addq $16, %rsp + iretq +ASM_END(trap_load) + #else /* __LP64__ */ #define TRAP_PUSH_REGISTERS \ @@ -103,7 +110,7 @@ ASM_END(trap_isr_ ## name) popl %ds; \ popl %es; \ popl %fs; \ - popl %gs; \ + popl %gs #define TRAP(vector, name) \ ASM_ENTRY(trap_isr_ ## name) \ @@ -130,6 +137,13 @@ ASM_ENTRY(trap_isr_ ## name) \ iret; \ ASM_END(trap_isr_ ## name) +ASM_ENTRY(trap_load) + movl 4(%esp), %esp + TRAP_POP_REGISTERS + addl $8, %esp + iret +ASM_END(trap_load) + #endif /* __LP64__ */ .text |