On Tue, Jan 02, 2024 at 09:11:07PM +0300, Vitaliy Makkoveev wrote:
> ifq_task_mtx initialized with IPL_NET priority, so this sequence
> started this.
>
> THR1 mtx_enter(&ifq->ifq_task_mtx)
> THR2 splnet() /* hv_wait(), just before hv_intr() */
> THR1 mtx_leave(&ifq->ifq_task_mtx)
> THR1 `-> Xspllower()
> THR1 skip
> THR1 `-> hv_intr()
>
> IMHO the spl*() protection in the network stack doesn???t work as
> expected.
I would say it works exactly as I expect.
Xresume_hyperv_upcall is registered in amd64/intr.c with IPL_NET.
#if NHYPERV > 0
isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO);
if (isp == NULL)
panic("can't allocate fixed interrupt source");
isp->is_recurse = Xrecurse_hyperv_upcall;
isp->is_resume = Xresume_hyperv_upcall;
fake_hyperv_intrhand.ih_level = IPL_NET;
isp->is_handlers = &fake_hyperv_intrhand;
isp->is_pic = &local_pic;
ci->ci_isources[LIR_HYPERV] = isp;
#endif
mtx_leave(&ifq->ifq_task_mtx) reduces the SPL level below SPL_NET.
So this code in spllower() jumps directly into Xrecurse_hyperv_upcall.
2: bsrq %rax,%rax
btrq %rax,CPUVAR(IPENDING)
movq CPUVAR(ISOURCES)(,%rax,8),%rax
movq IS_RECURSE(%rax),%rax
jmp retpoline_rax
END(Xspllower)
Xrecurse_hyperv_upcall jumps to Xresume_hyperv_upcall which calls
hv_intr, no hv_wait() involved.