aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2013-03-02 18:14:35 -0500
committerKevin O'Connor <kevin@koconnor.net>2013-03-03 15:45:01 -0500
commitf0d75a010e15be66e01211822e6f4e3c82ad8725 (patch)
treee7d7662809ef9f60d24a2edb49bc963afe883041
parent922aa1ba0a76086e5b6bacaaf4ee4211625a6764 (diff)
downloadseabios-f0d75a010e15be66e01211822e6f4e3c82ad8725.tar.gz
Support using the "extra stack" for all 16bit irq entry points.
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>
-rw-r--r--src/Kconfig9
-rw-r--r--src/romlayout.S58
2 files changed, 67 insertions, 0 deletions
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