The winxp boot loader does something curious - it sets an int 0x1c
handler, records the stack location, and then spins in place with irqs
enabled. The 0x1c handler alters the memory just past the stack
pointer so that when the timer irq returns the code jumps to a new
location and stop spinning. The winxp code relies on the fact that a
hw irq will always place 6 bytes at a specific location and that it
can alter those bytes.
The
ecdc655a patch does a full backup/restore of the register state.
Unfortunately, the restore overwrites the changes made by the winxp
0x1c handler.
This patch reverts much of
ecdc655a. Hardware irqs are still handled
on the extra stack, but only the essential register state is backed up
and restored.
Also, stack_hop_back is changed to only use %sp when changing states -
this enables the entry code to store just %esp instead of both %esp
and %sp.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
// INT 08h System Timer ISR Entry Point
void VISIBLE16
-handle_08(struct bregs *regs)
+handle_08(void)
{
- debug_enter(regs, DEBUG_ISR_08);
+ debug_isr(DEBUG_ISR_08);
floppy_tick();
// int70h: IRQ8 - CMOS RTC
void VISIBLE16
-handle_70(struct bregs *regs)
+handle_70(void)
{
- debug_enter(regs, DEBUG_ISR_70);
+ debug_isr(DEBUG_ISR_70);
// Check which modes are enabled and have occurred.
u8 registerB = inb_cmos(CMOS_STATUS_B);
// record completion in BIOS task complete flag
void VISIBLE16
-handle_76(struct bregs *regs)
+handle_76(void)
{
- debug_enter(regs, DEBUG_ISR_76);
+ debug_isr(DEBUG_ISR_76);
SET_BDA(disk_interrupt_flag, 0xff);
eoi_pic2();
}
// INT 0Eh Diskette Hardware ISR Entry Point
void VISIBLE16
-handle_0e(struct bregs *regs)
+handle_0e(void)
{
- debug_enter(regs, DEBUG_ISR_0e);
+ debug_isr(DEBUG_ISR_0e);
if (! CONFIG_FLOPPY)
goto done;
// NMI handler
void VISIBLE16
-handle_02(struct bregs *regs)
+handle_02(void)
{
- debug_enter(regs, DEBUG_ISR_02);
+ debug_isr(DEBUG_ISR_02);
}
void
// INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION
void VISIBLE16
-handle_75(struct bregs *regs)
+handle_75(void)
{
- debug_enter(regs, DEBUG_ISR_75);
+ debug_isr(DEBUG_ISR_75);
// clear irq13
outb(0, PORT_MATH_CLEAR);
, regs->code.seg, regs->code.offset, regs->flags);
}
+// Report entry to an Interrupt Service Routine (ISR).
+void
+__debug_isr(const char *fname)
+{
+ puts_cs(&debuginfo, fname);
+ putc(&debuginfo, '\n');
+ debug_serial_flush();
+}
+
// Function called on handler startup.
void
__debug_enter(struct bregs *regs, const char *fname)
// INT74h : PS/2 mouse hardware interrupt
void VISIBLE16
-handle_74(struct bregs *regs)
+handle_74(void)
{
if (! CONFIG_PS2PORT)
return;
- debug_enter(regs, DEBUG_ISR_74);
+ debug_isr(DEBUG_ISR_74);
u8 v = inb(PORT_PS2_STATUS);
if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
// INT09h : Keyboard Hardware Service Entry Point
void VISIBLE16
-handle_09(struct bregs *regs)
+handle_09(void)
{
if (! CONFIG_PS2PORT)
return;
- debug_enter(regs, DEBUG_ISR_09);
+ debug_isr(DEBUG_ISR_09);
// read key from keyboard controller
u8 v = inb(PORT_PS2_STATUS);
irqentry_extrastack:
cli
cld
- pushw %ds
+ pushw %ds // Set %ds:%eax to space on ExtraStack
pushl %eax
movl $_datalow_seg, %eax
movl %eax, %ds
movl StackPos, %eax
- subl $BREGS_size+12, %eax
- popl BREGS_eax(%eax)
- popw BREGS_ds(%eax)
- movl %edi, BREGS_edi(%eax)
- movl %esi, BREGS_esi(%eax)
- movl %ebp, BREGS_ebp(%eax)
- movl %ebx, BREGS_ebx(%eax)
- movl %edx, BREGS_edx(%eax)
- movl %ecx, BREGS_ecx(%eax)
- movw %es, BREGS_es(%eax)
+ subl $24, %eax
+ popl 0(%eax) // Backup %eax, %ds, %es, %ecx, %edx
+ popw 4(%eax)
+ movw %es, 6(%eax)
+ movl %ecx, 8(%eax)
popl %ecx
- popl BREGS_code(%eax)
- popw BREGS_flags(%eax)
-
- movw %ss, BREGS_size+8(%eax)
- movzwl %sp, %edx
- movl %edx, BREGS_size+4(%eax)
- movl %esp, BREGS_size+0(%eax)
- movw %ds, %dx
+ movl %edx, 12(%eax)
+ movl %esp, 16(%eax)
+ movzwl %sp, %esp
+ movw %ss, 20(%eax)
+
+ movw %ds, %dx // Setup %ss/%esp and call function
movw %dx, %ss
movl %eax, %esp
calll *%ecx
- movl %esp, %eax
- movw BREGS_size+8(%eax), %ss
- movl BREGS_size+0(%eax), %esp
- movl BREGS_edi(%eax), %edi
- movl BREGS_esi(%eax), %esi
- movl BREGS_ebp(%eax), %ebp
- movl BREGS_ebx(%eax), %ebx
- movl BREGS_edx(%eax), %edx
- movl BREGS_ecx(%eax), %ecx
- movw BREGS_es(%eax), %es
- pushw BREGS_flags(%eax)
- pushl BREGS_code(%eax)
- pushw BREGS_ds(%eax)
- pushl BREGS_eax(%eax)
+ movl %esp, %eax // Restore registers and return
+ movw 20(%eax), %ss
+ movl 16(%eax), %esp
+ movl 12(%eax), %edx
+ movl 8(%eax), %ecx
+ movw 6(%eax), %es
+ pushw 4(%eax)
+ pushl 0(%eax)
popl %eax
popw %ds
iretw
// Restore original callers' %ss/%esp
"movl -4(%4), %5\n"
"movl %5, %%ss\n"
- "movl %%ds:-8(%4), %%esp\n"
+ "movw %%ds:-8(%4), %%sp\n"
"movl %5, %%ds\n"
// Call func
"calll *%2\n"
void __dprintf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
void __debug_enter(struct bregs *regs, const char *fname);
+void __debug_isr(const char *fname);
void __debug_stub(struct bregs *regs, int lineno, const char *fname);
void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
__debug_enter((regs), __func__); \
} while (0)
+#define debug_isr(lvl) do { \
+ if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
+ __debug_isr(__func__); \
+ } while (0)
#define debug_stub(regs) \
__debug_stub((regs), __LINE__, __func__)
#define warn_invalid(regs) \