From a83ff550b4cbf0b1bc35f493c8715a69a9e28b7e Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Thu, 1 Jan 2009 21:00:59 -0500 Subject: [PATCH] Reduce stack usage of hw irq handlers. Avoid using call16_int() -- it consumes too much stack space. Instead, use a new function (call16_simpint). This assumes that the handler wont corrupt regs - which should be a safe assumption, because if they did corrupt regs they wouldn't work on any bios. Avoid enabling irqs in the hw irq handlers - there are no loops in the handlers that could cause any notable latency. --- src/clock.c | 14 ++++---------- src/kbd.c | 21 +++++++++------------ src/mouse.c | 9 +++++---- src/system.c | 5 ++--- src/util.c | 19 +++++++++++++++++++ src/util.h | 9 ++++----- 6 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/clock.c b/src/clock.c index c76ea75..caa94ba 100644 --- a/src/clock.c +++ b/src/clock.c @@ -411,7 +411,6 @@ void VISIBLE16 handle_08() { debug_isr(DEBUG_ISR_08); - irq_enable(); floppy_tick(); @@ -427,11 +426,8 @@ handle_08() SET_BDA(timer_counter, counter); // chain to user timer tick INT #0x1c - struct bregs br; - memset(&br, 0, sizeof(br)); - call16_int(0x1c, &br); - - irq_disable(); + u32 eax=0, flags; + call16_simpint(0x1c, &eax, &flags); eoi_pic1(); } @@ -541,10 +537,8 @@ handle_70() goto done; if (registerC & 0x20) { // Handle Alarm Interrupt. - struct bregs br; - memset(&br, 0, sizeof(br)); - call16_int(0x4a, &br); - irq_disable(); + u32 eax=0, flags; + call16_simpint(0x4a, &eax, &flags); } if (!(registerC & 0x40)) goto done; diff --git a/src/kbd.c b/src/kbd.c index 9c59005..3af7033 100644 --- a/src/kbd.c +++ b/src/kbd.c @@ -418,7 +418,10 @@ static struct scaninfo { { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ }; -static void +// Handle a scancode read from the ps2 port. Note that "noinline" is +// used to make sure the call to call16_simpint in handle_09 doesn't +// have the overhead of this function's stack. +static void noinline process_key(u8 scancode) { u8 shift_flags = GET_BDA(kbd_flag0); @@ -620,23 +623,17 @@ handle_09() } u8 key = inb(PORT_PS2_DATA); - irq_enable(); if (CONFIG_KBD_CALL_INT15_4F) { // allow for keyboard intercept - struct bregs tr; - memset(&tr, 0, sizeof(tr)); - tr.al = key; - tr.ah = 0x4f; - tr.flags = F_CF; - call16_int(0x15, &tr); - if (!(tr.flags & F_CF)) + u32 eax = (0x4f << 8) | key; + u32 flags; + call16_simpint(0x15, &eax, &flags); + if (!(flags & F_CF)) goto done; - key = tr.al; + key = eax; } process_key(key); - irq_disable(); - done: eoi_pic1(); } diff --git a/src/mouse.c b/src/mouse.c index 6c74fc1..65baa20 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -319,6 +319,8 @@ int74_function() SET_EBDA2(ebda_seg, mouse_flag1, 0); u32 func = GET_EBDA2(ebda_seg, far_call_pointer); + + irq_enable(); asm volatile( "pushl %0\n" "pushw %w1\n" // status @@ -328,10 +330,11 @@ int74_function() "lcallw *8(%%esp)\n" "addl $12, %%esp\n" "cld\n" - : "+a" (func), "+b" (status), "+c" (X), "+d" (Y) : - : "esi", "edi", "ebp", "cc" + : "r"(func), "r"(status), "r"(X), "r"(Y) + : "cc" ); + irq_disable(); } // INT74h : PS/2 mouse hardware interrupt @@ -342,9 +345,7 @@ handle_74() if (! CONFIG_PS2_MOUSE) goto done; - irq_enable(); int74_function(); - irq_disable(); done: eoi_pic2(); diff --git a/src/system.c b/src/system.c index 235e88c..47d5817 100644 --- a/src/system.c +++ b/src/system.c @@ -399,7 +399,6 @@ handle_75() // clear interrupt eoi_pic2(); // legacy nmi call - struct bregs br; - memset(&br, 0, sizeof(br)); - call16_int(0x02, &br); + u32 eax=0, flags; + call16_simpint(0x02, &eax, &flags); } diff --git a/src/util.c b/src/util.c index b94f0d1..abc1fb2 100644 --- a/src/util.c +++ b/src/util.c @@ -48,6 +48,25 @@ __call16_int(struct bregs *callregs, u16 offset) call16(callregs); } +inline void +call16_simpint(int nr, u32 *eax, u32 *flags) +{ + extern void __force_link_error__call16_simpint_only_in_16bit_mode(); + if (!MODE16) + __force_link_error__call16_simpint_only_in_16bit_mode(); + + asm volatile( + "stc\n" + "int %2\n" + "pushfl\n" + "popl %1\n" + "cld\n" + "cli\n" + : "+a"(*eax), "=r"(*flags) + : "i"(nr) + : "cc", "memory"); +} + // Switch to the extra stack in ebda and call a function. inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func) diff --git a/src/util.h b/src/util.h index 5db1ba0..acd5d0c 100644 --- a/src/util.h +++ b/src/util.h @@ -65,11 +65,13 @@ static inline u64 rdtscll(void) return val; } +// util.c +inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func); +u8 checksum(u8 *far_data, u32 len); void *memset(void *s, int c, size_t n); void *memcpy(void *d1, const void *s1, size_t len); void *memcpy_far(void *far_d1, const void *far_s1, size_t len); void *memmove(void *d, const void *s, size_t len); - struct bregs; inline void call16(struct bregs *callregs); inline void call16big(struct bregs *callregs); @@ -78,6 +80,7 @@ inline void __call16_int(struct bregs *callregs, u16 offset); extern void irq_trampoline_ ##nr (); \ __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \ } while (0) +inline void call16_simpint(int nr, u32 *eax, u32 *flags); // output.c void debug_serial_setup(); @@ -137,10 +140,6 @@ void VISIBLE16 handle_1553(struct bregs *regs); // pcibios.c void handle_1ab1(struct bregs *regs); -// util.c -inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func); -u8 checksum(u8 *far_data, u32 len); - // shadow.c void make_bios_writable(); void make_bios_readonly(); -- 2.39.5