From be9ed3064dc798c8e34fafa6d7d465a97f1bf039 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 13 Sep 2015 14:51:25 +0200 Subject: [PATCH] preliminary works to use the gs register in user space --- hermit/arch/x86/include/asm/tasks.h | 3 ++- hermit/arch/x86/kernel/entry.asm | 21 +++++++++++++-------- hermit/arch/x86/kernel/processor.c | 6 +++--- hermit/arch/x86/kernel/tasks.c | 10 +++++++++- hermit/kernel/tasks.c | 4 ++-- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/hermit/arch/x86/include/asm/tasks.h b/hermit/arch/x86/include/asm/tasks.h index 14de8a41f..2d8995fcc 100644 --- a/hermit/arch/x86/include/asm/tasks.h +++ b/hermit/arch/x86/include/asm/tasks.h @@ -55,11 +55,12 @@ void switch_context(size_t** stack); * @param task Pointer to the task structure * @param ep The entry point for code execution * @param arg Arguments list pointer for the task's stack + * @param core_id Id of the core, which is firstly used by the task * @return * - 0 on success * - -EINVAL (-22) on failure */ -int create_default_frame(task_t* task, entry_point_t ep, void* arg); +int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t core_id); /** @brief Jump to user code * diff --git a/hermit/arch/x86/kernel/entry.asm b/hermit/arch/x86/kernel/entry.asm index 3b556d7bd..285e9a428 100644 --- a/hermit/arch/x86/kernel/entry.asm +++ b/hermit/arch/x86/kernel/entry.asm @@ -38,6 +38,7 @@ extern kernel_end MSR_FS_BASE equ 0xc0000100 MSR_GS_BASE equ 0xc0000101 +MSR_KERNEL_GS_BASE equ 0xc0000102 ; We use a special name to map this section at the begin of our kernel ; => Multiboot expects its magic number at the beginning of the kernel. @@ -350,8 +351,10 @@ align 16 isrsyscall: ; IF flag is already cleared ; cli + ; only called from user space => get kernel-level selector swapgs + ; get kernel stack xchg rsp, [gs:kernel_stack] @@ -391,8 +394,10 @@ isrsyscall: cli - ; restore registers + ; restore return value pop rax + + ; restore registers pop rsi pop rdi pop rcx @@ -407,6 +412,7 @@ isrsyscall: ; set user-level selector swapgs + ; EFLAGS (and IF flag) will be restored by sysret ; sti o64 sysret @@ -536,12 +542,16 @@ common_switch: call finish_task_switch no_context_switch: + ; do we interrupt user-level code? + cmp QWORD [rsp+24+18*8], 0x08 + je short kernel_space2 + swapgs ; set GS to the user-level selector +kernel_space2: ; restore fs / gs register global Lpatch2 Lpatch2: jmp short Lwrfsgs ; we patch later this jump to enable wrfsbase/wrgsbase - add rsp, 8 - ;pop r15 + pop r15 ;wrgsbase r15 ; currently, we don't use the gs register pop r15 wrfsbase r15 @@ -575,11 +585,6 @@ Lgo3: pop rcx pop rax - ; do we interrupt user-level code? - cmp QWORD [rsp+24], 0x08 - je short kernel_space2 - swapgs ; set GS to the user-level selector -kernel_space2: add rsp, 16 iretq diff --git a/hermit/arch/x86/kernel/processor.c b/hermit/arch/x86/kernel/processor.c index 73ddd70a5..f8ec84281 100644 --- a/hermit/arch/x86/kernel/processor.c +++ b/hermit/arch/x86/kernel/processor.c @@ -33,9 +33,9 @@ #include /* - * * Note that linker symbols are not variables, they have no memory allocated for - * * maintaining a value, rather their address is their value. - * */ + * Note that linker symbols are not variables, they have no memory allocated for + * maintaining a value, rather their address is their value. + */ extern const void percore_start; extern const void percore_end0; extern const void percore_end; diff --git a/hermit/arch/x86/kernel/tasks.c b/hermit/arch/x86/kernel/tasks.c index a355ca599..8e16acd1b 100644 --- a/hermit/arch/x86/kernel/tasks.c +++ b/hermit/arch/x86/kernel/tasks.c @@ -40,6 +40,13 @@ #define START_ADDRESS 0x40200000 +/* + * Note that linker symbols are not variables, they have no memory allocated for + * maintaining a value, rather their address is their value. + */ +extern const void percore_start; +extern const void percore_end0; + extern uint64_t base; static inline void enter_user_task(size_t ep, size_t stack) @@ -128,7 +135,7 @@ size_t* get_current_stack(void) return curr_task->last_stack_pointer; } -int create_default_frame(task_t* task, entry_point_t ep, void* arg) +int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t core_id) { size_t *stack; struct state *stptr; @@ -179,6 +186,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg) } stptr->cs = 0x08; stptr->ss = 0x10; + stptr->gs = core_id * ((size_t) &percore_end0 - (size_t) &percore_start); stptr->rflags = 0x1202; stptr->userrsp = stptr->rsp; diff --git a/hermit/kernel/tasks.c b/hermit/kernel/tasks.c index 985bcc6cd..5b129b8d2 100644 --- a/hermit/kernel/tasks.c +++ b/hermit/kernel/tasks.c @@ -325,7 +325,7 @@ int clone_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio) if (id) *id = i; - ret = create_default_frame(task_table+i, ep, arg); + ret = create_default_frame(task_table+i, ep, arg, core_id); if (ret) goto out; @@ -418,7 +418,7 @@ int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio, uint32_t c *id = i; //kprintf("Create task %d with pml4 at 0x%llx\n", i, task_table[i].page_map); - ret = create_default_frame(task_table+i, ep, arg); + ret = create_default_frame(task_table+i, ep, arg, core_id); if (ret) goto out;