]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/pcb.c
xnu-792.6.76.tar.gz
[apple/xnu.git] / osfmk / i386 / pcb.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
37839358
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50
1c79356b
A
51#include <mach_rt.h>
52#include <mach_debug.h>
53#include <mach_ldebug.h>
54
55#include <sys/kdebug.h>
56
57#include <mach/kern_return.h>
58#include <mach/thread_status.h>
59#include <mach/vm_param.h>
1c79356b 60
91447636
A
61#include <i386/cpu_data.h>
62#include <i386/cpu_number.h>
63
1c79356b 64#include <kern/counters.h>
91447636 65#include <kern/kalloc.h>
1c79356b 66#include <kern/mach_param.h>
91447636
A
67#include <kern/processor.h>
68#include <kern/cpu_data.h>
69#include <kern/cpu_number.h>
1c79356b
A
70#include <kern/task.h>
71#include <kern/thread.h>
1c79356b
A
72#include <kern/sched_prim.h>
73#include <kern/misc_protos.h>
74#include <kern/assert.h>
75#include <kern/spl.h>
91447636 76#include <kern/machine.h>
1c79356b
A
77#include <ipc/ipc_port.h>
78#include <vm/vm_kern.h>
91447636 79#include <vm/vm_map.h>
1c79356b 80#include <vm/pmap.h>
91447636 81#include <vm/vm_protos.h>
1c79356b
A
82
83#include <i386/thread.h>
84#include <i386/eflags.h>
85#include <i386/proc_reg.h>
86#include <i386/seg.h>
87#include <i386/tss.h>
88#include <i386/user_ldt.h>
89#include <i386/fpu.h>
90#include <i386/iopb_entries.h>
91447636
A
91#include <i386/mp_desc.h>
92#include <i386/cpu_data.h>
1c79356b 93
55e303ae 94
1c79356b
A
95/*
96 * Maps state flavor to number of words in the state:
97 */
91447636
A
98__private_extern__
99unsigned int _MachineStateCount[] = {
1c79356b
A
100 /* FLAVOR_LIST */ 0,
101 i386_NEW_THREAD_STATE_COUNT,
102 i386_FLOAT_STATE_COUNT,
103 i386_ISA_PORT_MAP_STATE_COUNT,
104 i386_V86_ASSIST_STATE_COUNT,
105 i386_REGS_SEGS_STATE_COUNT,
106 i386_THREAD_SYSCALL_STATE_COUNT,
107 /* THREAD_STATE_NONE */ 0,
108 i386_SAVED_STATE_COUNT,
109};
110
111/* Forward */
112
91447636
A
113void act_machine_throughcall(thread_t thr_act);
114user_addr_t get_useraddr(void);
115void act_machine_return(int);
116void act_machine_sv_free(thread_t, int);
117
1c79356b 118extern thread_t Switch_context(
91447636
A
119 thread_t old,
120 thread_continue_t cont,
121 thread_t new);
1c79356b
A
122extern void Thread_continue(void);
123extern void Load_context(
91447636 124 thread_t thread);
1c79356b
A
125
126/*
127 * consider_machine_collect:
128 *
129 * Try to collect machine-dependent pages
130 */
131void
91447636 132consider_machine_collect(void)
1c79356b
A
133{
134}
135
1c79356b 136void
91447636 137consider_machine_adjust(void)
1c79356b 138{
1c79356b
A
139}
140
141
91447636
A
142// DEBUG
143int DEBUG_kldt = 0;
144int DEBUG_uldt = 0;
1c79356b 145
91447636
A
146static void
147act_machine_switch_pcb( thread_t new )
1c79356b 148{
91447636 149 pcb_t pcb = new->machine.pcb;
1c79356b 150 int mycpu;
1c79356b
A
151 register iopb_tss_t tss = pcb->ims.io_tss;
152 vm_offset_t pcb_stack_top;
91447636 153 register user_ldt_t uldt = pcb->ims.ldt;
1c79356b 154
91447636
A
155 assert(new->kernel_stack != 0);
156 STACK_IEL(new->kernel_stack)->saved_state =
157 &new->machine.pcb->iss;
1c79356b
A
158
159 /*
160 * Save a pointer to the top of the "kernel" stack -
161 * actually the place in the PCB where a trap into
162 * kernel mode will push the registers.
163 * The location depends on V8086 mode. If we are
164 * not in V8086 mode, then a trap into the kernel
165 * won`t save the v86 segments, so we leave room.
166 */
167
168 pcb_stack_top = (pcb->iss.efl & EFL_VM)
169 ? (int) (&pcb->iss + 1)
170 : (int) (&pcb->iss.v86_segs);
171
172 mp_disable_preemption();
173 mycpu = cpu_number();
174
175 if (tss == 0) {
176 /*
177 * No per-thread IO permissions.
178 * Use standard kernel TSS.
179 */
91447636 180 if (!(gdt_desc_p(KERNEL_TSS)->access & ACC_TSS_BUSY))
1c79356b 181 set_tr(KERNEL_TSS);
91447636 182 current_ktss()->esp0 = pcb_stack_top;
1c79356b
A
183 }
184 else {
185 /*
186 * Set the IO permissions. Use this thread`s TSS.
187 */
91447636 188 *gdt_desc_p(USER_TSS)
1c79356b
A
189 = *(struct real_descriptor *)tss->iopb_desc;
190 tss->tss.esp0 = pcb_stack_top;
191 set_tr(USER_TSS);
91447636 192 gdt_desc_p(KERNEL_TSS)->access &= ~ ACC_TSS_BUSY;
1c79356b 193 }
1c79356b 194
1c79356b 195 /*
91447636 196 * Set the thread`s LDT or LDT entry.
1c79356b 197 */
91447636 198 if (uldt == 0) {
55e303ae 199 struct real_descriptor *ldtp;
1c79356b
A
200 /*
201 * Use system LDT.
202 */
91447636
A
203 // Set up the tasks specific ldt entries if extant
204 ldtp = (struct real_descriptor *)current_ldt();
55e303ae 205 ldtp[sel_idx(USER_CTHREAD)] = pcb->cthread_desc;
91447636
A
206 if (pcb->uldt_selector != 0)
207 ldtp[sel_idx(pcb->uldt_selector)] = pcb->uldt_desc;
1c79356b
A
208 set_ldt(KERNEL_LDT);
209 }
210 else {
211 /*
91447636 212 * Thread has its own LDT. // THIS SHOULD BE REMOVED!!!!
1c79356b 213 */
91447636 214 *gdt_desc_p(USER_LDT) = uldt->desc;
1c79356b 215 set_ldt(USER_LDT);
91447636
A
216 /*debug*/
217 if ((DEBUG_uldt++ % 0x7fff) == 0)
218 printf("KERNEL----> setting user ldt");
219
1c79356b 220 }
55e303ae 221
1c79356b
A
222 mp_enable_preemption();
223 /*
224 * Load the floating-point context, if necessary.
225 */
226 fpu_load_context(pcb);
227
228}
229
1c79356b
A
230/*
231 * Switch to the first thread on a CPU.
232 */
233void
55e303ae 234machine_load_context(
1c79356b
A
235 thread_t new)
236{
1c79356b 237 act_machine_switch_pcb(new);
91447636 238 Load_context(new);
1c79356b
A
239}
240
241/*
242 * Switch to a new thread.
243 * Save the old thread`s kernel state or continuation,
244 * and return it.
245 */
246thread_t
55e303ae 247machine_switch_context(
91447636
A
248 thread_t old,
249 thread_continue_t continuation,
250 thread_t new)
1c79356b 251{
1c79356b 252#if MACH_RT
91447636 253 assert(current_cpu_datap()->cpu_active_stack == old->kernel_stack);
1c79356b 254#endif
1c79356b
A
255
256 /*
257 * Save FP registers if in use.
258 */
259 fpu_save_context(old);
260
1c79356b
A
261 /*
262 * Switch address maps if need be, even if not switching tasks.
263 * (A server activation may be "borrowing" a client map.)
264 */
265 {
266 int mycpu = cpu_number();
267
91447636 268 PMAP_SWITCH_CONTEXT(old, new, mycpu)
1c79356b
A
269 }
270
271 /*
272 * Load the rest of the user state for the new thread
273 */
91447636 274 act_machine_switch_pcb(new);
9bccf70c
A
275 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
276 (int)old, (int)new, old->sched_pri, new->sched_pri, 0);
55e303ae 277 old->continuation = NULL;
1c79356b
A
278 return(Switch_context(old, continuation, new));
279}
280
1c79356b
A
281/*
282 * act_machine_sv_free
283 * release saveareas associated with an act. if flag is true, release
284 * user level savearea(s) too, else don't
285 */
286void
91447636 287act_machine_sv_free(__unused thread_t act, __unused int flag)
1c79356b 288{
1c79356b
A
289}
290
91447636
A
291
292/*
293 * This is where registers that are not normally specified by the mach-o
294 * file on an execve would be nullified, perhaps to avoid a covert channel.
295 */
296kern_return_t
297machine_thread_state_initialize(
298 thread_t thread)
299{
300#pragma unused (thread)
301
302 return KERN_SUCCESS;
303}
304
305
1c79356b
A
306/*
307 * act_machine_set_state:
308 *
91447636 309 * Set the status of the specified thread.
1c79356b
A
310 */
311
312kern_return_t
55e303ae 313machine_thread_set_state(
91447636 314 thread_t thr_act,
1c79356b
A
315 thread_flavor_t flavor,
316 thread_state_t tstate,
317 mach_msg_type_number_t count)
318{
55e303ae 319 int kernel_act = 0;
1c79356b
A
320
321 switch (flavor) {
322 case THREAD_SYSCALL_STATE:
323 {
324 register struct thread_syscall_state *state;
325 register struct i386_saved_state *saved_state = USER_REGS(thr_act);
326
327 state = (struct thread_syscall_state *) tstate;
328 saved_state->eax = state->eax;
329 saved_state->edx = state->edx;
330 if (kernel_act)
331 saved_state->efl = state->efl;
332 else
333 saved_state->efl = (state->efl & ~EFL_USER_CLEAR) | EFL_USER_SET;
334 saved_state->eip = state->eip;
335 saved_state->uesp = state->esp;
336 break;
337 }
338
339 case i386_SAVED_STATE:
340 {
341 register struct i386_saved_state *state;
342 register struct i386_saved_state *saved_state;
343
344 if (count < i386_SAVED_STATE_COUNT) {
345 return(KERN_INVALID_ARGUMENT);
346 }
347
348 state = (struct i386_saved_state *) tstate;
349
91447636
A
350 /* Check segment selectors are safe */
351 if (!kernel_act &&
352 !valid_user_segment_selectors(state->cs,
353 state->ss,
354 state->ds,
355 state->es,
356 state->fs,
357 state->gs))
358 return KERN_INVALID_ARGUMENT;
359
1c79356b
A
360 saved_state = USER_REGS(thr_act);
361
362 /*
363 * General registers
364 */
365 saved_state->edi = state->edi;
366 saved_state->esi = state->esi;
367 saved_state->ebp = state->ebp;
368 saved_state->uesp = state->uesp;
369 saved_state->ebx = state->ebx;
370 saved_state->edx = state->edx;
371 saved_state->ecx = state->ecx;
372 saved_state->eax = state->eax;
373 saved_state->eip = state->eip;
374 if (kernel_act)
375 saved_state->efl = state->efl;
376 else
377 saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
378 | EFL_USER_SET;
379
380 /*
381 * Segment registers. Set differently in V8086 mode.
382 */
383 if (state->efl & EFL_VM) {
384 /*
385 * Set V8086 mode segment registers.
386 */
387 saved_state->cs = state->cs & 0xffff;
388 saved_state->ss = state->ss & 0xffff;
389 saved_state->v86_segs.v86_ds = state->ds & 0xffff;
390 saved_state->v86_segs.v86_es = state->es & 0xffff;
391 saved_state->v86_segs.v86_fs = state->fs & 0xffff;
392 saved_state->v86_segs.v86_gs = state->gs & 0xffff;
393
394 /*
395 * Zero protected mode segment registers.
396 */
397 saved_state->ds = 0;
398 saved_state->es = 0;
399 saved_state->fs = 0;
400 saved_state->gs = 0;
401
91447636 402 if (thr_act->machine.pcb->ims.v86s.int_table) {
1c79356b
A
403 /*
404 * Hardware assist on.
405 */
91447636 406 thr_act->machine.pcb->ims.v86s.flags =
1c79356b
A
407 state->efl & (EFL_TF | EFL_IF);
408 }
409 }
55e303ae 410 else if (kernel_act) {
1c79356b
A
411 /*
412 * 386 mode. Set segment registers for flat
413 * 32-bit address space.
414 */
55e303ae
A
415 saved_state->cs = KERNEL_CS;
416 saved_state->ss = KERNEL_DS;
417 saved_state->ds = KERNEL_DS;
418 saved_state->es = KERNEL_DS;
419 saved_state->fs = KERNEL_DS;
91447636 420 saved_state->gs = CPU_DATA_GS;
1c79356b
A
421 }
422 else {
423 /*
424 * User setting segment registers.
425 * Code and stack selectors have already been
426 * checked. Others will be reset by 'iret'
427 * if they are not valid.
428 */
429 saved_state->cs = state->cs;
430 saved_state->ss = state->ss;
431 saved_state->ds = state->ds;
432 saved_state->es = state->es;
433 saved_state->fs = state->fs;
434 saved_state->gs = state->gs;
435 }
436 break;
437 }
438
439 case i386_NEW_THREAD_STATE:
440 case i386_REGS_SEGS_STATE:
441 {
442 register struct i386_new_thread_state *state;
443 register struct i386_saved_state *saved_state;
444
445 if (count < i386_NEW_THREAD_STATE_COUNT) {
446 return(KERN_INVALID_ARGUMENT);
447 }
448
91447636
A
449 state = (struct i386_new_thread_state *) tstate;
450
1c79356b
A
451 if (flavor == i386_REGS_SEGS_STATE) {
452 /*
453 * Code and stack selectors must not be null,
454 * and must have user protection levels.
455 * Only the low 16 bits are valid.
456 */
457 state->cs &= 0xffff;
458 state->ss &= 0xffff;
459 state->ds &= 0xffff;
460 state->es &= 0xffff;
461 state->fs &= 0xffff;
462 state->gs &= 0xffff;
463
464 if (!kernel_act &&
91447636
A
465 !valid_user_segment_selectors(state->cs,
466 state->ss,
467 state->ds,
468 state->es,
469 state->fs,
470 state->gs))
1c79356b
A
471 return KERN_INVALID_ARGUMENT;
472 }
473
1c79356b
A
474 saved_state = USER_REGS(thr_act);
475
476 /*
477 * General registers
478 */
479 saved_state->edi = state->edi;
480 saved_state->esi = state->esi;
481 saved_state->ebp = state->ebp;
482 saved_state->uesp = state->uesp;
483 saved_state->ebx = state->ebx;
484 saved_state->edx = state->edx;
485 saved_state->ecx = state->ecx;
486 saved_state->eax = state->eax;
487 saved_state->eip = state->eip;
488 if (kernel_act)
489 saved_state->efl = state->efl;
490 else
491 saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
492 | EFL_USER_SET;
493
494 /*
495 * Segment registers. Set differently in V8086 mode.
496 */
497 if (state->efl & EFL_VM) {
498 /*
499 * Set V8086 mode segment registers.
500 */
501 saved_state->cs = state->cs & 0xffff;
502 saved_state->ss = state->ss & 0xffff;
503 saved_state->v86_segs.v86_ds = state->ds & 0xffff;
504 saved_state->v86_segs.v86_es = state->es & 0xffff;
505 saved_state->v86_segs.v86_fs = state->fs & 0xffff;
506 saved_state->v86_segs.v86_gs = state->gs & 0xffff;
507
508 /*
509 * Zero protected mode segment registers.
510 */
511 saved_state->ds = 0;
512 saved_state->es = 0;
513 saved_state->fs = 0;
514 saved_state->gs = 0;
515
91447636 516 if (thr_act->machine.pcb->ims.v86s.int_table) {
1c79356b
A
517 /*
518 * Hardware assist on.
519 */
91447636 520 thr_act->machine.pcb->ims.v86s.flags =
1c79356b
A
521 state->efl & (EFL_TF | EFL_IF);
522 }
523 }
55e303ae 524 else if (flavor == i386_NEW_THREAD_STATE && kernel_act) {
1c79356b
A
525 /*
526 * 386 mode. Set segment registers for flat
527 * 32-bit address space.
528 */
55e303ae
A
529 saved_state->cs = KERNEL_CS;
530 saved_state->ss = KERNEL_DS;
531 saved_state->ds = KERNEL_DS;
532 saved_state->es = KERNEL_DS;
533 saved_state->fs = KERNEL_DS;
91447636 534 saved_state->gs = CPU_DATA_GS;
1c79356b
A
535 }
536 else {
537 /*
538 * User setting segment registers.
539 * Code and stack selectors have already been
540 * checked. Others will be reset by 'iret'
541 * if they are not valid.
542 */
543 saved_state->cs = state->cs;
544 saved_state->ss = state->ss;
545 saved_state->ds = state->ds;
546 saved_state->es = state->es;
547 saved_state->fs = state->fs;
548 saved_state->gs = state->gs;
549 }
550 break;
551 }
552
553 case i386_FLOAT_STATE: {
55e303ae 554 if (count < i386_old_FLOAT_STATE_COUNT)
1c79356b 555 return(KERN_INVALID_ARGUMENT);
55e303ae
A
556 if (count < i386_FLOAT_STATE_COUNT)
557 return fpu_set_state(thr_act,(struct i386_float_state*)tstate);
558 else return fpu_set_fxstate(thr_act,(struct i386_float_state*)tstate);
1c79356b
A
559 }
560
561 /*
562 * Temporary - replace by i386_io_map
563 */
564 case i386_ISA_PORT_MAP_STATE: {
1c79356b
A
565 if (count < i386_ISA_PORT_MAP_STATE_COUNT)
566 return(KERN_INVALID_ARGUMENT);
567
568 break;
569 }
570
571 case i386_V86_ASSIST_STATE:
572 {
573 register struct i386_v86_assist_state *state;
574 vm_offset_t int_table;
575 int int_count;
576
577 if (count < i386_V86_ASSIST_STATE_COUNT)
578 return KERN_INVALID_ARGUMENT;
579
580 state = (struct i386_v86_assist_state *) tstate;
581 int_table = state->int_table;
582 int_count = state->int_count;
583
584 if (int_table >= VM_MAX_ADDRESS ||
585 int_table +
586 int_count * sizeof(struct v86_interrupt_table)
587 > VM_MAX_ADDRESS)
588 return KERN_INVALID_ARGUMENT;
589
91447636
A
590 thr_act->machine.pcb->ims.v86s.int_table = int_table;
591 thr_act->machine.pcb->ims.v86s.int_count = int_count;
1c79356b 592
91447636 593 thr_act->machine.pcb->ims.v86s.flags =
1c79356b
A
594 USER_REGS(thr_act)->efl & (EFL_TF | EFL_IF);
595 break;
596 }
597
598 case i386_THREAD_STATE: {
599 struct i386_saved_state *saved_state;
600 i386_thread_state_t *state25;
601
602 saved_state = USER_REGS(thr_act);
603 state25 = (i386_thread_state_t *)tstate;
604
605 saved_state->eax = state25->eax;
606 saved_state->ebx = state25->ebx;
607 saved_state->ecx = state25->ecx;
608 saved_state->edx = state25->edx;
609 saved_state->edi = state25->edi;
610 saved_state->esi = state25->esi;
611 saved_state->ebp = state25->ebp;
612 saved_state->uesp = state25->esp;
613 saved_state->efl = (state25->eflags & ~EFL_USER_CLEAR)
614 | EFL_USER_SET;
615 saved_state->eip = state25->eip;
616 saved_state->cs = USER_CS; /* FIXME? */
617 saved_state->ss = USER_DS;
618 saved_state->ds = USER_DS;
619 saved_state->es = USER_DS;
55e303ae
A
620 saved_state->fs = state25->fs;
621 saved_state->gs = state25->gs;
1c79356b
A
622 }
623 break;
624
625 default:
626 return(KERN_INVALID_ARGUMENT);
627 }
628
629 return(KERN_SUCCESS);
630}
631
632/*
633 * thread_getstatus:
634 *
635 * Get the status of the specified thread.
636 */
637
638
639kern_return_t
55e303ae 640machine_thread_get_state(
91447636 641 thread_t thr_act,
1c79356b
A
642 thread_flavor_t flavor,
643 thread_state_t tstate,
644 mach_msg_type_number_t *count)
645{
1c79356b
A
646 switch (flavor) {
647
648 case i386_SAVED_STATE:
649 {
650 register struct i386_saved_state *state;
651 register struct i386_saved_state *saved_state;
652
653 if (*count < i386_SAVED_STATE_COUNT)
654 return(KERN_INVALID_ARGUMENT);
655
656 state = (struct i386_saved_state *) tstate;
657 saved_state = USER_REGS(thr_act);
658
659 /*
660 * First, copy everything:
661 */
662 *state = *saved_state;
663
664 if (saved_state->efl & EFL_VM) {
665 /*
666 * V8086 mode.
667 */
668 state->ds = saved_state->v86_segs.v86_ds & 0xffff;
669 state->es = saved_state->v86_segs.v86_es & 0xffff;
670 state->fs = saved_state->v86_segs.v86_fs & 0xffff;
671 state->gs = saved_state->v86_segs.v86_gs & 0xffff;
672
91447636 673 if (thr_act->machine.pcb->ims.v86s.int_table) {
1c79356b
A
674 /*
675 * Hardware assist on
676 */
91447636 677 if ((thr_act->machine.pcb->ims.v86s.flags &
1c79356b
A
678 (EFL_IF|V86_IF_PENDING)) == 0)
679 state->efl &= ~EFL_IF;
680 }
681 }
682 else {
683 /*
684 * 386 mode.
685 */
686 state->ds = saved_state->ds & 0xffff;
687 state->es = saved_state->es & 0xffff;
688 state->fs = saved_state->fs & 0xffff;
689 state->gs = saved_state->gs & 0xffff;
690 }
691 *count = i386_SAVED_STATE_COUNT;
692 break;
693 }
694
695 case i386_NEW_THREAD_STATE:
696 case i386_REGS_SEGS_STATE:
697 {
698 register struct i386_new_thread_state *state;
699 register struct i386_saved_state *saved_state;
700
701 if (*count < i386_NEW_THREAD_STATE_COUNT)
702 return(KERN_INVALID_ARGUMENT);
703
704 state = (struct i386_new_thread_state *) tstate;
705 saved_state = USER_REGS(thr_act);
706
707 /*
708 * General registers.
709 */
710 state->edi = saved_state->edi;
711 state->esi = saved_state->esi;
712 state->ebp = saved_state->ebp;
713 state->ebx = saved_state->ebx;
714 state->edx = saved_state->edx;
715 state->ecx = saved_state->ecx;
716 state->eax = saved_state->eax;
717 state->eip = saved_state->eip;
718 state->efl = saved_state->efl;
719 state->uesp = saved_state->uesp;
720
721 state->cs = saved_state->cs;
722 state->ss = saved_state->ss;
723 if (saved_state->efl & EFL_VM) {
724 /*
725 * V8086 mode.
726 */
727 state->ds = saved_state->v86_segs.v86_ds & 0xffff;
728 state->es = saved_state->v86_segs.v86_es & 0xffff;
729 state->fs = saved_state->v86_segs.v86_fs & 0xffff;
730 state->gs = saved_state->v86_segs.v86_gs & 0xffff;
731
91447636 732 if (thr_act->machine.pcb->ims.v86s.int_table) {
1c79356b
A
733 /*
734 * Hardware assist on
735 */
91447636 736 if ((thr_act->machine.pcb->ims.v86s.flags &
1c79356b
A
737 (EFL_IF|V86_IF_PENDING)) == 0)
738 state->efl &= ~EFL_IF;
739 }
740 }
741 else {
742 /*
743 * 386 mode.
744 */
745 state->ds = saved_state->ds & 0xffff;
746 state->es = saved_state->es & 0xffff;
747 state->fs = saved_state->fs & 0xffff;
748 state->gs = saved_state->gs & 0xffff;
749 }
750 *count = i386_NEW_THREAD_STATE_COUNT;
751 break;
752 }
753
754 case THREAD_SYSCALL_STATE:
755 {
756 register struct thread_syscall_state *state;
757 register struct i386_saved_state *saved_state = USER_REGS(thr_act);
758
759 state = (struct thread_syscall_state *) tstate;
760 state->eax = saved_state->eax;
761 state->edx = saved_state->edx;
762 state->efl = saved_state->efl;
763 state->eip = saved_state->eip;
764 state->esp = saved_state->uesp;
765 *count = i386_THREAD_SYSCALL_STATE_COUNT;
766 break;
767 }
768
769 case THREAD_STATE_FLAVOR_LIST:
770 if (*count < 5)
771 return (KERN_INVALID_ARGUMENT);
772 tstate[0] = i386_NEW_THREAD_STATE;
773 tstate[1] = i386_FLOAT_STATE;
774 tstate[2] = i386_ISA_PORT_MAP_STATE;
775 tstate[3] = i386_V86_ASSIST_STATE;
776 tstate[4] = THREAD_SYSCALL_STATE;
777 *count = 5;
778 break;
779
780 case i386_FLOAT_STATE: {
55e303ae 781 if (*count < i386_old_FLOAT_STATE_COUNT)
1c79356b 782 return(KERN_INVALID_ARGUMENT);
55e303ae
A
783 if (*count< i386_FLOAT_STATE_COUNT) {
784 *count = i386_old_FLOAT_STATE_COUNT;
785 return fpu_get_state(thr_act,(struct i386_float_state *)tstate);
786 } else {
787 *count = i386_FLOAT_STATE_COUNT;
788 return fpu_get_fxstate(thr_act,(struct i386_float_state *)tstate);
789 }
1c79356b
A
790 }
791
792 /*
793 * Temporary - replace by i386_io_map
794 */
795 case i386_ISA_PORT_MAP_STATE: {
796 register struct i386_isa_port_map_state *state;
797 register iopb_tss_t tss;
798
799 if (*count < i386_ISA_PORT_MAP_STATE_COUNT)
800 return(KERN_INVALID_ARGUMENT);
801
802 state = (struct i386_isa_port_map_state *) tstate;
91447636 803 tss = thr_act->machine.pcb->ims.io_tss;
1c79356b
A
804
805 if (tss == 0) {
91447636 806 unsigned int i;
1c79356b
A
807
808 /*
809 * The thread has no ktss, so no IO permissions.
810 */
811
812 for (i = 0; i < sizeof state->pm; i++)
813 state->pm[i] = 0xff;
814 } else {
815 /*
816 * The thread has its own ktss.
817 */
818
819 bcopy((char *) tss->bitmap,
820 (char *) state->pm,
821 sizeof state->pm);
822 }
823
824 *count = i386_ISA_PORT_MAP_STATE_COUNT;
825 break;
826 }
827
828 case i386_V86_ASSIST_STATE:
829 {
830 register struct i386_v86_assist_state *state;
831
832 if (*count < i386_V86_ASSIST_STATE_COUNT)
833 return KERN_INVALID_ARGUMENT;
834
835 state = (struct i386_v86_assist_state *) tstate;
91447636
A
836 state->int_table = thr_act->machine.pcb->ims.v86s.int_table;
837 state->int_count = thr_act->machine.pcb->ims.v86s.int_count;
1c79356b
A
838
839 *count = i386_V86_ASSIST_STATE_COUNT;
840 break;
841 }
842
843 case i386_THREAD_STATE: {
844 struct i386_saved_state *saved_state;
845 i386_thread_state_t *state;
846
847 saved_state = USER_REGS(thr_act);
848 state = (i386_thread_state_t *)tstate;
849
850 state->eax = saved_state->eax;
851 state->ebx = saved_state->ebx;
852 state->ecx = saved_state->ecx;
853 state->edx = saved_state->edx;
854 state->edi = saved_state->edi;
855 state->esi = saved_state->esi;
856 state->ebp = saved_state->ebp;
857 state->esp = saved_state->uesp;
858 state->eflags = saved_state->efl;
859 state->eip = saved_state->eip;
860 state->cs = saved_state->cs;
861 state->ss = saved_state->ss;
862 state->ds = saved_state->ds;
863 state->es = saved_state->es;
864 state->fs = saved_state->fs;
865 state->gs = saved_state->gs;
866 break;
867 }
868
869 default:
870 return(KERN_INVALID_ARGUMENT);
871 }
872
873 return(KERN_SUCCESS);
874}
875
1c79356b
A
876/*
877 * Initialize the machine-dependent state for a new thread.
878 */
879kern_return_t
55e303ae
A
880machine_thread_create(
881 thread_t thread,
91447636 882 __unused task_t task)
1c79356b 883{
91447636 884 pcb_t pcb = &thread->machine.xxx_pcb;
1c79356b 885
91447636 886 thread->machine.pcb = pcb;
1c79356b 887
91447636 888 simple_lock_init(&pcb->lock, 0);
55e303ae
A
889
890 /*
891 * Guarantee that the bootstrapped thread will be in user
892 * mode.
893 */
894 pcb->iss.cs = USER_CS;
895 pcb->iss.ss = USER_DS;
896 pcb->iss.ds = USER_DS;
897 pcb->iss.es = USER_DS;
898 pcb->iss.fs = USER_DS;
899 pcb->iss.gs = USER_DS;
900 pcb->iss.efl = EFL_USER_SET;
901 {
55e303ae
A
902 struct real_descriptor *ldtp;
903 ldtp = (struct real_descriptor *)ldt;
904 pcb->cthread_desc = ldtp[sel_idx(USER_DS)];
91447636
A
905 pcb->uldt_desc = ldtp[sel_idx(USER_DS)];
906 pcb->uldt_selector = 0;
55e303ae 907 }
1c79356b 908
0b4e3aa0 909 /*
91447636 910 * Allocate a kernel stack per thread.
0b4e3aa0 911 */
91447636 912 stack_alloc(thread);
0b4e3aa0 913
1c79356b
A
914 return(KERN_SUCCESS);
915}
916
917/*
918 * Machine-dependent cleanup prior to destroying a thread
919 */
920void
55e303ae
A
921machine_thread_destroy(
922 thread_t thread)
1c79356b 923{
91447636 924 register pcb_t pcb = thread->machine.pcb;
1c79356b 925
55e303ae 926 assert(pcb);
91447636 927
55e303ae
A
928 if (pcb->ims.io_tss != 0)
929 iopb_destroy(pcb->ims.io_tss);
930 if (pcb->ims.ifps != 0)
91447636 931 fpu_free(pcb->ims.ifps);
55e303ae
A
932 if (pcb->ims.ldt != 0)
933 user_ldt_free(pcb->ims.ldt);
91447636 934 thread->machine.pcb = (pcb_t)0;
1c79356b
A
935}
936
937/*
938 * This is used to set the current thr_act/thread
939 * when starting up a new processor
940 */
941void
91447636 942machine_set_current_thread( thread_t thread )
1c79356b 943{
1c79356b 944 mp_disable_preemption();
1c79356b 945
91447636
A
946 current_cpu_datap()->cpu_active_thread = thread;
947 current_cpu_datap()->cpu_active_kloaded = THREAD_NULL;
1c79356b
A
948
949 mp_enable_preemption();
950}
951
1c79356b 952void
55e303ae 953machine_thread_terminate_self(void)
1c79356b 954{
1c79356b
A
955}
956
957void
958act_machine_return(int code)
959{
1c79356b
A
960 /*
961 * This code is called with nothing locked.
962 * It also returns with nothing locked, if it returns.
963 *
964 * This routine terminates the current thread activation.
965 * If this is the only activation associated with its
966 * thread shuttle, then the entire thread (shuttle plus
967 * activation) is terminated.
968 */
969 assert( code == KERN_TERMINATED );
1c79356b 970
1c79356b
A
971 thread_terminate_self();
972
973 /*NOTREACHED*/
974
91447636 975 panic("act_machine_return(%d): TALKING ZOMBIE! (1)", code);
1c79356b
A
976}
977
978
979/*
980 * Perform machine-dependent per-thread initializations
981 */
982void
55e303ae 983machine_thread_init(void)
1c79356b 984{
55e303ae
A
985 fpu_module_init();
986 iopb_init();
1c79356b
A
987}
988
989/*
990 * Some routines for debugging activation code
991 */
91447636
A
992static void dump_handlers(thread_t);
993void dump_regs(thread_t);
994int dump_act(thread_t thr_act);
1c79356b
A
995
996static void
91447636 997dump_handlers(thread_t thr_act)
1c79356b
A
998{
999 ReturnHandler *rhp = thr_act->handlers;
1000 int counter = 0;
1001
1002 printf("\t");
1003 while (rhp) {
1004 if (rhp == &thr_act->special_handler){
1005 if (rhp->next)
1006 printf("[NON-Zero next ptr(%x)]", rhp->next);
1007 printf("special_handler()->");
1008 break;
1009 }
1010 printf("hdlr_%d(%x)->",counter,rhp->handler);
1011 rhp = rhp->next;
1012 if (++counter > 32) {
1013 printf("Aborting: HUGE handler chain\n");
1014 break;
1015 }
1016 }
1017 printf("HLDR_NULL\n");
1018}
1019
1020void
91447636 1021dump_regs(thread_t thr_act)
1c79356b 1022{
91447636 1023 if (thr_act->machine.pcb) {
1c79356b
A
1024 register struct i386_saved_state *ssp = USER_REGS(thr_act);
1025 /* Print out user register state */
1026 printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n",
1027 ssp->edi, ssp->esi, ssp->ebp, ssp->ebx, ssp->edx);
1028 printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n",
1029 ssp->ecx, ssp->eax, ssp->eip, ssp->efl, ssp->uesp);
1030 printf("\t\tcs=%x ss=%x\n", ssp->cs, ssp->ss);
1031 }
1032}
1033
1034int
91447636 1035dump_act(thread_t thr_act)
1c79356b
A
1036{
1037 if (!thr_act)
1038 return(0);
1039
91447636 1040 printf("thread(0x%x)(%d): task=%x(%d)\n",
1c79356b 1041 thr_act, thr_act->ref_count,
1c79356b
A
1042 thr_act->task, thr_act->task ? thr_act->task->ref_count : 0);
1043
55e303ae 1044 printf("\tsusp=%d user_stop=%d active=%x ast=%x\n",
1c79356b
A
1045 thr_act->suspend_count, thr_act->user_stop_count,
1046 thr_act->active, thr_act->ast);
91447636 1047 printf("\tpcb=%x\n", thr_act->machine.pcb);
1c79356b 1048
91447636
A
1049 if (thr_act->kernel_stack) {
1050 vm_offset_t stack = thr_act->kernel_stack;
1c79356b
A
1051
1052 printf("\tk_stk %x eip %x ebx %x esp %x iss %x\n",
1053 stack, STACK_IKS(stack)->k_eip, STACK_IKS(stack)->k_ebx,
1054 STACK_IKS(stack)->k_esp, STACK_IEL(stack)->saved_state);
1055 }
1056
1057 dump_handlers(thr_act);
1058 dump_regs(thr_act);
1059 return((int)thr_act);
1060}
91447636
A
1061
1062user_addr_t
1063get_useraddr(void)
1c79356b
A
1064{
1065
91447636 1066 thread_t thr_act = current_thread();
1c79356b 1067
91447636
A
1068 if (thr_act->machine.pcb)
1069 return(thr_act->machine.pcb->iss.eip);
1c79356b
A
1070 else
1071 return(0);
1072
1073}
1074
1c79356b
A
1075/*
1076 * detach and return a kernel stack from a thread
1077 */
1078
1079vm_offset_t
55e303ae 1080machine_stack_detach(thread_t thread)
1c79356b
A
1081{
1082 vm_offset_t stack;
1083
1084 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_DETACH),
1085 thread, thread->priority,
1086 thread->sched_pri, 0,
1087 0);
1088
1089 stack = thread->kernel_stack;
1090 thread->kernel_stack = 0;
1091 return(stack);
1092}
1093
1094/*
1095 * attach a kernel stack to a thread and initialize it
1096 */
1097
1098void
91447636
A
1099machine_stack_attach(
1100 thread_t thread,
1101 vm_offset_t stack)
1c79356b
A
1102{
1103 struct i386_kernel_state *statep;
1c79356b
A
1104
1105 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH),
1106 thread, thread->priority,
91447636 1107 thread->sched_pri, 0, 0);
1c79356b
A
1108
1109 assert(stack);
1110 statep = STACK_IKS(stack);
1111 thread->kernel_stack = stack;
1112
1113 statep->k_eip = (unsigned long) Thread_continue;
91447636 1114 statep->k_ebx = (unsigned long) thread_continue;
1c79356b 1115 statep->k_esp = (unsigned long) STACK_IEL(stack);
55e303ae 1116
91447636 1117 STACK_IEL(stack)->saved_state = &thread->machine.pcb->iss;
1c79356b
A
1118
1119 return;
1120}
1121
1122/*
1123 * move a stack from old to new thread
1124 */
1125
1126void
55e303ae 1127machine_stack_handoff(thread_t old,
1c79356b
A
1128 thread_t new)
1129{
1c79356b 1130 vm_offset_t stack;
1c79356b
A
1131
1132 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF),
1133 thread, thread->priority,
91447636 1134 thread->sched_pri, 0, 0);
1c79356b 1135
91447636
A
1136 assert(new);
1137 assert(old);
1c79356b 1138
55e303ae 1139 stack = machine_stack_detach(old);
91447636 1140 machine_stack_attach(new, stack);
1c79356b 1141
91447636 1142 PMAP_SWITCH_CONTEXT(old->task, new->task, cpu_number());
1c79356b 1143
9bccf70c
A
1144 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF) | DBG_FUNC_NONE,
1145 (int)old, (int)new, old->sched_pri, new->sched_pri, 0);
1146
91447636 1147 machine_set_current_thread(new);
1c79356b 1148
91447636 1149 current_cpu_datap()->cpu_active_stack = new->kernel_stack;
1c79356b
A
1150
1151 return;
1152}
0b4e3aa0
A
1153
1154struct i386_act_context {
1155 struct i386_saved_state ss;
1156 struct i386_float_state fs;
1157};
1158
1159void *
1160act_thread_csave(void)
1161{
1162struct i386_act_context *ic;
1163kern_return_t kret;
1164int val;
1165
1166 ic = (struct i386_act_context *)kalloc(sizeof(struct i386_act_context));
1167
1168 if (ic == (struct i386_act_context *)NULL)
1169 return((void *)0);
1170
1171 val = i386_SAVED_STATE_COUNT;
91447636 1172 kret = machine_thread_get_state(current_thread(),
55e303ae
A
1173 i386_SAVED_STATE,
1174 (thread_state_t) &ic->ss,
1175 &val);
0b4e3aa0 1176 if (kret != KERN_SUCCESS) {
91447636 1177 kfree(ic,sizeof(struct i386_act_context));
0b4e3aa0
A
1178 return((void *)0);
1179 }
1180 val = i386_FLOAT_STATE_COUNT;
91447636 1181 kret = machine_thread_get_state(current_thread(),
55e303ae
A
1182 i386_FLOAT_STATE,
1183 (thread_state_t) &ic->fs,
1184 &val);
0b4e3aa0 1185 if (kret != KERN_SUCCESS) {
91447636 1186 kfree(ic,sizeof(struct i386_act_context));
0b4e3aa0
A
1187 return((void *)0);
1188 }
1189 return(ic);
1190}
1191void
1192act_thread_catt(void *ctx)
1193{
1194struct i386_act_context *ic;
1195kern_return_t kret;
0b4e3aa0
A
1196
1197 ic = (struct i386_act_context *)ctx;
1198
1199 if (ic == (struct i386_act_context *)NULL)
1200 return;
1201
91447636 1202 kret = machine_thread_set_state(current_thread(),
55e303ae
A
1203 i386_SAVED_STATE,
1204 (thread_state_t) &ic->ss,
1205 i386_SAVED_STATE_COUNT);
0b4e3aa0
A
1206 if (kret != KERN_SUCCESS)
1207 goto out;
1208
91447636 1209 kret = machine_thread_set_state(current_thread(),
55e303ae
A
1210 i386_FLOAT_STATE,
1211 (thread_state_t) &ic->fs,
1212 i386_FLOAT_STATE_COUNT);
0b4e3aa0
A
1213 if (kret != KERN_SUCCESS)
1214 goto out;
1215out:
91447636 1216 kfree(ic,sizeof(struct i386_act_context));
0b4e3aa0
A
1217}
1218
1219void act_thread_cfree(void *ctx)
1220{
91447636 1221 kfree(ctx,sizeof(struct i386_act_context));
0b4e3aa0
A
1222}
1223