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