21 |
|
|
22 |
#include "i386-trap.h" |
#include "i386-trap.h" |
23 |
#include "i386-segment.h" |
#include "i386-segment.h" |
24 |
|
#include "i386-regs.h" |
25 |
|
|
26 |
/* These are declared in cpu-locore.S */ |
/* These are declared in cpu-locore.S */ |
27 |
extern struct thread *cpu_switch_context (struct thread *, |
extern struct thread *cpu_switch_context (struct thread *, |
49 |
the argument-passing/return-value conventions. |
the argument-passing/return-value conventions. |
50 |
This function will not return normally, |
This function will not return normally, |
51 |
so we don`t have to worry about a return address. */ |
so we don`t have to worry about a return address. */ |
52 |
|
|
53 |
STACK_IKS(stack)->eip = (int) cpu_thread_continue; |
STACK_IKS(stack)->eip = (int) cpu_thread_continue; |
54 |
STACK_IKS(stack)->ebx = (int) continuation; |
STACK_IKS(stack)->ebx = (int) continuation; |
55 |
STACK_IKS(stack)->esp = (int) STACK_IEL(stack); |
STACK_IKS(stack)->esp = (int) STACK_IEL(stack); |
56 |
|
|
57 |
/* Point top of kernel stack to user`s registers. */ |
/* Point top of kernel stack to user`s registers. */ |
58 |
|
|
59 |
STACK_IEL(stack)->saved_state = &thread->pcb.trap_frame; |
STACK_IEL(stack)->saved_state = &thread->pcb.trap_frame; |
60 |
} |
} |
61 |
|
|
101 |
static void |
static void |
102 |
switch_ktss (struct pcb *pcb) |
switch_ktss (struct pcb *pcb) |
103 |
{ |
{ |
104 |
/* ??? set ESP0 here. */ |
vm_offset_t stack_top; |
105 |
|
|
106 |
|
/* Set ring 0 stack pointer to top of trap frame. */ |
107 |
|
|
108 |
|
stack_top = (int) (&pcb->trap_frame.v86_segs); |
109 |
|
|
110 |
|
ktss.esp0 = stack_top; |
111 |
|
ktss.ss0 = KERNEL_DS; |
112 |
|
|
113 |
|
/* Use system LDT. */ |
114 |
|
|
115 |
|
load_ldt (KERNEL_LDT); |
116 |
} |
} |
117 |
|
|
118 |
/* Switch to the first thread on a CPU. */ |
/* Switch to the first thread on a CPU. */ |
159 |
struct pcb *pcb = &thread->pcb; |
struct pcb *pcb = &thread->pcb; |
160 |
|
|
161 |
/* We can't let random values leak out to the user. */ |
/* We can't let random values leak out to the user. */ |
162 |
|
|
163 |
memset (pcb, 0, sizeof (struct pcb)); |
memset (pcb, 0, sizeof (struct pcb)); |
164 |
|
|
165 |
/* Guarantee that the bootstrapped thread will be in user |
/* Guarantee that the bootstrapped thread will be in user mode. */ |
166 |
mode. */ |
|
167 |
pcb->trap_frame.cs = USER_CS; |
pcb->trap_frame.cs = USER_CS; |
168 |
pcb->trap_frame.ss = USER_DS; |
pcb->trap_frame.ss = USER_DS; |
169 |
pcb->trap_frame.ds = USER_DS; |
pcb->trap_frame.ds = USER_DS; |
173 |
pcb->trap_frame.efl = 0x200; |
pcb->trap_frame.efl = 0x200; |
174 |
} |
} |
175 |
|
|
176 |
|
/* Get status information about THREAD. What type of status is specified |
177 |
|
with FLAVOR. Information is returned in STATUS. */ |
178 |
|
|
179 |
|
kern_return_t |
180 |
|
thread_get_status (struct thread *thread, thread_status_flavor_t flavor, |
181 |
|
thread_status_t status, int *count) |
182 |
|
{ |
183 |
|
switch (flavor) |
184 |
|
{ |
185 |
|
case THREAD_STATUS_FLAVOR_CPU_STATE: |
186 |
|
memcpy (status, & thread->pcb.trap_frame, |
187 |
|
sizeof (struct thread_state_i386)); |
188 |
|
*count = sizeof (struct thread_state_i386); |
189 |
|
return KERN_SUCCESS; |
190 |
|
|
191 |
|
default: |
192 |
|
panic ("invalid thread status?"); |
193 |
|
} |
194 |
|
return KERN_SUCCESS; |
195 |
|
} |
196 |
|
|
197 |
|
|
198 |
|
/* Set status information for THREAD. What type of status is specified |
199 |
|
with FLAVOR. Information is located in STATUS. */ |
200 |
|
|
201 |
|
kern_return_t |
202 |
|
thread_set_status (struct thread *thread, thread_status_flavor_t flavor, |
203 |
|
thread_status_t status, int count) |
204 |
|
{ |
205 |
|
switch (flavor) |
206 |
|
{ |
207 |
|
case THREAD_STATUS_FLAVOR_CPU_STATE: |
208 |
|
memcpy (& thread->pcb.trap_frame, status, |
209 |
|
sizeof (struct thread_state_i386)); |
210 |
|
return KERN_SUCCESS; |
211 |
|
|
212 |
|
default: |
213 |
|
panic ("invalid thread status?"); |
214 |
|
} |
215 |
|
return KERN_SUCCESS; |
216 |
|
} |
217 |
|
|