blob: 94648e06d24db265aa4d81738f4c4fdeb88ba77a [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2009 Corey Tabaka
3 * Copyright (c) 2014 Travis Geiselbrecht
4 * Copyright (c) 2015 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction,
9 * including without limitation the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25#include <sys/types.h>
26#include <string.h>
27#include <stdlib.h>
28#include <debug.h>
29#include <kernel/thread.h>
30#include <kernel/spinlock.h>
31#include <arch/x86.h>
32#include <arch/x86/descriptor.h>
33#include <arch/fpu.h>
34
35/*struct context_switch_frame {
36 uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
37 uint32_t ds, es, fs, gs;
38 uint32_t eip, cs, eflags;
39};*/
40struct context_switch_frame {
41 uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
42 uint32_t eflags;
43 uint32_t eip;
44};
45
46/* we're uniprocessor at this point for x86, so store a global pointer to the current thread */
47struct thread *_current_thread;
48
49extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
50
51static void initial_thread_func(void) __NO_RETURN;
52static void initial_thread_func(void)
53{
54 int ret;
55
56 /* release the thread lock that was implicitly held across the reschedule */
57 spin_unlock(&thread_lock);
58 arch_enable_ints();
59
60 ret = _current_thread->entry(_current_thread->arg);
61
62// dprintf("initial_thread_func: thread %p exiting with %d\n", _current_thread, ret);
63
64 thread_exit(ret);
65}
66
67void arch_thread_initialize(thread_t *t)
68{
69 // create a default stack frame on the stack
70 vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
71
72 // make sure the top of the stack is 8 byte aligned for EABI compliance
73 stack_top = ROUNDDOWN(stack_top, 8);
74
75 struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
76 frame--;
77
78 // fill it in
79 memset(frame, 0, sizeof(*frame));
80
81 frame->eip = (vaddr_t) &initial_thread_func;
82 frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
83 //frame->cs = CODE_SELECTOR;
84 //frame->fs = DATA_SELECTOR;
85 //frame->gs = DATA_SELECTOR;
86 //frame->es = DATA_SELECTOR;
87 //frame->ds = DATA_SELECTOR;
88
89 // set the stack pointer
90 t->arch.esp = (vaddr_t)frame;
91#if X86_WITH_FPU
92 memset(t->arch.fpu_buffer, 0, sizeof(t->arch.fpu_buffer));
93 t->arch.fpu_states = (vaddr_t *)ROUNDUP(((vaddr_t)t->arch.fpu_buffer), 16);
94#endif
95}
96
97void arch_dump_thread(thread_t *t)
98{
99 if (t->state != THREAD_RUNNING) {
100 dprintf(INFO, "\tarch: ");
101 dprintf(INFO, "sp 0x%lx\n", t->arch.esp);
102 }
103}
104
105void arch_context_switch(thread_t *oldthread, thread_t *newthread)
106{
107 //dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
108
109#if X86_WITH_FPU
110 fpu_context_switch(oldthread, newthread);
111#endif
112
113 __asm__ __volatile__ (
114 "pushl $1f \n\t"
115 "pushf \n\t"
116 "pusha \n\t"
117 "movl %%esp,(%%edx) \n\t"
118 "movl %%eax,%%esp \n\t"
119 "popa \n\t"
120 "popf \n\t"
121 "ret \n\t"
122 "1: \n\t"
123
124 :
125 : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
126 );
127
128 /*__asm__ __volatile__ (
129 "pushf \n\t"
130 "pushl %%cs \n\t"
131 "pushl $1f \n\t"
132 "pushl %%gs \n\t"
133 "pushl %%fs \n\t"
134 "pushl %%es \n\t"
135 "pushl %%ds \n\t"
136 "pusha \n\t"
137 "movl %%esp,(%%edx) \n\t"
138 "movl %%eax,%%esp \n\t"
139 "popa \n\t"
140 "popl %%ds \n\t"
141 "popl %%es \n\t"
142 "popl %%fs \n\t"
143 "popl %%gs \n\t"
144 "iret \n\t"
145 "1: "
146 :
147 : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
148 );*/
149}
150