|
|
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: #ifdef MACH_BSD
23: #include <cpus.h>
24: #include <mach_rt.h>
25: #include <mach_debug.h>
26: #include <mach_ldebug.h>
27:
28: #include <mach/kern_return.h>
29: #include <mach/thread_status.h>
30: #include <mach/vm_param.h>
31: #include <mach/rpc.h>
32:
33: #include <kern/counters.h>
34: #include <kern/cpu_data.h>
35: #include <kern/mach_param.h>
36: #include <kern/task.h>
37: #include <kern/thread.h>
38: #include <kern/thread_swap.h>
39: #include <kern/sched_prim.h>
40: #include <kern/misc_protos.h>
41: #include <kern/assert.h>
42: #include <kern/spl.h>
43: #include <ipc/ipc_port.h>
44: #include <vm/vm_kern.h>
45: #include <vm/pmap.h>
46:
47: #include <i386/thread.h>
48: #include <i386/eflags.h>
49: #include <i386/proc_reg.h>
50: #include <i386/seg.h>
51: #include <i386/tss.h>
52: #include <i386/user_ldt.h>
53: #include <i386/fpu.h>
54: #include <i386/iopb_entries.h>
55: #include <i386/machdep_call.h>
56:
57: #define USRSTACK 0xc0000000
58:
59: kern_return_t
60: thread_userstack(
61: thread_t,
62: int,
63: thread_state_t,
64: unsigned int,
65: vm_offset_t *
66: );
67:
68: kern_return_t
69: thread_entrypoint(
70: thread_t,
71: int,
72: thread_state_t,
73: unsigned int,
74: vm_offset_t *
75: );
76:
77: struct i386_saved_state *
78: get_user_regs(
79: thread_act_t);
80:
81: void
82: act_thread_dup(
83: thread_act_t,
84: thread_act_t
85: );
86:
87: unsigned int get_msr_exportmask(void);
88:
89: unsigned int get_msr_nbits(void);
90:
91: unsigned int get_msr_rbits(void);
92:
93: /*
94: * thread_userstack:
95: *
96: * Return the user stack pointer from the machine
97: * dependent thread state info.
98: */
99: kern_return_t
100: thread_userstack(
101: thread_t thread,
102: int flavor,
103: thread_state_t tstate,
104: unsigned int count,
105: vm_offset_t *user_stack
106: )
107: {
108: struct i386_saved_state *state;
109: i386_thread_state_t *state25;
110: vm_offset_t uesp;
111:
112: /*
113: * Set a default.
114: */
115: if (*user_stack == 0)
116: *user_stack = USRSTACK;
117:
118: switch (flavor) {
119: case i386_THREAD_STATE: /* FIXME */
120: state25 = (i386_thread_state_t *) tstate;
121: *user_stack = state25->esp ? state25->esp : USRSTACK;
122: break;
123:
124: case i386_NEW_THREAD_STATE:
125: if (count < i386_NEW_THREAD_STATE_COUNT)
126: return (KERN_INVALID_ARGUMENT);
127: else {
128: state = (struct i386_saved_state *) tstate;
129: uesp = state->uesp;
130: }
131:
132: /*
133: * If a valid user stack is specified, use it.
134: */
135: *user_stack = uesp ? uesp : USRSTACK;
136: break;
137: default :
138: return (KERN_INVALID_ARGUMENT);
139: }
140:
141: return (KERN_SUCCESS);
142: }
143:
144: kern_return_t
145: thread_entrypoint(
146: thread_t thread,
147: int flavor,
148: thread_state_t tstate,
149: unsigned int count,
150: vm_offset_t *entry_point
151: )
152: {
153: struct i386_saved_state *state;
154: i386_thread_state_t *state25;
155:
156: /*
157: * Set a default.
158: */
159: if (*entry_point == 0)
160: *entry_point = VM_MIN_ADDRESS;
161:
162: switch (flavor) {
163: case i386_THREAD_STATE:
164: state25 = (i386_thread_state_t *) tstate;
165: *entry_point = state25->eip ? state25->eip: VM_MIN_ADDRESS;
166: break;
167:
168: case i386_NEW_THREAD_STATE:
169: if (count < i386_THREAD_STATE_COUNT)
170: return (KERN_INVALID_ARGUMENT);
171: else {
172: state = (struct i386_saved_state *) tstate;
173:
174: /*
175: * If a valid entry point is specified, use it.
176: */
177: *entry_point = state->eip ? state->eip: VM_MIN_ADDRESS;
178: }
179: break;
180: }
181:
182: return (KERN_SUCCESS);
183: }
184:
185: struct i386_saved_state *
186: get_user_regs(thread_act_t th)
187: {
188: if (th->mact.pcb)
189: return(USER_REGS(th));
190: else {
191: printf("[get_user_regs: thread does not have pcb]");
192: return NULL;
193: }
194: }
195:
196: /*
197: * Duplicate parent state in child
198: * for U**X fork.
199: */
200: void
201: act_thread_dup(
202: thread_act_t parent,
203: thread_act_t child
204: )
205: {
206: struct i386_saved_state *parent_state, *child_state;
207: struct i386_machine_state *ims;
208: struct i386_float_state floatregs;
209:
210: #ifdef XXX
211: /* Save the FPU state */
212: if ((pcb_t)(per_proc_info[cpu_number()].fpu_pcb) == parent->mact.pcb) {
213: fp_state_save(parent);
214: }
215: #endif
216:
217: if (child->mact.pcb == NULL
218: || parent->mact.pcb == NULL) {
219: panic("[thread_dup, child (%x) or parent (%x) is NULL!]",
220: child->mact.pcb, parent->mact.pcb);
221: return;
222: }
223:
224: /* Copy over the i386_saved_state registers */
225: child->mact.pcb->iss = parent->mact.pcb->iss;
226:
227: /* Check to see if parent is using floating point
228: * and if so, copy the registers to the child
229: * FIXME - make sure this works.
230: */
231:
232: if (parent->mact.pcb->ims.ifps) {
233: if (fpu_get_state(parent, &floatregs) == KERN_SUCCESS)
234: fpu_set_state(child, &floatregs);
235: }
236:
237: /* FIXME - should a user specified LDT, TSS and V86 info
238: * be duplicated as well?? - probably not.
239: */
240: }
241:
242: /*
243: * FIXME - thread_set_child
244: */
245:
246: void thread_set_child(thread_act_t child, int pid);
247: void
248: thread_set_child(thread_act_t child, int pid)
249: {
250: child->mact.pcb->iss.eax = pid;
251: child->mact.pcb->iss.edx = 1;
252: child->mact.pcb->iss.efl &= ~EFL_CF;
253: }
254:
255:
256:
257: /*
258: * Move pages from one kernel virtual address to another.
259: * Both addresses are assumed to reside in the Sysmap,
260: * and size must be a multiple of the page size.
261: */
262: void
263: pagemove(
264: register caddr_t from,
265: register caddr_t to,
266: int size)
267: {
268: pmap_movepage((unsigned long)from, (unsigned long)to, (vm_size_t)size);
269: }
270:
271: /*
272: * System Call handling code
273: */
274:
275: #define ERESTART -1 /* restart syscall */
276: #define EJUSTRETURN -2 /* don't modify regs, just return */
277:
278: struct sysent { /* system call table */
279: unsigned short sy_narg; /* number of args */
280: unsigned short sy_parallel; /* can execute in parallel */
281: unsigned long (*sy_call)(void *, void *, int *); /* implementing function */
282: };
283:
284: extern struct sysent sysent[];
285:
286: void *get_bsdtask_info(
287: task_t);
288:
289: int set_bsduthreadargs (thread_act_t, struct i386_saved_state *, void *);
290:
291: void * get_bsduthreadarg(thread_act_t);
292:
293: void unix_syscall(struct i386_saved_state *);
294:
295: void
296: unix_syscall_return(int error)
297: {
298: panic("unix_syscall_return not implemented yet!!");
299: }
300:
301:
302: void
303: unix_syscall(struct i386_saved_state *regs)
304: {
305: thread_act_t thread;
306: void *p, *vt;
307: unsigned short code;
308: struct sysent *callp;
309: int nargs, error, rval[2];
310: vm_offset_t params;
311: extern int nsysent;
312:
313: thread = current_act();
314: p = get_bsdtask_info(current_task());
315:
316: //printf("[scall : eax %x]", regs->eax);
317: code = regs->eax;
318: params = (vm_offset_t) ((caddr_t)regs->uesp + sizeof (int));
319: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
320: if (callp == sysent) {
321: code = fuword(params);
322: params += sizeof (int);
323: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
324: }
325:
326: vt = get_bsduthreadarg(thread);
327:
328: if ((nargs = (callp->sy_narg * sizeof (int))) &&
329: (error = copyin((char *) params, (char *)vt , nargs)) != 0) {
330: regs->eax = error;
331: regs->efl |= EFL_CF;
332: thread_exception_return();
333: /* NOTREACHED */
334: }
335:
336: rval[0] = 0;
337: rval[1] = regs->edx;
338:
339: set_bsduthreadargs(thread, regs, NULL);
340:
341: if (callp->sy_narg > 8)
342: panic("unix_syscall max arg count exceeded (%d)", callp->sy_narg);
343:
344:
345: error = (*(callp->sy_call))(p, (void *) vt, rval);
346:
347: if (error == ERESTART) {
348: regs->eip -= 7;
349: }
350: else if (error != EJUSTRETURN) {
351: if (error) {
352: regs->eax = error;
353: regs->efl |= EFL_CF; /* carry bit */
354: } else { /* (not error) */
355: regs->eax = rval[0];
356: regs->edx = rval[1];
357: regs->efl &= ~EFL_CF;
358: }
359: }
360:
361: thread_exception_return();
362: /* NOTREACHED */
363: }
364:
365:
366: void
367: machdep_syscall( struct i386_saved_state *regs)
368: {
369: int trapno, nargs;
370: machdep_call_t *entry;
371: thread_t thread;
372:
373: trapno = regs->eax;
374: if (trapno < 0 || trapno >= machdep_call_count) {
375: regs->eax = (unsigned int)kern_invalid();
376:
377: thread_exception_return();
378: /* NOTREACHED */
379: }
380:
381: entry = &machdep_call_table[trapno];
382: nargs = entry->nargs;
383:
384: if (nargs > 0) {
385: int args[nargs];
386:
387: if (copyin((char *) regs->uesp + sizeof (int),
388: (char *) args,
389: nargs * sizeof (int))) {
390:
391: regs->eax = KERN_INVALID_ADDRESS;
392:
393: thread_exception_return();
394: /* NOTREACHED */
395: }
396:
397: asm volatile("
398: 1:
399: mov (%2),%%eax;
400: pushl %%eax;
401: sub $4,%2;
402: dec %1;
403: jne 1b;
404: mov %3,%%eax;
405: call *%%eax;
406: mov %%eax,%0"
407:
408: : "=r" (regs->eax)
409: : "r" (nargs),
410: "r" (&args[nargs - 1]),
411: "g" (entry->routine)
412: : "ax", "cx", "dx", "sp");
413: }
414: else
415: regs->eax = (unsigned int)(*entry->routine)();
416:
417: (void) thread_set_funneled(FALSE);
418:
419: thread_exception_return();
420: /* NOTREACHED */
421: }
422:
423:
424: kern_return_t
425: thread_set_cthread_self(int self)
426: {
427: current_act()->mact.pcb->cthread_self = (unsigned int)self;
428:
429: return (KERN_SUCCESS);
430: }
431:
432: kern_return_t
433: thread_get_cthread_self(void)
434: {
435: return ((kern_return_t)current_act()->mact.pcb->cthread_self);
436: }
437:
438: void
439: mach25_syscall(struct i386_saved_state *regs)
440: {
441: printf("*** Atttempt to execute a Mach 2.5 system call at EIP=%x EAX=%x(%d)\n",
442: regs->eip, regs->eax, -regs->eax);
443: panic("FIXME!");
444: }
445:
446: #endif /* MACH_BSD */
447:
448: #undef current_thread
449: thread_act_t
450: current_thread(void)
451: {
452: return(current_thread_fast());
453: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.