Closed ChinYikMing closed 3 months ago
You should clarify WFI implementation. WFI is crucial for SMP awareness, and I did the following incomplete work for semu. (Linux only)
static uint64_t read_time(vm_t *vm)
{
emu_state_t *data = (emu_state_t *) vm->priv;
return data->time;
}
static void wfi(vm_t *vm)
{
emu_state_t *data = (emu_state_t *) vm->priv;
struct timespec start;
clock_gettime(CLOCK_MONOTONIC, &start);
struct pollfd pfd[] = {
{data->timer_fd, 0, 0},
};
if (data->time < data->timer) {
int64_t ticks = data->timer - data->time;
ticks = (ticks * 1e9) / CLOCK_FREQ;
struct itimerspec spec = {
{0, 0},
{ticks / (int64_t) 1e9, ticks % (int64_t) 1e9},
};
timerfd_settime(data->timer_fd, 0, &spec, NULL);
pfd[0].events |= POLLIN;
}
while (!(vm->sip & vm->sie)) {
int ret = poll(pfd, sizeof(pfd) / sizeof(*pfd), -1);
assert(ret >= 0);
if (pfd[0].revents & POLLIN) {
vm->sip |= RV_INT_STI_BIT;
pfd[0].events &= ~POLLIN;
}
}
struct timespec end;
clock_gettime(CLOCK_MONOTONIC, &end);
int64_t ticks =
(end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec);
data->time += (ticks * CLOCK_FREQ) / 1e9;
}
The Wait for Interrupt instruction (WFI) provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing. As well, Linux kernel might call wait_for_interrupt() to enter idle state. In this commit, we could simply make PC + 4 and not really enter idle state.
Related: #310