|
30 | 30 | #define CPU_UP_TIMEOUT 100U /* millisecond */
|
31 | 31 | #define CPU_DOWN_TIMEOUT 100U /* millisecond */
|
32 | 32 |
|
| 33 | +#define AP_MASK (((1UL << phys_cpu_num) - 1UL) & ~(1UL << 0U)) |
| 34 | + |
33 | 35 | struct per_cpu_region per_cpu_data[CONFIG_MAX_PCPU_NUM] __aligned(PAGE_SIZE);
|
34 | 36 | static uint16_t phys_cpu_num = 0U;
|
35 | 37 | static uint64_t pcpu_sync = 0UL;
|
@@ -229,7 +231,9 @@ void init_cpu_post(uint16_t pcpu_id)
|
229 | 231 |
|
230 | 232 | /* Start all secondary cores */
|
231 | 233 | startup_paddr = prepare_trampoline();
|
232 |
| - start_cpus(); |
| 234 | + if (!start_cpus(AP_MASK)) { |
| 235 | + panic("Failed to start all secondary cores!"); |
| 236 | + } |
233 | 237 |
|
234 | 238 | ASSERT(get_cpu_id() == BOOT_CPU_ID, "");
|
235 | 239 | } else {
|
@@ -287,32 +291,45 @@ static void start_cpu(uint16_t pcpu_id)
|
287 | 291 |
|
288 | 292 | /* Check to see if expected CPU is actually up */
|
289 | 293 | if (!is_pcpu_active(pcpu_id)) {
|
290 |
| - /* Print error */ |
291 |
| - pr_fatal("Secondary CPUs failed to come up"); |
292 |
| - |
293 |
| - /* Error condition - loop endlessly for now */ |
294 |
| - do { |
295 |
| - } while (1); |
| 294 | + pr_fatal("Secondary CPU%hu failed to come up", pcpu_id); |
| 295 | + cpu_set_current_state(pcpu_id, PCPU_STATE_DEAD); |
296 | 296 | }
|
297 | 297 | }
|
298 | 298 |
|
299 |
| -void start_cpus(void) |
| 299 | + |
| 300 | +/** |
| 301 | + * @brief Start all cpus if the bit is set in mask except itself |
| 302 | + * |
| 303 | + * @param[in] mask bits mask of cpus which should be started |
| 304 | + * |
| 305 | + * @return true if all cpus set in mask are started |
| 306 | + * @return false if there are any cpus set in mask aren't started |
| 307 | + */ |
| 308 | +bool start_cpus(uint64_t mask) |
300 | 309 | {
|
301 | 310 | uint16_t i;
|
| 311 | + uint16_t pcpu_id = get_cpu_id(); |
| 312 | + uint64_t expected_start_mask = mask; |
302 | 313 |
|
303 | 314 | /* secondary cpu start up will wait for pcpu_sync -> 0UL */
|
304 | 315 | atomic_store64(&pcpu_sync, 1UL);
|
305 | 316 |
|
306 |
| - for (i = 0U; i < phys_cpu_num; i++) { |
307 |
| - if (get_cpu_id() == i) { |
308 |
| - continue; |
| 317 | + i = ffs64(expected_start_mask); |
| 318 | + while (i != INVALID_BIT_INDEX) { |
| 319 | + bitmap_clear_nolock(i, &expected_start_mask); |
| 320 | + |
| 321 | + if (pcpu_id == i) { |
| 322 | + continue; /* Avoid start itself */ |
309 | 323 | }
|
310 | 324 |
|
311 | 325 | start_cpu(i);
|
| 326 | + i = ffs64(expected_start_mask); |
312 | 327 | }
|
313 | 328 |
|
314 | 329 | /* Trigger event to allow secondary CPUs to continue */
|
315 | 330 | atomic_store64(&pcpu_sync, 0UL);
|
| 331 | + |
| 332 | + return ((pcpu_active_bitmap & mask) == mask); |
316 | 333 | }
|
317 | 334 |
|
318 | 335 | void stop_cpus(void)
|
|
0 commit comments