1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <string.h>
5
6 #include <sys/kconfig.h>
7 #include <sys/kassert.h>
8 #include <sys/kmem.h>
9 #include <sys/mp.h>
10 #include <sys/thread.h>
11 #include <machine/amd64.h>
12 #include <machine/amd64op.h>
13 #include <machine/trap.h>
14 #include <machine/pmap.h>
15
16 extern void ThreadKThreadEntry(TrapFrame *tf);
17 extern void switchstack(uint64_t *oldrsp, uint64_t rsp);
18
19 void
Thread_InitArch(Thread * thr)20 Thread_InitArch(Thread *thr)
21 {
22 thr->arch.useFP = true;
23 }
24
25 void
Thread_SetupKThread(Thread * thr,void (* f)(),uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)26 Thread_SetupKThread(Thread *thr, void (*f)(),
27 uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
28 {
29 // Initialize stack
30 uint64_t stacktop = thr->kstack + PGSIZE;
31 ThreadArchStackFrame *sf;
32 TrapFrame *tf;
33
34 tf = (TrapFrame *)(stacktop - sizeof(*tf));
35 sf = (ThreadArchStackFrame *)(stacktop - sizeof(*tf) - sizeof(*sf));
36 thr->arch.rsp = (uint64_t)sf;
37
38 memset(tf, 0, sizeof(*tf));
39 memset(sf, 0, sizeof(*sf));
40
41 // Setup thread exit function on stack
42
43 sf->rip = (uint64_t)&ThreadKThreadEntry;
44 sf->rdi = (uint64_t)tf;
45
46 tf->ds = 0;
47 tf->ss = 0; //SEL_KDS;
48 tf->rsp = stacktop;
49 tf->cs = SEL_KCS;
50 tf->rip = (uint64_t)f;
51 tf->rdi = (uint64_t)arg1;
52 tf->rsi = (uint64_t)arg2;
53 tf->rdx = (uint64_t)arg3;
54 tf->rflags = RFLAGS_IF;
55 }
56
57 static void
ThreadEnterUserLevelCB(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)58 ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
59 {
60 TrapFrame tf;
61
62 memset(&tf, 0, sizeof(tf));
63 tf.ds = SEL_UDS | 3;
64 tf.rip = (uint64_t)arg1;
65 tf.cs = SEL_UCS | 3;
66 tf.rsp = (uint64_t)arg2 + MEM_USERSPACE_STKLEN - PGSIZE;
67 tf.ss = SEL_UDS | 3;
68 tf.rflags = RFLAGS_IF;
69 tf.rdi = (uint64_t)arg3; /* Userspace Argument */
70
71 Trap_Pop(&tf);
72 }
73
74 void
Thread_SetupUThread(Thread * thr,uintptr_t rip,uintptr_t arg)75 Thread_SetupUThread(Thread *thr, uintptr_t rip, uintptr_t arg)
76 {
77 Thread_SetupKThread(thr, ThreadEnterUserLevelCB, rip,
78 thr->ustack, arg);
79 }
80
81 extern TaskStateSegment64 TSS[MAX_CPUS];
82
83 void
Thread_SwitchArch(Thread * oldthr,Thread * newthr)84 Thread_SwitchArch(Thread *oldthr, Thread *newthr)
85 {
86 /*
87 * Save and restore floating point and vector CPU state using the fxsave
88 * and fxrstor instructions.
89 */
90 if (oldthr->arch.useFP)
91 {
92 fxsave(&oldthr->arch.xsa);
93 }
94
95 if (newthr->arch.useFP)
96 {
97 fxrstor(&newthr->arch.xsa);
98 }
99
100 clts();
101
102 // Jump to trapframe
103 switchstack(&oldthr->arch.rsp, newthr->arch.rsp);
104
105 // Set new RSP0
106 TSS[CPU()].rsp0 = oldthr->kstack + 4096;
107 }
108
109