2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 * Mach Operating System
35 * Copyright (c) 1991,1990 Carnegie Mellon University
36 * All Rights Reserved.
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.
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.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
60 #include <mach_debug.h>
61 #include <mach_ldebug.h>
63 #include <sys/kdebug.h>
65 #include <mach/kern_return.h>
66 #include <mach/thread_status.h>
67 #include <mach/vm_param.h>
69 #include <i386/cpu_data.h>
70 #include <i386/cpu_number.h>
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>
84 #include <kern/machine.h>
85 #include <ipc/ipc_port.h>
86 #include <vm/vm_kern.h>
87 #include <vm/vm_map.h>
89 #include <vm/vm_protos.h>
91 #include <i386/thread.h>
92 #include <i386/eflags.h>
93 #include <i386/proc_reg.h>
96 #include <i386/user_ldt.h>
98 #include <i386/iopb_entries.h>
99 #include <i386/mp_desc.h>
100 #include <i386/cpu_data.h>
104 * Maps state flavor to number of words in the state:
107 unsigned int _MachineStateCount
[] = {
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
,
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);
126 extern thread_t
Switch_context(
128 thread_continue_t cont
,
130 extern void Thread_continue(void);
131 extern void Load_context(
135 * consider_machine_collect:
137 * Try to collect machine-dependent pages
140 consider_machine_collect(void)
145 consider_machine_adjust(void)
155 act_machine_switch_pcb( thread_t
new )
157 pcb_t pcb
= new->machine
.pcb
;
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
;
163 assert(new->kernel_stack
!= 0);
164 STACK_IEL(new->kernel_stack
)->saved_state
=
165 &new->machine
.pcb
->iss
;
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.
176 pcb_stack_top
= (pcb
->iss
.efl
& EFL_VM
)
177 ? (int) (&pcb
->iss
+ 1)
178 : (int) (&pcb
->iss
.v86_segs
);
180 mp_disable_preemption();
181 mycpu
= cpu_number();
185 * No per-thread IO permissions.
186 * Use standard kernel TSS.
188 if (!(gdt_desc_p(KERNEL_TSS
)->access
& ACC_TSS_BUSY
))
190 current_ktss()->esp0
= pcb_stack_top
;
194 * Set the IO permissions. Use this thread`s TSS.
196 *gdt_desc_p(USER_TSS
)
197 = *(struct real_descriptor
*)tss
->iopb_desc
;
198 tss
->tss
.esp0
= pcb_stack_top
;
200 gdt_desc_p(KERNEL_TSS
)->access
&= ~ ACC_TSS_BUSY
;
204 * Set the thread`s LDT or LDT entry.
207 struct real_descriptor
*ldtp
;
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
;
220 * Thread has its own LDT. // THIS SHOULD BE REMOVED!!!!
222 *gdt_desc_p(USER_LDT
) = uldt
->desc
;
225 if ((DEBUG_uldt
++ % 0x7fff) == 0)
226 printf("KERNEL----> setting user ldt");
230 mp_enable_preemption();
232 * Load the floating-point context, if necessary.
234 fpu_load_context(pcb
);
239 * Switch to the first thread on a CPU.
242 machine_load_context(
245 act_machine_switch_pcb(new);
250 * Switch to a new thread.
251 * Save the old thread`s kernel state or continuation,
255 machine_switch_context(
257 thread_continue_t continuation
,
261 assert(current_cpu_datap()->cpu_active_stack
== old
->kernel_stack
);
265 * Save FP registers if in use.
267 fpu_save_context(old
);
270 * Switch address maps if need be, even if not switching tasks.
271 * (A server activation may be "borrowing" a client map.)
274 int mycpu
= cpu_number();
276 PMAP_SWITCH_CONTEXT(old
, new, mycpu
)
280 * Load the rest of the user state for the new thread
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));
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
295 act_machine_sv_free(__unused thread_t act
, __unused
int flag
)
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.
305 machine_thread_state_initialize(
308 #pragma unused (thread)
315 * act_machine_set_state:
317 * Set the status of the specified thread.
321 machine_thread_set_state(
323 thread_flavor_t flavor
,
324 thread_state_t tstate
,
325 mach_msg_type_number_t count
)
330 case THREAD_SYSCALL_STATE
:
332 register struct thread_syscall_state
*state
;
333 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
335 state
= (struct thread_syscall_state
*) tstate
;
336 saved_state
->eax
= state
->eax
;
337 saved_state
->edx
= state
->edx
;
339 saved_state
->efl
= state
->efl
;
341 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
) | EFL_USER_SET
;
342 saved_state
->eip
= state
->eip
;
343 saved_state
->uesp
= state
->esp
;
347 case i386_SAVED_STATE
:
349 register struct i386_saved_state
*state
;
350 register struct i386_saved_state
*saved_state
;
352 if (count
< i386_SAVED_STATE_COUNT
) {
353 return(KERN_INVALID_ARGUMENT
);
356 state
= (struct i386_saved_state
*) tstate
;
358 /* Check segment selectors are safe */
360 !valid_user_segment_selectors(state
->cs
,
366 return KERN_INVALID_ARGUMENT
;
368 saved_state
= USER_REGS(thr_act
);
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
;
383 saved_state
->efl
= state
->efl
;
385 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
389 * Segment registers. Set differently in V8086 mode.
391 if (state
->efl
& EFL_VM
) {
393 * Set V8086 mode segment registers.
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;
403 * Zero protected mode segment registers.
410 if (thr_act
->machine
.pcb
->ims
.v86s
.int_table
) {
412 * Hardware assist on.
414 thr_act
->machine
.pcb
->ims
.v86s
.flags
=
415 state
->efl
& (EFL_TF
| EFL_IF
);
418 else if (kernel_act
) {
420 * 386 mode. Set segment registers for flat
421 * 32-bit address space.
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
;
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.
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
;
447 case i386_NEW_THREAD_STATE
:
448 case i386_REGS_SEGS_STATE
:
450 register struct i386_new_thread_state
*state
;
451 register struct i386_saved_state
*saved_state
;
453 if (count
< i386_NEW_THREAD_STATE_COUNT
) {
454 return(KERN_INVALID_ARGUMENT
);
457 state
= (struct i386_new_thread_state
*) tstate
;
459 if (flavor
== i386_REGS_SEGS_STATE
) {
461 * Code and stack selectors must not be null,
462 * and must have user protection levels.
463 * Only the low 16 bits are valid.
473 !valid_user_segment_selectors(state
->cs
,
479 return KERN_INVALID_ARGUMENT
;
482 saved_state
= USER_REGS(thr_act
);
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
;
497 saved_state
->efl
= state
->efl
;
499 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
503 * Segment registers. Set differently in V8086 mode.
505 if (state
->efl
& EFL_VM
) {
507 * Set V8086 mode segment registers.
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;
517 * Zero protected mode segment registers.
524 if (thr_act
->machine
.pcb
->ims
.v86s
.int_table
) {
526 * Hardware assist on.
528 thr_act
->machine
.pcb
->ims
.v86s
.flags
=
529 state
->efl
& (EFL_TF
| EFL_IF
);
532 else if (flavor
== i386_NEW_THREAD_STATE
&& kernel_act
) {
534 * 386 mode. Set segment registers for flat
535 * 32-bit address space.
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
;
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.
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
;
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
);
570 * Temporary - replace by i386_io_map
572 case i386_ISA_PORT_MAP_STATE
: {
573 if (count
< i386_ISA_PORT_MAP_STATE_COUNT
)
574 return(KERN_INVALID_ARGUMENT
);
579 case i386_V86_ASSIST_STATE
:
581 register struct i386_v86_assist_state
*state
;
582 vm_offset_t int_table
;
585 if (count
< i386_V86_ASSIST_STATE_COUNT
)
586 return KERN_INVALID_ARGUMENT
;
588 state
= (struct i386_v86_assist_state
*) tstate
;
589 int_table
= state
->int_table
;
590 int_count
= state
->int_count
;
592 if (int_table
>= VM_MAX_ADDRESS
||
594 int_count
* sizeof(struct v86_interrupt_table
)
596 return KERN_INVALID_ARGUMENT
;
598 thr_act
->machine
.pcb
->ims
.v86s
.int_table
= int_table
;
599 thr_act
->machine
.pcb
->ims
.v86s
.int_count
= int_count
;
601 thr_act
->machine
.pcb
->ims
.v86s
.flags
=
602 USER_REGS(thr_act
)->efl
& (EFL_TF
| EFL_IF
);
606 case i386_THREAD_STATE
: {
607 struct i386_saved_state
*saved_state
;
608 i386_thread_state_t
*state25
;
610 saved_state
= USER_REGS(thr_act
);
611 state25
= (i386_thread_state_t
*)tstate
;
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
)
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
;
634 return(KERN_INVALID_ARGUMENT
);
637 return(KERN_SUCCESS
);
643 * Get the status of the specified thread.
648 machine_thread_get_state(
650 thread_flavor_t flavor
,
651 thread_state_t tstate
,
652 mach_msg_type_number_t
*count
)
656 case i386_SAVED_STATE
:
658 register struct i386_saved_state
*state
;
659 register struct i386_saved_state
*saved_state
;
661 if (*count
< i386_SAVED_STATE_COUNT
)
662 return(KERN_INVALID_ARGUMENT
);
664 state
= (struct i386_saved_state
*) tstate
;
665 saved_state
= USER_REGS(thr_act
);
668 * First, copy everything:
670 *state
= *saved_state
;
672 if (saved_state
->efl
& EFL_VM
) {
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;
681 if (thr_act
->machine
.pcb
->ims
.v86s
.int_table
) {
685 if ((thr_act
->machine
.pcb
->ims
.v86s
.flags
&
686 (EFL_IF
|V86_IF_PENDING
)) == 0)
687 state
->efl
&= ~EFL_IF
;
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;
699 *count
= i386_SAVED_STATE_COUNT
;
703 case i386_NEW_THREAD_STATE
:
704 case i386_REGS_SEGS_STATE
:
706 register struct i386_new_thread_state
*state
;
707 register struct i386_saved_state
*saved_state
;
709 if (*count
< i386_NEW_THREAD_STATE_COUNT
)
710 return(KERN_INVALID_ARGUMENT
);
712 state
= (struct i386_new_thread_state
*) tstate
;
713 saved_state
= USER_REGS(thr_act
);
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
;
729 state
->cs
= saved_state
->cs
;
730 state
->ss
= saved_state
->ss
;
731 if (saved_state
->efl
& EFL_VM
) {
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;
740 if (thr_act
->machine
.pcb
->ims
.v86s
.int_table
) {
744 if ((thr_act
->machine
.pcb
->ims
.v86s
.flags
&
745 (EFL_IF
|V86_IF_PENDING
)) == 0)
746 state
->efl
&= ~EFL_IF
;
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;
758 *count
= i386_NEW_THREAD_STATE_COUNT
;
762 case THREAD_SYSCALL_STATE
:
764 register struct thread_syscall_state
*state
;
765 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
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
;
777 case THREAD_STATE_FLAVOR_LIST
:
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
;
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
);
795 *count
= i386_FLOAT_STATE_COUNT
;
796 return fpu_get_fxstate(thr_act
,(struct i386_float_state
*)tstate
);
801 * Temporary - replace by i386_io_map
803 case i386_ISA_PORT_MAP_STATE
: {
804 register struct i386_isa_port_map_state
*state
;
805 register iopb_tss_t tss
;
807 if (*count
< i386_ISA_PORT_MAP_STATE_COUNT
)
808 return(KERN_INVALID_ARGUMENT
);
810 state
= (struct i386_isa_port_map_state
*) tstate
;
811 tss
= thr_act
->machine
.pcb
->ims
.io_tss
;
817 * The thread has no ktss, so no IO permissions.
820 for (i
= 0; i
< sizeof state
->pm
; i
++)
824 * The thread has its own ktss.
827 bcopy((char *) tss
->bitmap
,
832 *count
= i386_ISA_PORT_MAP_STATE_COUNT
;
836 case i386_V86_ASSIST_STATE
:
838 register struct i386_v86_assist_state
*state
;
840 if (*count
< i386_V86_ASSIST_STATE_COUNT
)
841 return KERN_INVALID_ARGUMENT
;
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
;
847 *count
= i386_V86_ASSIST_STATE_COUNT
;
851 case i386_THREAD_STATE
: {
852 struct i386_saved_state
*saved_state
;
853 i386_thread_state_t
*state
;
855 saved_state
= USER_REGS(thr_act
);
856 state
= (i386_thread_state_t
*)tstate
;
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
;
878 return(KERN_INVALID_ARGUMENT
);
881 return(KERN_SUCCESS
);
885 * Initialize the machine-dependent state for a new thread.
888 machine_thread_create(
890 __unused task_t task
)
892 pcb_t pcb
= &thread
->machine
.xxx_pcb
;
894 thread
->machine
.pcb
= pcb
;
896 simple_lock_init(&pcb
->lock
, 0);
899 * Guarantee that the bootstrapped thread will be in user
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
;
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;
918 * Allocate a kernel stack per thread.
922 return(KERN_SUCCESS
);
926 * Machine-dependent cleanup prior to destroying a thread
929 machine_thread_destroy(
932 register pcb_t pcb
= thread
->machine
.pcb
;
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;
946 * This is used to set the current thr_act/thread
947 * when starting up a new processor
950 machine_set_current_thread( thread_t thread
)
952 mp_disable_preemption();
954 current_cpu_datap()->cpu_active_thread
= thread
;
955 current_cpu_datap()->cpu_active_kloaded
= THREAD_NULL
;
957 mp_enable_preemption();
961 machine_thread_terminate_self(void)
966 act_machine_return(int code
)
969 * This code is called with nothing locked.
970 * It also returns with nothing locked, if it returns.
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.
977 assert( code
== KERN_TERMINATED
);
979 thread_terminate_self();
983 panic("act_machine_return(%d): TALKING ZOMBIE! (1)", code
);
988 * Perform machine-dependent per-thread initializations
991 machine_thread_init(void)
998 * Some routines for debugging activation code
1000 static void dump_handlers(thread_t
);
1001 void dump_regs(thread_t
);
1002 int dump_act(thread_t thr_act
);
1005 dump_handlers(thread_t thr_act
)
1007 ReturnHandler
*rhp
= thr_act
->handlers
;
1012 if (rhp
== &thr_act
->special_handler
){
1014 printf("[NON-Zero next ptr(%x)]", rhp
->next
);
1015 printf("special_handler()->");
1018 printf("hdlr_%d(%x)->",counter
,rhp
->handler
);
1020 if (++counter
> 32) {
1021 printf("Aborting: HUGE handler chain\n");
1025 printf("HLDR_NULL\n");
1029 dump_regs(thread_t thr_act
)
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
);
1043 dump_act(thread_t thr_act
)
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);
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
);
1057 if (thr_act
->kernel_stack
) {
1058 vm_offset_t stack
= thr_act
->kernel_stack
;
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
);
1065 dump_handlers(thr_act
);
1067 return((int)thr_act
);
1074 thread_t thr_act
= current_thread();
1076 if (thr_act
->machine
.pcb
)
1077 return(thr_act
->machine
.pcb
->iss
.eip
);
1084 * detach and return a kernel stack from a thread
1088 machine_stack_detach(thread_t thread
)
1092 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_DETACH
),
1093 thread
, thread
->priority
,
1094 thread
->sched_pri
, 0,
1097 stack
= thread
->kernel_stack
;
1098 thread
->kernel_stack
= 0;
1103 * attach a kernel stack to a thread and initialize it
1107 machine_stack_attach(
1111 struct i386_kernel_state
*statep
;
1113 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_ATTACH
),
1114 thread
, thread
->priority
,
1115 thread
->sched_pri
, 0, 0);
1118 statep
= STACK_IKS(stack
);
1119 thread
->kernel_stack
= stack
;
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
);
1125 STACK_IEL(stack
)->saved_state
= &thread
->machine
.pcb
->iss
;
1131 * move a stack from old to new thread
1135 machine_stack_handoff(thread_t old
,
1140 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_HANDOFF
),
1141 thread
, thread
->priority
,
1142 thread
->sched_pri
, 0, 0);
1147 stack
= machine_stack_detach(old
);
1148 machine_stack_attach(new, stack
);
1150 PMAP_SWITCH_CONTEXT(old
->task
, new->task
, cpu_number());
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);
1155 machine_set_current_thread(new);
1157 current_cpu_datap()->cpu_active_stack
= new->kernel_stack
;
1162 struct i386_act_context
{
1163 struct i386_saved_state ss
;
1164 struct i386_float_state fs
;
1168 act_thread_csave(void)
1170 struct i386_act_context
*ic
;
1174 ic
= (struct i386_act_context
*)kalloc(sizeof(struct i386_act_context
));
1176 if (ic
== (struct i386_act_context
*)NULL
)
1179 val
= i386_SAVED_STATE_COUNT
;
1180 kret
= machine_thread_get_state(current_thread(),
1182 (thread_state_t
) &ic
->ss
,
1184 if (kret
!= KERN_SUCCESS
) {
1185 kfree(ic
,sizeof(struct i386_act_context
));
1188 val
= i386_FLOAT_STATE_COUNT
;
1189 kret
= machine_thread_get_state(current_thread(),
1191 (thread_state_t
) &ic
->fs
,
1193 if (kret
!= KERN_SUCCESS
) {
1194 kfree(ic
,sizeof(struct i386_act_context
));
1200 act_thread_catt(void *ctx
)
1202 struct i386_act_context
*ic
;
1205 ic
= (struct i386_act_context
*)ctx
;
1207 if (ic
== (struct i386_act_context
*)NULL
)
1210 kret
= machine_thread_set_state(current_thread(),
1212 (thread_state_t
) &ic
->ss
,
1213 i386_SAVED_STATE_COUNT
);
1214 if (kret
!= KERN_SUCCESS
)
1217 kret
= machine_thread_set_state(current_thread(),
1219 (thread_state_t
) &ic
->fs
,
1220 i386_FLOAT_STATE_COUNT
);
1221 if (kret
!= KERN_SUCCESS
)
1224 kfree(ic
,sizeof(struct i386_act_context
));
1227 void act_thread_cfree(void *ctx
)
1229 kfree(ctx
,sizeof(struct i386_act_context
));