diff --git a/driver/hvisor_main.c b/driver/hvisor_main.c index 11fca95e..76345253 100644 --- a/driver/hvisor_main.c +++ b/driver/hvisor_main.c @@ -471,6 +471,12 @@ static irqreturn_t virtio_irq_handler(int irq, void *dev_id) { pr_err("eventfd_signal: counter overflow or no increment\n"); #endif +#ifdef LOONGARCH64 + /* Re-arm the level-like wakeup line after recording the eventfd kick. */ + if (hvisor_call(HVISOR_HC_CLEAR_INJECT_IRQ, 0, HVISOR_VIRTIO_WAKEUP_HWI)) + pr_err_ratelimited("failed to acknowledge virtio wakeup HWI\n"); +#endif + return IRQ_HANDLED; } diff --git a/include/hvisor.h b/include/hvisor.h index df448b93..68b77c48 100644 --- a/include/hvisor.h +++ b/include/hvisor.h @@ -212,6 +212,7 @@ struct hvisor_scmi_power_args { #define HVISOR_DEASSERT_IRQ _IOW(1, 11, struct hvisor_irq_line_args) #define HVISOR_HC_CLEAR_INJECT_IRQ 11 // hvcall code in hvisor +#define HVISOR_VIRTIO_WAKEUP_HWI 4 // LoongArch CPUINTC HWI2 #endif /* LOONGARCH64 */ #ifdef LOONGARCH64 diff --git a/tools/virtio/virtio.c b/tools/virtio/virtio.c index 2d3cc4e0..244f783e 100644 --- a/tools/virtio/virtio.c +++ b/tools/virtio/virtio.c @@ -1391,14 +1391,24 @@ void handle_virtio_requests(void) { return; } - // Initial state: Mark backend as ready to receive notifications - __atomic_store_n(&virtio_bridge->need_wakeup, 1, memory_order_relaxed); - log_info("virtio request handler loop started."); int signal_count = 0, proc_count = 0; struct epoll_event events[16]; + +#ifdef LOONGARCH64 + /* + * Drain requests that may have arrived before the event loop became ready. + * consume_pending_requests() also performs the sleep handshake: it sets + * need_wakeup, issues a full barrier, and rechecks the ring before + * returning. + */ + proc_count += consume_pending_requests(); +#else + // Preserve the existing initialization behavior on other architectures. + __atomic_store_n(&virtio_bridge->need_wakeup, 1, memory_order_relaxed); +#endif + while (true) { -#ifndef LOONGARCH64 log_debug("signal_count is %d, proc_count is %d", signal_count, proc_count); @@ -1428,14 +1438,11 @@ void handle_virtio_requests(void) { if (read(efd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) { continue; } -#endif // Process all pending requests until the ring is empty proc_count += consume_pending_requests(); -#ifndef LOONGARCH64 } } -#endif } }