2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach_debug.h>
30 #include <mach_ldebug.h>
32 #include <mach/kern_return.h>
33 #include <mach/mach_traps.h>
34 #include <mach/thread_status.h>
35 #include <mach/vm_param.h>
37 #include <kern/counters.h>
38 #include <kern/cpu_data.h>
39 #include <kern/mach_param.h>
40 #include <kern/task.h>
41 #include <kern/thread.h>
42 #include <kern/sched_prim.h>
43 #include <kern/misc_protos.h>
44 #include <kern/assert.h>
45 #include <kern/debug.h>
47 #include <kern/syscall_sw.h>
48 #include <ipc/ipc_port.h>
49 #include <vm/vm_kern.h>
52 #include <i386/cpu_number.h>
53 #include <i386/eflags.h>
54 #include <i386/proc_reg.h>
56 #include <i386/user_ldt.h>
58 #include <i386/machdep_call.h>
59 #include <i386/vmparam.h>
60 #include <i386/mp_desc.h>
61 #include <i386/misc_protos.h>
62 #include <i386/thread.h>
63 #include <i386/trap.h>
65 #include <mach/i386/syscall_sw.h>
66 #include <sys/syscall.h>
67 #include <sys/kdebug.h>
68 #include <sys/errno.h>
69 #include <../bsd/sys/sysent.h>
72 extern void mach_kauth_cred_uthread_update(void);
73 extern void throttle_lowpri_io(int);
77 #include <security/mac_mach_internal.h>
80 void * find_user_regs(thread_t
);
82 unsigned int get_msr_exportmask(void);
84 unsigned int get_msr_nbits(void);
86 unsigned int get_msr_rbits(void);
91 * Return the user stack pointer from the machine
92 * dependent thread state info.
96 __unused thread_t thread
,
98 thread_state_t tstate
,
100 mach_vm_offset_t
*user_stack
,
102 __unused boolean_t is64bit
110 case x86_THREAD_STATE32
:
112 x86_thread_state32_t
*state25
;
114 if (__improbable(count
!= x86_THREAD_STATE32_COUNT
)) {
115 return KERN_INVALID_ARGUMENT
;
118 state25
= (x86_thread_state32_t
*) tstate
;
121 *user_stack
= state25
->esp
;
126 *user_stack
= VM_USRSTACK32
;
134 case x86_THREAD_FULL_STATE64
:
136 x86_thread_full_state64_t
*state25
;
138 if (__improbable(count
!= x86_THREAD_FULL_STATE64_COUNT
)) {
139 return KERN_INVALID_ARGUMENT
;
142 state25
= (x86_thread_full_state64_t
*) tstate
;
144 if (state25
->ss64
.rsp
) {
145 *user_stack
= state25
->ss64
.rsp
;
150 *user_stack
= VM_USRSTACK64
;
158 case x86_THREAD_STATE64
:
160 x86_thread_state64_t
*state25
;
162 if (__improbable(count
!= x86_THREAD_STATE64_COUNT
)) {
163 return KERN_INVALID_ARGUMENT
;
166 state25
= (x86_thread_state64_t
*) tstate
;
169 *user_stack
= state25
->rsp
;
174 *user_stack
= VM_USRSTACK64
;
183 return KERN_INVALID_ARGUMENT
;
190 * thread_userstackdefault:
192 * Return the default stack location for the
193 * thread, if otherwise unknown.
196 thread_userstackdefault(
197 mach_vm_offset_t
*default_user_stack
,
201 *default_user_stack
= VM_USRSTACK64
;
203 *default_user_stack
= VM_USRSTACK32
;
210 __unused thread_t thread
,
212 thread_state_t tstate
,
214 mach_vm_offset_t
*entry_point
220 if (*entry_point
== 0) {
221 *entry_point
= VM_MIN_ADDRESS
;
225 case x86_THREAD_STATE32
:
227 x86_thread_state32_t
*state25
;
229 if (count
!= x86_THREAD_STATE32_COUNT
) {
230 return KERN_INVALID_ARGUMENT
;
233 state25
= (i386_thread_state_t
*) tstate
;
234 *entry_point
= state25
->eip
? state25
->eip
: VM_MIN_ADDRESS
;
238 case x86_THREAD_STATE64
:
240 x86_thread_state64_t
*state25
;
242 if (count
!= x86_THREAD_STATE64_COUNT
) {
243 return KERN_INVALID_ARGUMENT
;
246 state25
= (x86_thread_state64_t
*) tstate
;
247 *entry_point
= state25
->rip
? state25
->rip
: VM_MIN_ADDRESS64
;
255 * FIXME - thread_set_child
258 void thread_set_child(thread_t child
, int pid
);
260 thread_set_child(thread_t child
, int pid
)
262 pal_register_cache_state(child
, DIRTY
);
264 if (thread_is_64bit_addr(child
)) {
265 x86_saved_state64_t
*iss64
;
267 iss64
= USER_REGS64(child
);
271 iss64
->isf
.rflags
&= ~EFL_CF
;
273 x86_saved_state32_t
*iss32
;
275 iss32
= USER_REGS32(child
);
279 iss32
->efl
&= ~EFL_CF
;
286 * System Call handling code
289 extern long fuword(vm_offset_t
);
291 __attribute__((noreturn
))
293 machdep_syscall(x86_saved_state_t
*state
)
295 int args
[machdep_call_count
];
298 const machdep_call_t
*entry
;
299 x86_saved_state32_t
*regs
;
301 assert(is_saved_state32(state
));
302 regs
= saved_state32(state
);
306 kprintf("machdep_syscall(0x%08x) code=%d\n", regs
, trapno
);
309 DEBUG_KPRINT_SYSCALL_MDEP(
310 "machdep_syscall: trapno=%d\n", trapno
);
312 if (trapno
< 0 || trapno
>= machdep_call_count
) {
313 regs
->eax
= (unsigned int)kern_invalid(NULL
);
315 thread_exception_return();
318 entry
= &machdep_call_table
[trapno
];
319 nargs
= entry
->nargs
;
322 if (copyin((user_addr_t
) regs
->uesp
+ sizeof(int),
323 (char *) args
, (nargs
* sizeof(int)))) {
324 regs
->eax
= KERN_INVALID_ADDRESS
;
326 thread_exception_return();
332 regs
->eax
= (*entry
->routine
.args_0
)();
335 regs
->eax
= (*entry
->routine
.args_1
)(args
[0]);
338 regs
->eax
= (*entry
->routine
.args_2
)(args
[0], args
[1]);
341 if (!entry
->bsd_style
) {
342 regs
->eax
= (*entry
->routine
.args_3
)(args
[0], args
[1], args
[2]);
347 error
= (*entry
->routine
.args_bsd_3
)(&rval
, args
[0], args
[1], args
[2]);
350 regs
->efl
|= EFL_CF
; /* carry bit */
353 regs
->efl
&= ~EFL_CF
;
358 regs
->eax
= (*entry
->routine
.args_4
)(args
[0], args
[1], args
[2], args
[3]);
362 panic("machdep_syscall: too many args");
365 DEBUG_KPRINT_SYSCALL_MDEP("machdep_syscall: retval=%u\n", regs
->eax
);
367 #if DEBUG || DEVELOPMENT
368 kern_allocation_name_t
369 prior __assert_only
= thread_get_kernel_state(current_thread())->allocation_name
;
370 assertf(prior
== NULL
, "thread_set_allocation_name(\"%s\") not cleared", kern_allocation_get_name(prior
));
371 #endif /* DEBUG || DEVELOPMENT */
373 throttle_lowpri_io(1);
375 thread_exception_return();
379 __attribute__((noreturn
))
381 machdep_syscall64(x86_saved_state_t
*state
)
384 const machdep_call_t
*entry
;
385 x86_saved_state64_t
*regs
;
387 assert(is_saved_state64(state
));
388 regs
= saved_state64(state
);
390 trapno
= (int)(regs
->rax
& SYSCALL_NUMBER_MASK
);
392 DEBUG_KPRINT_SYSCALL_MDEP(
393 "machdep_syscall64: trapno=%d\n", trapno
);
395 if (trapno
< 0 || trapno
>= machdep_call_count
) {
396 regs
->rax
= (unsigned int)kern_invalid(NULL
);
398 thread_exception_return();
401 entry
= &machdep_call_table64
[trapno
];
403 switch (entry
->nargs
) {
405 regs
->rax
= (*entry
->routine
.args_0
)();
408 regs
->rax
= (*entry
->routine
.args64_1
)(regs
->rdi
);
411 regs
->rax
= (*entry
->routine
.args64_2
)(regs
->rdi
, regs
->rsi
);
414 if (!entry
->bsd_style
) {
415 regs
->rax
= (*entry
->routine
.args64_3
)(regs
->rdi
, regs
->rsi
, regs
->rdx
);
420 error
= (*entry
->routine
.args64_bsd_3
)(&rval
, regs
->rdi
, regs
->rsi
, regs
->rdx
);
422 regs
->rax
= (uint64_t)error
;
423 regs
->isf
.rflags
|= EFL_CF
; /* carry bit */
426 regs
->isf
.rflags
&= ~(uint64_t)EFL_CF
;
431 panic("machdep_syscall64: too many args");
434 DEBUG_KPRINT_SYSCALL_MDEP("machdep_syscall: retval=%llu\n", regs
->rax
);
436 #if DEBUG || DEVELOPMENT
437 kern_allocation_name_t
438 prior __assert_only
= thread_get_kernel_state(current_thread())->allocation_name
;
439 assertf(prior
== NULL
, "thread_set_allocation_name(\"%s\") not cleared", kern_allocation_get_name(prior
));
440 #endif /* DEBUG || DEVELOPMENT */
442 throttle_lowpri_io(1);
444 thread_exception_return();
448 #endif /* MACH_BSD */
451 typedef kern_return_t (*mach_call_t
)(void *);
453 struct mach_call_args
{
466 mach_call_arg_munger32(uint32_t sp
, struct mach_call_args
*args
, const mach_trap_t
*trapp
);
470 mach_call_arg_munger32(uint32_t sp
, struct mach_call_args
*args
, const mach_trap_t
*trapp
)
472 if (copyin((user_addr_t
)(sp
+ sizeof(int)), (char *)args
, trapp
->mach_trap_u32_words
* sizeof(int))) {
473 return KERN_INVALID_ARGUMENT
;
475 #if CONFIG_REQUIRES_U32_MUNGING
476 trapp
->mach_trap_arg_munge32(args
);
478 #error U32 mach traps on x86_64 kernel requires munging
484 __private_extern__
void mach_call_munger(x86_saved_state_t
*state
);
486 extern const char *mach_syscall_name_table
[];
488 __attribute__((noreturn
))
490 mach_call_munger(x86_saved_state_t
*state
)
494 mach_call_t mach_call
;
495 kern_return_t retval
;
496 struct mach_call_args args
= {
507 x86_saved_state32_t
*regs
;
509 struct uthread
*ut
= get_bsdthread_info(current_thread());
510 uthread_reset_proc_refcount(ut
);
512 assert(is_saved_state32(state
));
513 regs
= saved_state32(state
);
515 call_number
= -(regs
->eax
);
517 DEBUG_KPRINT_SYSCALL_MACH(
518 "mach_call_munger: code=%d(%s)\n",
519 call_number
, mach_syscall_name_table
[call_number
]);
521 kprintf("mach_call_munger(0x%08x) code=%d\n", regs
, call_number
);
524 if (call_number
< 0 || call_number
>= mach_trap_count
) {
525 i386_exception(EXC_SYSCALL
, call_number
, 1);
528 mach_call
= (mach_call_t
)mach_trap_table
[call_number
].mach_trap_function
;
530 if (mach_call
== (mach_call_t
)kern_invalid
) {
531 DEBUG_KPRINT_SYSCALL_MACH(
532 "mach_call_munger: kern_invalid 0x%x\n", regs
->eax
);
533 i386_exception(EXC_SYSCALL
, call_number
, 1);
537 argc
= mach_trap_table
[call_number
].mach_trap_arg_count
;
539 retval
= mach_call_arg_munger32(regs
->uesp
, &args
, &mach_trap_table
[call_number
]);
540 if (retval
!= KERN_SUCCESS
) {
543 DEBUG_KPRINT_SYSCALL_MACH(
544 "mach_call_munger: retval=0x%x\n", retval
);
546 thread_exception_return();
552 mach_kauth_cred_uthread_update();
555 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
556 MACHDBG_CODE(DBG_MACH_EXCP_SC
, (call_number
)) | DBG_FUNC_START
,
557 args
.arg1
, args
.arg2
, args
.arg3
, args
.arg4
, 0);
560 /* Check mach trap filter mask, if exists. */
561 task_t task
= current_task();
562 uint8_t *filter_mask
= task
->mach_trap_filter_mask
;
564 if (__improbable(filter_mask
!= NULL
&&
565 !bitstr_test(filter_mask
, call_number
))) {
566 /* Not in filter mask, evaluate policy. */
567 if (mac_task_mach_trap_evaluate
!= NULL
) {
568 retval
= mac_task_mach_trap_evaluate(get_bsdtask_info(task
),
575 #endif /* CONFIG_MACF */
577 retval
= mach_call(&args
);
583 DEBUG_KPRINT_SYSCALL_MACH("mach_call_munger: retval=0x%x\n", retval
);
585 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
586 MACHDBG_CODE(DBG_MACH_EXCP_SC
, (call_number
)) | DBG_FUNC_END
,
591 #if DEBUG || DEVELOPMENT
592 kern_allocation_name_t
593 prior __assert_only
= thread_get_kernel_state(current_thread())->allocation_name
;
594 assertf(prior
== NULL
, "thread_set_allocation_name(\"%s\") not cleared", kern_allocation_get_name(prior
));
595 #endif /* DEBUG || DEVELOPMENT */
597 throttle_lowpri_io(1);
600 if (__improbable(uthread_get_proc_refcount(ut
) != 0)) {
601 panic("system call returned with uu_proc_refcount != 0");
605 thread_exception_return();
610 __private_extern__
void mach_call_munger64(x86_saved_state_t
*regs
);
612 __attribute__((noreturn
))
614 mach_call_munger64(x86_saved_state_t
*state
)
618 mach_call_t mach_call
;
619 struct mach_call_args args
= {
630 x86_saved_state64_t
*regs
;
632 struct uthread
*ut
= get_bsdthread_info(current_thread());
633 uthread_reset_proc_refcount(ut
);
635 assert(is_saved_state64(state
));
636 regs
= saved_state64(state
);
638 call_number
= (int)(regs
->rax
& SYSCALL_NUMBER_MASK
);
640 DEBUG_KPRINT_SYSCALL_MACH(
641 "mach_call_munger64: code=%d(%s)\n",
642 call_number
, mach_syscall_name_table
[call_number
]);
644 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
645 MACHDBG_CODE(DBG_MACH_EXCP_SC
, (call_number
)) | DBG_FUNC_START
,
646 regs
->rdi
, regs
->rsi
, regs
->rdx
, regs
->r10
, 0);
648 if (call_number
< 0 || call_number
>= mach_trap_count
) {
649 i386_exception(EXC_SYSCALL
, regs
->rax
, 1);
652 mach_call
= (mach_call_t
)mach_trap_table
[call_number
].mach_trap_function
;
654 if (mach_call
== (mach_call_t
)kern_invalid
) {
655 i386_exception(EXC_SYSCALL
, regs
->rax
, 1);
658 argc
= mach_trap_table
[call_number
].mach_trap_arg_count
;
660 int args_in_regs
= MIN(6, argc
);
661 __nochk_memcpy(&args
.arg1
, ®s
->rdi
, args_in_regs
* sizeof(syscall_arg_t
));
667 copyin_count
= (argc
- 6) * (int)sizeof(syscall_arg_t
);
669 if (copyin((user_addr_t
)(regs
->isf
.rsp
+ sizeof(user_addr_t
)), (char *)&args
.arg7
, copyin_count
)) {
670 regs
->rax
= KERN_INVALID_ARGUMENT
;
672 thread_exception_return();
679 mach_kauth_cred_uthread_update();
683 /* Check syscall filter mask, if exists. */
684 task_t task
= current_task();
685 uint8_t *filter_mask
= task
->mach_trap_filter_mask
;
687 if (__improbable(filter_mask
!= NULL
&&
688 !bitstr_test(filter_mask
, call_number
))) {
689 /* Not in filter mask, evaluate policy. */
690 if (mac_task_mach_trap_evaluate
!= NULL
) {
691 regs
->rax
= mac_task_mach_trap_evaluate(get_bsdtask_info(task
),
698 #endif /* CONFIG_MACF */
700 regs
->rax
= (uint64_t)mach_call((void *)&args
);
706 DEBUG_KPRINT_SYSCALL_MACH( "mach_call_munger64: retval=0x%llx\n", regs
->rax
);
708 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
709 MACHDBG_CODE(DBG_MACH_EXCP_SC
, (call_number
)) | DBG_FUNC_END
,
710 regs
->rax
, 0, 0, 0, 0);
712 #if DEBUG || DEVELOPMENT
713 kern_allocation_name_t
714 prior __assert_only
= thread_get_kernel_state(current_thread())->allocation_name
;
715 assertf(prior
== NULL
, "thread_set_allocation_name(\"%s\") not cleared", kern_allocation_get_name(prior
));
716 #endif /* DEBUG || DEVELOPMENT */
718 throttle_lowpri_io(1);
721 if (__improbable(uthread_get_proc_refcount(ut
) != 0)) {
722 panic("system call returned with uu_proc_refcount != 0");
726 thread_exception_return();
732 * thread_setuserstack:
734 * Sets the user stack pointer into the machine
735 * dependent thread state info.
740 mach_vm_address_t user_stack
)
742 pal_register_cache_state(thread
, DIRTY
);
743 if (thread_is_64bit_addr(thread
)) {
744 x86_saved_state64_t
*iss64
;
746 iss64
= USER_REGS64(thread
);
748 iss64
->isf
.rsp
= (uint64_t)user_stack
;
750 x86_saved_state32_t
*iss32
;
752 iss32
= USER_REGS32(thread
);
754 iss32
->uesp
= CAST_DOWN_EXPLICIT(unsigned int, user_stack
);
759 * thread_adjuserstack:
761 * Returns the adjusted user stack pointer from the machine
762 * dependent thread state info. Used for small (<2G) deltas.
769 pal_register_cache_state(thread
, DIRTY
);
770 if (thread_is_64bit_addr(thread
)) {
771 x86_saved_state64_t
*iss64
;
773 iss64
= USER_REGS64(thread
);
775 iss64
->isf
.rsp
+= adjust
;
777 return iss64
->isf
.rsp
;
779 x86_saved_state32_t
*iss32
;
781 iss32
= USER_REGS32(thread
);
783 iss32
->uesp
+= adjust
;
785 return CAST_USER_ADDR_T(iss32
->uesp
);
790 * thread_setentrypoint:
792 * Sets the user PC into the machine
793 * dependent thread state info.
796 thread_setentrypoint(thread_t thread
, mach_vm_address_t entry
)
798 pal_register_cache_state(thread
, DIRTY
);
799 if (thread_is_64bit_addr(thread
)) {
800 x86_saved_state64_t
*iss64
;
802 iss64
= USER_REGS64(thread
);
804 iss64
->isf
.rip
= (uint64_t)entry
;
806 x86_saved_state32_t
*iss32
;
808 iss32
= USER_REGS32(thread
);
810 iss32
->eip
= CAST_DOWN_EXPLICIT(unsigned int, entry
);
816 thread_setsinglestep(thread_t thread
, int on
)
818 pal_register_cache_state(thread
, DIRTY
);
819 if (thread_is_64bit_addr(thread
)) {
820 x86_saved_state64_t
*iss64
;
822 iss64
= USER_REGS64(thread
);
825 iss64
->isf
.rflags
|= EFL_TF
;
827 iss64
->isf
.rflags
&= ~EFL_TF
;
830 x86_saved_state32_t
*iss32
;
832 iss32
= USER_REGS32(thread
);
835 iss32
->efl
|= EFL_TF
;
837 if (iss32
->cs
== SYSENTER_CS
) {
838 iss32
->cs
= SYSENTER_TF_CS
;
841 iss32
->efl
&= ~EFL_TF
;
849 get_user_regs(thread_t th
)
851 pal_register_cache_state(th
, DIRTY
);
852 return USER_STATE(th
);
856 find_user_regs(thread_t thread
)
858 return get_user_regs(thread
);
863 * DTrace would like to have a peek at the kernel interrupt state, if available.
865 x86_saved_state_t
*find_kern_regs(thread_t
);
868 find_kern_regs(thread_t thread
)
870 if (thread
== current_thread() &&
871 NULL
!= current_cpu_datap()->cpu_int_state
&&
872 !(USER_STATE(thread
) == current_cpu_datap()->cpu_int_state
&&
873 current_cpu_datap()->cpu_interrupt_level
== 1)) {
874 return current_cpu_datap()->cpu_int_state
;
880 vm_offset_t
dtrace_get_cpu_int_stack_top(void);
883 dtrace_get_cpu_int_stack_top(void)
885 return current_cpu_datap()->cpu_int_stack_top
;