17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*a3114836SGerry Liu * Common Development and Distribution License (the "License"). 6*a3114836SGerry Liu * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/param.h> 287c478bd9Sstevel@tonic-gate #include <sys/var.h> 297c478bd9Sstevel@tonic-gate #include <sys/thread.h> 307c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 317c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 327c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 337c478bd9Sstevel@tonic-gate #include <sys/systm.h> 347c478bd9Sstevel@tonic-gate #include <sys/errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 367c478bd9Sstevel@tonic-gate #include <sys/procset.h> 377c478bd9Sstevel@tonic-gate #include <sys/processor.h> 387c478bd9Sstevel@tonic-gate #include <sys/debug.h> 397c478bd9Sstevel@tonic-gate #include <sys/policy.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * CPU state diagram 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * P_SPARE 457c478bd9Sstevel@tonic-gate * P_POWEROFF <---> P_OFFLINE <---> P_ONLINE <---> P_NOINTR 467c478bd9Sstevel@tonic-gate * P_FAULTED 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate int 49*a3114836SGerry Liu p_online_internal_locked(processorid_t cpun, int new_status, int *old_status) 507c478bd9Sstevel@tonic-gate { 517c478bd9Sstevel@tonic-gate cpu_t *cp; 527c478bd9Sstevel@tonic-gate int status; 537c478bd9Sstevel@tonic-gate int error = 0; 547c478bd9Sstevel@tonic-gate int flags = 0; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * Try to get a pointer to the requested CPU structure. 587c478bd9Sstevel@tonic-gate */ 59*a3114836SGerry Liu ASSERT(MUTEX_HELD(&cpu_lock)); 607c478bd9Sstevel@tonic-gate if ((cp = cpu_get(cpun)) == NULL) { 617c478bd9Sstevel@tonic-gate error = EINVAL; 627c478bd9Sstevel@tonic-gate goto out; 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate if (new_status & P_FORCED) 667c478bd9Sstevel@tonic-gate flags = CPU_FORCED; 677c478bd9Sstevel@tonic-gate *old_status = status = cpu_get_state(cp); /* get processor status */ 687c478bd9Sstevel@tonic-gate new_status &= ~P_FORCED; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * Perform credentials check. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate switch (new_status) { 747c478bd9Sstevel@tonic-gate case P_STATUS: 757c478bd9Sstevel@tonic-gate goto out; 767c478bd9Sstevel@tonic-gate case P_ONLINE: 777c478bd9Sstevel@tonic-gate case P_OFFLINE: 787c478bd9Sstevel@tonic-gate case P_NOINTR: 797c478bd9Sstevel@tonic-gate case P_FAULTED: 807c478bd9Sstevel@tonic-gate case P_SPARE: 817c478bd9Sstevel@tonic-gate if (secpolicy_ponline(CRED()) != 0) 827c478bd9Sstevel@tonic-gate error = EPERM; 837c478bd9Sstevel@tonic-gate break; 847c478bd9Sstevel@tonic-gate default: 857c478bd9Sstevel@tonic-gate error = EINVAL; 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (error) 897c478bd9Sstevel@tonic-gate goto out; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * return 0 if the CPU is already in the desired new state. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate if (status == new_status) 957c478bd9Sstevel@tonic-gate goto out; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate switch (new_status) { 987c478bd9Sstevel@tonic-gate case P_ONLINE: 997c478bd9Sstevel@tonic-gate switch (status) { 1007c478bd9Sstevel@tonic-gate case P_POWEROFF: 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * If CPU is powered off, power it on. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate if (error = cpu_poweron(cp)) 1057c478bd9Sstevel@tonic-gate break; 1067c478bd9Sstevel@tonic-gate ASSERT(cpu_get_state(cp) == P_OFFLINE); 1077c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1087c478bd9Sstevel@tonic-gate case P_OFFLINE: 1097c478bd9Sstevel@tonic-gate case P_FAULTED: 1107c478bd9Sstevel@tonic-gate case P_SPARE: 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * If CPU is in one of the offline states, 1137c478bd9Sstevel@tonic-gate * bring it online. 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate error = cpu_online(cp); 1167c478bd9Sstevel@tonic-gate break; 1177c478bd9Sstevel@tonic-gate case P_NOINTR: 1187c478bd9Sstevel@tonic-gate cpu_intr_enable(cp); 1197c478bd9Sstevel@tonic-gate break; 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate break; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate case P_OFFLINE: 1247c478bd9Sstevel@tonic-gate switch (status) { 1257c478bd9Sstevel@tonic-gate case P_NOINTR: 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Before we take the CPU offline, we first enable I/O 1287c478bd9Sstevel@tonic-gate * interrupts. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate cpu_intr_enable(cp); 1317c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1327c478bd9Sstevel@tonic-gate case P_ONLINE: 1337c478bd9Sstevel@tonic-gate case P_FAULTED: 1347c478bd9Sstevel@tonic-gate case P_SPARE: 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * CPU is online, or in a special offline state. 1377c478bd9Sstevel@tonic-gate * Take it offline. 1387c478bd9Sstevel@tonic-gate */ 1397c478bd9Sstevel@tonic-gate error = cpu_offline(cp, flags); 1407c478bd9Sstevel@tonic-gate break; 1417c478bd9Sstevel@tonic-gate case P_POWEROFF: 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * If CPU is powered off, power it on. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate error = cpu_poweron(cp); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate break; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate case P_NOINTR: 1507c478bd9Sstevel@tonic-gate switch (status) { 1517c478bd9Sstevel@tonic-gate case P_POWEROFF: 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * if CPU is powered off, power it on. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate if (error = cpu_poweron(cp)) 1567c478bd9Sstevel@tonic-gate break; 1577c478bd9Sstevel@tonic-gate ASSERT(cpu_get_state(cp) == P_OFFLINE); 1587c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1597c478bd9Sstevel@tonic-gate case P_OFFLINE: 1607c478bd9Sstevel@tonic-gate case P_FAULTED: 1617c478bd9Sstevel@tonic-gate case P_SPARE: 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * First, bring the CPU online. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate if (error = cpu_online(cp)) 1667c478bd9Sstevel@tonic-gate break; 1677c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1687c478bd9Sstevel@tonic-gate case P_ONLINE: 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * CPU is now online. Try to disable interrupts. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate error = cpu_intr_disable(cp); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate break; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate case P_FAULTED: 1777c478bd9Sstevel@tonic-gate switch (status) { 1787c478bd9Sstevel@tonic-gate case P_POWEROFF: 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * If CPU is powered off, power it on. 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate if (error = cpu_poweron(cp)) 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate ASSERT(cpu_get_state(cp) == P_OFFLINE); 1857c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1867c478bd9Sstevel@tonic-gate case P_OFFLINE: 1877c478bd9Sstevel@tonic-gate case P_SPARE: 1887c478bd9Sstevel@tonic-gate case P_ONLINE: 1897c478bd9Sstevel@tonic-gate case P_NOINTR: 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Mark this CPU as faulted. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate error = cpu_faulted(cp, flags); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate break; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate case P_SPARE: 1987c478bd9Sstevel@tonic-gate switch (status) { 1997c478bd9Sstevel@tonic-gate case P_POWEROFF: 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * If CPU is powered off, power it on. 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate if (error = cpu_poweron(cp)) 2047c478bd9Sstevel@tonic-gate break; 2057c478bd9Sstevel@tonic-gate ASSERT(cpu_get_state(cp) == P_OFFLINE); 2067c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2077c478bd9Sstevel@tonic-gate case P_OFFLINE: 2087c478bd9Sstevel@tonic-gate case P_FAULTED: 2097c478bd9Sstevel@tonic-gate case P_ONLINE: 2107c478bd9Sstevel@tonic-gate case P_NOINTR: 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * Mark this CPU as a spare. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate error = cpu_spare(cp, flags); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate out: 2197c478bd9Sstevel@tonic-gate return (error); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 222*a3114836SGerry Liu int 223*a3114836SGerry Liu p_online_internal(processorid_t cpun, int new_status, int *old_status) 224*a3114836SGerry Liu { 225*a3114836SGerry Liu int rc; 226*a3114836SGerry Liu 227*a3114836SGerry Liu mutex_enter(&cpu_lock); /* protects CPU states */ 228*a3114836SGerry Liu rc = p_online_internal_locked(cpun, new_status, old_status); 229*a3114836SGerry Liu mutex_exit(&cpu_lock); 230*a3114836SGerry Liu 231*a3114836SGerry Liu return (rc); 232*a3114836SGerry Liu } 233*a3114836SGerry Liu 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * p_online(2) - get/change processor operational status. 2367c478bd9Sstevel@tonic-gate * 2377c478bd9Sstevel@tonic-gate * As noted in os/cpu.c, the P_ONLINE and other state constants are for use 2387c478bd9Sstevel@tonic-gate * only in this system call path and other paths conveying CPU state to 2397c478bd9Sstevel@tonic-gate * userland. In general, other kernel consumers should be using the accessor 2407c478bd9Sstevel@tonic-gate * functions in uts/common/os/cpu.c. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate int 2437c478bd9Sstevel@tonic-gate p_online(processorid_t cpun, int new_status) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate int ret; 2467c478bd9Sstevel@tonic-gate int old_status; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate ret = p_online_internal(cpun, new_status, &old_status); 2497c478bd9Sstevel@tonic-gate if (ret != 0) 2507c478bd9Sstevel@tonic-gate return (set_errno(ret)); 2517c478bd9Sstevel@tonic-gate return (old_status); 2527c478bd9Sstevel@tonic-gate } 253