This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ce22c28e88b05ea0e77d43ad16b5069c5278a1f7 Author: p-szafonimateusz <[email protected]> AuthorDate: Tue Jun 4 08:51:22 2024 +0200 arch/x86_64: add kernel stack support arch/x86_64: add kernel stack support Signed-off-by: p-szafonimateusz <[email protected]> --- arch/x86_64/include/intel64/irq.h | 26 +++++ arch/x86_64/include/irq.h | 18 +++- arch/x86_64/src/common/CMakeLists.txt | 9 ++ arch/x86_64/src/common/Make.defs | 13 ++- arch/x86_64/src/common/x86_64_addrenv_kstack.c | 109 +++++++++++++++++++++ arch/x86_64/src/common/x86_64_exit.c | 6 ++ arch/x86_64/src/common/x86_64_internal.h | 22 ++++- arch/x86_64/src/common/x86_64_pthread_start.c | 13 +++ arch/x86_64/src/common/x86_64_switchcontext.c | 6 ++ arch/x86_64/src/common/x86_64_syscall.c | 34 +++++++ arch/x86_64/src/common/x86_64_task_start.c | 13 +++ arch/x86_64/src/intel64/intel64_cpu.c | 3 + arch/x86_64/src/intel64/intel64_head.S | 47 ++++++++- arch/x86_64/src/intel64/intel64_initialstate.c | 52 ++++++++-- .../x86_64/src/intel64/intel64_schedulesigaction.c | 24 +++++ 15 files changed, 377 insertions(+), 18 deletions(-) diff --git a/arch/x86_64/include/intel64/irq.h b/arch/x86_64/include/intel64/irq.h index c149604749..e1289e5558 100644 --- a/arch/x86_64/include/intel64/irq.h +++ b/arch/x86_64/include/intel64/irq.h @@ -528,6 +528,15 @@ struct xcptcontext uint64_t saved_rflags; uint64_t saved_rsp; +#ifdef CONFIG_ARCH_KERNEL_STACK + /* For kernel stack enabled we can't use tcb->xcp.regs[REG_RSP] as it may + * point to kernel stack if signaled task is waiting now in + * up_switch_context() + */ + + uint64_t saved_ursp; +#endif + /* Register save area - allocated from stack in up_initial_state() */ uint64_t *regs; @@ -540,6 +549,23 @@ struct xcptcontext uint8_t nsyscalls; struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST]; #endif + +#ifdef CONFIG_ARCH_ADDRENV +# ifdef CONFIG_ARCH_KERNEL_STACK + /* In this configuration, all syscalls execute from an internal kernel + * stack. Why? Because when we instantiate and initialize the address + * environment of the new user process, we will temporarily lose the + * address environment of the old user process, including its stack + * contents. The kernel C logic will crash immediately with no valid + * stack in place. + */ + + uintptr_t *ustkptr; /* Saved user stack pointer */ + uintptr_t *kstack; /* Allocate base of the (aligned) kernel stack */ + uintptr_t *ktopstk; /* Top of kernel stack */ + uintptr_t *kstkptr; /* Saved kernel stack pointer */ +# endif +#endif }; #endif diff --git a/arch/x86_64/include/irq.h b/arch/x86_64/include/irq.h index 92024a910f..f46544a1c8 100644 --- a/arch/x86_64/include/irq.h +++ b/arch/x86_64/include/irq.h @@ -49,8 +49,9 @@ * Pre-processor Definitions ****************************************************************************/ -#define X86_64_CPUPRIV_USTACK_OFFSET (16) -#define X86_64_CPUPRIV_UVBASE_OFFSET (24) +#define X86_64_CPUPRIV_USTACK_OFFSET (16) +#define X86_64_CPUPRIV_UVBASE_OFFSET (24) +#define X86_64_CPUPRIV_KTOPSTK_OFFSET (32) /**************************************************************************** * Public Data @@ -82,6 +83,19 @@ struct intel64_cpu_s uint64_t *uvbase; #endif + +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Kernel stack pointer. + * + * We have to track the current kernel stack pointer to handle + * syscalls in kernel mode. All registers are occupied when entering + * syscall, so we cannot get this value from tcb in syscall handler. + * We keep referenve to kernel stack in CPU private data and update it + * at each context switch. + */ + + uint64_t *ktopstk; +#endif }; /**************************************************************************** diff --git a/arch/x86_64/src/common/CMakeLists.txt b/arch/x86_64/src/common/CMakeLists.txt index 5a4334fbe3..5fb128f2ec 100644 --- a/arch/x86_64/src/common/CMakeLists.txt +++ b/arch/x86_64/src/common/CMakeLists.txt @@ -68,4 +68,13 @@ if(NOT CONFIG_ALARM_ARCH) list(APPEND SRCS x86_64_udelay.c x86_64_mdelay.c) endif() +if(CONFIG_ARCH_KERNEL_STACK) + list(APPEND SRCS x86_64_addrenv_kstack.c) +endif() + +if(NOT CONFIG_BUILD_FLAT) + list(APPEND SRCS x86_64_task_start.c x86_64_pthread_start.c + x86_64_signal_dispatch.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/x86_64/src/common/Make.defs b/arch/x86_64/src/common/Make.defs index bb18944627..429afc7647 100644 --- a/arch/x86_64/src/common/Make.defs +++ b/arch/x86_64/src/common/Make.defs @@ -58,7 +58,18 @@ CMN_CSRCS += x86_64_mmu.c endif ifeq ($(CONFIG_ARCH_ADDRENV),y) -CMN_CSRCS += x86_64_addrenv.c x86_64_addrenv_perms.c +CMN_CSRCS += x86_64_addrenv.c x86_64_pgalloc.c x86_64_addrenv_perms.c +endif + +ifeq ($(CONFIG_ARCH_KERNEL_STACK),y) +CMN_CSRCS += x86_64_addrenv_kstack.c +endif + +ifneq ($(CONFIG_BUILD_FLAT),y) +CMN_CSRCS += x86_64_task_start.c +CMN_CSRCS += x86_64_pthread_start.c +CMN_CSRCS += x86_64_signal_dispatch.c +CMN_UASRCS += x86_64_signal_handler.S endif ifndef CONFIG_ALARM_ARCH diff --git a/arch/x86_64/src/common/x86_64_addrenv_kstack.c b/arch/x86_64/src/common/x86_64_addrenv_kstack.c new file mode 100644 index 0000000000..6a56bf7ca6 --- /dev/null +++ b/arch/x86_64/src/common/x86_64_addrenv_kstack.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/x86_64/src/common/x86_64_addrenv_kstack.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/sched.h> +#include <nuttx/kmalloc.h> +#include <nuttx/addrenv.h> +#include <nuttx/arch.h> + +#include "addrenv.h" + +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_addrenv_kstackalloc + * + * Description: + * This function is called when a new thread is created to allocate + * the new thread's kernel stack. This function may be called for certain + * terminating threads which have no kernel stack. It must be tolerant of + * that case. + * + * Input Parameters: + * tcb - The TCB of the thread that requires the kernel stack. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_addrenv_kstackalloc(struct tcb_s *tcb) +{ + DEBUGASSERT(tcb && tcb->xcp.kstack == NULL); + + /* Allocate the kernel stack */ + + tcb->xcp.kstack = kmm_memalign(STACK_ALIGNMENT, ARCH_KERNEL_STACKSIZE); + if (!tcb->xcp.kstack) + { + berr("ERROR: Failed to allocate the kernel stack\n"); + return -ENOMEM; + } + + return OK; +} + +/**************************************************************************** + * Name: up_addrenv_kstackfree + * + * Description: + * This function is called when any thread exits. This function frees + * the kernel stack. + * + * Input Parameters: + * tcb - The TCB of the thread that no longer requires the kernel stack. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_addrenv_kstackfree(struct tcb_s *tcb) +{ + DEBUGASSERT(tcb); + + /* Does the exiting thread have a kernel stack? */ + + if (tcb->xcp.kstack) + { + /* Yes.. Free the kernel stack */ + + kmm_free(tcb->xcp.kstack); + tcb->xcp.kstack = NULL; + } + + return OK; +} + +#endif /* CONFIG_ARCH_ADDRENV && CONFIG_ARCH_KERNEL_STACK */ diff --git a/arch/x86_64/src/common/x86_64_exit.c b/arch/x86_64/src/common/x86_64_exit.c index 093f60fcac..eccaa89e2a 100644 --- a/arch/x86_64/src/common/x86_64_exit.c +++ b/arch/x86_64/src/common/x86_64_exit.c @@ -89,6 +89,12 @@ void up_exit(int status) restore_critical_section(tcb, this_cpu()); +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Update kernel stack top pointer */ + + x86_64_set_ktopstk(tcb->xcp.ktopstk); +#endif + /* Then switch contexts */ x86_64_fullcontextrestore(tcb->xcp.regs); diff --git a/arch/x86_64/src/common/x86_64_internal.h b/arch/x86_64/src/common/x86_64_internal.h index b1f972aefc..0d1bde0860 100644 --- a/arch/x86_64/src/common/x86_64_internal.h +++ b/arch/x86_64/src/common/x86_64_internal.h @@ -32,6 +32,7 @@ # include <nuttx/sched.h> # include <stdint.h> # include <arch/io.h> +# include <arch/irq.h> # include <arch/multiboot2.h> #endif @@ -191,15 +192,34 @@ extern uint8_t _stbss[]; /* Start of .tbss */ extern uint8_t _etbss[]; /* End+1 of .tbss */ #endif +#ifndef __ASSEMBLY__ + /**************************************************************************** * Inline Functions ****************************************************************************/ +#ifdef CONFIG_ARCH_KERNEL_STACK +static inline_function uint64_t *x86_64_get_ktopstk(void) +{ + uint64_t *ktopstk; + __asm__ volatile("movq %%gs:(%c1), %0" + : "=rm" (ktopstk) + : "i" (offsetof(struct intel64_cpu_s, ktopstk))); + return ktopstk; +} + +static inline_function void x86_64_set_ktopstk(uint64_t *ktopstk) +{ + __asm__ volatile("movq %0, %%gs:(%c1)" + :: "r" (ktopstk), "i" (offsetof(struct intel64_cpu_s, + ktopstk))); +} +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -#ifndef __ASSEMBLY__ /* Atomic modification of registers */ void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits); diff --git a/arch/x86_64/src/common/x86_64_pthread_start.c b/arch/x86_64/src/common/x86_64_pthread_start.c index e24d06efcc..de09eef41b 100644 --- a/arch/x86_64/src/common/x86_64_pthread_start.c +++ b/arch/x86_64/src/common/x86_64_pthread_start.c @@ -27,6 +27,8 @@ #include <nuttx/arch.h> #include <assert.h> +#include "sched/sched.h" + #include <arch/syscall.h> #include "x86_64_internal.h" @@ -66,6 +68,17 @@ void up_pthread_start(pthread_trampoline_t startup, pthread_startroutine_t entrypt, pthread_addr_t arg) { +#ifdef CONFIG_ARCH_KERNEL_STACK + struct tcb_s *tcb = this_task(); + + /* Make sure that kernel stack is set for current CPU */ + + if (x86_64_get_ktopstk() == NULL) + { + x86_64_set_ktopstk(tcb->xcp.ktopstk); + } +#endif + /* Let sys_call3() do all of the work */ sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt, diff --git a/arch/x86_64/src/common/x86_64_switchcontext.c b/arch/x86_64/src/common/x86_64_switchcontext.c index cb461e8708..d7e0883b17 100644 --- a/arch/x86_64/src/common/x86_64_switchcontext.c +++ b/arch/x86_64/src/common/x86_64_switchcontext.c @@ -59,6 +59,12 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) { int cpu; +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Update kernel stack top pointer */ + + x86_64_set_ktopstk(tcb->xcp.ktopstk); +#endif + /* Are we in an interrupt handler? */ if (up_interrupt_context()) diff --git a/arch/x86_64/src/common/x86_64_syscall.c b/arch/x86_64/src/common/x86_64_syscall.c index cea1ad977d..1da8e300b7 100644 --- a/arch/x86_64/src/common/x86_64_syscall.c +++ b/arch/x86_64/src/common/x86_64_syscall.c @@ -218,6 +218,34 @@ uint64_t *x86_64_syscall(uint64_t *regs) regs[REG_RDX] = arg4; /* ucontext */ regs[REG_R10] = arg1; /* sighand */ +#ifdef CONFIG_ARCH_KERNEL_STACK + /* If we are signalling a user process, then we must be operating + * on the kernel stack now. We need to switch back to the user + * stack before dispatching the signal handler to the user code. + * The existence of an allocated kernel stack is sufficient + * information to make this decision. + */ + + if (rtcb->xcp.kstack != NULL) + { + uint64_t usp; + + /* Copy "info" into user stack */ + + usp = rtcb->xcp.saved_ursp - 8; + + /* Create a frame for info and copy the kernel info */ + + usp = usp - sizeof(siginfo_t); + memcpy((void *)usp, (void *)regs[REG_RSI], sizeof(siginfo_t)); + + /* Now set the updated SP and user copy of "info" to RSI */ + + regs[REG_RSP] = usp; + regs[REG_RSI] = usp; + } +#endif + break; } @@ -276,6 +304,12 @@ uint64_t *x86_64_syscall(uint64_t *regs) rtcb->xcp.syscall[rtcb->xcp.nsyscalls].sysreturn = regs[REG_RCX]; rtcb->xcp.nsyscalls += 1; +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Store reference to user RSP for signals */ + + rtcb->xcp.saved_ursp = regs[REG_RSP]; +#endif + /* Call syscall function */ ret = stub(nbr, arg1, arg2, arg3, arg4, arg5, arg6); diff --git a/arch/x86_64/src/common/x86_64_task_start.c b/arch/x86_64/src/common/x86_64_task_start.c index c70e999040..8e12802032 100644 --- a/arch/x86_64/src/common/x86_64_task_start.c +++ b/arch/x86_64/src/common/x86_64_task_start.c @@ -26,6 +26,8 @@ #include <nuttx/arch.h> #include <assert.h> +#include "sched/sched.h" + #include <arch/syscall.h> #include "x86_64_internal.h" @@ -63,6 +65,17 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) { +#ifdef CONFIG_ARCH_KERNEL_STACK + struct tcb_s *tcb = this_task(); + + /* Make sure that kernel stack is set for current CPU */ + + if (x86_64_get_ktopstk() == NULL) + { + x86_64_set_ktopstk(tcb->xcp.ktopstk); + } +#endif + /* Let sys_call3() do all of the work */ sys_call3(SYS_task_start, (uintptr_t)taskentry, (uintptr_t)argc, diff --git a/arch/x86_64/src/intel64/intel64_cpu.c b/arch/x86_64/src/intel64/intel64_cpu.c index 2a6565d984..7ae497aaa1 100644 --- a/arch/x86_64/src/intel64/intel64_cpu.c +++ b/arch/x86_64/src/intel64/intel64_cpu.c @@ -246,6 +246,9 @@ void x86_64_cpu_init(void) g_cpu_priv[i].ustack = NULL; g_cpu_priv[i].uvbase = (uint64_t *)CONFIG_ARCH_TEXT_VBASE; #endif +#ifdef CONFIG_ARCH_KERNEL_STACK + g_cpu_priv[i].ktopstk = NULL; +#endif /* Store private CPU in TSS */ diff --git a/arch/x86_64/src/intel64/intel64_head.S b/arch/x86_64/src/intel64/intel64_head.S index b8174b503c..757879e7e9 100644 --- a/arch/x86_64/src/intel64/intel64_head.S +++ b/arch/x86_64/src/intel64/intel64_head.S @@ -552,10 +552,32 @@ x86_64_syscall_entry: /* Store current RSP on CPU private data first */ movq %rsp, %gs:X86_64_CPUPRIV_USTACK_OFFSET - /* Store return address - we need free register to store - * CPU context but at this point we don't have any. +#ifdef CONFIG_ARCH_KERNEL_STACK + /* If current RSP is greater than kernel stack, we have to switch stack. + * Otherwise we are in nested syscall and we can't modify stack pointer + */ + cmp %gs:X86_64_CPUPRIV_UVBASE_OFFSET, %rsp + jb no_kstack_switch + + /* Change to kernel stack */ + movq %gs:X86_64_CPUPRIV_KTOPSTK_OFFSET, %rsp +no_kstack_switch: +#endif + + /* Store some registers on stack. + * We need some free registers here to handle stored registers alignment + * and kernel stack for nested syscalls but at this point we don't have any + * + * RDI is needed only for CONFIG_ARCH_KERNEL_STACK=y but to simplify + * the logic here - we always release it. */ pushq %rcx + pushq %rdi + + /* Get original kernel stack for this call */ + + movq %rsp, %rdi + add $16, %rdi /* Get aligned registers area */ movq %rsp, %rcx @@ -566,7 +588,6 @@ x86_64_syscall_entry: /* Syscall arguments */ movq %rax, (8*REG_RAX)(%rcx) - movq %rdi, (8*REG_RDI)(%rcx) movq %rsi, (8*REG_RSI)(%rcx) movq %rdx, (8*REG_RDX)(%rcx) movq %r10, (8*REG_R10)(%rcx) @@ -602,16 +623,27 @@ x86_64_syscall_entry: xsave (%rcx) #endif - /* Save RCX */ + /* Save RDI and RCX which are on stack now */ + popq (8*REG_RDI)(%rcx) popq (8*REG_RCX)(%rcx) - /* Store user stack pointer */ + /* Store user stack pointer. We can't movq directly here. + * NOTE: for nested syscalls this value points to kernel stack. + */ pushq %gs:X86_64_CPUPRIV_USTACK_OFFSET popq (8*REG_RSP)(%rcx) /* Move stack pointer after registers area */ movq %rcx, %rsp +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Update stored kernel stack */ + movq %rsp, %gs:X86_64_CPUPRIV_KTOPSTK_OFFSET + + /* Store original kernel stack on stack which is now in RDI */ + pushq %rdi +#endif + /* Return value from syscall stored in rax */ movq %rcx, %rdi call x86_64_syscall @@ -626,6 +658,11 @@ x86_64_syscall_entry: xrstor (%rdi) #endif +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Restore original kernel stack */ + popq %gs:X86_64_CPUPRIV_KTOPSTK_OFFSET +#endif + /* Restore original user RSP */ movq (8*REG_RSP)(%rdi), %rsp diff --git a/arch/x86_64/src/intel64/intel64_initialstate.c b/arch/x86_64/src/intel64/intel64_initialstate.c index b020174e03..81f324ec4b 100644 --- a/arch/x86_64/src/intel64/intel64_initialstate.c +++ b/arch/x86_64/src/intel64/intel64_initialstate.c @@ -45,6 +45,12 @@ # error XCPTCONTEXT_SIZE must be aligned to XCPTCONTEXT_ALIGN ! #endif +/* Aligned size of the kernel stack */ + +#ifdef CONFIG_ARCH_KERNEL_STACK +# define ARCH_KERNEL_STACKSIZE STACK_ALIGN_UP(CONFIG_ARCH_KERNEL_STACKSIZE) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -65,6 +71,10 @@ void up_initial_state(struct tcb_s *tcb) { struct xcptcontext *xcp = &tcb->xcp; + uint64_t topstack; +#ifdef CONFIG_ARCH_KERNEL_STACK + uintptr_t *kstack = xcp->kstack; +#endif /* Initialize the idle thread stack */ @@ -102,11 +112,11 @@ void up_initial_state(struct tcb_s *tcb) #ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE /* Set the FCW to 1f80 */ - xcp->regs[1] = (uint64_t)0x0000037f00000000; + xcp->regs[1] = (uint64_t)0x0000037f00000000; /* Set the MXCSR to 1f80 */ - xcp->regs[3] = (uint64_t)0x0000000000001f80; + xcp->regs[3] = (uint64_t)0x0000000000001f80; #else /* Initialize XSAVE region with a valid state */ @@ -116,25 +126,49 @@ void up_initial_state(struct tcb_s *tcb) : "memory"); #endif + topstack = (uint64_t)xcp->regs - 8; + /* Save the initial stack pointer... the value of the stackpointer before * the "interrupt occurs." */ - xcp->regs[REG_RSP] = (uint64_t)xcp->regs - 8; - xcp->regs[REG_RBP] = 0; + xcp->regs[REG_RSP] = topstack; + xcp->regs[REG_RBP] = 0; + +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Use the process kernel stack to store context for user processes + * in syscalls. + */ + + if (kstack) + { + xcp->kstack = kstack; + xcp->ustkptr = (uintptr_t *)topstack; + topstack = (uintptr_t)kstack + ARCH_KERNEL_STACKSIZE; + xcp->ktopstk = (uintptr_t *)topstack; + xcp->kstkptr = xcp->ktopstk; + + /* Initialize kernel stack top reference */ + + if (x86_64_get_ktopstk() == NULL) + { + x86_64_set_ktopstk(tcb->xcp.ktopstk); + } + } +#endif /* Save the task entry point */ - xcp->regs[REG_RIP] = (uint64_t)tcb->start; + xcp->regs[REG_RIP] = (uint64_t)tcb->start; /* Set up the segment registers... assume the same segment as the caller. * That is not a good assumption in the long run. */ - xcp->regs[REG_DS] = up_getds(); - xcp->regs[REG_CS] = up_getcs(); - xcp->regs[REG_SS] = up_getss(); - xcp->regs[REG_ES] = up_getes(); + xcp->regs[REG_DS] = up_getds(); + xcp->regs[REG_CS] = up_getcs(); + xcp->regs[REG_SS] = up_getss(); + xcp->regs[REG_ES] = up_getes(); /* FS used by for TLS * used by some libc for TLS and segment reference diff --git a/arch/x86_64/src/intel64/intel64_schedulesigaction.c b/arch/x86_64/src/intel64/intel64_schedulesigaction.c index c581165fc2..0a9bd0f279 100644 --- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c +++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c @@ -126,6 +126,18 @@ void up_schedule_sigaction(struct tcb_s *tcb) up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; up_current_regs()[REG_RFLAGS] = 0; + +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Update segments to kernel segments */ + + up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS]; + up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS]; + up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS]; + + /* Update RSP to kernel stack */ + + up_current_regs()[REG_RSP] = (uint64_t)x86_64_get_ktopstk(); +#endif } } @@ -216,6 +228,18 @@ void up_schedule_sigaction(struct tcb_s *tcb) up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; up_current_regs()[REG_RFLAGS] = 0; +#ifdef CONFIG_ARCH_KERNEL_STACK + /* Update segments to kernel segments */ + + up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS]; + up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS]; + up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS]; + + /* Update RSP to kernel stack */ + + up_current_regs()[REG_RSP] = + (uint64_t)x86_64_get_ktopstk(); +#endif /* Mark that full context switch is necessary when we * return from interrupt handler. * In that case RIP, RSP and RFLAGS are changed, but
