This simple series changes SeaBIOS to use its extra stack for all regular real-mode software interrupt entry points. This has the advantage of using significantly less stack space, which can make old programs more likely to run. As an example, SeaBIOS can boot and run DOS 1.0 with this series applied.
However, by using the extra stack (which resides in the e-segment), the code will likely not work for any code that invokes the real-mode software interrupts while in 16bit protected mode. I don't believe that is common, but it is difficult to know if there are any users. I will send a separate email on that topic.
-Kevin
Kevin O'Connor (2): Check for and handle PCI BIOS calls separately from handle_1a path. Jump into extra stack for all regular real-mode software irq entry points.
src/clock.c | 2 +- src/config.h | 2 +- src/pcibios.c | 12 ++++++++-- src/post.c | 2 +- src/romlayout.S | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/util.h | 1 - 6 files changed, 76 insertions(+), 11 deletions(-)
The PCI BIOS spec requires that the real-mode entry point (either int 0x1a or jump to f000:fe6e) support 16bit protected mode calls. So, handle that separately to ensure it works properly.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/clock.c | 2 +- src/config.h | 2 +- src/pcibios.c | 12 ++++++++++-- src/post.c | 2 +- src/romlayout.S | 12 +++++++++++- src/util.h | 1 - 6 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/clock.c b/src/clock.c index 69e9f17..97e415f 100644 --- a/src/clock.c +++ b/src/clock.c @@ -509,7 +509,7 @@ 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; + // case 0xb1 is handled direclty in romlayout.S/pcibios.c default: handle_1aXX(regs); break; } } diff --git a/src/config.h b/src/config.h index 3a70867..eecb461 100644 --- a/src/config.h +++ b/src/config.h @@ -96,7 +96,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 e4bd7c0..68a2e08 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -176,7 +176,7 @@ handle_1ab1XX(struct bregs *regs) set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED); }
-void +static void handle_1ab1(struct bregs *regs) { //debug_stub(regs); @@ -201,6 +201,14 @@ handle_1ab1(struct bregs *regs) } }
+// Entry point for 16bit pci bios functions. +void VISIBLE16 +handle_pcibios16(struct bregs *regs) +{ + debug_enter(regs, DEBUG_HDL_pcibios); + handle_1ab1(regs); +} +
/**************************************************************** * 32bit interface @@ -210,7 +218,7 @@ handle_1ab1(struct bregs *regs) void VISIBLE32SEG handle_pcibios32(struct bregs *regs) { - debug_enter(regs, DEBUG_HDL_pcibios32); + debug_enter(regs, DEBUG_HDL_pcibios); handle_1ab1(regs); }
diff --git a/src/post.c b/src/post.c index 3101505..8d1c024 100644 --- a/src/post.c +++ b/src/post.c @@ -61,7 +61,7 @@ init_ivt(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 8125277..3ef69bf 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -334,7 +334,14 @@ entry_apm32: popfl lretl
-// PCI-BIOS 32bit entry point +// PCI-BIOS entry points + .code16gcc + DECLFUNC entry_pcibios16 +entry_pcibios16: + ENTRY_ARG handle_pcibios16 + iretw + + .code32 DECLFUNC entry_pcibios32 entry_pcibios32: pushfl @@ -554,6 +561,9 @@ entry_10_0x0f: // 0xfa6e - vgafont8 in font.c
ORG 0xfe6e +entry_1a_official: + cmpb $0xb1, %ah + je entry_pcibios16 // PCIBIOS calls can be in protected mode IRQ_ENTRY_ARG 1a
ORG 0xfea5 diff --git a/src/util.h b/src/util.h index dbee0e5..c0a8aaa 100644 --- a/src/util.h +++ b/src/util.h @@ -334,7 +334,6 @@ void apm_shutdown(void); void handle_1553(struct bregs *regs);
// pcibios.c -void handle_1ab1(struct bregs *regs); void bios32_setup(void);
// shadow.c
Use the extra stack for all entry points. This significantly reduces the stack overhead of SeaBIOS on the caller's stack.
However, this patch will likely break any code that attempts to call a regular real-mode software handler while in 16bit protected mode.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/romlayout.S | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-)
diff --git a/src/romlayout.S b/src/romlayout.S index 3ef69bf..036fd31 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -435,9 +435,57 @@ irqentry_extrastack: iretw
// Main entry point for interrupts with args - DECLFUNC irqentryarg -irqentryarg: - ENTRY_ARG_ST + DECLFUNC irqentry_arg_extrastack +irqentry_arg_extrastack: + cli + cld + pushw %ds // Set %ds:%eax to space on ExtraStack + pushl %eax + movl $_datalow_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
// Define an entry point for hardware interrupts. @@ -458,7 +506,7 @@ irqentryarg: .global entry_\num entry_\num : pushl $ handle_\num - jmp irqentryarg + jmp irqentry_arg_extrastack .endm
.macro DECL_IRQ_ENTRY_ARG num