1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <object.h> 8#include <machine.h> 9#include <arch/model/statedata.h> 10#include <arch/kernel/vspace.h> 11#include <arch/kernel/thread.h> 12#include <linker.h> 13 14void Arch_switchToThread(tcb_t *tcb) 15{ 16 /* set PD */ 17 setVMRoot(tcb); 18#ifdef ENABLE_SMP_SUPPORT 19 asm volatile("movq %[value], %%gs:%c[offset]" 20 : 21 : [value] "r"(&tcb->tcbArch.tcbContext.registers[Error + 1]), 22 [offset] "i"(OFFSETOF(nodeInfo_t, currentThreadUserContext))); 23#endif 24 if (config_set(CONFIG_KERNEL_X86_IBPB_ON_CONTEXT_SWITCH)) { 25 x86_ibpb(); 26 } 27 28 if (config_set(CONFIG_KERNEL_X86_RSB_ON_CONTEXT_SWITCH)) { 29 x86_flush_rsb(); 30 } 31} 32 33BOOT_CODE void Arch_configureIdleThread(tcb_t *tcb) 34{ 35 setRegister(tcb, FLAGS, FLAGS_USER_DEFAULT); 36 setRegister(tcb, NextIP, (uint64_t)idleThreadStart); 37 setRegister(tcb, CS, SEL_CS_0); 38 setRegister(tcb, SS, SEL_DS_0); 39 /* We set the RSP to 0, even though the idle thread will never touch it, as it 40 * allows us to distinguish an interrupt from the idle thread from an interrupt 41 * from kernel execution, just by examining the saved RSP value (since the kernel 42 * thread will have a valid RSP, and never 0). See traps.S for the other side of this 43 */ 44 setRegister(tcb, RSP, 0); 45} 46 47void Arch_switchToIdleThread(void) 48{ 49 tcb_t *tcb = NODE_STATE(ksIdleThread); 50 /* Force the idle thread to run on kernel page table */ 51 setVMRoot(tcb); 52#ifdef ENABLE_SMP_SUPPORT 53 asm volatile("movq %[value], %%gs:%c[offset]" 54 : 55 : [value] "r"(&tcb->tcbArch.tcbContext.registers[Error + 1]), 56 [offset] "i"(OFFSETOF(nodeInfo_t, currentThreadUserContext))); 57#endif 58} 59 60void Arch_activateIdleThread(tcb_t *tcb) 61{ 62 /* Don't need to do anything */ 63} 64 65void Mode_postModifyRegisters(tcb_t *tptr) 66{ 67 /* Setting Error to 0 will force a return by the interrupt path, which 68 * does a full restore. Unless we're the current thread, in which case 69 * we still have to go back out via a sysret */ 70 if (tptr != NODE_STATE(ksCurThread)) { 71 setRegister(tptr, Error, 0); 72 } 73} 74