UNDI ISR: save and restore 32-bit registers
authorH. Peter Anvin <hpa@zytor.com>
Sat, 9 Feb 2008 00:19:02 +0000 (16:19 -0800)
committerMichael Brown <mcb30@etherboot.org>
Mon, 11 Feb 2008 15:09:47 +0000 (15:09 +0000)
As written, if the if the UNDI ISR call clobbers the upper halves of
any of the GPRs (which by convention it is permitted to do, and by
paranoia should be expected to do) then nothing in the interrupt
handler will recover the state.

Additionally, save/restore %fs and %gs out of sheer paranoia - it's a
cheap enough operation, and may prevent problems due to poorly written
UNDI stacks.

src/arch/i386/drivers/net/undiisr.S

index 2463014..15e1a63 100644 (file)
@@ -21,7 +21,9 @@ undiisr:
        /* Preserve registers */
        pushw   %ds
        pushw   %es
        /* Preserve registers */
        pushw   %ds
        pushw   %es
-       pusha
+       pushw   %fs
+       pushw   %gs
+       pushal
 
        /* Set up our segment registers */
        movw    %cs:rm_ds, %ax
 
        /* Set up our segment registers */
        movw    %cs:rm_ds, %ax
@@ -32,8 +34,7 @@ undiisr:
        je      chain
        
        /* Issue UNDI API call */
        je      chain
        
        /* Issue UNDI API call */
-       pushw   %ds
-       popw    %es
+       movw    %ax, %es
        movw    $undinet_params, %di
        movw    $PXENV_UNDI_ISR, %bx
        movw    $PXENV_UNDI_ISR_IN_START, funcflag
        movw    $undinet_params, %di
        movw    $PXENV_UNDI_ISR, %bx
        movw    $PXENV_UNDI_ISR_IN_START, funcflag
@@ -62,7 +63,9 @@ chain:        /* Chain to next handler */
        lcall   *undiisr_next_handler
        
 exit:  /* Restore registers and return */
        lcall   *undiisr_next_handler
        
 exit:  /* Restore registers and return */
-       popa
+       popal
+       popw    %gs
+       popw    %fs
        popw    %es
        popw    %ds
        iret
        popw    %es
        popw    %ds
        iret