From 621c2886aa0eb41e49923996c1853b861f7e7e96 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 8 Feb 2008 16:19:02 -0800 Subject: [PATCH 1/2] UNDI ISR: save and restore 32-bit registers 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 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/arch/i386/drivers/net/undiisr.S b/src/arch/i386/drivers/net/undiisr.S index 24630148..15e1a63a 100644 --- a/src/arch/i386/drivers/net/undiisr.S +++ b/src/arch/i386/drivers/net/undiisr.S @@ -21,7 +21,9 @@ undiisr: /* Preserve registers */ pushw %ds pushw %es - pusha + pushw %fs + pushw %gs + pushal /* Set up our segment registers */ movw %cs:rm_ds, %ax @@ -32,8 +34,7 @@ undiisr: 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 @@ -62,7 +63,9 @@ chain: /* Chain to next handler */ lcall *undiisr_next_handler exit: /* Restore registers and return */ - popa + popal + popw %gs + popw %fs popw %es popw %ds iret From 9aec835541ffc2f5f959fd1fa9367c4e2754db2c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 10 Feb 2008 18:13:06 -0800 Subject: [PATCH 2/2] undiisr.S: save/restore upper half of %eflags Since we don't know what the UNDI code does, it is safest to save/restore %eflags even though the lower half of %eflags is automatically saved by the interrupt itself. --- src/arch/i386/drivers/net/undiisr.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/i386/drivers/net/undiisr.S b/src/arch/i386/drivers/net/undiisr.S index 15e1a63a..f1c9eb15 100644 --- a/src/arch/i386/drivers/net/undiisr.S +++ b/src/arch/i386/drivers/net/undiisr.S @@ -23,6 +23,7 @@ undiisr: pushw %es pushw %fs pushw %gs + pushfl pushal /* Set up our segment registers */ @@ -64,6 +65,7 @@ chain: /* Chain to next handler */ exit: /* Restore registers and return */ popal + popfl popw %gs popw %fs popw %es