metal-cos/sys/amd64/thread.c

119 lines
2.5 KiB
C
Raw Normal View History

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
2014-11-29 23:46:17 +00:00
#include <sys/kconfig.h>
#include <sys/kassert.h>
2014-10-15 01:02:19 +00:00
#include <sys/kmem.h>
2014-11-29 23:46:17 +00:00
#include <sys/mp.h>
#include <sys/thread.h>
#include <machine/cpu.h>
#include <machine/cpuop.h>
#include <machine/trap.h>
2015-01-17 01:57:21 +00:00
#include <machine/pmap.h>
2023-10-24 02:24:43 +00:00
extern TaskStateSegment64 TSS[MAX_CPUS];
extern Thread *curProc[MAX_CPUS];
extern Spinlock schedLock;
extern void switchstack(uint64_t *oldrsp, uint64_t rsp);
void
Thread_InitArch(Thread *thr)
{
thr->arch.useFP = true;
}
2023-10-24 02:24:43 +00:00
void
ThreadKThreadEntry(TrapFrame *tf) __NO_LOCK_ANALYSIS
{
TSS[CPU()].rsp0 = curProc[CPU()]->kstack + 4096;
Spinlock_Unlock(&schedLock);
Trap_Pop(tf);
}
void
2015-01-17 01:57:21 +00:00
Thread_SetupKThread(Thread *thr, void (*f)(),
uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
{
// Initialize stack
uint64_t stacktop = thr->kstack + PGSIZE;
ThreadArchStackFrame *sf;
TrapFrame *tf;
tf = (TrapFrame *)(stacktop - sizeof(*tf));
sf = (ThreadArchStackFrame *)(stacktop - sizeof(*tf) - sizeof(*sf));
thr->arch.rsp = (uint64_t)sf;
memset(tf, 0, sizeof(*tf));
memset(sf, 0, sizeof(*sf));
// Setup thread exit function on stack
sf->rip = (uint64_t)&ThreadKThreadEntry;
sf->rdi = (uint64_t)tf;
tf->ds = 0;
tf->ss = 0; //SEL_KDS;
tf->rsp = stacktop;
tf->cs = SEL_KCS;
tf->rip = (uint64_t)f;
2015-01-17 01:57:21 +00:00
tf->rdi = (uint64_t)arg1;
tf->rsi = (uint64_t)arg2;
tf->rdx = (uint64_t)arg3;
tf->rflags = RFLAGS_IF;
}
2015-01-06 01:06:35 +00:00
static void
2015-01-17 01:57:21 +00:00
ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
2015-01-06 01:06:35 +00:00
{
TrapFrame tf;
memset(&tf, 0, sizeof(tf));
tf.ds = SEL_UDS | 3;
2015-01-17 01:57:21 +00:00
tf.rip = (uint64_t)arg1;
2015-01-06 01:06:35 +00:00
tf.cs = SEL_UCS | 3;
2023-08-20 23:04:28 +00:00
tf.rsp = (uint64_t)arg2 + MEM_USERSPACE_STKLEN - PGSIZE;
2015-01-06 01:06:35 +00:00
tf.ss = SEL_UDS | 3;
tf.rflags = RFLAGS_IF;
2015-01-17 01:57:21 +00:00
tf.rdi = (uint64_t)arg3; /* Userspace Argument */
2015-01-06 01:06:35 +00:00
Trap_Pop(&tf);
}
void
2015-01-17 01:57:21 +00:00
Thread_SetupUThread(Thread *thr, uintptr_t rip, uintptr_t arg)
2015-01-06 01:06:35 +00:00
{
2015-01-17 01:57:21 +00:00
Thread_SetupKThread(thr, ThreadEnterUserLevelCB, rip,
thr->ustack, arg);
2015-01-06 01:06:35 +00:00
}
void
Thread_SwitchArch(Thread *oldthr, Thread *newthr)
{
2023-08-20 23:04:28 +00:00
/*
* Save and restore floating point and vector CPU state using the fxsave
* and fxrstor instructions.
*/
if (oldthr->arch.useFP)
{
fxsave(&oldthr->arch.xsa);
}
if (newthr->arch.useFP)
{
fxrstor(&newthr->arch.xsa);
}
clts();
// Jump to trapframe
switchstack(&oldthr->arch.rsp, newthr->arch.rsp);
2014-11-29 23:46:17 +00:00
// Set new RSP0
TSS[CPU()].rsp0 = oldthr->kstack + 4096;
}