+ int args[machdep_call_count];
+ int trapno;
+ int nargs;
+ const machdep_call_t *entry;
+ x86_saved_state32_t *regs;
+
+ assert(is_saved_state32(state));
+ regs = saved_state32(state);
+
+ trapno = regs->eax;
+#if DEBUG_TRACE
+ kprintf("machdep_syscall(0x%08x) code=%d\n", regs, trapno);
+#endif
+
+ DEBUG_KPRINT_SYSCALL_MDEP(
+ "machdep_syscall: trapno=%d\n", trapno);
+
+ if (trapno < 0 || trapno >= machdep_call_count) {
+ regs->eax = (unsigned int)kern_invalid(NULL);
+
+ thread_exception_return();
+ /* NOTREACHED */
+ }
+ entry = &machdep_call_table[trapno];
+ nargs = entry->nargs;
+
+ if (nargs != 0) {
+ if (copyin((user_addr_t) regs->uesp + sizeof(int),
+ (char *) args, (nargs * sizeof(int)))) {
+ regs->eax = KERN_INVALID_ADDRESS;
+
+ thread_exception_return();
+ /* NOTREACHED */
+ }
+ }
+ switch (nargs) {
+ case 0:
+ regs->eax = (*entry->routine.args_0)();
+ break;
+ case 1:
+ regs->eax = (*entry->routine.args_1)(args[0]);
+ break;
+ case 2:
+ regs->eax = (*entry->routine.args_2)(args[0], args[1]);
+ break;
+ case 3:
+ if (!entry->bsd_style) {
+ regs->eax = (*entry->routine.args_3)(args[0], args[1], args[2]);
+ } else {
+ int error;
+ uint32_t rval;
+
+ error = (*entry->routine.args_bsd_3)(&rval, args[0], args[1], args[2]);
+ if (error) {
+ regs->eax = error;
+ regs->efl |= EFL_CF; /* carry bit */
+ } else {
+ regs->eax = rval;
+ regs->efl &= ~EFL_CF;
+ }
+ }
+ break;
+ case 4:
+ regs->eax = (*entry->routine.args_4)(args[0], args[1], args[2], args[3]);
+ break;
+
+ default:
+ panic("machdep_syscall: too many args");
+ }
+
+ DEBUG_KPRINT_SYSCALL_MDEP("machdep_syscall: retval=%u\n", regs->eax);
+
+#if DEBUG || DEVELOPMENT
+ kern_allocation_name_t
+ prior __assert_only = thread_get_kernel_state(current_thread())->allocation_name;
+ assertf(prior == NULL, "thread_set_allocation_name(\"%s\") not cleared", kern_allocation_get_name(prior));
+#endif /* DEBUG || DEVELOPMENT */
+
+ throttle_lowpri_io(1);
+
+ thread_exception_return();
+ /* NOTREACHED */