1 /* 2 * QEMU support -- ARM Power Control specific functions. 3 * 4 * Copyright (c) 2016 Jean-Christophe Dubois 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * 9 */ 10 11 #include "qemu/osdep.h" 12 #include "cpu.h" 13 #include "cpu-qom.h" 14 #include "internals.h" 15 #include "arm-powerctl.h" 16 #include "qemu/log.h" 17 #include "qemu/main-loop.h" 18 19 #ifndef DEBUG_ARM_POWERCTL 20 #define DEBUG_ARM_POWERCTL 0 21 #endif 22 23 #define DPRINTF(fmt, args...) \ 24 do { \ 25 if (DEBUG_ARM_POWERCTL) { \ 26 fprintf(stderr, "[ARM]%s: " fmt , __func__, ##args); \ 27 } \ 28 } while (0) 29 30 CPUState *arm_get_cpu_by_id(uint64_t id) 31 { 32 CPUState *cpu; 33 34 DPRINTF("cpu %" PRId64 "\n", id); 35 36 CPU_FOREACH(cpu) { 37 ARMCPU *armcpu = ARM_CPU(cpu); 38 39 if (armcpu->mp_affinity == id) { 40 return cpu; 41 } 42 } 43 44 qemu_log_mask(LOG_GUEST_ERROR, 45 "[ARM]%s: Requesting unknown CPU %" PRId64 "\n", 46 __func__, id); 47 48 return NULL; 49 } 50 51 struct CpuOnInfo { 52 uint64_t entry; 53 uint64_t context_id; 54 uint32_t target_el; 55 bool target_aa64; 56 }; 57 58 59 static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, 60 run_on_cpu_data data) 61 { 62 ARMCPU *target_cpu = ARM_CPU(target_cpu_state); 63 struct CpuOnInfo *info = (struct CpuOnInfo *) data.host_ptr; 64 65 /* Initialize the cpu we are turning on */ 66 cpu_reset(target_cpu_state); 67 target_cpu_state->halted = 0; 68 69 if (info->target_aa64) { 70 if ((info->target_el < 3) && arm_feature(&target_cpu->env, 71 ARM_FEATURE_EL3)) { 72 /* 73 * As target mode is AArch64, we need to set lower 74 * exception level (the requested level 2) to AArch64 75 */ 76 target_cpu->env.cp15.scr_el3 |= SCR_RW; 77 } 78 79 if ((info->target_el < 2) && arm_feature(&target_cpu->env, 80 ARM_FEATURE_EL2)) { 81 /* 82 * As target mode is AArch64, we need to set lower 83 * exception level (the requested level 1) to AArch64 84 */ 85 target_cpu->env.cp15.hcr_el2 |= HCR_RW; 86 } 87 88 target_cpu->env.pstate = aarch64_pstate_mode(info->target_el, true); 89 } else { 90 /* We are requested to boot in AArch32 mode */ 91 static const uint32_t mode_for_el[] = { 0, 92 ARM_CPU_MODE_SVC, 93 ARM_CPU_MODE_HYP, 94 ARM_CPU_MODE_SVC }; 95 96 cpsr_write(&target_cpu->env, mode_for_el[info->target_el], CPSR_M, 97 CPSRWriteRaw); 98 } 99 100 if (info->target_el == 3) { 101 /* Processor is in secure mode */ 102 target_cpu->env.cp15.scr_el3 &= ~SCR_NS; 103 } else { 104 /* Processor is not in secure mode */ 105 target_cpu->env.cp15.scr_el3 |= SCR_NS; 106 107 /* Set NSACR.{CP11,CP10} so NS can access the FPU */ 108 target_cpu->env.cp15.nsacr |= 3 << 10; 109 110 /* 111 * If QEMU is providing the equivalent of EL3 firmware, then we need 112 * to make sure a CPU targeting EL2 comes out of reset with a 113 * functional HVC insn. 114 */ 115 if (arm_feature(&target_cpu->env, ARM_FEATURE_EL3) 116 && info->target_el == 2) { 117 target_cpu->env.cp15.scr_el3 |= SCR_HCE; 118 } 119 } 120 121 /* We check if the started CPU is now at the correct level */ 122 assert(info->target_el == arm_current_el(&target_cpu->env)); 123 124 if (info->target_aa64) { 125 target_cpu->env.xregs[0] = info->context_id; 126 } else { 127 target_cpu->env.regs[0] = info->context_id; 128 } 129 130 /* Start the new CPU at the requested address */ 131 cpu_set_pc(target_cpu_state, info->entry); 132 133 g_free(info); 134 135 /* Finally set the power status */ 136 assert(qemu_mutex_iothread_locked()); 137 target_cpu->power_state = PSCI_ON; 138 } 139 140 int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, 141 uint32_t target_el, bool target_aa64) 142 { 143 CPUState *target_cpu_state; 144 ARMCPU *target_cpu; 145 struct CpuOnInfo *info; 146 147 assert(qemu_mutex_iothread_locked()); 148 149 DPRINTF("cpu %" PRId64 " (EL %d, %s) @ 0x%" PRIx64 " with R0 = 0x%" PRIx64 150 "\n", cpuid, target_el, target_aa64 ? "aarch64" : "aarch32", entry, 151 context_id); 152 153 /* requested EL level need to be in the 1 to 3 range */ 154 assert((target_el > 0) && (target_el < 4)); 155 156 if (target_aa64 && (entry & 3)) { 157 /* 158 * if we are booting in AArch64 mode then "entry" needs to be 4 bytes 159 * aligned. 160 */ 161 return QEMU_ARM_POWERCTL_INVALID_PARAM; 162 } 163 164 /* Retrieve the cpu we are powering up */ 165 target_cpu_state = arm_get_cpu_by_id(cpuid); 166 if (!target_cpu_state) { 167 /* The cpu was not found */ 168 return QEMU_ARM_POWERCTL_INVALID_PARAM; 169 } 170 171 target_cpu = ARM_CPU(target_cpu_state); 172 if (target_cpu->power_state == PSCI_ON) { 173 qemu_log_mask(LOG_GUEST_ERROR, 174 "[ARM]%s: CPU %" PRId64 " is already on\n", 175 __func__, cpuid); 176 return QEMU_ARM_POWERCTL_ALREADY_ON; 177 } 178 179 /* 180 * The newly brought CPU is requested to enter the exception level 181 * "target_el" and be in the requested mode (AArch64 or AArch32). 182 */ 183 184 if (((target_el == 3) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) || 185 ((target_el == 2) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL2))) { 186 /* 187 * The CPU does not support requested level 188 */ 189 return QEMU_ARM_POWERCTL_INVALID_PARAM; 190 } 191 192 if (!target_aa64 && arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64)) { 193 /* 194 * For now we don't support booting an AArch64 CPU in AArch32 mode 195 * TODO: We should add this support later 196 */ 197 qemu_log_mask(LOG_UNIMP, 198 "[ARM]%s: Starting AArch64 CPU %" PRId64 199 " in AArch32 mode is not supported yet\n", 200 __func__, cpuid); 201 return QEMU_ARM_POWERCTL_INVALID_PARAM; 202 } 203 204 /* 205 * If another CPU has powered the target on we are in the state 206 * ON_PENDING and additional attempts to power on the CPU should 207 * fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI 208 * spec) 209 */ 210 if (target_cpu->power_state == PSCI_ON_PENDING) { 211 qemu_log_mask(LOG_GUEST_ERROR, 212 "[ARM]%s: CPU %" PRId64 " is already powering on\n", 213 __func__, cpuid); 214 return QEMU_ARM_POWERCTL_ON_PENDING; 215 } 216 217 /* To avoid racing with a CPU we are just kicking off we do the 218 * final bit of preparation for the work in the target CPUs 219 * context. 220 */ 221 info = g_new(struct CpuOnInfo, 1); 222 info->entry = entry; 223 info->context_id = context_id; 224 info->target_el = target_el; 225 info->target_aa64 = target_aa64; 226 227 async_run_on_cpu(target_cpu_state, arm_set_cpu_on_async_work, 228 RUN_ON_CPU_HOST_PTR(info)); 229 230 /* We are good to go */ 231 return QEMU_ARM_POWERCTL_RET_SUCCESS; 232 } 233 234 static void arm_set_cpu_on_and_reset_async_work(CPUState *target_cpu_state, 235 run_on_cpu_data data) 236 { 237 ARMCPU *target_cpu = ARM_CPU(target_cpu_state); 238 239 /* Initialize the cpu we are turning on */ 240 cpu_reset(target_cpu_state); 241 target_cpu_state->halted = 0; 242 243 /* Finally set the power status */ 244 assert(qemu_mutex_iothread_locked()); 245 target_cpu->power_state = PSCI_ON; 246 } 247 248 int arm_set_cpu_on_and_reset(uint64_t cpuid) 249 { 250 CPUState *target_cpu_state; 251 ARMCPU *target_cpu; 252 253 assert(qemu_mutex_iothread_locked()); 254 255 /* Retrieve the cpu we are powering up */ 256 target_cpu_state = arm_get_cpu_by_id(cpuid); 257 if (!target_cpu_state) { 258 /* The cpu was not found */ 259 return QEMU_ARM_POWERCTL_INVALID_PARAM; 260 } 261 262 target_cpu = ARM_CPU(target_cpu_state); 263 if (target_cpu->power_state == PSCI_ON) { 264 qemu_log_mask(LOG_GUEST_ERROR, 265 "[ARM]%s: CPU %" PRId64 " is already on\n", 266 __func__, cpuid); 267 return QEMU_ARM_POWERCTL_ALREADY_ON; 268 } 269 270 /* 271 * If another CPU has powered the target on we are in the state 272 * ON_PENDING and additional attempts to power on the CPU should 273 * fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI 274 * spec) 275 */ 276 if (target_cpu->power_state == PSCI_ON_PENDING) { 277 qemu_log_mask(LOG_GUEST_ERROR, 278 "[ARM]%s: CPU %" PRId64 " is already powering on\n", 279 __func__, cpuid); 280 return QEMU_ARM_POWERCTL_ON_PENDING; 281 } 282 283 async_run_on_cpu(target_cpu_state, arm_set_cpu_on_and_reset_async_work, 284 RUN_ON_CPU_NULL); 285 286 /* We are good to go */ 287 return QEMU_ARM_POWERCTL_RET_SUCCESS; 288 } 289 290 static void arm_set_cpu_off_async_work(CPUState *target_cpu_state, 291 run_on_cpu_data data) 292 { 293 ARMCPU *target_cpu = ARM_CPU(target_cpu_state); 294 295 assert(qemu_mutex_iothread_locked()); 296 target_cpu->power_state = PSCI_OFF; 297 target_cpu_state->halted = 1; 298 target_cpu_state->exception_index = EXCP_HLT; 299 } 300 301 int arm_set_cpu_off(uint64_t cpuid) 302 { 303 CPUState *target_cpu_state; 304 ARMCPU *target_cpu; 305 306 assert(qemu_mutex_iothread_locked()); 307 308 DPRINTF("cpu %" PRId64 "\n", cpuid); 309 310 /* change to the cpu we are powering up */ 311 target_cpu_state = arm_get_cpu_by_id(cpuid); 312 if (!target_cpu_state) { 313 return QEMU_ARM_POWERCTL_INVALID_PARAM; 314 } 315 target_cpu = ARM_CPU(target_cpu_state); 316 if (target_cpu->power_state == PSCI_OFF) { 317 qemu_log_mask(LOG_GUEST_ERROR, 318 "[ARM]%s: CPU %" PRId64 " is already off\n", 319 __func__, cpuid); 320 return QEMU_ARM_POWERCTL_IS_OFF; 321 } 322 323 /* Queue work to run under the target vCPUs context */ 324 async_run_on_cpu(target_cpu_state, arm_set_cpu_off_async_work, 325 RUN_ON_CPU_NULL); 326 327 return QEMU_ARM_POWERCTL_RET_SUCCESS; 328 } 329 330 static void arm_reset_cpu_async_work(CPUState *target_cpu_state, 331 run_on_cpu_data data) 332 { 333 /* Reset the cpu */ 334 cpu_reset(target_cpu_state); 335 } 336 337 int arm_reset_cpu(uint64_t cpuid) 338 { 339 CPUState *target_cpu_state; 340 ARMCPU *target_cpu; 341 342 assert(qemu_mutex_iothread_locked()); 343 344 DPRINTF("cpu %" PRId64 "\n", cpuid); 345 346 /* change to the cpu we are resetting */ 347 target_cpu_state = arm_get_cpu_by_id(cpuid); 348 if (!target_cpu_state) { 349 return QEMU_ARM_POWERCTL_INVALID_PARAM; 350 } 351 target_cpu = ARM_CPU(target_cpu_state); 352 353 if (target_cpu->power_state == PSCI_OFF) { 354 qemu_log_mask(LOG_GUEST_ERROR, 355 "[ARM]%s: CPU %" PRId64 " is off\n", 356 __func__, cpuid); 357 return QEMU_ARM_POWERCTL_IS_OFF; 358 } 359 360 /* Queue work to run under the target vCPUs context */ 361 async_run_on_cpu(target_cpu_state, arm_reset_cpu_async_work, 362 RUN_ON_CPU_NULL); 363 364 return QEMU_ARM_POWERCTL_RET_SUCCESS; 365 } 366