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