This series creates a config option for using the "extra stack" for all legacy 16bit irq entry points, and it defaults the option on. By using this internal stack, SeaBIOS doesn't use much of the caller's stack and it makes it less likely a stack overflow will occur. However, using an internal stack could break programs that call the BIOS in 16bit protected mode.
This series was discussed about a year ago. There haven't been any examples located where this breaks OSes, and it is known to improve some really old OSes (eg, DOS 1.0). It is a config option, so if it can be disabled to aid in testing.
Kevin O'Connor (2): Separate out 16bit PCI-BIOS entry point from regular int 0x1a entry point. Support using the "extra stack" for all 16bit irq entry points.
src/Kconfig | 9 +++++++ src/clock.c | 1 - src/config.h | 2 +- src/pcibios.c | 16 ++++++------- src/post.c | 2 +- src/romlayout.S | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 90 insertions(+), 13 deletions(-)
The PCI-BIOS entry point can be called in 16bit protected mode, so separate its entry code from the legacy 0x1a code.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/clock.c | 1 - src/config.h | 2 +- src/pcibios.c | 16 ++++++++-------- src/post.c | 2 +- src/romlayout.S | 15 +++++++++++++-- 5 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/src/clock.c b/src/clock.c index 79b18f9..2ab6adb 100644 --- a/src/clock.c +++ b/src/clock.c @@ -552,7 +552,6 @@ handle_1a(struct bregs *regs) case 0x05: handle_1a05(regs); break; case 0x06: handle_1a06(regs); break; case 0x07: handle_1a07(regs); break; - case 0xb1: handle_1ab1(regs); break; default: handle_1aXX(regs); break; } } diff --git a/src/config.h b/src/config.h index 0b9b1ab..8b888b9 100644 --- a/src/config.h +++ b/src/config.h @@ -94,7 +94,7 @@ #define DEBUG_ISR_hwpic2 5 #define DEBUG_HDL_pnp 1 #define DEBUG_HDL_pmm 1 -#define DEBUG_HDL_pcibios32 9 +#define DEBUG_HDL_pcibios 9 #define DEBUG_HDL_apm 9
#define DEBUG_unimplemented 2 diff --git a/src/pcibios.c b/src/pcibios.c index 0f3ec5b..3c5f519 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -201,19 +201,19 @@ handle_1ab1(struct bregs *regs) } }
+// Entry point for pci bios functions. +void VISIBLE16 VISIBLE32SEG +handle_pcibios(struct bregs *regs) +{ + debug_enter(regs, DEBUG_HDL_pcibios); + handle_1ab1(regs); +} +
/**************************************************************** * 32bit interface ****************************************************************/
-// Entry point for 32bit pci bios functions. -void VISIBLE32SEG -handle_pcibios32(struct bregs *regs) -{ - debug_enter(regs, DEBUG_HDL_pcibios32); - handle_1ab1(regs); -} - struct bios32_s { u32 signature; u32 entry; diff --git a/src/post.c b/src/post.c index 4d3262f..ff201fa 100644 --- a/src/post.c +++ b/src/post.c @@ -64,7 +64,7 @@ ivt_init(void) SET_IVT(0x17, FUNC16(entry_17)); SET_IVT(0x18, FUNC16(entry_18)); SET_IVT(0x19, FUNC16(entry_19_official)); - SET_IVT(0x1a, FUNC16(entry_1a)); + SET_IVT(0x1a, FUNC16(entry_1a_official)); SET_IVT(0x40, FUNC16(entry_40));
// INT 60h-66h reserved for user interrupt diff --git a/src/romlayout.S b/src/romlayout.S index b1628ef..b152b3e 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -334,19 +334,26 @@ entry_apm32: popfl lretl
-// PCI-BIOS 32bit entry point +// PCI-BIOS entry points DECLFUNC entry_pcibios32 entry_pcibios32: pushfl pushl %gs // Backup %gs and set %gs=%ds pushl %ds popl %gs - ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32 + ENTRY_ARG_ESP _cfunc32seg_handle_pcibios popl %gs popfl lretl
+ .code16gcc + DECLFUNC entry_pcibios16 +entry_pcibios16: + ENTRY_ARG handle_pcibios + iretw + // BIOS32 support + .code32 DECLFUNC entry_bios32 entry_bios32: pushfl @@ -600,6 +607,10 @@ entry_10_0x0f: // 0xfa6e - vgafont8 in font.c
ORG 0xfe6e + .global entry_1a_official +entry_1a_official: + cmpb $0xb1, %ah + je entry_pcibios16 // PCIBIOS calls can be in protected mode IRQ_ENTRY_ARG 1a
ORG 0xfea5
Using the internal stack reduces the amount of space that SeaBIOS uses on the caller's stack. This is known to help some very old operating systems (like DOS 1.0). However, there is a possibility that this will break any operating systems that calls a legacy 16bit irq in 16bit protected mode (no OSes have yet to be identified as doing this), so make the ability config dependent.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/Kconfig | 9 +++++++++ src/romlayout.S | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+)
diff --git a/src/Kconfig b/src/Kconfig index 98a6642..3141069 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -103,6 +103,15 @@ endchoice default y help Support floppy images in coreboot flash. + config ENTRY_EXTRASTACK + bool "Use internal stack for 16bit interrupt entry points" + default y + help + Utilize an internal stack for all the legacy 16bit + interrupt entry points. This reduces the amount of space + on the caller's stack that SeaBIOS uses. This may + adversely impact any legacy operating systems that call + the BIOS in 16bit protected mode.
endmenu
diff --git a/src/romlayout.S b/src/romlayout.S index b152b3e..291b798 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -480,6 +480,60 @@ irqentry_extrastack: popw %ds iretw
+ // Main entry point for interrupts handled on extra stack + DECLFUNC irqentry_arg_extrastack +irqentry_arg_extrastack: + cli + cld + pushw %ds // Set %ds:%eax to space on ExtraStack + pushl %eax + movl $_zonelow_seg, %eax + movl %eax, %ds + movl StackPos, %eax + subl $BREGS_size+8, %eax + popl BREGS_eax(%eax) // Backup registers + 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) + popl %ecx + movw %es, BREGS_es(%eax) + movl %esp, BREGS_size+0(%eax) + movzwl %sp, %esp + movw %ss, BREGS_size+4(%eax) + movl (%esp), %edx + movl %edx, BREGS_code(%eax) + movw 4(%esp), %dx + movw %dx, BREGS_flags(%eax) + + movw %ds, %dx // Setup %ss/%esp and call function + movw %dx, %ss + movl %eax, %esp + calll *%ecx + + movl %esp, %eax // Restore registers and return + movw BREGS_size+4(%eax), %ss + movl BREGS_size+0(%eax), %esp + popl %edx + popw %dx + pushw BREGS_flags(%eax) + pushl BREGS_code(%eax) + 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_ds(%eax) + pushl BREGS_eax(%eax) + popl %eax + popw %ds + iretw + // Main entry point for interrupts with args DECLFUNC irqentryarg irqentryarg: @@ -504,7 +558,11 @@ irqentryarg: .global entry_\num entry_\num : pushl $ handle_\num +#if CONFIG_ENTRY_EXTRASTACK + jmp irqentry_arg_extrastack +#else jmp irqentryarg +#endif .endm
.macro DECL_IRQ_ENTRY_ARG num