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