1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/cpuvar.h> 30 #include <sys/cpu_module.h> 31 #include <sys/machsystm.h> 32 #include <sys/archsystm.h> 33 #include <sys/prom_plat.h> 34 #include <sys/hypervisor_api.h> 35 #include <sys/hsvc.h> 36 37 extern uint64_t xc_tick_limit; 38 extern uint64_t xc_tick_jump_limit; 39 40 extern void cpu_intrq_unregister_powerdown(uint64_t doneflag_va); 41 42 /* 43 * set_idle_cpu is called from idle() when a CPU becomes idle. 44 */ 45 /*ARGSUSED*/ 46 void 47 set_idle_cpu(int cpun) 48 { 49 } 50 51 /* 52 * unset_idle_cpu is called from idle() when a CPU is no longer idle. 53 */ 54 /*ARGSUSED*/ 55 void 56 unset_idle_cpu(int cpun) 57 { 58 } 59 60 /* 61 * Stop a CPU based on its cpuid, using the cpu_stop hypervisor call. 62 * Since this requires that the hypervisor force a remote CPU to stop, 63 * the assumption is made that this should take roughly the same amount 64 * of time as a CPU mondo. Consequently, the mondo timeout is used to 65 * determine when to give up waiting for the CPU to stop. 66 * 67 * Attempts to stop a CPU already in the stopped or error state will 68 * silently succeed. Zero is returned on success and a non-negative 69 * errno value is returned on failure. 70 */ 71 int 72 stopcpu_bycpuid(int cpuid) 73 { 74 uint64_t loop_cnt; 75 uint64_t state; 76 uint64_t rv; 77 uint64_t major = 0; 78 uint64_t minor = 0; 79 uint64_t cpu_stop_time_limit; 80 extern uint64_t xc_mondo_time_limit; 81 82 ASSERT(MUTEX_HELD(&cpu_lock)); 83 84 /* 85 * Check the state of the CPU up front to see if an 86 * attempt to stop it is even necessary. 87 */ 88 if (hv_cpu_state(cpuid, &state) != H_EOK) 89 return (EINVAL); 90 91 /* treat stopped and error state the same */ 92 if (state != CPU_STATE_RUNNING) { 93 /* nothing to do */ 94 return (0); 95 } 96 97 /* 98 * The HV API to stop a CPU is only supported in 99 * version 1.1 and later of the core group. If an 100 * older version of the HV is in use, return not 101 * supported. 102 */ 103 if (hsvc_version(HSVC_GROUP_CORE, &major, &minor) != 0) 104 return (EINVAL); 105 106 ASSERT(major != 0); 107 108 if ((major == 1) && (minor < 1)) 109 return (ENOTSUP); 110 111 /* use the mondo timeout if it has been initialized */ 112 cpu_stop_time_limit = xc_mondo_time_limit; 113 114 /* 115 * If called early in boot before the mondo time limit 116 * is set, use a reasonable timeout based on the the 117 * clock frequency of the current CPU. 118 */ 119 if (cpu_stop_time_limit == 0) 120 cpu_stop_time_limit = cpunodes[CPU->cpu_id].clock_freq; 121 122 /* should only fail if called too early in boot */ 123 ASSERT(cpu_stop_time_limit > 0); 124 125 loop_cnt = 0; 126 127 /* 128 * Attempt to stop the CPU, retrying if it is busy. 129 */ 130 while (loop_cnt++ < cpu_stop_time_limit) { 131 132 if ((rv = hv_cpu_stop(cpuid)) != H_EWOULDBLOCK) 133 break; 134 } 135 136 if (loop_cnt == cpu_stop_time_limit) 137 return (ETIMEDOUT); 138 139 if (rv != H_EOK) 140 return (EINVAL); 141 142 /* 143 * Verify that the CPU has reached the stopped state. 144 */ 145 while (loop_cnt++ < cpu_stop_time_limit) { 146 147 if (hv_cpu_state(cpuid, &state) != H_EOK) 148 return (EINVAL); 149 150 /* treat stopped and error state the same */ 151 if (state != CPU_STATE_RUNNING) 152 break; 153 } 154 155 return ((loop_cnt == cpu_stop_time_limit) ? ETIMEDOUT : 0); 156 } 157 158 /* 159 * X-trap to the target to unregister its interrupt and error queues 160 * and put it in a safe place just before the CPU is stopped. After 161 * unregistering its queues, the target CPU must not return from the 162 * trap to priv or user context. Ensure that the interrupt CPU unregister 163 * succeeded. 164 */ 165 void 166 xt_cpu_unreg_powerdown(struct cpu *cpup) 167 { 168 uint8_t volatile not_done; 169 uint64_t starttick, endtick, tick, lasttick; 170 processorid_t cpuid = cpup->cpu_id; 171 172 kpreempt_disable(); 173 174 /* 175 * Sun4v uses a queue for receiving mondos. Successful 176 * transmission of a mondo only indicates that the mondo 177 * has been written into the queue. 178 * 179 * Set the not_done flag to 1 before sending the cross 180 * trap and wait until the other cpu resets it to 0. 181 */ 182 183 not_done = 1; 184 185 xt_one_unchecked(cpuid, (xcfunc_t *)cpu_intrq_unregister_powerdown, 186 (uint64_t)¬_done, 0); 187 188 starttick = lasttick = gettick(); 189 endtick = starttick + xc_tick_limit; 190 191 while (not_done) { 192 193 tick = gettick(); 194 195 /* 196 * If there is a big jump between the current tick 197 * count and lasttick, we have probably hit a break 198 * point. Adjust endtick accordingly to avoid panic. 199 */ 200 if (tick > (lasttick + xc_tick_jump_limit)) { 201 endtick += (tick - lasttick); 202 } 203 204 lasttick = tick; 205 if (tick > endtick) { 206 cmn_err(CE_CONT, "Cross trap timeout at cpu id %x\n", 207 cpuid); 208 cmn_err(CE_WARN, "xt_intrq_unreg_powerdown: timeout"); 209 } 210 } 211 212 kpreempt_enable(); 213 } 214 215 int 216 plat_cpu_poweroff(struct cpu *cp) 217 { 218 int rv = 0; 219 int status; 220 processorid_t cpuid = cp->cpu_id; 221 222 ASSERT(MUTEX_HELD(&cpu_lock)); 223 224 /* 225 * Capture all CPUs (except for detaching proc) to prevent 226 * crosscalls to the detaching proc until it has cleared its 227 * bit in cpu_ready_set. 228 * 229 * The CPU's remain paused and the prom_mutex is known to be free. 230 * This prevents the x-trap victim from blocking when doing prom 231 * IEEE-1275 calls at a high PIL level. 232 */ 233 promsafe_pause_cpus(); 234 235 /* 236 * Quiesce interrupts on the target CPU. We do this by setting 237 * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) 238 * to prevent it from receiving cross calls and cross traps. This 239 * prevents the processor from receiving any new soft interrupts. 240 */ 241 mp_cpu_quiesce(cp); 242 243 /* 244 * Send a cross trap to the cpu to unregister its interrupt 245 * error queues. 246 */ 247 xt_cpu_unreg_powerdown(cp); 248 249 cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF; 250 251 /* call into the Hypervisor to stop the CPU */ 252 if ((status = stopcpu_bycpuid(cpuid)) != 0) { 253 rv = -1; 254 } 255 256 start_cpus(); 257 258 if (rv != 0) { 259 cmn_err(CE_WARN, "failed to stop cpu %d (%d)", cpuid, status); 260 /* mark the CPU faulted so that it cannot be onlined */ 261 cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_FAULTED; 262 } 263 264 return (rv); 265 } 266 267 int 268 plat_cpu_poweron(struct cpu *cp) 269 { 270 extern void restart_other_cpu(int); 271 272 ASSERT(MUTEX_HELD(&cpu_lock)); 273 274 cp->cpu_flags &= ~CPU_POWEROFF; 275 276 restart_other_cpu(cp->cpu_id); 277 278 return (0); 279 } 280