Skip to content

Commit c2809ea

Browse files
authored
Merge pull request #111 from sysprog21/fix-smp4-boot-hang
Fix SMP=4 boot hang regression
2 parents a56f5bd + 523748e commit c2809ea

File tree

1 file changed

+13
-15
lines changed

1 file changed

+13
-15
lines changed

main.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,22 +1191,20 @@ static int semu_run(emu_state_t *emu)
11911191
size_t pfd_count = 0;
11921192
int timer_index = -1;
11931193

1194-
/* Add periodic timer fd (1ms interval for guest timer emulation).
1195-
* Only add timer when ALL harts are active (none idle) to allow
1196-
* poll() to sleep when any harts are in WFI. When harts are idle,
1197-
* timer updates can be deferred until they wake up.
1198-
*
1199-
* During SMP boot (started_harts < vm->n_hart), always include the
1200-
* timer to ensure secondary harts can complete initialization. Only
1201-
* apply conditional exclusion after all harts have started.
1202-
*
1203-
* For single-hart configurations (n_hart == 1), disable
1204-
* optimization entirely to avoid boot issues, as the first hart
1205-
* starts immediately.
1194+
/* Add periodic timer fd (1ms interval). Excluded when harts are
1195+
* idle to allow poll() sleep, but always included during:
1196+
* 1. Single-hart mode (n_hart == 1)
1197+
* 2. Boot phase (!boot_complete) - prevents deadlock when kernel
1198+
* briefly puts all harts in WFI while waiting for timer IRQ
1199+
* 3. Active execution (idle_harts == 0)
12061200
*/
12071201
bool all_harts_started = (started_harts >= vm->n_hart);
1202+
const uint64_t BOOT_SETTLE_ITERATIONS = 5000;
1203+
bool boot_complete =
1204+
all_harts_started &&
1205+
(emu->peripheral_update_ctr > BOOT_SETTLE_ITERATIONS);
12081206
bool harts_active =
1209-
(vm->n_hart == 1) || !all_harts_started || (idle_harts == 0);
1207+
(vm->n_hart == 1) || !boot_complete || (idle_harts == 0);
12101208
#ifdef __APPLE__
12111209
/* macOS: use kqueue with EVFILT_TIMER */
12121210
if (kq >= 0 && pfd_count < poll_capacity && harts_active) {
@@ -1227,7 +1225,7 @@ static int semu_run(emu_state_t *emu)
12271225
/* Add UART input fd (stdin for keyboard input).
12281226
* Only add UART when:
12291227
* 1. Single-hart configuration (n_hart == 1), OR
1230-
* 2. Not all harts started (!all_harts_started), OR
1228+
* 2. Boot not complete (!boot_complete), OR
12311229
* 3. All harts are active (idle_harts == 0), OR
12321230
* 4. A hart is actively waiting for UART input
12331231
*
@@ -1236,7 +1234,7 @@ static int semu_run(emu_state_t *emu)
12361234
* input (Ctrl+A x) may be delayed by up to poll_timeout (10ms)
12371235
* when harts are idle, which is acceptable for an emulator.
12381236
*/
1239-
bool need_uart = (vm->n_hart == 1) || !all_harts_started ||
1237+
bool need_uart = (vm->n_hart == 1) || !boot_complete ||
12401238
(idle_harts == 0) || emu->uart.has_waiting_hart;
12411239
if (emu->uart.in_fd >= 0 && pfd_count < poll_capacity &&
12421240
need_uart) {

0 commit comments

Comments
 (0)