2 * Copyright (c) 2013 Apple Computer, 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@
30 * System Overrides syscall implementation
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/proc_internal.h>
39 #include <sys/kauth.h>
40 #include <sys/unistd.h>
43 #include <mach/mach_types.h>
44 #include <mach/vm_param.h>
45 #include <kern/task.h>
46 #include <kern/locks.h>
47 #include <kern/assert.h>
48 #include <kern/sched_prim.h>
50 #include <sys/kern_overrides.h>
51 #include <sys/bsdtask_info.h>
52 #include <sys/kdebug.h>
53 #include <sys/sysproto.h>
54 #include <sys/msgbuf.h>
56 /* Mutex for global system override state */
57 static lck_mtx_t sys_override_lock
;
58 static lck_grp_t
*sys_override_mtx_grp
;
59 static lck_attr_t
*sys_override_mtx_attr
;
60 static lck_grp_attr_t
*sys_override_mtx_grp_attr
;
62 /* Assertion counts for system properties */
63 static int64_t io_throttle_assert_cnt
;
64 static int64_t cpu_throttle_assert_cnt
;
66 /* Wait Channel for system override */
67 static uint64_t sys_override_wait
;
69 /* Global variable to indicate if system_override is enabled */
70 int sys_override_enabled
;
72 /* Sysctl definition for sys_override_enabled */
73 SYSCTL_INT(_debug
, OID_AUTO
, sys_override_enabled
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sys_override_enabled
, 0, "");
75 /* Forward Declarations */
76 static void enable_system_override(uint64_t flags
);
77 static void disable_system_override(uint64_t flags
);
78 static __attribute__((noinline
)) void PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout
);
80 /***************************** system_override ********************/
82 * int system_override(uint64_t timeout, uint64_t flags);
86 init_system_override()
88 sys_override_mtx_grp_attr
= lck_grp_attr_alloc_init();
89 sys_override_mtx_grp
= lck_grp_alloc_init("system_override", sys_override_mtx_grp_attr
);
90 sys_override_mtx_attr
= lck_attr_alloc_init();
91 lck_mtx_init(&sys_override_lock
, sys_override_mtx_grp
, sys_override_mtx_attr
);
92 io_throttle_assert_cnt
= cpu_throttle_assert_cnt
= 0;
93 sys_override_enabled
= 1;
96 /* system call implementation */
98 system_override(__unused
struct proc
*p
, struct system_override_args
* uap
, __unused
int32_t *retval
)
100 uint64_t timeout
= uap
->timeout
;
101 uint64_t flags
= uap
->flags
;
104 /* Check credentials for caller. Only entitled processes are allowed to make this call. */
105 if ((error
= priv_check_cred(kauth_cred_get(), PRIV_SYSTEM_OVERRIDE
, 0))) {
109 /* Check to see if some flags are specified. */
110 if ((flags
& ~SYS_OVERRIDE_FLAGS_MASK
) != 0) {
115 if (flags
== SYS_OVERRIDE_DISABLE
) {
117 printf("Process %s [%d] disabling system_override()\n", current_proc()->p_comm
, current_proc()->p_pid
);
119 lck_mtx_lock(&sys_override_lock
);
121 if (io_throttle_assert_cnt
> 0)
122 sys_override_io_throttle(THROTTLE_IO_ENABLE
);
123 if (cpu_throttle_assert_cnt
> 0)
124 sys_override_cpu_throttle(CPU_THROTTLE_ENABLE
);
126 sys_override_enabled
= 0;
128 lck_mtx_unlock(&sys_override_lock
);
133 lck_mtx_lock(&sys_override_lock
);
135 enable_system_override(flags
);
137 PROCESS_OVERRIDING_SYSTEM_DEFAULTS(timeout
);
139 disable_system_override(flags
);
141 lck_mtx_unlock(&sys_override_lock
);
148 * Call for enabling global system override.
149 * This should be called only with the sys_override_lock held.
152 enable_system_override(uint64_t flags
)
155 if (flags
& SYS_OVERRIDE_IO_THROTTLE
) {
156 if ((io_throttle_assert_cnt
== 0) && sys_override_enabled
) {
157 /* Disable I/O Throttling */
158 printf("Process %s [%d] disabling system-wide I/O Throttling\n", current_proc()->p_comm
, current_proc()->p_pid
);
159 sys_override_io_throttle(THROTTLE_IO_DISABLE
);
161 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE
, IO_THROTTLE_DISABLE
) | DBG_FUNC_START
, current_proc()->p_pid
, 0, 0, 0, 0);
162 io_throttle_assert_cnt
++;
165 if (flags
& SYS_OVERRIDE_CPU_THROTTLE
) {
166 if ((cpu_throttle_assert_cnt
== 0) && sys_override_enabled
) {
167 /* Disable CPU Throttling */
168 printf("Process %s [%d] disabling system-wide CPU Throttling\n", current_proc()->p_comm
, current_proc()->p_pid
);
169 sys_override_cpu_throttle(CPU_THROTTLE_DISABLE
);
171 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
, MACH_CPU_THROTTLE_DISABLE
) | DBG_FUNC_START
, current_proc()->p_pid
, 0, 0, 0, 0);
172 cpu_throttle_assert_cnt
++;
178 * Call for disabling global system override.
179 * This should be called only with the sys_override_lock held.
182 disable_system_override(uint64_t flags
)
185 if (flags
& SYS_OVERRIDE_IO_THROTTLE
) {
186 assert(io_throttle_assert_cnt
> 0);
187 io_throttle_assert_cnt
--;
188 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE
, IO_THROTTLE_DISABLE
) | DBG_FUNC_END
, current_proc()->p_pid
, 0, 0, 0, 0);
189 if ((io_throttle_assert_cnt
== 0) && sys_override_enabled
) {
190 /* Enable I/O Throttling */
191 sys_override_io_throttle(THROTTLE_IO_ENABLE
);
195 if (flags
& SYS_OVERRIDE_CPU_THROTTLE
) {
196 assert(cpu_throttle_assert_cnt
> 0);
197 cpu_throttle_assert_cnt
--;
198 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
, MACH_CPU_THROTTLE_DISABLE
) | DBG_FUNC_END
, current_proc()->p_pid
, 0, 0, 0, 0);
199 if ((cpu_throttle_assert_cnt
== 0) && sys_override_enabled
) {
200 /* Enable CPU Throttling */
201 sys_override_cpu_throttle(CPU_THROTTLE_ENABLE
);
206 static __attribute__((noinline
)) void
207 PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout
)
210 ts
.tv_sec
= timeout
/ NSEC_PER_SEC
;
211 ts
.tv_nsec
= timeout
- ((long)ts
.tv_sec
* NSEC_PER_SEC
);
212 msleep((caddr_t
)&sys_override_wait
, &sys_override_lock
, PRIBIO
| PCATCH
, "system_override", &ts
);