dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / kernel / syscall / p_online.c
blob652a73534b7bbefb39f1fdbf7020892175dff0d9
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/var.h>
29 #include <sys/thread.h>
30 #include <sys/cpuvar.h>
31 #include <sys/kstat.h>
32 #include <sys/uadmin.h>
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/cmn_err.h>
36 #include <sys/procset.h>
37 #include <sys/processor.h>
38 #include <sys/debug.h>
39 #include <sys/policy.h>
42 * CPU state diagram
44 * P_SPARE
45 * P_POWEROFF <---> P_OFFLINE <---> P_ONLINE <---> P_NOINTR
46 * P_FAULTED
48 int
49 p_online_internal_locked(processorid_t cpun, int new_status, int *old_status)
51 cpu_t *cp;
52 int status;
53 int error = 0;
54 int flags = 0;
57 * Try to get a pointer to the requested CPU structure.
59 ASSERT(MUTEX_HELD(&cpu_lock));
60 if ((cp = cpu_get(cpun)) == NULL) {
61 error = EINVAL;
62 goto out;
65 if (new_status & P_FORCED)
66 flags = CPU_FORCED;
67 *old_status = status = cpu_get_state(cp); /* get processor status */
68 new_status &= ~P_FORCED;
71 * Perform credentials check.
73 switch (new_status) {
74 case P_STATUS:
75 goto out;
76 case P_ONLINE:
77 case P_OFFLINE:
78 case P_NOINTR:
79 case P_FAULTED:
80 case P_SPARE:
81 if (secpolicy_ponline(CRED()) != 0)
82 error = EPERM;
83 break;
84 default:
85 error = EINVAL;
88 if (error)
89 goto out;
92 * return 0 if the CPU is already in the desired new state.
94 if (status == new_status)
95 goto out;
97 switch (new_status) {
98 case P_ONLINE:
99 switch (status) {
100 case P_POWEROFF:
102 * If CPU is powered off, power it on.
104 if (error = cpu_poweron(cp))
105 break;
106 ASSERT(cpu_get_state(cp) == P_OFFLINE);
107 /* FALLTHROUGH */
108 case P_OFFLINE:
109 case P_FAULTED:
110 case P_SPARE:
112 * If CPU is in one of the offline states,
113 * bring it online.
115 error = cpu_online(cp);
116 break;
117 case P_NOINTR:
118 cpu_intr_enable(cp);
119 break;
121 break;
123 case P_OFFLINE:
124 switch (status) {
125 case P_NOINTR:
127 * Before we take the CPU offline, we first enable I/O
128 * interrupts.
130 cpu_intr_enable(cp);
131 /* FALLTHROUGH */
132 case P_ONLINE:
133 case P_FAULTED:
134 case P_SPARE:
136 * CPU is online, or in a special offline state.
137 * Take it offline.
139 error = cpu_offline(cp, flags);
140 break;
141 case P_POWEROFF:
143 * If CPU is powered off, power it on.
145 error = cpu_poweron(cp);
147 break;
149 case P_NOINTR:
150 switch (status) {
151 case P_POWEROFF:
153 * if CPU is powered off, power it on.
155 if (error = cpu_poweron(cp))
156 break;
157 ASSERT(cpu_get_state(cp) == P_OFFLINE);
158 /* FALLTHROUGH */
159 case P_OFFLINE:
160 case P_FAULTED:
161 case P_SPARE:
163 * First, bring the CPU online.
165 if (error = cpu_online(cp))
166 break;
167 /* FALLTHROUGH */
168 case P_ONLINE:
170 * CPU is now online. Try to disable interrupts.
172 error = cpu_intr_disable(cp);
174 break;
176 case P_FAULTED:
177 switch (status) {
178 case P_POWEROFF:
180 * If CPU is powered off, power it on.
182 if (error = cpu_poweron(cp))
183 break;
184 ASSERT(cpu_get_state(cp) == P_OFFLINE);
185 /*FALLTHROUGH*/
186 case P_OFFLINE:
187 case P_SPARE:
188 case P_ONLINE:
189 case P_NOINTR:
191 * Mark this CPU as faulted.
193 error = cpu_faulted(cp, flags);
195 break;
197 case P_SPARE:
198 switch (status) {
199 case P_POWEROFF:
201 * If CPU is powered off, power it on.
203 if (error = cpu_poweron(cp))
204 break;
205 ASSERT(cpu_get_state(cp) == P_OFFLINE);
206 /*FALLTHROUGH*/
207 case P_OFFLINE:
208 case P_FAULTED:
209 case P_ONLINE:
210 case P_NOINTR:
212 * Mark this CPU as a spare.
214 error = cpu_spare(cp, flags);
216 break;
218 out:
219 return (error);
223 p_online_internal(processorid_t cpun, int new_status, int *old_status)
225 int rc;
227 mutex_enter(&cpu_lock); /* protects CPU states */
228 rc = p_online_internal_locked(cpun, new_status, old_status);
229 mutex_exit(&cpu_lock);
231 return (rc);
235 * p_online(2) - get/change processor operational status.
237 * As noted in os/cpu.c, the P_ONLINE and other state constants are for use
238 * only in this system call path and other paths conveying CPU state to
239 * userland. In general, other kernel consumers should be using the accessor
240 * functions in kernel/os/cpu.c.
243 p_online(processorid_t cpun, int new_status)
245 int ret;
246 int old_status;
248 ret = p_online_internal(cpun, new_status, &old_status);
249 if (ret != 0)
250 return (set_errno(ret));
251 return (old_status);