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