2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
56 #include <mach_debug.h>
57 #include <mach_ldebug.h>
59 #include <sys/kdebug.h>
61 #include <mach/kern_return.h>
62 #include <mach/thread_status.h>
63 #include <mach/vm_param.h>
65 #include <kern/counters.h>
66 #include <kern/mach_param.h>
67 #include <kern/task.h>
68 #include <kern/thread.h>
69 #include <kern/thread_act.h>
70 #include <kern/thread_swap.h>
71 #include <kern/sched_prim.h>
72 #include <kern/misc_protos.h>
73 #include <kern/assert.h>
75 #include <ipc/ipc_port.h>
76 #include <vm/vm_kern.h>
79 #include <i386/thread.h>
80 #include <i386/eflags.h>
81 #include <i386/proc_reg.h>
84 #include <i386/user_ldt.h>
86 #include <i386/iopb_entries.h>
89 * Maps state flavor to number of words in the state:
91 unsigned int state_count
[] = {
93 i386_NEW_THREAD_STATE_COUNT
,
94 i386_FLOAT_STATE_COUNT
,
95 i386_ISA_PORT_MAP_STATE_COUNT
,
96 i386_V86_ASSIST_STATE_COUNT
,
97 i386_REGS_SEGS_STATE_COUNT
,
98 i386_THREAD_SYSCALL_STATE_COUNT
,
99 /* THREAD_STATE_NONE */ 0,
100 i386_SAVED_STATE_COUNT
,
105 void act_machine_throughcall(thread_act_t thr_act
);
106 extern thread_t
Switch_context(
110 extern void Thread_continue(void);
111 extern void Load_context(
115 * consider_machine_collect:
117 * Try to collect machine-dependent pages
120 consider_machine_collect()
125 consider_machine_adjust()
131 * machine_kernel_stack_init:
133 * Initialize a kernel stack which has already been
134 * attached to its thread_activation.
138 machine_kernel_stack_init(
140 void (*start_pos
)(thread_t
))
142 thread_act_t thr_act
= thread
->top_act
;
146 stack
= thread
->kernel_stack
;
150 if (watchacts
& WA_PCB
) {
151 printf("machine_kernel_stack_init(thr=%x,stk=%x,start_pos=%x)\n",
152 thread
,stack
,start_pos
);
153 printf("\tstack_iks=%x, stack_iel=%x\n",
154 STACK_IKS(stack
), STACK_IEL(stack
));
156 #endif /* MACH_ASSERT */
159 * We want to run at start_pos, giving it as an argument
160 * the return value from Load_context/Switch_context.
161 * Thread_continue takes care of the mismatch between
162 * the argument-passing/return-value conventions.
163 * This function will not return normally,
164 * so we don`t have to worry about a return address.
166 STACK_IKS(stack
)->k_eip
= (int) Thread_continue
;
167 STACK_IKS(stack
)->k_ebx
= (int) start_pos
;
168 STACK_IKS(stack
)->k_esp
= (int) STACK_IEL(stack
);
171 * Point top of kernel stack to user`s registers.
173 STACK_IEL(stack
)->saved_state
= &thr_act
->mact
.pcb
->iss
;
178 #define curr_gdt(mycpu) (mp_gdt[mycpu])
179 #define curr_ktss(mycpu) (mp_ktss[mycpu])
181 #define curr_gdt(mycpu) (gdt)
182 #define curr_ktss(mycpu) (&ktss)
185 #define gdt_desc_p(mycpu,sel) \
186 ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
189 act_machine_switch_pcb( thread_act_t new_act
)
191 pcb_t pcb
= new_act
->mact
.pcb
;
194 register iopb_tss_t tss
= pcb
->ims
.io_tss
;
195 vm_offset_t pcb_stack_top
;
197 assert(new_act
->thread
!= NULL
);
198 assert(new_act
->thread
->kernel_stack
!= 0);
199 STACK_IEL(new_act
->thread
->kernel_stack
)->saved_state
=
200 &new_act
->mact
.pcb
->iss
;
203 * Save a pointer to the top of the "kernel" stack -
204 * actually the place in the PCB where a trap into
205 * kernel mode will push the registers.
206 * The location depends on V8086 mode. If we are
207 * not in V8086 mode, then a trap into the kernel
208 * won`t save the v86 segments, so we leave room.
211 pcb_stack_top
= (pcb
->iss
.efl
& EFL_VM
)
212 ? (int) (&pcb
->iss
+ 1)
213 : (int) (&pcb
->iss
.v86_segs
);
215 mp_disable_preemption();
216 mycpu
= cpu_number();
220 * No per-thread IO permissions.
221 * Use standard kernel TSS.
223 if (!(gdt_desc_p(mycpu
,KERNEL_TSS
)->access
& ACC_TSS_BUSY
))
225 curr_ktss(mycpu
)->esp0
= pcb_stack_top
;
229 * Set the IO permissions. Use this thread`s TSS.
231 *gdt_desc_p(mycpu
,USER_TSS
)
232 = *(struct real_descriptor
*)tss
->iopb_desc
;
233 tss
->tss
.esp0
= pcb_stack_top
;
235 gdt_desc_p(mycpu
,KERNEL_TSS
)->access
&= ~ ACC_TSS_BUSY
;
240 register user_ldt_t ldt
= pcb
->ims
.ldt
;
242 * Set the thread`s LDT.
252 * Thread has its own LDT.
254 *gdt_desc_p(mycpu
,USER_LDT
) = ldt
->desc
;
258 mp_enable_preemption();
260 * Load the floating-point context, if necessary.
262 fpu_load_context(pcb
);
267 * flush out any lazily evaluated HW state in the
268 * owning thread's context, before termination.
271 thread_machine_flush( thread_act_t cur_act
)
277 * Switch to the first thread on a CPU.
283 act_machine_switch_pcb(new->top_act
);
288 * Number of times we needed to swap an activation back in before
291 int switch_act_swapins
= 0;
296 * Machine-dependent details of activation switching. Called with
297 * RPC locks held and preemption disabled.
307 * Switch the vm, ast and pcb context.
308 * Save FP registers if in use and set TS (task switch) bit.
310 fpu_save_context(thread
);
312 active_stacks
[cpu
] = thread
->kernel_stack
;
313 ast_context(new, cpu
);
315 PMAP_SWITCH_CONTEXT(old
, new, cpu
);
316 act_machine_switch_pcb(new);
320 * Switch to a new thread.
321 * Save the old thread`s kernel state or continuation,
327 void (*continuation
)(void),
330 register thread_act_t old_act
= old
->top_act
,
331 new_act
= new->top_act
;
334 assert(old_act
->kernel_loaded
||
335 active_stacks
[cpu_number()] == old_act
->thread
->kernel_stack
);
336 assert (get_preemption_level() == 1);
338 check_simple_locks();
341 * Save FP registers if in use.
343 fpu_save_context(old
);
346 if (watchacts
& WA_SWITCH
)
347 printf("\tswitch_context(old=%x con=%x new=%x)\n",
348 old
, continuation
, new);
349 #endif /* MACH_ASSERT */
352 * Switch address maps if need be, even if not switching tasks.
353 * (A server activation may be "borrowing" a client map.)
356 int mycpu
= cpu_number();
358 PMAP_SWITCH_CONTEXT(old_act
, new_act
, mycpu
)
362 * Load the rest of the user state for the new thread
364 act_machine_switch_pcb(new_act
);
365 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_SCHED
) | DBG_FUNC_NONE
,
366 (int)old
, (int)new, old
->sched_pri
, new->sched_pri
, 0);
367 return(Switch_context(old
, continuation
, new));
371 pcb_module_init(void)
378 pcb_init( register thread_act_t thr_act
)
382 assert(thr_act
->mact
.pcb
== (pcb_t
)0);
383 pcb
= thr_act
->mact
.pcb
= &thr_act
->mact
.xxx_pcb
;
386 if (watchacts
& WA_PCB
)
387 printf("pcb_init(%x) pcb=%x\n", thr_act
, pcb
);
388 #endif /* MACH_ASSERT */
391 * We can't let random values leak out to the user.
392 * (however, act_create() zeroed the entire thr_act, mact, pcb)
393 * bzero((char *) pcb, sizeof *pcb);
395 simple_lock_init(&pcb
->lock
, ETAP_MISC_PCB
);
398 * Guarantee that the bootstrapped thread will be in user
401 pcb
->iss
.cs
= USER_CS
;
402 pcb
->iss
.ss
= USER_DS
;
403 pcb
->iss
.ds
= USER_DS
;
404 pcb
->iss
.es
= USER_DS
;
405 pcb
->iss
.fs
= USER_DS
;
406 pcb
->iss
.gs
= USER_DS
;
407 pcb
->iss
.efl
= EFL_USER_SET
;
411 * Adjust saved register state for thread belonging to task
412 * created with kernel_task_create().
416 thread_act_t thr_act
)
418 register pcb_t pcb
= thr_act
->mact
.pcb
;
420 pcb
->iss
.cs
= KERNEL_CS
;
421 pcb
->iss
.ss
= KERNEL_DS
;
422 pcb
->iss
.ds
= KERNEL_DS
;
423 pcb
->iss
.es
= KERNEL_DS
;
424 pcb
->iss
.fs
= KERNEL_DS
;
425 pcb
->iss
.gs
= CPU_DATA
;
430 register thread_act_t thr_act
)
432 register pcb_t pcb
= thr_act
->mact
.pcb
;
436 if (pcb
->ims
.io_tss
!= 0)
437 iopb_destroy(pcb
->ims
.io_tss
);
438 if (pcb
->ims
.ifps
!= 0)
439 fp_free(pcb
->ims
.ifps
);
440 if (pcb
->ims
.ldt
!= 0)
441 user_ldt_free(pcb
->ims
.ldt
);
442 thr_act
->mact
.pcb
= (pcb_t
)0;
448 * Attempt to free excess pcb memory.
453 register thread_act_t thr_act
)
455 /* accomplishes very little */
459 * act_machine_sv_free
460 * release saveareas associated with an act. if flag is true, release
461 * user level savearea(s) too, else don't
464 act_machine_sv_free(thread_act_t act
, int flag
)
470 * act_machine_set_state:
472 * Set the status of the specified thread. Called with "appropriate"
473 * thread-related locks held (see act_lock_thread()), so
474 * thr_act->thread is guaranteed not to change.
478 act_machine_set_state(
479 thread_act_t thr_act
,
480 thread_flavor_t flavor
,
481 thread_state_t tstate
,
482 mach_msg_type_number_t count
)
484 int kernel_act
= thr_act
->kernel_loading
||
485 thr_act
->kernel_loaded
;
488 if (watchacts
& WA_STATE
)
489 printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
490 current_act(), thr_act
, flavor
, tstate
, count
);
491 #endif /* MACH_ASSERT */
494 case THREAD_SYSCALL_STATE
:
496 register struct thread_syscall_state
*state
;
497 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
499 state
= (struct thread_syscall_state
*) tstate
;
500 saved_state
->eax
= state
->eax
;
501 saved_state
->edx
= state
->edx
;
503 saved_state
->efl
= state
->efl
;
505 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
) | EFL_USER_SET
;
506 saved_state
->eip
= state
->eip
;
507 saved_state
->uesp
= state
->esp
;
511 case i386_SAVED_STATE
:
513 register struct i386_saved_state
*state
;
514 register struct i386_saved_state
*saved_state
;
516 if (count
< i386_SAVED_STATE_COUNT
) {
517 return(KERN_INVALID_ARGUMENT
);
520 state
= (struct i386_saved_state
*) tstate
;
522 saved_state
= USER_REGS(thr_act
);
527 saved_state
->edi
= state
->edi
;
528 saved_state
->esi
= state
->esi
;
529 saved_state
->ebp
= state
->ebp
;
530 saved_state
->uesp
= state
->uesp
;
531 saved_state
->ebx
= state
->ebx
;
532 saved_state
->edx
= state
->edx
;
533 saved_state
->ecx
= state
->ecx
;
534 saved_state
->eax
= state
->eax
;
535 saved_state
->eip
= state
->eip
;
537 saved_state
->efl
= state
->efl
;
539 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
543 * Segment registers. Set differently in V8086 mode.
545 if (state
->efl
& EFL_VM
) {
547 * Set V8086 mode segment registers.
549 saved_state
->cs
= state
->cs
& 0xffff;
550 saved_state
->ss
= state
->ss
& 0xffff;
551 saved_state
->v86_segs
.v86_ds
= state
->ds
& 0xffff;
552 saved_state
->v86_segs
.v86_es
= state
->es
& 0xffff;
553 saved_state
->v86_segs
.v86_fs
= state
->fs
& 0xffff;
554 saved_state
->v86_segs
.v86_gs
= state
->gs
& 0xffff;
557 * Zero protected mode segment registers.
564 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
566 * Hardware assist on.
568 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
569 state
->efl
& (EFL_TF
| EFL_IF
);
572 else if (!kernel_act
) {
574 * 386 mode. Set segment registers for flat
575 * 32-bit address space.
577 saved_state
->cs
= USER_CS
;
578 saved_state
->ss
= USER_DS
;
579 saved_state
->ds
= USER_DS
;
580 saved_state
->es
= USER_DS
;
581 saved_state
->fs
= USER_DS
;
582 saved_state
->gs
= USER_DS
;
586 * User setting segment registers.
587 * Code and stack selectors have already been
588 * checked. Others will be reset by 'iret'
589 * if they are not valid.
591 saved_state
->cs
= state
->cs
;
592 saved_state
->ss
= state
->ss
;
593 saved_state
->ds
= state
->ds
;
594 saved_state
->es
= state
->es
;
595 saved_state
->fs
= state
->fs
;
596 saved_state
->gs
= state
->gs
;
601 case i386_NEW_THREAD_STATE
:
602 case i386_REGS_SEGS_STATE
:
604 register struct i386_new_thread_state
*state
;
605 register struct i386_saved_state
*saved_state
;
607 if (count
< i386_NEW_THREAD_STATE_COUNT
) {
608 return(KERN_INVALID_ARGUMENT
);
611 if (flavor
== i386_REGS_SEGS_STATE
) {
613 * Code and stack selectors must not be null,
614 * and must have user protection levels.
615 * Only the low 16 bits are valid.
625 (state
->cs
== 0 || (state
->cs
& SEL_PL
) != SEL_PL_U
626 || state
->ss
== 0 || (state
->ss
& SEL_PL
) != SEL_PL_U
))
627 return KERN_INVALID_ARGUMENT
;
630 state
= (struct i386_new_thread_state
*) tstate
;
632 saved_state
= USER_REGS(thr_act
);
637 saved_state
->edi
= state
->edi
;
638 saved_state
->esi
= state
->esi
;
639 saved_state
->ebp
= state
->ebp
;
640 saved_state
->uesp
= state
->uesp
;
641 saved_state
->ebx
= state
->ebx
;
642 saved_state
->edx
= state
->edx
;
643 saved_state
->ecx
= state
->ecx
;
644 saved_state
->eax
= state
->eax
;
645 saved_state
->eip
= state
->eip
;
647 saved_state
->efl
= state
->efl
;
649 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
653 * Segment registers. Set differently in V8086 mode.
655 if (state
->efl
& EFL_VM
) {
657 * Set V8086 mode segment registers.
659 saved_state
->cs
= state
->cs
& 0xffff;
660 saved_state
->ss
= state
->ss
& 0xffff;
661 saved_state
->v86_segs
.v86_ds
= state
->ds
& 0xffff;
662 saved_state
->v86_segs
.v86_es
= state
->es
& 0xffff;
663 saved_state
->v86_segs
.v86_fs
= state
->fs
& 0xffff;
664 saved_state
->v86_segs
.v86_gs
= state
->gs
& 0xffff;
667 * Zero protected mode segment registers.
674 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
676 * Hardware assist on.
678 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
679 state
->efl
& (EFL_TF
| EFL_IF
);
682 else if (flavor
== i386_NEW_THREAD_STATE
&& !kernel_act
) {
684 * 386 mode. Set segment registers for flat
685 * 32-bit address space.
687 saved_state
->cs
= USER_CS
;
688 saved_state
->ss
= USER_DS
;
689 saved_state
->ds
= USER_DS
;
690 saved_state
->es
= USER_DS
;
691 saved_state
->fs
= USER_DS
;
692 saved_state
->gs
= USER_DS
;
696 * User setting segment registers.
697 * Code and stack selectors have already been
698 * checked. Others will be reset by 'iret'
699 * if they are not valid.
701 saved_state
->cs
= state
->cs
;
702 saved_state
->ss
= state
->ss
;
703 saved_state
->ds
= state
->ds
;
704 saved_state
->es
= state
->es
;
705 saved_state
->fs
= state
->fs
;
706 saved_state
->gs
= state
->gs
;
711 case i386_FLOAT_STATE
: {
713 if (count
< i386_FLOAT_STATE_COUNT
)
714 return(KERN_INVALID_ARGUMENT
);
716 return fpu_set_state(thr_act
,(struct i386_float_state
*)tstate
);
720 * Temporary - replace by i386_io_map
722 case i386_ISA_PORT_MAP_STATE
: {
723 register struct i386_isa_port_map_state
*state
;
724 register iopb_tss_t tss
;
726 if (count
< i386_ISA_PORT_MAP_STATE_COUNT
)
727 return(KERN_INVALID_ARGUMENT
);
732 case i386_V86_ASSIST_STATE
:
734 register struct i386_v86_assist_state
*state
;
735 vm_offset_t int_table
;
738 if (count
< i386_V86_ASSIST_STATE_COUNT
)
739 return KERN_INVALID_ARGUMENT
;
741 state
= (struct i386_v86_assist_state
*) tstate
;
742 int_table
= state
->int_table
;
743 int_count
= state
->int_count
;
745 if (int_table
>= VM_MAX_ADDRESS
||
747 int_count
* sizeof(struct v86_interrupt_table
)
749 return KERN_INVALID_ARGUMENT
;
751 thr_act
->mact
.pcb
->ims
.v86s
.int_table
= int_table
;
752 thr_act
->mact
.pcb
->ims
.v86s
.int_count
= int_count
;
754 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
755 USER_REGS(thr_act
)->efl
& (EFL_TF
| EFL_IF
);
759 case i386_THREAD_STATE
: {
760 struct i386_saved_state
*saved_state
;
761 i386_thread_state_t
*state25
;
763 saved_state
= USER_REGS(thr_act
);
764 state25
= (i386_thread_state_t
*)tstate
;
766 saved_state
->eax
= state25
->eax
;
767 saved_state
->ebx
= state25
->ebx
;
768 saved_state
->ecx
= state25
->ecx
;
769 saved_state
->edx
= state25
->edx
;
770 saved_state
->edi
= state25
->edi
;
771 saved_state
->esi
= state25
->esi
;
772 saved_state
->ebp
= state25
->ebp
;
773 saved_state
->uesp
= state25
->esp
;
774 saved_state
->efl
= (state25
->eflags
& ~EFL_USER_CLEAR
)
776 saved_state
->eip
= state25
->eip
;
777 saved_state
->cs
= USER_CS
; /* FIXME? */
778 saved_state
->ss
= USER_DS
;
779 saved_state
->ds
= USER_DS
;
780 saved_state
->es
= USER_DS
;
781 saved_state
->fs
= USER_DS
;
782 saved_state
->gs
= USER_DS
;
787 return(KERN_INVALID_ARGUMENT
);
790 return(KERN_SUCCESS
);
796 * Get the status of the specified thread.
801 act_machine_get_state(
802 thread_act_t thr_act
,
803 thread_flavor_t flavor
,
804 thread_state_t tstate
,
805 mach_msg_type_number_t
*count
)
808 if (watchacts
& WA_STATE
)
809 printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
810 current_act(), thr_act
, flavor
, tstate
,
811 count
, (count
? *count
: 0));
812 #endif /* MACH_ASSERT */
816 case i386_SAVED_STATE
:
818 register struct i386_saved_state
*state
;
819 register struct i386_saved_state
*saved_state
;
821 if (*count
< i386_SAVED_STATE_COUNT
)
822 return(KERN_INVALID_ARGUMENT
);
824 state
= (struct i386_saved_state
*) tstate
;
825 saved_state
= USER_REGS(thr_act
);
828 * First, copy everything:
830 *state
= *saved_state
;
832 if (saved_state
->efl
& EFL_VM
) {
836 state
->ds
= saved_state
->v86_segs
.v86_ds
& 0xffff;
837 state
->es
= saved_state
->v86_segs
.v86_es
& 0xffff;
838 state
->fs
= saved_state
->v86_segs
.v86_fs
& 0xffff;
839 state
->gs
= saved_state
->v86_segs
.v86_gs
& 0xffff;
841 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
845 if ((thr_act
->mact
.pcb
->ims
.v86s
.flags
&
846 (EFL_IF
|V86_IF_PENDING
)) == 0)
847 state
->efl
&= ~EFL_IF
;
854 state
->ds
= saved_state
->ds
& 0xffff;
855 state
->es
= saved_state
->es
& 0xffff;
856 state
->fs
= saved_state
->fs
& 0xffff;
857 state
->gs
= saved_state
->gs
& 0xffff;
859 *count
= i386_SAVED_STATE_COUNT
;
863 case i386_NEW_THREAD_STATE
:
864 case i386_REGS_SEGS_STATE
:
866 register struct i386_new_thread_state
*state
;
867 register struct i386_saved_state
*saved_state
;
869 if (*count
< i386_NEW_THREAD_STATE_COUNT
)
870 return(KERN_INVALID_ARGUMENT
);
872 state
= (struct i386_new_thread_state
*) tstate
;
873 saved_state
= USER_REGS(thr_act
);
878 state
->edi
= saved_state
->edi
;
879 state
->esi
= saved_state
->esi
;
880 state
->ebp
= saved_state
->ebp
;
881 state
->ebx
= saved_state
->ebx
;
882 state
->edx
= saved_state
->edx
;
883 state
->ecx
= saved_state
->ecx
;
884 state
->eax
= saved_state
->eax
;
885 state
->eip
= saved_state
->eip
;
886 state
->efl
= saved_state
->efl
;
887 state
->uesp
= saved_state
->uesp
;
889 state
->cs
= saved_state
->cs
;
890 state
->ss
= saved_state
->ss
;
891 if (saved_state
->efl
& EFL_VM
) {
895 state
->ds
= saved_state
->v86_segs
.v86_ds
& 0xffff;
896 state
->es
= saved_state
->v86_segs
.v86_es
& 0xffff;
897 state
->fs
= saved_state
->v86_segs
.v86_fs
& 0xffff;
898 state
->gs
= saved_state
->v86_segs
.v86_gs
& 0xffff;
900 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
904 if ((thr_act
->mact
.pcb
->ims
.v86s
.flags
&
905 (EFL_IF
|V86_IF_PENDING
)) == 0)
906 state
->efl
&= ~EFL_IF
;
913 state
->ds
= saved_state
->ds
& 0xffff;
914 state
->es
= saved_state
->es
& 0xffff;
915 state
->fs
= saved_state
->fs
& 0xffff;
916 state
->gs
= saved_state
->gs
& 0xffff;
918 *count
= i386_NEW_THREAD_STATE_COUNT
;
922 case THREAD_SYSCALL_STATE
:
924 register struct thread_syscall_state
*state
;
925 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
927 state
= (struct thread_syscall_state
*) tstate
;
928 state
->eax
= saved_state
->eax
;
929 state
->edx
= saved_state
->edx
;
930 state
->efl
= saved_state
->efl
;
931 state
->eip
= saved_state
->eip
;
932 state
->esp
= saved_state
->uesp
;
933 *count
= i386_THREAD_SYSCALL_STATE_COUNT
;
937 case THREAD_STATE_FLAVOR_LIST
:
939 return (KERN_INVALID_ARGUMENT
);
940 tstate
[0] = i386_NEW_THREAD_STATE
;
941 tstate
[1] = i386_FLOAT_STATE
;
942 tstate
[2] = i386_ISA_PORT_MAP_STATE
;
943 tstate
[3] = i386_V86_ASSIST_STATE
;
944 tstate
[4] = THREAD_SYSCALL_STATE
;
948 case i386_FLOAT_STATE
: {
950 if (*count
< i386_FLOAT_STATE_COUNT
)
951 return(KERN_INVALID_ARGUMENT
);
953 *count
= i386_FLOAT_STATE_COUNT
;
954 return fpu_get_state(thr_act
,(struct i386_float_state
*)tstate
);
958 * Temporary - replace by i386_io_map
960 case i386_ISA_PORT_MAP_STATE
: {
961 register struct i386_isa_port_map_state
*state
;
962 register iopb_tss_t tss
;
964 if (*count
< i386_ISA_PORT_MAP_STATE_COUNT
)
965 return(KERN_INVALID_ARGUMENT
);
967 state
= (struct i386_isa_port_map_state
*) tstate
;
968 tss
= thr_act
->mact
.pcb
->ims
.io_tss
;
974 * The thread has no ktss, so no IO permissions.
977 for (i
= 0; i
< sizeof state
->pm
; i
++)
981 * The thread has its own ktss.
984 bcopy((char *) tss
->bitmap
,
989 *count
= i386_ISA_PORT_MAP_STATE_COUNT
;
993 case i386_V86_ASSIST_STATE
:
995 register struct i386_v86_assist_state
*state
;
997 if (*count
< i386_V86_ASSIST_STATE_COUNT
)
998 return KERN_INVALID_ARGUMENT
;
1000 state
= (struct i386_v86_assist_state
*) tstate
;
1001 state
->int_table
= thr_act
->mact
.pcb
->ims
.v86s
.int_table
;
1002 state
->int_count
= thr_act
->mact
.pcb
->ims
.v86s
.int_count
;
1004 *count
= i386_V86_ASSIST_STATE_COUNT
;
1008 case i386_THREAD_STATE
: {
1009 struct i386_saved_state
*saved_state
;
1010 i386_thread_state_t
*state
;
1012 saved_state
= USER_REGS(thr_act
);
1013 state
= (i386_thread_state_t
*)tstate
;
1015 state
->eax
= saved_state
->eax
;
1016 state
->ebx
= saved_state
->ebx
;
1017 state
->ecx
= saved_state
->ecx
;
1018 state
->edx
= saved_state
->edx
;
1019 state
->edi
= saved_state
->edi
;
1020 state
->esi
= saved_state
->esi
;
1021 state
->ebp
= saved_state
->ebp
;
1022 state
->esp
= saved_state
->uesp
;
1023 state
->eflags
= saved_state
->efl
;
1024 state
->eip
= saved_state
->eip
;
1025 state
->cs
= saved_state
->cs
;
1026 state
->ss
= saved_state
->ss
;
1027 state
->ds
= saved_state
->ds
;
1028 state
->es
= saved_state
->es
;
1029 state
->fs
= saved_state
->fs
;
1030 state
->gs
= saved_state
->gs
;
1035 return(KERN_INVALID_ARGUMENT
);
1038 return(KERN_SUCCESS
);
1042 * Alter the thread`s state so that a following thread_exception_return
1043 * will make the thread return 'retval' from a syscall.
1046 thread_set_syscall_return(
1048 kern_return_t retval
)
1050 thread
->top_act
->mact
.pcb
->iss
.eax
= retval
;
1054 * Initialize the machine-dependent state for a new thread.
1057 thread_machine_create(thread_t thread
, thread_act_t thr_act
, void (*start_pos
)(thread_t
))
1059 MachineThrAct_t mact
= &thr_act
->mact
;
1062 if (watchacts
& WA_PCB
)
1063 printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n",
1064 thread
, thr_act
, start_pos
);
1065 #endif /* MACH_ASSERT */
1067 assert(thread
!= NULL
);
1068 assert(thr_act
!= NULL
);
1071 * Allocate a kernel stack per shuttle
1073 thread
->kernel_stack
= (int)stack_alloc(thread
,start_pos
);
1074 thread
->state
&= ~TH_STACK_HANDOFF
;
1075 assert(thread
->kernel_stack
!= 0);
1078 * Point top of kernel stack to user`s registers.
1080 STACK_IEL(thread
->kernel_stack
)->saved_state
= &mact
->pcb
->iss
;
1082 return(KERN_SUCCESS
);
1086 * Machine-dependent cleanup prior to destroying a thread
1089 thread_machine_destroy( thread_t thread
)
1093 if (thread
->kernel_stack
!= 0) {
1101 * This is used to set the current thr_act/thread
1102 * when starting up a new processor
1105 thread_machine_set_current( thread_t thread
)
1107 register int my_cpu
;
1109 mp_disable_preemption();
1110 my_cpu
= cpu_number();
1112 cpu_data
[my_cpu
].active_thread
= thread
;
1113 active_kloaded
[my_cpu
] =
1114 thread
->top_act
->kernel_loaded
? thread
->top_act
: THR_ACT_NULL
;
1116 mp_enable_preemption();
1121 * Pool of kernel activations.
1124 void act_machine_init()
1127 thread_act_t thr_act
;
1130 if (watchacts
& WA_PCB
)
1131 printf("act_machine_init()\n");
1132 #endif /* MACH_ASSERT */
1134 /* Good to verify this once */
1135 assert( THREAD_MACHINE_STATE_MAX
<= THREAD_STATE_MAX
);
1139 act_machine_create(task_t task
, thread_act_t thr_act
)
1141 MachineThrAct_t mact
= &thr_act
->mact
;
1145 if (watchacts
& WA_PCB
)
1146 printf("act_machine_create(task=%x,thr_act=%x) pcb=%x\n",
1147 task
,thr_act
, &mact
->xxx_pcb
);
1148 #endif /* MACH_ASSERT */
1151 * Clear & Init the pcb (sets up user-mode s regs)
1155 return KERN_SUCCESS
;
1159 act_virtual_machine_destroy(thread_act_t thr_act
)
1165 act_machine_destroy(thread_act_t thr_act
)
1169 if (watchacts
& WA_PCB
)
1170 printf("act_machine_destroy(0x%x)\n", thr_act
);
1171 #endif /* MACH_ASSERT */
1173 pcb_terminate(thr_act
);
1177 act_machine_return(int code
)
1179 thread_act_t thr_act
= current_act();
1183 * We don't go through the locking dance here needed to
1184 * acquire thr_act->thread safely.
1187 if (watchacts
& WA_EXIT
)
1188 printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n",
1189 code
, thr_act
, thr_act
->ref_count
,
1190 thr_act
->thread
, thr_act
->thread
->ref_count
);
1191 #endif /* MACH_ASSERT */
1194 * This code is called with nothing locked.
1195 * It also returns with nothing locked, if it returns.
1197 * This routine terminates the current thread activation.
1198 * If this is the only activation associated with its
1199 * thread shuttle, then the entire thread (shuttle plus
1200 * activation) is terminated.
1202 assert( code
== KERN_TERMINATED
);
1205 /* This is the only activation attached to the shuttle... */
1206 /* terminate the entire thread (shuttle plus activation) */
1208 assert(thr_act
->thread
->top_act
== thr_act
);
1209 thread_terminate_self();
1213 panic("act_machine_return: TALKING ZOMBIE! (1)");
1218 * Perform machine-dependent per-thread initializations
1221 thread_machine_init(void)
1227 * Some routines for debugging activation code
1229 static void dump_handlers(thread_act_t
);
1230 void dump_regs(thread_act_t
);
1233 dump_handlers(thread_act_t thr_act
)
1235 ReturnHandler
*rhp
= thr_act
->handlers
;
1240 if (rhp
== &thr_act
->special_handler
){
1242 printf("[NON-Zero next ptr(%x)]", rhp
->next
);
1243 printf("special_handler()->");
1246 printf("hdlr_%d(%x)->",counter
,rhp
->handler
);
1248 if (++counter
> 32) {
1249 printf("Aborting: HUGE handler chain\n");
1253 printf("HLDR_NULL\n");
1257 dump_regs(thread_act_t thr_act
)
1259 if (thr_act
->mact
.pcb
) {
1260 register struct i386_saved_state
*ssp
= USER_REGS(thr_act
);
1261 /* Print out user register state */
1262 printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n",
1263 ssp
->edi
, ssp
->esi
, ssp
->ebp
, ssp
->ebx
, ssp
->edx
);
1264 printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n",
1265 ssp
->ecx
, ssp
->eax
, ssp
->eip
, ssp
->efl
, ssp
->uesp
);
1266 printf("\t\tcs=%x ss=%x\n", ssp
->cs
, ssp
->ss
);
1271 dump_act(thread_act_t thr_act
)
1276 printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n",
1277 thr_act
, thr_act
->ref_count
,
1278 thr_act
->thread
, thr_act
->thread
? thr_act
->thread
->ref_count
:0,
1279 thr_act
->task
, thr_act
->task
? thr_act
->task
->ref_count
: 0);
1281 printf("\talerts=%x mask=%x susp=%d user_stop=%d active=%x ast=%x\n",
1282 thr_act
->alerts
, thr_act
->alert_mask
,
1283 thr_act
->suspend_count
, thr_act
->user_stop_count
,
1284 thr_act
->active
, thr_act
->ast
);
1285 printf("\thi=%x lo=%x\n", thr_act
->higher
, thr_act
->lower
);
1286 printf("\tpcb=%x\n", thr_act
->mact
.pcb
);
1288 if (thr_act
->thread
&& thr_act
->thread
->kernel_stack
) {
1289 vm_offset_t stack
= thr_act
->thread
->kernel_stack
;
1291 printf("\tk_stk %x eip %x ebx %x esp %x iss %x\n",
1292 stack
, STACK_IKS(stack
)->k_eip
, STACK_IKS(stack
)->k_ebx
,
1293 STACK_IKS(stack
)->k_esp
, STACK_IEL(stack
)->saved_state
);
1296 dump_handlers(thr_act
);
1298 return((int)thr_act
);
1304 thread_act_t thr_act
= current_act();
1306 if (thr_act
->mact
.pcb
)
1307 return(thr_act
->mact
.pcb
->iss
.eip
);
1314 thread_swapin_mach_alloc(thread_t thread
)
1317 /* 386 does not have saveareas */
1321 * detach and return a kernel stack from a thread
1325 stack_detach(thread_t thread
)
1329 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_DETACH
),
1330 thread
, thread
->priority
,
1331 thread
->sched_pri
, 0,
1334 stack
= thread
->kernel_stack
;
1335 thread
->kernel_stack
= 0;
1340 * attach a kernel stack to a thread and initialize it
1344 stack_attach(struct thread_shuttle
*thread
,
1346 void (*start_pos
)(thread_t
))
1348 struct i386_kernel_state
*statep
;
1350 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_ATTACH
),
1351 thread
, thread
->priority
,
1352 thread
->sched_pri
, continuation
,
1356 statep
= STACK_IKS(stack
);
1357 thread
->kernel_stack
= stack
;
1359 statep
->k_eip
= (unsigned long) Thread_continue
;
1360 statep
->k_ebx
= (unsigned long) start_pos
;
1361 statep
->k_esp
= (unsigned long) STACK_IEL(stack
);
1362 assert(thread
->top_act
);
1363 STACK_IEL(stack
)->saved_state
= &thread
->top_act
->mact
.pcb
->iss
;
1369 * move a stack from old to new thread
1373 stack_handoff(thread_t old
,
1380 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_HANDOFF
),
1381 thread
, thread
->priority
,
1382 thread
->sched_pri
, continuation
,
1385 assert(new->top_act
);
1386 assert(old
->top_act
);
1388 stack
= stack_detach(old
);
1389 stack_attach(new, stack
, 0);
1391 new_pmap
= new->top_act
->task
->map
->pmap
;
1392 if (old
->top_act
->task
->map
->pmap
!= new_pmap
)
1393 PMAP_ACTIVATE_MAP(new->top_act
->task
->map
, cpu_number());
1395 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_HANDOFF
) | DBG_FUNC_NONE
,
1396 (int)old
, (int)new, old
->sched_pri
, new->sched_pri
, 0);
1398 thread_machine_set_current(new);
1400 active_stacks
[cpu_number()] = new->kernel_stack
;
1405 struct i386_act_context
{
1406 struct i386_saved_state ss
;
1407 struct i386_float_state fs
;
1411 act_thread_csave(void)
1413 struct i386_act_context
*ic
;
1417 ic
= (struct i386_act_context
*)kalloc(sizeof(struct i386_act_context
));
1419 if (ic
== (struct i386_act_context
*)NULL
)
1422 val
= i386_SAVED_STATE_COUNT
;
1423 kret
= act_machine_get_state(current_act(), i386_SAVED_STATE
, &ic
->ss
, &val
);
1424 if (kret
!= KERN_SUCCESS
) {
1425 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1428 val
= i386_FLOAT_STATE_COUNT
;
1429 kret
= act_machine_get_state(current_act(), i386_FLOAT_STATE
, &ic
->fs
, &val
);
1430 if (kret
!= KERN_SUCCESS
) {
1431 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1437 act_thread_catt(void *ctx
)
1439 struct i386_act_context
*ic
;
1443 ic
= (struct i386_act_context
*)ctx
;
1445 if (ic
== (struct i386_act_context
*)NULL
)
1448 kret
= act_machine_set_state(current_act(), i386_SAVED_STATE
, &ic
->ss
, i386_SAVED_STATE_COUNT
);
1449 if (kret
!= KERN_SUCCESS
)
1452 kret
= act_machine_set_state(current_act(), i386_FLOAT_STATE
, &ic
->fs
, i386_FLOAT_STATE_COUNT
);
1453 if (kret
!= KERN_SUCCESS
)
1456 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1459 void act_thread_cfree(void *ctx
)
1461 kfree((vm_offset_t
)ctx
,sizeof(struct i386_act_context
));