|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50:
51: #include <cpus.h>
52: #include <mach_rt.h>
53: #include <mach_debug.h>
54: #include <mach_ldebug.h>
55:
56: #include <mach/kern_return.h>
57: #include <mach/thread_status.h>
58: #include <mach/vm_param.h>
59: #include <mach/rpc.h>
60:
61: #include <kern/counters.h>
62: #include <kern/mach_param.h>
63: #include <kern/task.h>
64: #include <kern/thread.h>
65: #include <kern/thread_act.h>
66: #include <kern/thread_swap.h>
67: #include <kern/sched_prim.h>
68: #include <kern/misc_protos.h>
69: #include <kern/assert.h>
70: #include <kern/spl.h>
71: #include <ipc/ipc_port.h>
72: #include <vm/vm_kern.h>
73: #include <vm/pmap.h>
74:
75: #include <i386/thread.h>
76: #include <i386/eflags.h>
77: #include <i386/proc_reg.h>
78: #include <i386/seg.h>
79: #include <i386/tss.h>
80: #include <i386/user_ldt.h>
81: #include <i386/fpu.h>
82: #include <i386/iopb_entries.h>
83:
84: /*
85: * Maps state flavor to number of words in the state:
86: */
87: unsigned int state_count[] = {
88: /* FLAVOR_LIST */ 0,
89: i386_NEW_THREAD_STATE_COUNT,
90: i386_FLOAT_STATE_COUNT,
91: i386_ISA_PORT_MAP_STATE_COUNT,
92: i386_V86_ASSIST_STATE_COUNT,
93: i386_REGS_SEGS_STATE_COUNT,
94: i386_THREAD_SYSCALL_STATE_COUNT,
95: /* THREAD_STATE_NONE */ 0,
96: i386_SAVED_STATE_COUNT,
97: };
98:
99: /* Forward */
100:
101: void act_machine_throughcall(thread_act_t thr_act);
102: extern thread_t Switch_context(
103: thread_t old,
104: void (*cont)(void),
105: thread_t new);
106: extern void Thread_continue(void);
107: extern void Load_context(
108: thread_t thread);
109:
110: /*
111: * consider_machine_collect:
112: *
113: * Try to collect machine-dependent pages
114: */
115: void
116: consider_machine_collect()
117: {
118: }
119:
120: /*
121: * machine_kernel_stack_init:
122: *
123: * Initialize a kernel stack which has already been
124: * attached to its thread_activation.
125: */
126:
127: void
128: machine_kernel_stack_init(
129: thread_t thread,
130: void (*continuation)(void))
131: {
132: thread_act_t thr_act = thread->top_act;
133: vm_offset_t stack;
134:
135: assert(thr_act);
136: stack = thread->kernel_stack;
137: assert(stack);
138:
139: #if MACH_ASSERT
140: if (watchacts & WA_PCB) {
141: printf("machine_kernel_stack_init(thr=%x,stk=%x,cont=%x)\n",
142: thread,stack,continuation);
143: printf("\tstack_iks=%x, stack_iel=%x\n",
144: STACK_IKS(stack), STACK_IEL(stack));
145: }
146: #endif /* MACH_ASSERT */
147:
148: /*
149: * We want to run continuation, giving it as an argument
150: * the return value from Load_context/Switch_context.
151: * Thread_continue takes care of the mismatch between
152: * the argument-passing/return-value conventions.
153: * This function will not return normally,
154: * so we don`t have to worry about a return address.
155: */
156: STACK_IKS(stack)->k_eip = (int) Thread_continue;
157: STACK_IKS(stack)->k_ebx = (int) continuation;
158: STACK_IKS(stack)->k_esp = (int) STACK_IEL(stack);
159:
160: /*
161: * Point top of kernel stack to user`s registers.
162: */
163: STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss;
164: }
165:
166:
167: #if NCPUS > 1
168: #define curr_gdt(mycpu) (mp_gdt[mycpu])
169: #define curr_ktss(mycpu) (mp_ktss[mycpu])
170: #else
171: #define curr_gdt(mycpu) (gdt)
172: #define curr_ktss(mycpu) (&ktss)
173: #endif
174:
175: #define gdt_desc_p(mycpu,sel) \
176: ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
177:
178: void
179: act_machine_switch_pcb( thread_act_t new_act )
180: {
181: pcb_t pcb = new_act->mact.pcb;
182: int mycpu;
183: {
184: register iopb_tss_t tss = pcb->ims.io_tss;
185: vm_offset_t pcb_stack_top;
186:
187: assert(new_act->thread != NULL);
188: assert(new_act->thread->kernel_stack != 0);
189: STACK_IEL(new_act->thread->kernel_stack)->saved_state =
190: &new_act->mact.pcb->iss;
191:
192: /*
193: * Save a pointer to the top of the "kernel" stack -
194: * actually the place in the PCB where a trap into
195: * kernel mode will push the registers.
196: * The location depends on V8086 mode. If we are
197: * not in V8086 mode, then a trap into the kernel
198: * won`t save the v86 segments, so we leave room.
199: */
200:
201: pcb_stack_top = (pcb->iss.efl & EFL_VM)
202: ? (int) (&pcb->iss + 1)
203: : (int) (&pcb->iss.v86_segs);
204:
205: mp_disable_preemption();
206: mycpu = cpu_number();
207:
208: if (tss == 0) {
209: /*
210: * No per-thread IO permissions.
211: * Use standard kernel TSS.
212: */
213: if (!(gdt_desc_p(mycpu,KERNEL_TSS)->access & ACC_TSS_BUSY))
214: set_tr(KERNEL_TSS);
215: curr_ktss(mycpu)->esp0 = pcb_stack_top;
216: }
217: else {
218: /*
219: * Set the IO permissions. Use this thread`s TSS.
220: */
221: *gdt_desc_p(mycpu,USER_TSS)
222: = *(struct real_descriptor *)tss->iopb_desc;
223: tss->tss.esp0 = pcb_stack_top;
224: set_tr(USER_TSS);
225: gdt_desc_p(mycpu,KERNEL_TSS)->access &= ~ ACC_TSS_BUSY;
226: }
227: }
228:
229: {
230: register user_ldt_t ldt = pcb->ims.ldt;
231: /*
232: * Set the thread`s LDT.
233: */
234: if (ldt == 0) {
235: /*
236: * Use system LDT.
237: */
238: set_ldt(KERNEL_LDT);
239: }
240: else {
241: /*
242: * Thread has its own LDT.
243: */
244: *gdt_desc_p(mycpu,USER_LDT) = ldt->desc;
245: set_ldt(USER_LDT);
246: }
247: }
248: mp_enable_preemption();
249: /*
250: * Load the floating-point context, if necessary.
251: */
252: fpu_load_context(pcb);
253:
254: }
255:
256: /*
257: * flush out any lazily evaluated HW state in the
258: * owning thread's context, before termination.
259: */
260: void
261: thread_machine_flush( thread_act_t cur_act )
262: {
263: fpflush(cur_act);
264: }
265:
266: /*
267: * Switch to the first thread on a CPU.
268: */
269: void
270: load_context(
271: thread_t new)
272: {
273: act_machine_switch_pcb(new->top_act);
274: Load_context(new);
275: }
276:
277: /*
278: * Number of times we needed to swap an activation back in before
279: * switching to it.
280: */
281: int switch_act_swapins = 0;
282:
283: /*
284: * machine_switch_act
285: *
286: * Machine-dependent details of activation switching. Called with
287: * RPC locks held and preemption disabled.
288: */
289: void
290: machine_switch_act(
291: thread_t thread,
292: thread_act_t old,
293: thread_act_t new,
294: int cpu)
295: {
296: /*
297: * Switch the vm, ast and pcb context.
298: * Save FP registers if in use and set TS (task switch) bit.
299: */
300: fpu_save_context(thread);
301:
302: active_stacks[cpu] = thread->kernel_stack;
303: ast_context(new, cpu);
304:
305: PMAP_SWITCH_CONTEXT(old, new, cpu);
306: act_machine_switch_pcb(new);
307: }
308:
309: /*
310: * Switch to a new thread.
311: * Save the old thread`s kernel state or continuation,
312: * and return it.
313: */
314: thread_t
315: switch_context(
316: thread_t old,
317: void (*continuation)(void),
318: thread_t new)
319: {
320: register thread_act_t old_act = old->top_act,
321: new_act = new->top_act;
322:
323: #if MACH_RT
324: assert(old_act->kernel_loaded ||
325: active_stacks[cpu_number()] == old_act->thread->kernel_stack);
326: assert (get_preemption_level() == 1);
327: #endif
328: check_simple_locks();
329:
330: /*
331: * Save FP registers if in use.
332: */
333: fpu_save_context(old);
334:
335: #if MACH_ASSERT
336: if (watchacts & WA_SWITCH)
337: printf("\tswitch_context(old=%x con=%x new=%x)\n",
338: old, continuation, new);
339: #endif /* MACH_ASSERT */
340:
341: /*
342: * Switch address maps if need be, even if not switching tasks.
343: * (A server activation may be "borrowing" a client map.)
344: */
345: {
346: int mycpu = cpu_number();
347:
348: PMAP_SWITCH_CONTEXT(old_act, new_act, mycpu)
349: }
350:
351: /*
352: * Load the rest of the user state for the new thread
353: */
354: act_machine_switch_pcb(new_act);
355: return(Switch_context(old, continuation, new));
356: }
357:
358: void
359: pcb_module_init(void)
360: {
361: fpu_module_init();
362: iopb_init();
363: }
364:
365: void
366: pcb_init( register thread_act_t thr_act )
367: {
368: register pcb_t pcb;
369:
370: assert(thr_act->mact.pcb == (pcb_t)0);
371: pcb = thr_act->mact.pcb = &thr_act->mact.xxx_pcb;
372:
373: #if MACH_ASSERT
374: if (watchacts & WA_PCB)
375: printf("pcb_init(%x) pcb=%x\n", thr_act, pcb);
376: #endif /* MACH_ASSERT */
377:
378: /*
379: * We can't let random values leak out to the user.
380: * (however, act_create() zeroed the entire thr_act, mact, pcb)
381: * bzero((char *) pcb, sizeof *pcb);
382: */
383: simple_lock_init(&pcb->lock, ETAP_MISC_PCB);
384:
385: /*
386: * Guarantee that the bootstrapped thread will be in user
387: * mode.
388: */
389: pcb->iss.cs = USER_CS;
390: pcb->iss.ss = USER_DS;
391: pcb->iss.ds = USER_DS;
392: pcb->iss.es = USER_DS;
393: pcb->iss.fs = USER_DS;
394: pcb->iss.gs = USER_DS;
395: pcb->iss.efl = EFL_USER_SET;
396: }
397:
398: /*
399: * Adjust saved register state for thread belonging to task
400: * created with kernel_task_create().
401: */
402: void
403: pcb_user_to_kernel(
404: thread_act_t thr_act)
405: {
406: register pcb_t pcb = thr_act->mact.pcb;
407:
408: pcb->iss.cs = KERNEL_CS;
409: pcb->iss.ss = KERNEL_DS;
410: pcb->iss.ds = KERNEL_DS;
411: pcb->iss.es = KERNEL_DS;
412: pcb->iss.fs = KERNEL_DS;
413: pcb->iss.gs = CPU_DATA;
414: }
415:
416: void
417: pcb_terminate(
418: register thread_act_t thr_act)
419: {
420: register pcb_t pcb = thr_act->mact.pcb;
421:
422: assert(pcb);
423:
424: if (pcb->ims.io_tss != 0)
425: iopb_destroy(pcb->ims.io_tss);
426: if (pcb->ims.ifps != 0)
427: fp_free(pcb->ims.ifps);
428: if (pcb->ims.ldt != 0)
429: user_ldt_free(pcb->ims.ldt);
430: thr_act->mact.pcb = (pcb_t)0;
431: }
432:
433: /*
434: * pcb_collect:
435: *
436: * Attempt to free excess pcb memory.
437: */
438:
439: void
440: pcb_collect(
441: register thread_act_t thr_act)
442: {
443: /* accomplishes very little */
444: }
445:
446: /*
447: * act_machine_sv_free
448: * release saveareas associated with an act. if flag is true, release
449: * user level savearea(s) too, else don't
450: */
451: void
452: act_machine_sv_free(thread_act_t act, int flag)
453: {
454:
455: }
456:
457: /*
458: * act_machine_set_state:
459: *
460: * Set the status of the specified thread. Called with "appropriate"
461: * thread-related locks held (see act_lock_thread()), so
462: * thr_act->thread is guaranteed not to change.
463: */
464:
465: kern_return_t
466: act_machine_set_state(
467: thread_act_t thr_act,
468: thread_flavor_t flavor,
469: thread_state_t tstate,
470: mach_msg_type_number_t count)
471: {
472: int kernel_act = thr_act->kernel_loading ||
473: thr_act->kernel_loaded;
474:
475: #if MACH_ASSERT
476: if (watchacts & WA_STATE)
477: printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
478: current_act(), thr_act, flavor, tstate, count);
479: #endif /* MACH_ASSERT */
480:
481: switch (flavor) {
482: case THREAD_SYSCALL_STATE:
483: {
484: register struct thread_syscall_state *state;
485: register struct i386_saved_state *saved_state = USER_REGS(thr_act);
486:
487: state = (struct thread_syscall_state *) tstate;
488: saved_state->eax = state->eax;
489: saved_state->edx = state->edx;
490: if (kernel_act)
491: saved_state->efl = state->efl;
492: else
493: saved_state->efl = (state->efl & ~EFL_USER_CLEAR) | EFL_USER_SET;
494: saved_state->eip = state->eip;
495: saved_state->uesp = state->esp;
496: break;
497: }
498:
499: case i386_SAVED_STATE:
500: {
501: register struct i386_saved_state *state;
502: register struct i386_saved_state *saved_state;
503:
504: if (count < i386_SAVED_STATE_COUNT) {
505: return(KERN_INVALID_ARGUMENT);
506: }
507:
508: state = (struct i386_saved_state *) tstate;
509:
510: saved_state = USER_REGS(thr_act);
511:
512: /*
513: * General registers
514: */
515: saved_state->edi = state->edi;
516: saved_state->esi = state->esi;
517: saved_state->ebp = state->ebp;
518: saved_state->uesp = state->uesp;
519: saved_state->ebx = state->ebx;
520: saved_state->edx = state->edx;
521: saved_state->ecx = state->ecx;
522: saved_state->eax = state->eax;
523: saved_state->eip = state->eip;
524: if (kernel_act)
525: saved_state->efl = state->efl;
526: else
527: saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
528: | EFL_USER_SET;
529:
530: /*
531: * Segment registers. Set differently in V8086 mode.
532: */
533: if (state->efl & EFL_VM) {
534: /*
535: * Set V8086 mode segment registers.
536: */
537: saved_state->cs = state->cs & 0xffff;
538: saved_state->ss = state->ss & 0xffff;
539: saved_state->v86_segs.v86_ds = state->ds & 0xffff;
540: saved_state->v86_segs.v86_es = state->es & 0xffff;
541: saved_state->v86_segs.v86_fs = state->fs & 0xffff;
542: saved_state->v86_segs.v86_gs = state->gs & 0xffff;
543:
544: /*
545: * Zero protected mode segment registers.
546: */
547: saved_state->ds = 0;
548: saved_state->es = 0;
549: saved_state->fs = 0;
550: saved_state->gs = 0;
551:
552: if (thr_act->mact.pcb->ims.v86s.int_table) {
553: /*
554: * Hardware assist on.
555: */
556: thr_act->mact.pcb->ims.v86s.flags =
557: state->efl & (EFL_TF | EFL_IF);
558: }
559: }
560: else if (!kernel_act) {
561: /*
562: * 386 mode. Set segment registers for flat
563: * 32-bit address space.
564: */
565: saved_state->cs = USER_CS;
566: saved_state->ss = USER_DS;
567: saved_state->ds = USER_DS;
568: saved_state->es = USER_DS;
569: saved_state->fs = USER_DS;
570: saved_state->gs = USER_DS;
571: }
572: else {
573: /*
574: * User setting segment registers.
575: * Code and stack selectors have already been
576: * checked. Others will be reset by 'iret'
577: * if they are not valid.
578: */
579: saved_state->cs = state->cs;
580: saved_state->ss = state->ss;
581: saved_state->ds = state->ds;
582: saved_state->es = state->es;
583: saved_state->fs = state->fs;
584: saved_state->gs = state->gs;
585: }
586: break;
587: }
588:
589: case i386_NEW_THREAD_STATE:
590: case i386_REGS_SEGS_STATE:
591: {
592: register struct i386_new_thread_state *state;
593: register struct i386_saved_state *saved_state;
594:
595: if (count < i386_NEW_THREAD_STATE_COUNT) {
596: return(KERN_INVALID_ARGUMENT);
597: }
598:
599: if (flavor == i386_REGS_SEGS_STATE) {
600: /*
601: * Code and stack selectors must not be null,
602: * and must have user protection levels.
603: * Only the low 16 bits are valid.
604: */
605: state->cs &= 0xffff;
606: state->ss &= 0xffff;
607: state->ds &= 0xffff;
608: state->es &= 0xffff;
609: state->fs &= 0xffff;
610: state->gs &= 0xffff;
611:
612: if (!kernel_act &&
613: (state->cs == 0 || (state->cs & SEL_PL) != SEL_PL_U
614: || state->ss == 0 || (state->ss & SEL_PL) != SEL_PL_U))
615: return KERN_INVALID_ARGUMENT;
616: }
617:
618: state = (struct i386_new_thread_state *) tstate;
619:
620: saved_state = USER_REGS(thr_act);
621:
622: /*
623: * General registers
624: */
625: saved_state->edi = state->edi;
626: saved_state->esi = state->esi;
627: saved_state->ebp = state->ebp;
628: saved_state->uesp = state->uesp;
629: saved_state->ebx = state->ebx;
630: saved_state->edx = state->edx;
631: saved_state->ecx = state->ecx;
632: saved_state->eax = state->eax;
633: saved_state->eip = state->eip;
634: if (kernel_act)
635: saved_state->efl = state->efl;
636: else
637: saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
638: | EFL_USER_SET;
639:
640: /*
641: * Segment registers. Set differently in V8086 mode.
642: */
643: if (state->efl & EFL_VM) {
644: /*
645: * Set V8086 mode segment registers.
646: */
647: saved_state->cs = state->cs & 0xffff;
648: saved_state->ss = state->ss & 0xffff;
649: saved_state->v86_segs.v86_ds = state->ds & 0xffff;
650: saved_state->v86_segs.v86_es = state->es & 0xffff;
651: saved_state->v86_segs.v86_fs = state->fs & 0xffff;
652: saved_state->v86_segs.v86_gs = state->gs & 0xffff;
653:
654: /*
655: * Zero protected mode segment registers.
656: */
657: saved_state->ds = 0;
658: saved_state->es = 0;
659: saved_state->fs = 0;
660: saved_state->gs = 0;
661:
662: if (thr_act->mact.pcb->ims.v86s.int_table) {
663: /*
664: * Hardware assist on.
665: */
666: thr_act->mact.pcb->ims.v86s.flags =
667: state->efl & (EFL_TF | EFL_IF);
668: }
669: }
670: else if (flavor == i386_NEW_THREAD_STATE && !kernel_act) {
671: /*
672: * 386 mode. Set segment registers for flat
673: * 32-bit address space.
674: */
675: saved_state->cs = USER_CS;
676: saved_state->ss = USER_DS;
677: saved_state->ds = USER_DS;
678: saved_state->es = USER_DS;
679: saved_state->fs = USER_DS;
680: saved_state->gs = USER_DS;
681: }
682: else {
683: /*
684: * User setting segment registers.
685: * Code and stack selectors have already been
686: * checked. Others will be reset by 'iret'
687: * if they are not valid.
688: */
689: saved_state->cs = state->cs;
690: saved_state->ss = state->ss;
691: saved_state->ds = state->ds;
692: saved_state->es = state->es;
693: saved_state->fs = state->fs;
694: saved_state->gs = state->gs;
695: }
696: break;
697: }
698:
699: case i386_FLOAT_STATE: {
700:
701: if (count < i386_FLOAT_STATE_COUNT)
702: return(KERN_INVALID_ARGUMENT);
703:
704: return fpu_set_state(thr_act,(struct i386_float_state*)tstate);
705: }
706:
707: /*
708: * Temporary - replace by i386_io_map
709: */
710: case i386_ISA_PORT_MAP_STATE: {
711: register struct i386_isa_port_map_state *state;
712: register iopb_tss_t tss;
713:
714: if (count < i386_ISA_PORT_MAP_STATE_COUNT)
715: return(KERN_INVALID_ARGUMENT);
716:
717: break;
718: }
719:
720: case i386_V86_ASSIST_STATE:
721: {
722: register struct i386_v86_assist_state *state;
723: vm_offset_t int_table;
724: int int_count;
725:
726: if (count < i386_V86_ASSIST_STATE_COUNT)
727: return KERN_INVALID_ARGUMENT;
728:
729: state = (struct i386_v86_assist_state *) tstate;
730: int_table = state->int_table;
731: int_count = state->int_count;
732:
733: if (int_table >= VM_MAX_ADDRESS ||
734: int_table +
735: int_count * sizeof(struct v86_interrupt_table)
736: > VM_MAX_ADDRESS)
737: return KERN_INVALID_ARGUMENT;
738:
739: thr_act->mact.pcb->ims.v86s.int_table = int_table;
740: thr_act->mact.pcb->ims.v86s.int_count = int_count;
741:
742: thr_act->mact.pcb->ims.v86s.flags =
743: USER_REGS(thr_act)->efl & (EFL_TF | EFL_IF);
744: break;
745: }
746:
747: case i386_THREAD_STATE: {
748: struct i386_saved_state *saved_state;
749: i386_thread_state_t *state25;
750:
751: saved_state = USER_REGS(thr_act);
752: state25 = (i386_thread_state_t *)tstate;
753:
754: saved_state->eax = state25->eax;
755: saved_state->ebx = state25->ebx;
756: saved_state->ecx = state25->ecx;
757: saved_state->edx = state25->edx;
758: saved_state->edi = state25->edi;
759: saved_state->esi = state25->esi;
760: saved_state->ebp = state25->ebp;
761: saved_state->uesp = state25->esp;
762: saved_state->efl = (state25->eflags & ~EFL_USER_CLEAR)
763: | EFL_USER_SET;
764: saved_state->eip = state25->eip;
765: saved_state->cs = USER_CS; /* FIXME? */
766: saved_state->ss = USER_DS;
767: saved_state->ds = USER_DS;
768: saved_state->es = USER_DS;
769: saved_state->fs = USER_DS;
770: saved_state->gs = USER_DS;
771: }
772: break;
773:
774: default:
775: return(KERN_INVALID_ARGUMENT);
776: }
777:
778: return(KERN_SUCCESS);
779: }
780:
781: /*
782: * thread_getstatus:
783: *
784: * Get the status of the specified thread.
785: */
786:
787:
788: kern_return_t
789: act_machine_get_state(
790: thread_act_t thr_act,
791: thread_flavor_t flavor,
792: thread_state_t tstate,
793: mach_msg_type_number_t *count)
794: {
795: #if MACH_ASSERT
796: if (watchacts & WA_STATE)
797: printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
798: current_act(), thr_act, flavor, tstate,
799: count, (count ? *count : 0));
800: #endif /* MACH_ASSERT */
801:
802: switch (flavor) {
803:
804: case i386_SAVED_STATE:
805: {
806: register struct i386_saved_state *state;
807: register struct i386_saved_state *saved_state;
808:
809: if (*count < i386_SAVED_STATE_COUNT)
810: return(KERN_INVALID_ARGUMENT);
811:
812: state = (struct i386_saved_state *) tstate;
813: saved_state = USER_REGS(thr_act);
814:
815: /*
816: * First, copy everything:
817: */
818: *state = *saved_state;
819:
820: if (saved_state->efl & EFL_VM) {
821: /*
822: * V8086 mode.
823: */
824: state->ds = saved_state->v86_segs.v86_ds & 0xffff;
825: state->es = saved_state->v86_segs.v86_es & 0xffff;
826: state->fs = saved_state->v86_segs.v86_fs & 0xffff;
827: state->gs = saved_state->v86_segs.v86_gs & 0xffff;
828:
829: if (thr_act->mact.pcb->ims.v86s.int_table) {
830: /*
831: * Hardware assist on
832: */
833: if ((thr_act->mact.pcb->ims.v86s.flags &
834: (EFL_IF|V86_IF_PENDING)) == 0)
835: state->efl &= ~EFL_IF;
836: }
837: }
838: else {
839: /*
840: * 386 mode.
841: */
842: state->ds = saved_state->ds & 0xffff;
843: state->es = saved_state->es & 0xffff;
844: state->fs = saved_state->fs & 0xffff;
845: state->gs = saved_state->gs & 0xffff;
846: }
847: *count = i386_SAVED_STATE_COUNT;
848: break;
849: }
850:
851: case i386_NEW_THREAD_STATE:
852: case i386_REGS_SEGS_STATE:
853: {
854: register struct i386_new_thread_state *state;
855: register struct i386_saved_state *saved_state;
856:
857: if (*count < i386_NEW_THREAD_STATE_COUNT)
858: return(KERN_INVALID_ARGUMENT);
859:
860: state = (struct i386_new_thread_state *) tstate;
861: saved_state = USER_REGS(thr_act);
862:
863: /*
864: * General registers.
865: */
866: state->edi = saved_state->edi;
867: state->esi = saved_state->esi;
868: state->ebp = saved_state->ebp;
869: state->ebx = saved_state->ebx;
870: state->edx = saved_state->edx;
871: state->ecx = saved_state->ecx;
872: state->eax = saved_state->eax;
873: state->eip = saved_state->eip;
874: state->efl = saved_state->efl;
875: state->uesp = saved_state->uesp;
876:
877: state->cs = saved_state->cs;
878: state->ss = saved_state->ss;
879: if (saved_state->efl & EFL_VM) {
880: /*
881: * V8086 mode.
882: */
883: state->ds = saved_state->v86_segs.v86_ds & 0xffff;
884: state->es = saved_state->v86_segs.v86_es & 0xffff;
885: state->fs = saved_state->v86_segs.v86_fs & 0xffff;
886: state->gs = saved_state->v86_segs.v86_gs & 0xffff;
887:
888: if (thr_act->mact.pcb->ims.v86s.int_table) {
889: /*
890: * Hardware assist on
891: */
892: if ((thr_act->mact.pcb->ims.v86s.flags &
893: (EFL_IF|V86_IF_PENDING)) == 0)
894: state->efl &= ~EFL_IF;
895: }
896: }
897: else {
898: /*
899: * 386 mode.
900: */
901: state->ds = saved_state->ds & 0xffff;
902: state->es = saved_state->es & 0xffff;
903: state->fs = saved_state->fs & 0xffff;
904: state->gs = saved_state->gs & 0xffff;
905: }
906: *count = i386_NEW_THREAD_STATE_COUNT;
907: break;
908: }
909:
910: case THREAD_SYSCALL_STATE:
911: {
912: register struct thread_syscall_state *state;
913: register struct i386_saved_state *saved_state = USER_REGS(thr_act);
914:
915: state = (struct thread_syscall_state *) tstate;
916: state->eax = saved_state->eax;
917: state->edx = saved_state->edx;
918: state->efl = saved_state->efl;
919: state->eip = saved_state->eip;
920: state->esp = saved_state->uesp;
921: *count = i386_THREAD_SYSCALL_STATE_COUNT;
922: break;
923: }
924:
925: case THREAD_STATE_FLAVOR_LIST:
926: if (*count < 5)
927: return (KERN_INVALID_ARGUMENT);
928: tstate[0] = i386_NEW_THREAD_STATE;
929: tstate[1] = i386_FLOAT_STATE;
930: tstate[2] = i386_ISA_PORT_MAP_STATE;
931: tstate[3] = i386_V86_ASSIST_STATE;
932: tstate[4] = THREAD_SYSCALL_STATE;
933: *count = 5;
934: break;
935:
936: case i386_FLOAT_STATE: {
937:
938: if (*count < i386_FLOAT_STATE_COUNT)
939: return(KERN_INVALID_ARGUMENT);
940:
941: *count = i386_FLOAT_STATE_COUNT;
942: return fpu_get_state(thr_act,(struct i386_float_state *)tstate);
943: }
944:
945: /*
946: * Temporary - replace by i386_io_map
947: */
948: case i386_ISA_PORT_MAP_STATE: {
949: register struct i386_isa_port_map_state *state;
950: register iopb_tss_t tss;
951:
952: if (*count < i386_ISA_PORT_MAP_STATE_COUNT)
953: return(KERN_INVALID_ARGUMENT);
954:
955: state = (struct i386_isa_port_map_state *) tstate;
956: tss = thr_act->mact.pcb->ims.io_tss;
957:
958: if (tss == 0) {
959: int i;
960:
961: /*
962: * The thread has no ktss, so no IO permissions.
963: */
964:
965: for (i = 0; i < sizeof state->pm; i++)
966: state->pm[i] = 0xff;
967: } else {
968: /*
969: * The thread has its own ktss.
970: */
971:
972: bcopy((char *) tss->bitmap,
973: (char *) state->pm,
974: sizeof state->pm);
975: }
976:
977: *count = i386_ISA_PORT_MAP_STATE_COUNT;
978: break;
979: }
980:
981: case i386_V86_ASSIST_STATE:
982: {
983: register struct i386_v86_assist_state *state;
984:
985: if (*count < i386_V86_ASSIST_STATE_COUNT)
986: return KERN_INVALID_ARGUMENT;
987:
988: state = (struct i386_v86_assist_state *) tstate;
989: state->int_table = thr_act->mact.pcb->ims.v86s.int_table;
990: state->int_count = thr_act->mact.pcb->ims.v86s.int_count;
991:
992: *count = i386_V86_ASSIST_STATE_COUNT;
993: break;
994: }
995:
996: case i386_THREAD_STATE: {
997: struct i386_saved_state *saved_state;
998: i386_thread_state_t *state;
999:
1000: saved_state = USER_REGS(thr_act);
1001: state = (i386_thread_state_t *)tstate;
1002:
1003: state->eax = saved_state->eax;
1004: state->ebx = saved_state->ebx;
1005: state->ecx = saved_state->ecx;
1006: state->edx = saved_state->edx;
1007: state->edi = saved_state->edi;
1008: state->esi = saved_state->esi;
1009: state->ebp = saved_state->ebp;
1010: state->esp = saved_state->uesp;
1011: state->eflags = saved_state->efl;
1012: state->eip = saved_state->eip;
1013: state->cs = saved_state->cs;
1014: state->ss = saved_state->ss;
1015: state->ds = saved_state->ds;
1016: state->es = saved_state->es;
1017: state->fs = saved_state->fs;
1018: state->gs = saved_state->gs;
1019: break;
1020: }
1021:
1022: default:
1023: return(KERN_INVALID_ARGUMENT);
1024: }
1025:
1026: return(KERN_SUCCESS);
1027: }
1028:
1029: /*
1030: * Alter the thread`s state so that a following thread_exception_return
1031: * will make the thread return 'retval' from a syscall.
1032: */
1033: void
1034: thread_set_syscall_return(
1035: thread_t thread,
1036: kern_return_t retval)
1037: {
1038: thread->top_act->mact.pcb->iss.eax = retval;
1039: }
1040:
1041: /*
1042: * Initialize the machine-dependent state for a new thread.
1043: */
1044: kern_return_t
1045: thread_machine_create(thread_t thread, thread_act_t thr_act, void (*start_pos)(void))
1046: {
1047: MachineThrAct_t mact = &thr_act->mact;
1048:
1049: #if MACH_ASSERT
1050: if (watchacts & WA_PCB)
1051: printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n",
1052: thread, thr_act, start_pos);
1053: #endif /* MACH_ASSERT */
1054:
1055: assert(thread != NULL);
1056: assert(thr_act != NULL);
1057:
1058: /*
1059: * Allocate a kernel stack per shuttle
1060: */
1061: thread->kernel_stack = (int)stack_alloc(thread,start_pos);
1062: assert(thread->kernel_stack != 0);
1063:
1064: /*
1065: * Point top of kernel stack to user`s registers.
1066: */
1067: STACK_IEL(thread->kernel_stack)->saved_state = &mact->pcb->iss;
1068:
1069: /*
1070: * Utah code fiddles with pcb here - (we don't need to)
1071: */
1072: return(KERN_SUCCESS);
1073: }
1074:
1075: /*
1076: * Machine-dependent cleanup prior to destroying a thread
1077: */
1078: void
1079: thread_machine_destroy( thread_t thread )
1080: {
1081: spl_t s;
1082:
1083: assert(thread->kernel_stack != 0);
1084:
1085: s = splsched();
1086: stack_free(thread);
1087: splx(s);
1088: }
1089:
1090: /*
1091: * This is used to set the current thr_act/thread
1092: * when starting up a new processor
1093: */
1094: void
1095: thread_machine_set_current( thread_t thread )
1096: {
1097: register int my_cpu;
1098:
1099: mp_disable_preemption();
1100: my_cpu = cpu_number();
1101:
1102: cpu_data[my_cpu].active_thread = thread;
1103: active_kloaded[my_cpu] =
1104: thread->top_act->kernel_loaded ? thread->top_act : THR_ACT_NULL;
1105:
1106: mp_enable_preemption();
1107: }
1108:
1109:
1110: /*
1111: * Pool of kernel activations.
1112: */
1113:
1114: void act_machine_init()
1115: {
1116: int i;
1117: thread_act_t thr_act;
1118:
1119: #if MACH_ASSERT
1120: if (watchacts & WA_PCB)
1121: printf("act_machine_init()\n");
1122: #endif /* MACH_ASSERT */
1123:
1124: /* Good to verify this once */
1125: assert( THREAD_MACHINE_STATE_MAX <= THREAD_STATE_MAX );
1126:
1127: /*
1128: * If we start using kernel activations,
1129: * would normally create kernel_thread_pool here,
1130: * populating it from the act_zone
1131: */
1132: }
1133:
1134: kern_return_t
1135: act_machine_create(task_t task, thread_act_t thr_act)
1136: {
1137: MachineThrAct_t mact = &thr_act->mact;
1138: pcb_t pcb;
1139:
1140: #if MACH_ASSERT
1141: if (watchacts & WA_PCB)
1142: printf("act_machine_create(task=%x,thr_act=%x) pcb=%x\n",
1143: task,thr_act, &mact->xxx_pcb);
1144: #endif /* MACH_ASSERT */
1145:
1146: /*
1147: * Clear & Init the pcb (sets up user-mode s regs)
1148: */
1149: pcb_init(thr_act);
1150:
1151: return KERN_SUCCESS;
1152: }
1153:
1154: void
1155: act_machine_destroy(thread_act_t thr_act)
1156: {
1157:
1158: #if MACH_ASSERT
1159: if (watchacts & WA_PCB)
1160: printf("act_machine_destroy(0x%x)\n", thr_act);
1161: #endif /* MACH_ASSERT */
1162:
1163: pcb_terminate(thr_act);
1164: }
1165:
1166: void
1167: act_machine_return(int code)
1168: {
1169: thread_act_t thr_act = current_act();
1170: thread_act_t cur_act;
1171: thread_t cur_thread = current_thread();
1172: vm_offset_t pcb_stack;
1173: unsigned int uesp, ueip;
1174: struct ipc_port *iplock;
1175:
1176: #if MACH_ASSERT
1177: /*
1178: * We don't go through the locking dance here needed to
1179: * acquire thr_act->thread safely.
1180: */
1181:
1182: if (watchacts & WA_EXIT)
1183: printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n",
1184: code, thr_act, thr_act->ref_count,
1185: thr_act->thread, thr_act->thread
1186: ? thr_act->thread->ref_count : 0);
1187: #endif /* MACH_ASSERT */
1188:
1189: /*
1190: * This code is called with nothing locked.
1191: * It also returns with nothing locked, if it returns.
1192: *
1193: * This routine terminates the current thread activation.
1194: * If this is the only activation associated with its
1195: * thread shuttle, then the entire thread (shuttle plus
1196: * activation) is terminated.
1197: */
1198: assert( code == KERN_TERMINATED );
1199: assert( thr_act );
1200:
1201: #ifdef CALLOUT_RPC_MODEL
1202:
1203: /*
1204: * JMM - RPC is not going to be done with a callout/direct-
1205: * stack manipulation mechanism. Instead we will return/
1206: * unwind normally as if from a continuation.
1207: */
1208: act_lock_thread(thr_act);
1209: iplock = thr_act->pool_port; /* remember for unlock call */
1210:
1211: if (thr_act->thread->top_act != thr_act) {
1212: /*
1213: * this is not the top activation;
1214: * if possible, we should clone the shuttle so that
1215: * both the root RPC-chain and the soon-to-be-orphaned
1216: * RPC-chain have shuttles
1217: *
1218: * JMM - Cloning shuttles isn't the right approach. We
1219: * need to alert the higher up activations to return our
1220: * shuttle (because scheduling attributes may TRUELY be
1221: * unique and not cloneable.
1222: */
1223: act_unlock_thread(thr_act);
1224: panic("act_machine_return: ORPHAN CASE NOT YET IMPLEMENTED");
1225: }
1226:
1227: if (thr_act->lower != THR_ACT_NULL) {
1228: /* send it an appropriate return code */
1229: thr_act->lower->alerts |= SERVER_TERMINATED;
1230: install_special_handler(thr_act->lower);
1231:
1232: /* Return to previous act with error code */
1233: act_locked_act_reference(thr_act); /* keep it around */
1234: act_switch_swapcheck(cur_thread, (ipc_port_t)0);
1235: (void) switch_act(THR_ACT_NULL);
1236: /* assert(thr_act->ref_count == 0); */ /* XXX */
1237: cur_act = cur_thread->top_act;
1238: MACH_RPC_RET(cur_act) = KERN_RPC_SERVER_TERMINATED;
1239:
1240: machine_kernel_stack_init(cur_thread,
1241: (void (*)(void)) mach_rpc_return_error);
1242: /*
1243: * The following unlocks must be done separately since fields
1244: * used by `act_unlock_thread()' have been cleared, meaning
1245: * that it would not release all of the appropriate locks.
1246: */
1247: rpc_unlock(cur_thread);
1248: if (iplock) ip_unlock(iplock); /* must be done separately */
1249: act_unlock(thr_act);
1250: act_deallocate(thr_act); /* free it */
1251: Load_context(cur_thread);
1252: /*NOTREACHED*/
1253:
1254: panic("act_machine_return: TALKING ZOMBIE! (2)");
1255: }
1256: act_unlock_thread(thr_act);
1257:
1258: #endif /* CALLOUT_RPC_MODEL */
1259:
1260: /* This is the only activation attached to the shuttle... */
1261: /* terminate the entire thread (shuttle plus activation) */
1262:
1263: assert(thr_act->thread->top_act == thr_act);
1264: thread_terminate_self();
1265:
1266: /*NOTREACHED*/
1267:
1268: panic("act_machine_return: TALKING ZOMBIE! (1)");
1269: }
1270:
1271:
1272: /*
1273: * Perform machine-dependent per-thread initializations
1274: */
1275: void
1276: thread_machine_init(void)
1277: {
1278: pcb_module_init();
1279: }
1280:
1281: /*
1282: * Some routines for debugging activation code
1283: */
1284: static void dump_handlers(thread_act_t);
1285: void dump_regs(thread_act_t);
1286:
1287: static void
1288: dump_handlers(thread_act_t thr_act)
1289: {
1290: ReturnHandler *rhp = thr_act->handlers;
1291: int counter = 0;
1292:
1293: printf("\t");
1294: while (rhp) {
1295: if (rhp == &thr_act->special_handler){
1296: if (rhp->next)
1297: printf("[NON-Zero next ptr(%x)]", rhp->next);
1298: printf("special_handler()->");
1299: break;
1300: }
1301: printf("hdlr_%d(%x)->",counter,rhp->handler);
1302: rhp = rhp->next;
1303: if (++counter > 32) {
1304: printf("Aborting: HUGE handler chain\n");
1305: break;
1306: }
1307: }
1308: printf("HLDR_NULL\n");
1309: }
1310:
1311: void
1312: dump_regs(thread_act_t thr_act)
1313: {
1314: if (thr_act->mact.pcb) {
1315: register struct i386_saved_state *ssp = USER_REGS(thr_act);
1316: /* Print out user register state */
1317: printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n",
1318: ssp->edi, ssp->esi, ssp->ebp, ssp->ebx, ssp->edx);
1319: printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n",
1320: ssp->ecx, ssp->eax, ssp->eip, ssp->efl, ssp->uesp);
1321: printf("\t\tcs=%x ss=%x\n", ssp->cs, ssp->ss);
1322: }
1323: }
1324:
1325: int
1326: dump_act(thread_act_t thr_act)
1327: {
1328: if (!thr_act)
1329: return(0);
1330:
1331: printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n",
1332: thr_act, thr_act->ref_count,
1333: thr_act->thread, thr_act->thread ? thr_act->thread->ref_count:0,
1334: thr_act->task, thr_act->task ? thr_act->task->ref_count : 0);
1335:
1336: if (thr_act->pool_port) {
1337: thread_pool_t actpp = &thr_act->pool_port->ip_thread_pool;
1338: printf("\tpool(acts_p=%x, waiting=%d) pool_next %x\n",
1339: actpp->thr_acts, actpp->waiting, thr_act->thread_pool_next);
1340: }else
1341: printf("\tno thread_pool\n");
1342:
1343: printf("\talerts=%x mask=%x susp=%d user_stop=%d active=%x ast=%x\n",
1344: thr_act->alerts, thr_act->alert_mask,
1345: thr_act->suspend_count, thr_act->user_stop_count,
1346: thr_act->active, thr_act->ast);
1347: printf("\thi=%x lo=%x\n", thr_act->higher, thr_act->lower);
1348: printf("\tpcb=%x, ustk=%x\n",
1349: thr_act->mact.pcb, thr_act->user_stack);
1350:
1351: if (thr_act->thread && thr_act->thread->kernel_stack) {
1352: vm_offset_t stack = thr_act->thread->kernel_stack;
1353:
1354: printf("\tk_stk %x eip %x ebx %x esp %x iss %x\n",
1355: stack, STACK_IKS(stack)->k_eip, STACK_IKS(stack)->k_ebx,
1356: STACK_IKS(stack)->k_esp, STACK_IEL(stack)->saved_state);
1357: }
1358:
1359: dump_handlers(thr_act);
1360: dump_regs(thr_act);
1361: return((int)thr_act);
1362: }
1363: unsigned int
1364: get_useraddr()
1365: {
1366:
1367: thread_act_t thr_act = current_act();
1368:
1369: if (thr_act->mact.pcb)
1370: return(thr_act->mact.pcb->iss.eip);
1371: else
1372: return(0);
1373:
1374: }
1375:
1376: void
1377: thread_swapin_mach_alloc(thread_t thread)
1378: {
1379:
1380: /* 386 does not have saveareas */
1381:
1382: }
1383: /*
1384: * detach and return a kernel stack from a thread
1385: */
1386:
1387: vm_offset_t
1388: stack_detach(thread_t thread)
1389: {
1390: vm_offset_t stack;
1391:
1392: #ifdef KDEBUG
1393: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_DETACH),
1394: thread, thread->priority,
1395: thread->sched_pri, 0,
1396: 0);
1397: #endif
1398:
1399: stack = thread->kernel_stack;
1400: thread->kernel_stack = 0;
1401: return(stack);
1402: }
1403:
1404: /*
1405: * attach a kernel stack to a thread and initialize it
1406: */
1407:
1408: void
1409: stack_attach(struct thread_shuttle *thread,
1410: vm_offset_t stack,
1411: void (*continuation)(void))
1412: {
1413: struct i386_kernel_state *statep;
1414: thread_act_t thr_act;
1415:
1416: #ifdef KDEBUG
1417: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH),
1418: thread, thread->priority,
1419: thread->sched_pri, continuation,
1420: 0);
1421: #endif
1422:
1423: assert(stack);
1424: statep = STACK_IKS(stack);
1425: thread->kernel_stack = stack;
1426:
1427: statep->k_eip = (unsigned long) Thread_continue;
1428: statep->k_ebx = (unsigned long) continuation;
1429: statep->k_esp = (unsigned long) STACK_IEL(stack);
1430:
1431: STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss;
1432:
1433: return;
1434: }
1435:
1436: /*
1437: * move a stack from old to new thread
1438: */
1439:
1440: void
1441: stack_handoff(thread_t old,
1442: thread_t new)
1443: {
1444:
1445: vm_offset_t stack;
1446: pmap_t new_pmap;
1447:
1448: #ifdef KDEBUG
1449: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF),
1450: thread, thread->priority,
1451: thread->sched_pri, continuation,
1452: 0);
1453: #endif
1454:
1455: assert(new->top_act);
1456: assert(old->top_act);
1457:
1458: stack = stack_detach(old);
1459: stack_attach(new, stack, 0);
1460:
1461: new_pmap = new->top_act->task->map->pmap;
1462: if (old->top_act->task->map->pmap != new_pmap)
1463: PMAP_ACTIVATE_MAP(new->top_act->task->map, cpu_number());
1464:
1465: thread_machine_set_current(new);
1466:
1467: active_stacks[cpu_number()] = new->kernel_stack;
1468:
1469: return;
1470: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.