2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
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.
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.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 #include <mach_debug.h>
54 #include <mach_ldebug.h>
56 #include <sys/kdebug.h>
58 #include <mach/kern_return.h>
59 #include <mach/thread_status.h>
60 #include <mach/vm_param.h>
62 #include <kern/counters.h>
63 #include <kern/mach_param.h>
64 #include <kern/task.h>
65 #include <kern/thread.h>
66 #include <kern/thread_act.h>
67 #include <kern/thread_swap.h>
68 #include <kern/sched_prim.h>
69 #include <kern/misc_protos.h>
70 #include <kern/assert.h>
72 #include <ipc/ipc_port.h>
73 #include <vm/vm_kern.h>
76 #include <i386/thread.h>
77 #include <i386/eflags.h>
78 #include <i386/proc_reg.h>
81 #include <i386/user_ldt.h>
83 #include <i386/iopb_entries.h>
86 * Maps state flavor to number of words in the state:
88 unsigned int state_count
[] = {
90 i386_NEW_THREAD_STATE_COUNT
,
91 i386_FLOAT_STATE_COUNT
,
92 i386_ISA_PORT_MAP_STATE_COUNT
,
93 i386_V86_ASSIST_STATE_COUNT
,
94 i386_REGS_SEGS_STATE_COUNT
,
95 i386_THREAD_SYSCALL_STATE_COUNT
,
96 /* THREAD_STATE_NONE */ 0,
97 i386_SAVED_STATE_COUNT
,
102 void act_machine_throughcall(thread_act_t thr_act
);
103 extern thread_t
Switch_context(
107 extern void Thread_continue(void);
108 extern void Load_context(
112 * consider_machine_collect:
114 * Try to collect machine-dependent pages
117 consider_machine_collect()
122 consider_machine_adjust()
128 * machine_kernel_stack_init:
130 * Initialize a kernel stack which has already been
131 * attached to its thread_activation.
135 machine_kernel_stack_init(
137 void (*start_pos
)(thread_t
))
139 thread_act_t thr_act
= thread
->top_act
;
143 stack
= thread
->kernel_stack
;
147 if (watchacts
& WA_PCB
) {
148 printf("machine_kernel_stack_init(thr=%x,stk=%x,start_pos=%x)\n",
149 thread
,stack
,start_pos
);
150 printf("\tstack_iks=%x, stack_iel=%x\n",
151 STACK_IKS(stack
), STACK_IEL(stack
));
153 #endif /* MACH_ASSERT */
156 * We want to run at start_pos, giving it as an argument
157 * the return value from Load_context/Switch_context.
158 * Thread_continue takes care of the mismatch between
159 * the argument-passing/return-value conventions.
160 * This function will not return normally,
161 * so we don`t have to worry about a return address.
163 STACK_IKS(stack
)->k_eip
= (int) Thread_continue
;
164 STACK_IKS(stack
)->k_ebx
= (int) start_pos
;
165 STACK_IKS(stack
)->k_esp
= (int) STACK_IEL(stack
);
168 * Point top of kernel stack to user`s registers.
170 STACK_IEL(stack
)->saved_state
= &thr_act
->mact
.pcb
->iss
;
175 #define curr_gdt(mycpu) (mp_gdt[mycpu])
176 #define curr_ktss(mycpu) (mp_ktss[mycpu])
178 #define curr_gdt(mycpu) (gdt)
179 #define curr_ktss(mycpu) (&ktss)
182 #define gdt_desc_p(mycpu,sel) \
183 ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
186 act_machine_switch_pcb( thread_act_t new_act
)
188 pcb_t pcb
= new_act
->mact
.pcb
;
191 register iopb_tss_t tss
= pcb
->ims
.io_tss
;
192 vm_offset_t pcb_stack_top
;
194 assert(new_act
->thread
!= NULL
);
195 assert(new_act
->thread
->kernel_stack
!= 0);
196 STACK_IEL(new_act
->thread
->kernel_stack
)->saved_state
=
197 &new_act
->mact
.pcb
->iss
;
200 * Save a pointer to the top of the "kernel" stack -
201 * actually the place in the PCB where a trap into
202 * kernel mode will push the registers.
203 * The location depends on V8086 mode. If we are
204 * not in V8086 mode, then a trap into the kernel
205 * won`t save the v86 segments, so we leave room.
208 pcb_stack_top
= (pcb
->iss
.efl
& EFL_VM
)
209 ? (int) (&pcb
->iss
+ 1)
210 : (int) (&pcb
->iss
.v86_segs
);
212 mp_disable_preemption();
213 mycpu
= cpu_number();
217 * No per-thread IO permissions.
218 * Use standard kernel TSS.
220 if (!(gdt_desc_p(mycpu
,KERNEL_TSS
)->access
& ACC_TSS_BUSY
))
222 curr_ktss(mycpu
)->esp0
= pcb_stack_top
;
226 * Set the IO permissions. Use this thread`s TSS.
228 *gdt_desc_p(mycpu
,USER_TSS
)
229 = *(struct real_descriptor
*)tss
->iopb_desc
;
230 tss
->tss
.esp0
= pcb_stack_top
;
232 gdt_desc_p(mycpu
,KERNEL_TSS
)->access
&= ~ ACC_TSS_BUSY
;
237 register user_ldt_t ldt
= pcb
->ims
.ldt
;
239 * Set the thread`s LDT.
249 * Thread has its own LDT.
251 *gdt_desc_p(mycpu
,USER_LDT
) = ldt
->desc
;
255 mp_enable_preemption();
257 * Load the floating-point context, if necessary.
259 fpu_load_context(pcb
);
264 * flush out any lazily evaluated HW state in the
265 * owning thread's context, before termination.
268 thread_machine_flush( thread_act_t cur_act
)
274 * Switch to the first thread on a CPU.
280 act_machine_switch_pcb(new->top_act
);
285 * Number of times we needed to swap an activation back in before
288 int switch_act_swapins
= 0;
293 * Machine-dependent details of activation switching. Called with
294 * RPC locks held and preemption disabled.
304 * Switch the vm, ast and pcb context.
305 * Save FP registers if in use and set TS (task switch) bit.
307 fpu_save_context(thread
);
309 active_stacks
[cpu
] = thread
->kernel_stack
;
310 ast_context(new, cpu
);
312 PMAP_SWITCH_CONTEXT(old
, new, cpu
);
313 act_machine_switch_pcb(new);
317 * Switch to a new thread.
318 * Save the old thread`s kernel state or continuation,
324 void (*continuation
)(void),
327 register thread_act_t old_act
= old
->top_act
,
328 new_act
= new->top_act
;
331 assert(old_act
->kernel_loaded
||
332 active_stacks
[cpu_number()] == old_act
->thread
->kernel_stack
);
333 assert (get_preemption_level() == 1);
335 check_simple_locks();
338 * Save FP registers if in use.
340 fpu_save_context(old
);
343 if (watchacts
& WA_SWITCH
)
344 printf("\tswitch_context(old=%x con=%x new=%x)\n",
345 old
, continuation
, new);
346 #endif /* MACH_ASSERT */
349 * Switch address maps if need be, even if not switching tasks.
350 * (A server activation may be "borrowing" a client map.)
353 int mycpu
= cpu_number();
355 PMAP_SWITCH_CONTEXT(old_act
, new_act
, mycpu
)
359 * Load the rest of the user state for the new thread
361 act_machine_switch_pcb(new_act
);
362 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_SCHED
) | DBG_FUNC_NONE
,
363 (int)old
, (int)new, old
->sched_pri
, new->sched_pri
, 0);
364 return(Switch_context(old
, continuation
, new));
368 pcb_module_init(void)
375 pcb_init( register thread_act_t thr_act
)
379 assert(thr_act
->mact
.pcb
== (pcb_t
)0);
380 pcb
= thr_act
->mact
.pcb
= &thr_act
->mact
.xxx_pcb
;
383 if (watchacts
& WA_PCB
)
384 printf("pcb_init(%x) pcb=%x\n", thr_act
, pcb
);
385 #endif /* MACH_ASSERT */
388 * We can't let random values leak out to the user.
389 * (however, act_create() zeroed the entire thr_act, mact, pcb)
390 * bzero((char *) pcb, sizeof *pcb);
392 simple_lock_init(&pcb
->lock
, ETAP_MISC_PCB
);
395 * Guarantee that the bootstrapped thread will be in user
398 pcb
->iss
.cs
= USER_CS
;
399 pcb
->iss
.ss
= USER_DS
;
400 pcb
->iss
.ds
= USER_DS
;
401 pcb
->iss
.es
= USER_DS
;
402 pcb
->iss
.fs
= USER_DS
;
403 pcb
->iss
.gs
= USER_DS
;
404 pcb
->iss
.efl
= EFL_USER_SET
;
408 * Adjust saved register state for thread belonging to task
409 * created with kernel_task_create().
413 thread_act_t thr_act
)
415 register pcb_t pcb
= thr_act
->mact
.pcb
;
417 pcb
->iss
.cs
= KERNEL_CS
;
418 pcb
->iss
.ss
= KERNEL_DS
;
419 pcb
->iss
.ds
= KERNEL_DS
;
420 pcb
->iss
.es
= KERNEL_DS
;
421 pcb
->iss
.fs
= KERNEL_DS
;
422 pcb
->iss
.gs
= CPU_DATA
;
427 register thread_act_t thr_act
)
429 register pcb_t pcb
= thr_act
->mact
.pcb
;
433 if (pcb
->ims
.io_tss
!= 0)
434 iopb_destroy(pcb
->ims
.io_tss
);
435 if (pcb
->ims
.ifps
!= 0)
436 fp_free(pcb
->ims
.ifps
);
437 if (pcb
->ims
.ldt
!= 0)
438 user_ldt_free(pcb
->ims
.ldt
);
439 thr_act
->mact
.pcb
= (pcb_t
)0;
445 * Attempt to free excess pcb memory.
450 register thread_act_t thr_act
)
452 /* accomplishes very little */
456 * act_machine_sv_free
457 * release saveareas associated with an act. if flag is true, release
458 * user level savearea(s) too, else don't
461 act_machine_sv_free(thread_act_t act
, int flag
)
467 * act_machine_set_state:
469 * Set the status of the specified thread. Called with "appropriate"
470 * thread-related locks held (see act_lock_thread()), so
471 * thr_act->thread is guaranteed not to change.
475 act_machine_set_state(
476 thread_act_t thr_act
,
477 thread_flavor_t flavor
,
478 thread_state_t tstate
,
479 mach_msg_type_number_t count
)
481 int kernel_act
= thr_act
->kernel_loading
||
482 thr_act
->kernel_loaded
;
485 if (watchacts
& WA_STATE
)
486 printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
487 current_act(), thr_act
, flavor
, tstate
, count
);
488 #endif /* MACH_ASSERT */
491 case THREAD_SYSCALL_STATE
:
493 register struct thread_syscall_state
*state
;
494 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
496 state
= (struct thread_syscall_state
*) tstate
;
497 saved_state
->eax
= state
->eax
;
498 saved_state
->edx
= state
->edx
;
500 saved_state
->efl
= state
->efl
;
502 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
) | EFL_USER_SET
;
503 saved_state
->eip
= state
->eip
;
504 saved_state
->uesp
= state
->esp
;
508 case i386_SAVED_STATE
:
510 register struct i386_saved_state
*state
;
511 register struct i386_saved_state
*saved_state
;
513 if (count
< i386_SAVED_STATE_COUNT
) {
514 return(KERN_INVALID_ARGUMENT
);
517 state
= (struct i386_saved_state
*) tstate
;
519 saved_state
= USER_REGS(thr_act
);
524 saved_state
->edi
= state
->edi
;
525 saved_state
->esi
= state
->esi
;
526 saved_state
->ebp
= state
->ebp
;
527 saved_state
->uesp
= state
->uesp
;
528 saved_state
->ebx
= state
->ebx
;
529 saved_state
->edx
= state
->edx
;
530 saved_state
->ecx
= state
->ecx
;
531 saved_state
->eax
= state
->eax
;
532 saved_state
->eip
= state
->eip
;
534 saved_state
->efl
= state
->efl
;
536 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
540 * Segment registers. Set differently in V8086 mode.
542 if (state
->efl
& EFL_VM
) {
544 * Set V8086 mode segment registers.
546 saved_state
->cs
= state
->cs
& 0xffff;
547 saved_state
->ss
= state
->ss
& 0xffff;
548 saved_state
->v86_segs
.v86_ds
= state
->ds
& 0xffff;
549 saved_state
->v86_segs
.v86_es
= state
->es
& 0xffff;
550 saved_state
->v86_segs
.v86_fs
= state
->fs
& 0xffff;
551 saved_state
->v86_segs
.v86_gs
= state
->gs
& 0xffff;
554 * Zero protected mode segment registers.
561 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
563 * Hardware assist on.
565 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
566 state
->efl
& (EFL_TF
| EFL_IF
);
569 else if (!kernel_act
) {
571 * 386 mode. Set segment registers for flat
572 * 32-bit address space.
574 saved_state
->cs
= USER_CS
;
575 saved_state
->ss
= USER_DS
;
576 saved_state
->ds
= USER_DS
;
577 saved_state
->es
= USER_DS
;
578 saved_state
->fs
= USER_DS
;
579 saved_state
->gs
= USER_DS
;
583 * User setting segment registers.
584 * Code and stack selectors have already been
585 * checked. Others will be reset by 'iret'
586 * if they are not valid.
588 saved_state
->cs
= state
->cs
;
589 saved_state
->ss
= state
->ss
;
590 saved_state
->ds
= state
->ds
;
591 saved_state
->es
= state
->es
;
592 saved_state
->fs
= state
->fs
;
593 saved_state
->gs
= state
->gs
;
598 case i386_NEW_THREAD_STATE
:
599 case i386_REGS_SEGS_STATE
:
601 register struct i386_new_thread_state
*state
;
602 register struct i386_saved_state
*saved_state
;
604 if (count
< i386_NEW_THREAD_STATE_COUNT
) {
605 return(KERN_INVALID_ARGUMENT
);
608 if (flavor
== i386_REGS_SEGS_STATE
) {
610 * Code and stack selectors must not be null,
611 * and must have user protection levels.
612 * Only the low 16 bits are valid.
622 (state
->cs
== 0 || (state
->cs
& SEL_PL
) != SEL_PL_U
623 || state
->ss
== 0 || (state
->ss
& SEL_PL
) != SEL_PL_U
))
624 return KERN_INVALID_ARGUMENT
;
627 state
= (struct i386_new_thread_state
*) tstate
;
629 saved_state
= USER_REGS(thr_act
);
634 saved_state
->edi
= state
->edi
;
635 saved_state
->esi
= state
->esi
;
636 saved_state
->ebp
= state
->ebp
;
637 saved_state
->uesp
= state
->uesp
;
638 saved_state
->ebx
= state
->ebx
;
639 saved_state
->edx
= state
->edx
;
640 saved_state
->ecx
= state
->ecx
;
641 saved_state
->eax
= state
->eax
;
642 saved_state
->eip
= state
->eip
;
644 saved_state
->efl
= state
->efl
;
646 saved_state
->efl
= (state
->efl
& ~EFL_USER_CLEAR
)
650 * Segment registers. Set differently in V8086 mode.
652 if (state
->efl
& EFL_VM
) {
654 * Set V8086 mode segment registers.
656 saved_state
->cs
= state
->cs
& 0xffff;
657 saved_state
->ss
= state
->ss
& 0xffff;
658 saved_state
->v86_segs
.v86_ds
= state
->ds
& 0xffff;
659 saved_state
->v86_segs
.v86_es
= state
->es
& 0xffff;
660 saved_state
->v86_segs
.v86_fs
= state
->fs
& 0xffff;
661 saved_state
->v86_segs
.v86_gs
= state
->gs
& 0xffff;
664 * Zero protected mode segment registers.
671 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
673 * Hardware assist on.
675 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
676 state
->efl
& (EFL_TF
| EFL_IF
);
679 else if (flavor
== i386_NEW_THREAD_STATE
&& !kernel_act
) {
681 * 386 mode. Set segment registers for flat
682 * 32-bit address space.
684 saved_state
->cs
= USER_CS
;
685 saved_state
->ss
= USER_DS
;
686 saved_state
->ds
= USER_DS
;
687 saved_state
->es
= USER_DS
;
688 saved_state
->fs
= USER_DS
;
689 saved_state
->gs
= USER_DS
;
693 * User setting segment registers.
694 * Code and stack selectors have already been
695 * checked. Others will be reset by 'iret'
696 * if they are not valid.
698 saved_state
->cs
= state
->cs
;
699 saved_state
->ss
= state
->ss
;
700 saved_state
->ds
= state
->ds
;
701 saved_state
->es
= state
->es
;
702 saved_state
->fs
= state
->fs
;
703 saved_state
->gs
= state
->gs
;
708 case i386_FLOAT_STATE
: {
710 if (count
< i386_FLOAT_STATE_COUNT
)
711 return(KERN_INVALID_ARGUMENT
);
713 return fpu_set_state(thr_act
,(struct i386_float_state
*)tstate
);
717 * Temporary - replace by i386_io_map
719 case i386_ISA_PORT_MAP_STATE
: {
720 register struct i386_isa_port_map_state
*state
;
721 register iopb_tss_t tss
;
723 if (count
< i386_ISA_PORT_MAP_STATE_COUNT
)
724 return(KERN_INVALID_ARGUMENT
);
729 case i386_V86_ASSIST_STATE
:
731 register struct i386_v86_assist_state
*state
;
732 vm_offset_t int_table
;
735 if (count
< i386_V86_ASSIST_STATE_COUNT
)
736 return KERN_INVALID_ARGUMENT
;
738 state
= (struct i386_v86_assist_state
*) tstate
;
739 int_table
= state
->int_table
;
740 int_count
= state
->int_count
;
742 if (int_table
>= VM_MAX_ADDRESS
||
744 int_count
* sizeof(struct v86_interrupt_table
)
746 return KERN_INVALID_ARGUMENT
;
748 thr_act
->mact
.pcb
->ims
.v86s
.int_table
= int_table
;
749 thr_act
->mact
.pcb
->ims
.v86s
.int_count
= int_count
;
751 thr_act
->mact
.pcb
->ims
.v86s
.flags
=
752 USER_REGS(thr_act
)->efl
& (EFL_TF
| EFL_IF
);
756 case i386_THREAD_STATE
: {
757 struct i386_saved_state
*saved_state
;
758 i386_thread_state_t
*state25
;
760 saved_state
= USER_REGS(thr_act
);
761 state25
= (i386_thread_state_t
*)tstate
;
763 saved_state
->eax
= state25
->eax
;
764 saved_state
->ebx
= state25
->ebx
;
765 saved_state
->ecx
= state25
->ecx
;
766 saved_state
->edx
= state25
->edx
;
767 saved_state
->edi
= state25
->edi
;
768 saved_state
->esi
= state25
->esi
;
769 saved_state
->ebp
= state25
->ebp
;
770 saved_state
->uesp
= state25
->esp
;
771 saved_state
->efl
= (state25
->eflags
& ~EFL_USER_CLEAR
)
773 saved_state
->eip
= state25
->eip
;
774 saved_state
->cs
= USER_CS
; /* FIXME? */
775 saved_state
->ss
= USER_DS
;
776 saved_state
->ds
= USER_DS
;
777 saved_state
->es
= USER_DS
;
778 saved_state
->fs
= USER_DS
;
779 saved_state
->gs
= USER_DS
;
784 return(KERN_INVALID_ARGUMENT
);
787 return(KERN_SUCCESS
);
793 * Get the status of the specified thread.
798 act_machine_get_state(
799 thread_act_t thr_act
,
800 thread_flavor_t flavor
,
801 thread_state_t tstate
,
802 mach_msg_type_number_t
*count
)
805 if (watchacts
& WA_STATE
)
806 printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
807 current_act(), thr_act
, flavor
, tstate
,
808 count
, (count
? *count
: 0));
809 #endif /* MACH_ASSERT */
813 case i386_SAVED_STATE
:
815 register struct i386_saved_state
*state
;
816 register struct i386_saved_state
*saved_state
;
818 if (*count
< i386_SAVED_STATE_COUNT
)
819 return(KERN_INVALID_ARGUMENT
);
821 state
= (struct i386_saved_state
*) tstate
;
822 saved_state
= USER_REGS(thr_act
);
825 * First, copy everything:
827 *state
= *saved_state
;
829 if (saved_state
->efl
& EFL_VM
) {
833 state
->ds
= saved_state
->v86_segs
.v86_ds
& 0xffff;
834 state
->es
= saved_state
->v86_segs
.v86_es
& 0xffff;
835 state
->fs
= saved_state
->v86_segs
.v86_fs
& 0xffff;
836 state
->gs
= saved_state
->v86_segs
.v86_gs
& 0xffff;
838 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
842 if ((thr_act
->mact
.pcb
->ims
.v86s
.flags
&
843 (EFL_IF
|V86_IF_PENDING
)) == 0)
844 state
->efl
&= ~EFL_IF
;
851 state
->ds
= saved_state
->ds
& 0xffff;
852 state
->es
= saved_state
->es
& 0xffff;
853 state
->fs
= saved_state
->fs
& 0xffff;
854 state
->gs
= saved_state
->gs
& 0xffff;
856 *count
= i386_SAVED_STATE_COUNT
;
860 case i386_NEW_THREAD_STATE
:
861 case i386_REGS_SEGS_STATE
:
863 register struct i386_new_thread_state
*state
;
864 register struct i386_saved_state
*saved_state
;
866 if (*count
< i386_NEW_THREAD_STATE_COUNT
)
867 return(KERN_INVALID_ARGUMENT
);
869 state
= (struct i386_new_thread_state
*) tstate
;
870 saved_state
= USER_REGS(thr_act
);
875 state
->edi
= saved_state
->edi
;
876 state
->esi
= saved_state
->esi
;
877 state
->ebp
= saved_state
->ebp
;
878 state
->ebx
= saved_state
->ebx
;
879 state
->edx
= saved_state
->edx
;
880 state
->ecx
= saved_state
->ecx
;
881 state
->eax
= saved_state
->eax
;
882 state
->eip
= saved_state
->eip
;
883 state
->efl
= saved_state
->efl
;
884 state
->uesp
= saved_state
->uesp
;
886 state
->cs
= saved_state
->cs
;
887 state
->ss
= saved_state
->ss
;
888 if (saved_state
->efl
& EFL_VM
) {
892 state
->ds
= saved_state
->v86_segs
.v86_ds
& 0xffff;
893 state
->es
= saved_state
->v86_segs
.v86_es
& 0xffff;
894 state
->fs
= saved_state
->v86_segs
.v86_fs
& 0xffff;
895 state
->gs
= saved_state
->v86_segs
.v86_gs
& 0xffff;
897 if (thr_act
->mact
.pcb
->ims
.v86s
.int_table
) {
901 if ((thr_act
->mact
.pcb
->ims
.v86s
.flags
&
902 (EFL_IF
|V86_IF_PENDING
)) == 0)
903 state
->efl
&= ~EFL_IF
;
910 state
->ds
= saved_state
->ds
& 0xffff;
911 state
->es
= saved_state
->es
& 0xffff;
912 state
->fs
= saved_state
->fs
& 0xffff;
913 state
->gs
= saved_state
->gs
& 0xffff;
915 *count
= i386_NEW_THREAD_STATE_COUNT
;
919 case THREAD_SYSCALL_STATE
:
921 register struct thread_syscall_state
*state
;
922 register struct i386_saved_state
*saved_state
= USER_REGS(thr_act
);
924 state
= (struct thread_syscall_state
*) tstate
;
925 state
->eax
= saved_state
->eax
;
926 state
->edx
= saved_state
->edx
;
927 state
->efl
= saved_state
->efl
;
928 state
->eip
= saved_state
->eip
;
929 state
->esp
= saved_state
->uesp
;
930 *count
= i386_THREAD_SYSCALL_STATE_COUNT
;
934 case THREAD_STATE_FLAVOR_LIST
:
936 return (KERN_INVALID_ARGUMENT
);
937 tstate
[0] = i386_NEW_THREAD_STATE
;
938 tstate
[1] = i386_FLOAT_STATE
;
939 tstate
[2] = i386_ISA_PORT_MAP_STATE
;
940 tstate
[3] = i386_V86_ASSIST_STATE
;
941 tstate
[4] = THREAD_SYSCALL_STATE
;
945 case i386_FLOAT_STATE
: {
947 if (*count
< i386_FLOAT_STATE_COUNT
)
948 return(KERN_INVALID_ARGUMENT
);
950 *count
= i386_FLOAT_STATE_COUNT
;
951 return fpu_get_state(thr_act
,(struct i386_float_state
*)tstate
);
955 * Temporary - replace by i386_io_map
957 case i386_ISA_PORT_MAP_STATE
: {
958 register struct i386_isa_port_map_state
*state
;
959 register iopb_tss_t tss
;
961 if (*count
< i386_ISA_PORT_MAP_STATE_COUNT
)
962 return(KERN_INVALID_ARGUMENT
);
964 state
= (struct i386_isa_port_map_state
*) tstate
;
965 tss
= thr_act
->mact
.pcb
->ims
.io_tss
;
971 * The thread has no ktss, so no IO permissions.
974 for (i
= 0; i
< sizeof state
->pm
; i
++)
978 * The thread has its own ktss.
981 bcopy((char *) tss
->bitmap
,
986 *count
= i386_ISA_PORT_MAP_STATE_COUNT
;
990 case i386_V86_ASSIST_STATE
:
992 register struct i386_v86_assist_state
*state
;
994 if (*count
< i386_V86_ASSIST_STATE_COUNT
)
995 return KERN_INVALID_ARGUMENT
;
997 state
= (struct i386_v86_assist_state
*) tstate
;
998 state
->int_table
= thr_act
->mact
.pcb
->ims
.v86s
.int_table
;
999 state
->int_count
= thr_act
->mact
.pcb
->ims
.v86s
.int_count
;
1001 *count
= i386_V86_ASSIST_STATE_COUNT
;
1005 case i386_THREAD_STATE
: {
1006 struct i386_saved_state
*saved_state
;
1007 i386_thread_state_t
*state
;
1009 saved_state
= USER_REGS(thr_act
);
1010 state
= (i386_thread_state_t
*)tstate
;
1012 state
->eax
= saved_state
->eax
;
1013 state
->ebx
= saved_state
->ebx
;
1014 state
->ecx
= saved_state
->ecx
;
1015 state
->edx
= saved_state
->edx
;
1016 state
->edi
= saved_state
->edi
;
1017 state
->esi
= saved_state
->esi
;
1018 state
->ebp
= saved_state
->ebp
;
1019 state
->esp
= saved_state
->uesp
;
1020 state
->eflags
= saved_state
->efl
;
1021 state
->eip
= saved_state
->eip
;
1022 state
->cs
= saved_state
->cs
;
1023 state
->ss
= saved_state
->ss
;
1024 state
->ds
= saved_state
->ds
;
1025 state
->es
= saved_state
->es
;
1026 state
->fs
= saved_state
->fs
;
1027 state
->gs
= saved_state
->gs
;
1032 return(KERN_INVALID_ARGUMENT
);
1035 return(KERN_SUCCESS
);
1039 * Alter the thread`s state so that a following thread_exception_return
1040 * will make the thread return 'retval' from a syscall.
1043 thread_set_syscall_return(
1045 kern_return_t retval
)
1047 thread
->top_act
->mact
.pcb
->iss
.eax
= retval
;
1051 * Initialize the machine-dependent state for a new thread.
1054 thread_machine_create(thread_t thread
, thread_act_t thr_act
, void (*start_pos
)(thread_t
))
1056 MachineThrAct_t mact
= &thr_act
->mact
;
1059 if (watchacts
& WA_PCB
)
1060 printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n",
1061 thread
, thr_act
, start_pos
);
1062 #endif /* MACH_ASSERT */
1064 assert(thread
!= NULL
);
1065 assert(thr_act
!= NULL
);
1068 * Allocate a kernel stack per shuttle
1070 thread
->kernel_stack
= (int)stack_alloc(thread
,start_pos
);
1071 thread
->state
&= ~TH_STACK_HANDOFF
;
1072 assert(thread
->kernel_stack
!= 0);
1075 * Point top of kernel stack to user`s registers.
1077 STACK_IEL(thread
->kernel_stack
)->saved_state
= &mact
->pcb
->iss
;
1079 return(KERN_SUCCESS
);
1083 * Machine-dependent cleanup prior to destroying a thread
1086 thread_machine_destroy( thread_t thread
)
1090 if (thread
->kernel_stack
!= 0) {
1098 * This is used to set the current thr_act/thread
1099 * when starting up a new processor
1102 thread_machine_set_current( thread_t thread
)
1104 register int my_cpu
;
1106 mp_disable_preemption();
1107 my_cpu
= cpu_number();
1109 cpu_data
[my_cpu
].active_thread
= thread
;
1110 active_kloaded
[my_cpu
] =
1111 thread
->top_act
->kernel_loaded
? thread
->top_act
: THR_ACT_NULL
;
1113 mp_enable_preemption();
1118 * Pool of kernel activations.
1121 void act_machine_init()
1124 thread_act_t thr_act
;
1127 if (watchacts
& WA_PCB
)
1128 printf("act_machine_init()\n");
1129 #endif /* MACH_ASSERT */
1131 /* Good to verify this once */
1132 assert( THREAD_MACHINE_STATE_MAX
<= THREAD_STATE_MAX
);
1136 act_machine_create(task_t task
, thread_act_t thr_act
)
1138 MachineThrAct_t mact
= &thr_act
->mact
;
1142 if (watchacts
& WA_PCB
)
1143 printf("act_machine_create(task=%x,thr_act=%x) pcb=%x\n",
1144 task
,thr_act
, &mact
->xxx_pcb
);
1145 #endif /* MACH_ASSERT */
1148 * Clear & Init the pcb (sets up user-mode s regs)
1152 return KERN_SUCCESS
;
1156 act_virtual_machine_destroy(thread_act_t thr_act
)
1162 act_machine_destroy(thread_act_t thr_act
)
1166 if (watchacts
& WA_PCB
)
1167 printf("act_machine_destroy(0x%x)\n", thr_act
);
1168 #endif /* MACH_ASSERT */
1170 pcb_terminate(thr_act
);
1174 act_machine_return(int code
)
1176 thread_act_t thr_act
= current_act();
1180 * We don't go through the locking dance here needed to
1181 * acquire thr_act->thread safely.
1184 if (watchacts
& WA_EXIT
)
1185 printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n",
1186 code
, thr_act
, thr_act
->ref_count
,
1187 thr_act
->thread
, thr_act
->thread
->ref_count
);
1188 #endif /* MACH_ASSERT */
1191 * This code is called with nothing locked.
1192 * It also returns with nothing locked, if it returns.
1194 * This routine terminates the current thread activation.
1195 * If this is the only activation associated with its
1196 * thread shuttle, then the entire thread (shuttle plus
1197 * activation) is terminated.
1199 assert( code
== KERN_TERMINATED
);
1202 /* This is the only activation attached to the shuttle... */
1203 /* terminate the entire thread (shuttle plus activation) */
1205 assert(thr_act
->thread
->top_act
== thr_act
);
1206 thread_terminate_self();
1210 panic("act_machine_return: TALKING ZOMBIE! (1)");
1215 * Perform machine-dependent per-thread initializations
1218 thread_machine_init(void)
1224 * Some routines for debugging activation code
1226 static void dump_handlers(thread_act_t
);
1227 void dump_regs(thread_act_t
);
1230 dump_handlers(thread_act_t thr_act
)
1232 ReturnHandler
*rhp
= thr_act
->handlers
;
1237 if (rhp
== &thr_act
->special_handler
){
1239 printf("[NON-Zero next ptr(%x)]", rhp
->next
);
1240 printf("special_handler()->");
1243 printf("hdlr_%d(%x)->",counter
,rhp
->handler
);
1245 if (++counter
> 32) {
1246 printf("Aborting: HUGE handler chain\n");
1250 printf("HLDR_NULL\n");
1254 dump_regs(thread_act_t thr_act
)
1256 if (thr_act
->mact
.pcb
) {
1257 register struct i386_saved_state
*ssp
= USER_REGS(thr_act
);
1258 /* Print out user register state */
1259 printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n",
1260 ssp
->edi
, ssp
->esi
, ssp
->ebp
, ssp
->ebx
, ssp
->edx
);
1261 printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n",
1262 ssp
->ecx
, ssp
->eax
, ssp
->eip
, ssp
->efl
, ssp
->uesp
);
1263 printf("\t\tcs=%x ss=%x\n", ssp
->cs
, ssp
->ss
);
1268 dump_act(thread_act_t thr_act
)
1273 printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n",
1274 thr_act
, thr_act
->ref_count
,
1275 thr_act
->thread
, thr_act
->thread
? thr_act
->thread
->ref_count
:0,
1276 thr_act
->task
, thr_act
->task
? thr_act
->task
->ref_count
: 0);
1278 printf("\talerts=%x mask=%x susp=%d user_stop=%d active=%x ast=%x\n",
1279 thr_act
->alerts
, thr_act
->alert_mask
,
1280 thr_act
->suspend_count
, thr_act
->user_stop_count
,
1281 thr_act
->active
, thr_act
->ast
);
1282 printf("\thi=%x lo=%x\n", thr_act
->higher
, thr_act
->lower
);
1283 printf("\tpcb=%x\n", thr_act
->mact
.pcb
);
1285 if (thr_act
->thread
&& thr_act
->thread
->kernel_stack
) {
1286 vm_offset_t stack
= thr_act
->thread
->kernel_stack
;
1288 printf("\tk_stk %x eip %x ebx %x esp %x iss %x\n",
1289 stack
, STACK_IKS(stack
)->k_eip
, STACK_IKS(stack
)->k_ebx
,
1290 STACK_IKS(stack
)->k_esp
, STACK_IEL(stack
)->saved_state
);
1293 dump_handlers(thr_act
);
1295 return((int)thr_act
);
1301 thread_act_t thr_act
= current_act();
1303 if (thr_act
->mact
.pcb
)
1304 return(thr_act
->mact
.pcb
->iss
.eip
);
1311 thread_swapin_mach_alloc(thread_t thread
)
1314 /* 386 does not have saveareas */
1318 * detach and return a kernel stack from a thread
1322 stack_detach(thread_t thread
)
1326 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_DETACH
),
1327 thread
, thread
->priority
,
1328 thread
->sched_pri
, 0,
1331 stack
= thread
->kernel_stack
;
1332 thread
->kernel_stack
= 0;
1337 * attach a kernel stack to a thread and initialize it
1341 stack_attach(struct thread_shuttle
*thread
,
1343 void (*start_pos
)(thread_t
))
1345 struct i386_kernel_state
*statep
;
1347 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_ATTACH
),
1348 thread
, thread
->priority
,
1349 thread
->sched_pri
, continuation
,
1353 statep
= STACK_IKS(stack
);
1354 thread
->kernel_stack
= stack
;
1356 statep
->k_eip
= (unsigned long) Thread_continue
;
1357 statep
->k_ebx
= (unsigned long) start_pos
;
1358 statep
->k_esp
= (unsigned long) STACK_IEL(stack
);
1359 assert(thread
->top_act
);
1360 STACK_IEL(stack
)->saved_state
= &thread
->top_act
->mact
.pcb
->iss
;
1366 * move a stack from old to new thread
1370 stack_handoff(thread_t old
,
1377 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_HANDOFF
),
1378 thread
, thread
->priority
,
1379 thread
->sched_pri
, continuation
,
1382 assert(new->top_act
);
1383 assert(old
->top_act
);
1385 stack
= stack_detach(old
);
1386 stack_attach(new, stack
, 0);
1388 new_pmap
= new->top_act
->task
->map
->pmap
;
1389 if (old
->top_act
->task
->map
->pmap
!= new_pmap
)
1390 PMAP_ACTIVATE_MAP(new->top_act
->task
->map
, cpu_number());
1392 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_HANDOFF
) | DBG_FUNC_NONE
,
1393 (int)old
, (int)new, old
->sched_pri
, new->sched_pri
, 0);
1395 thread_machine_set_current(new);
1397 active_stacks
[cpu_number()] = new->kernel_stack
;
1402 struct i386_act_context
{
1403 struct i386_saved_state ss
;
1404 struct i386_float_state fs
;
1408 act_thread_csave(void)
1410 struct i386_act_context
*ic
;
1414 ic
= (struct i386_act_context
*)kalloc(sizeof(struct i386_act_context
));
1416 if (ic
== (struct i386_act_context
*)NULL
)
1419 val
= i386_SAVED_STATE_COUNT
;
1420 kret
= act_machine_get_state(current_act(), i386_SAVED_STATE
, &ic
->ss
, &val
);
1421 if (kret
!= KERN_SUCCESS
) {
1422 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1425 val
= i386_FLOAT_STATE_COUNT
;
1426 kret
= act_machine_get_state(current_act(), i386_FLOAT_STATE
, &ic
->fs
, &val
);
1427 if (kret
!= KERN_SUCCESS
) {
1428 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1434 act_thread_catt(void *ctx
)
1436 struct i386_act_context
*ic
;
1440 ic
= (struct i386_act_context
*)ctx
;
1442 if (ic
== (struct i386_act_context
*)NULL
)
1445 kret
= act_machine_set_state(current_act(), i386_SAVED_STATE
, &ic
->ss
, i386_SAVED_STATE_COUNT
);
1446 if (kret
!= KERN_SUCCESS
)
1449 kret
= act_machine_set_state(current_act(), i386_FLOAT_STATE
, &ic
->fs
, i386_FLOAT_STATE_COUNT
);
1450 if (kret
!= KERN_SUCCESS
)
1453 kfree((vm_offset_t
)ic
,sizeof(struct i386_act_context
));
1456 void act_thread_cfree(void *ctx
)
1458 kfree((vm_offset_t
)ctx
,sizeof(struct i386_act_context
));