]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_overrides.c
xnu-4570.71.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_overrides.c
CommitLineData
39236c6e
A
1/*
2 * Copyright (c) 2013 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*
30 * System Overrides syscall implementation
31 */
32
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>
38#include <sys/proc.h>
39#include <sys/kauth.h>
40#include <sys/unistd.h>
41#include <sys/priv.h>
39236c6e
A
42
43#include <mach/mach_types.h>
44#include <mach/vm_param.h>
45#include <kern/task.h>
fe8ab488 46#include <kern/locks.h>
39236c6e
A
47#include <kern/assert.h>
48#include <kern/sched_prim.h>
49
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>
55
56/* Mutex for global system override state */
57static lck_mtx_t sys_override_lock;
58static lck_grp_t *sys_override_mtx_grp;
59static lck_attr_t *sys_override_mtx_attr;
60static lck_grp_attr_t *sys_override_mtx_grp_attr;
61
62/* Assertion counts for system properties */
63static int64_t io_throttle_assert_cnt;
64static int64_t cpu_throttle_assert_cnt;
65
66/* Wait Channel for system override */
67static uint64_t sys_override_wait;
68
fe8ab488
A
69/* Global variable to indicate if system_override is enabled */
70int sys_override_enabled;
71
72/* Sysctl definition for sys_override_enabled */
73SYSCTL_INT(_debug, OID_AUTO, sys_override_enabled, CTLFLAG_RW | CTLFLAG_LOCKED, &sys_override_enabled, 0, "");
74
39236c6e
A
75/* Forward Declarations */
76static void enable_system_override(uint64_t flags);
77static void disable_system_override(uint64_t flags);
78static __attribute__((noinline)) void PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout);
79
80/***************************** system_override ********************/
81/*
82 * int system_override(uint64_t timeout, uint64_t flags);
83 */
84
85void
86init_system_override()
87{
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;
fe8ab488 93 sys_override_enabled = 1;
39236c6e
A
94}
95
96/* system call implementation */
97int
98system_override(__unused struct proc *p, struct system_override_args * uap, __unused int32_t *retval)
99{
100 uint64_t timeout = uap->timeout;
101 uint64_t flags = uap->flags;
102 int error = 0;
103
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))) {
106 goto out;
107 }
108
fe8ab488
A
109 /* Check to see if some flags are specified. */
110 if ((flags & ~SYS_OVERRIDE_FLAGS_MASK) != 0) {
39236c6e
A
111 error = EINVAL;
112 goto out;
113 }
114
fe8ab488
A
115 if (flags == SYS_OVERRIDE_DISABLE) {
116
117 printf("Process %s [%d] disabling system_override()\n", current_proc()->p_comm, current_proc()->p_pid);
118
119 lck_mtx_lock(&sys_override_lock);
120
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);
125
126 sys_override_enabled = 0;
127
128 lck_mtx_unlock(&sys_override_lock);
129
130 goto out;
131 }
132
39236c6e
A
133 lck_mtx_lock(&sys_override_lock);
134
135 enable_system_override(flags);
136
137 PROCESS_OVERRIDING_SYSTEM_DEFAULTS(timeout);
138
139 disable_system_override(flags);
140
141 lck_mtx_unlock(&sys_override_lock);
142
143out:
144 return error;
145}
146
147/*
148 * Call for enabling global system override.
149 * This should be called only with the sys_override_lock held.
150 */
151static void
152enable_system_override(uint64_t flags)
153{
154
155 if (flags & SYS_OVERRIDE_IO_THROTTLE) {
fe8ab488 156 if ((io_throttle_assert_cnt == 0) && sys_override_enabled) {
39236c6e
A
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);
39236c6e
A
159 sys_override_io_throttle(THROTTLE_IO_DISABLE);
160 }
fe8ab488 161 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE, IO_THROTTLE_DISABLE) | DBG_FUNC_START, current_proc()->p_pid, 0, 0, 0, 0);
39236c6e
A
162 io_throttle_assert_cnt++;
163 }
164
165 if (flags & SYS_OVERRIDE_CPU_THROTTLE) {
fe8ab488 166 if ((cpu_throttle_assert_cnt == 0) && sys_override_enabled) {
39236c6e
A
167 /* Disable CPU Throttling */
168 printf("Process %s [%d] disabling system-wide CPU Throttling\n", current_proc()->p_comm, current_proc()->p_pid);
39236c6e
A
169 sys_override_cpu_throttle(CPU_THROTTLE_DISABLE);
170 }
fe8ab488 171 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_CPU_THROTTLE_DISABLE) | DBG_FUNC_START, current_proc()->p_pid, 0, 0, 0, 0);
39236c6e
A
172 cpu_throttle_assert_cnt++;
173 }
174
175}
176
177/*
178 * Call for disabling global system override.
179 * This should be called only with the sys_override_lock held.
180 */
181static void
182disable_system_override(uint64_t flags)
183{
184
185 if (flags & SYS_OVERRIDE_IO_THROTTLE) {
186 assert(io_throttle_assert_cnt > 0);
187 io_throttle_assert_cnt--;
fe8ab488
A
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) {
39236c6e 190 /* Enable I/O Throttling */
39236c6e
A
191 sys_override_io_throttle(THROTTLE_IO_ENABLE);
192 }
193 }
194
195 if (flags & SYS_OVERRIDE_CPU_THROTTLE) {
196 assert(cpu_throttle_assert_cnt > 0);
197 cpu_throttle_assert_cnt--;
fe8ab488
A
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) {
39236c6e 200 /* Enable CPU Throttling */
39236c6e
A
201 sys_override_cpu_throttle(CPU_THROTTLE_ENABLE);
202 }
203 }
204}
205
206static __attribute__((noinline)) void
207PROCESS_OVERRIDING_SYSTEM_DEFAULTS(uint64_t timeout)
208{
209 struct timespec ts;
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);
213}
214