Hi,

After some extensive hair pulling by OpenBSD developers and discussions
with friendly folks at Microsoft, we've come to a conclusion that the
reason why Hyper-V legacy network controller doesn't work on OpenBSD
is due to particularities in the low level interrupt acknowledgement
code.

Basically an I/O APIC (or an I/O APIC emulation) may get stuck and
won't deliver further interrupts if an interrupt is acknowledged
after being masked in an associated Routing Table Entry (RTE).

Our implementation masks interrupt sources only when it needs to defer
servicing the interrupt due to the Interrupt Priority Level being too
high.  It would also go ahead and acknowledge the interrupt after
masking it and then acknowledge again after being called to resume
servicing the interrupt and unmasking it.  This behavior is deemed
needlessly excessive and potentially harmful.

The change has already  been tested by a few people and is included in
the latest snapshot, but we would welcome tests on older amd64 hardware
(laptops, Opterons, Athlons, etc) to make sure we're not introducing a
regression.

Cheers,
Mike


diff --git sys/arch/amd64/amd64/vector.S sys/arch/amd64/amd64/vector.S
index f60d725..107d11e 100644
--- sys/arch/amd64/amd64/vector.S
+++ sys/arch/amd64/amd64/vector.S
@@ -540,19 +540,17 @@ IDTVEC(intr_##name##num)                                  
        ;\
 7:                                                                     \
        cli                                                             ;\
        movq    $(1 << num),%rax                                        ;\
        orq     %rax,CPUVAR(IPENDING)                                   ;\
        level_mask(num)                                                 ;\
-       late_ack(num)                                                   ;\
        sti                                                             ;\
        jmp     _C_LABEL(Xdoreti)       /* lower spl and do ASTs */     ;\
 10:                                                                    \
        cli                                                             ;\
        movq    $(1 << num),%rax                                        ;\
        orq     %rax,CPUVAR(IPENDING)                                   ;\
        level_mask(num)                                                 ;\
-       late_ack(num)                                                   ;\
        INTRFASTEXIT                                                    ;\
 9:                                                                     \
        unmask(num)                                                     ;\
        late_ack(num)                                                   ;\
        INTRFASTEXIT

Reply via email to