summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown2014-04-28 22:11:04 +0200
committerMichael Brown2014-04-29 19:24:10 +0200
commitaaf276ccd4819de791d7a1295f26f36f29fb3cb6 (patch)
treef8ed740bb762eaa8a0f6be557ff5e830cbf5e4a6 /src/arch
parent[librm] Allow interrupts in protected mode (diff)
downloadipxe-aaf276ccd4819de791d7a1295f26f36f29fb3cb6.tar.gz
ipxe-aaf276ccd4819de791d7a1295f26f36f29fb3cb6.tar.xz
ipxe-aaf276ccd4819de791d7a1295f26f36f29fb3cb6.zip
[comboot] Use built-in interrupt reflector
We now have the ability to handle interrupts while in protected mode, and so no longer need to set up a dedicated interrupt descriptor table while running COM32 executables. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/image/com32.c52
-rw-r--r--src/arch/i386/include/comboot.h45
-rw-r--r--src/arch/i386/interface/syslinux/com32_call.c17
-rw-r--r--src/arch/i386/interface/syslinux/com32_wrapper.S26
4 files changed, 6 insertions, 134 deletions
diff --git a/src/arch/i386/image/com32.c b/src/arch/i386/image/com32.c
index 5cc9a4476..c12ffb684 100644
--- a/src/arch/i386/image/com32.c
+++ b/src/arch/i386/image/com32.c
@@ -41,13 +41,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/init.h>
#include <ipxe/io.h>
-struct idt_register com32_external_idtr = {
- .limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
- .base = COM32_IDT
-};
-
-struct idt_register com32_internal_idtr;
-
/**
* Execute COMBOOT image
*
@@ -95,8 +88,6 @@ static int com32_exec_loop ( struct image *image ) {
unregister_image ( image );
__asm__ __volatile__ (
- "sidt com32_internal_idtr\n\t"
- "lidt com32_external_idtr\n\t" /* Set up IDT */
"movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
"movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
"call _virt_to_phys\n\t" /* Switch to flat physical address space */
@@ -110,8 +101,7 @@ static int com32_exec_loop ( struct image *image ) {
"pushl $6\n\t" /* Number of additional arguments */
"call *%6\n\t" /* Execute image */
"cli\n\t" /* Disable interrupts */
- "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
- "lidt com32_internal_idtr\n\t" /* Switch back to internal IDT (for debugging) */
+ "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
"movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
:
:
@@ -201,55 +191,25 @@ static int com32_identify ( struct image *image ) {
/**
- * Load COM32 image into memory and set up the IDT
+ * Load COM32 image into memory
* @v image COM32 image
* @ret rc Return status code
*/
static int com32_load_image ( struct image *image ) {
- physaddr_t com32_irq_wrapper_phys;
- struct idt_descriptor *idt;
- struct ijb_entry *ijb;
size_t filesz, memsz;
userptr_t buffer;
- int rc, i;
-
- /* The interrupt descriptor table, interrupt jump buffer, and
- * image data are all contiguous in memory. Prepare them all at once.
- */
- filesz = image->len +
- COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) +
- COM32_NUM_IDT_ENTRIES * sizeof ( struct ijb_entry );
+ int rc;
+
+ filesz = image->len;
memsz = filesz;
- buffer = phys_to_user ( COM32_IDT );
+ buffer = phys_to_user ( COM32_START_PHYS );
if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
image, strerror ( rc ) );
return rc;
}
- /* Write the IDT and IJB */
- idt = phys_to_virt ( COM32_IDT );
- ijb = phys_to_virt ( COM32_IJB );
- com32_irq_wrapper_phys = virt_to_phys ( com32_irq_wrapper );
-
- for ( i = 0; i < COM32_NUM_IDT_ENTRIES; i++ ) {
- uint32_t ijb_address = virt_to_phys ( &ijb[i] );
-
- idt[i].offset_low = ijb_address & 0xFFFF;
- idt[i].selector = PHYSICAL_CS;
- idt[i].flags = IDT_INTERRUPT_GATE_FLAGS;
- idt[i].offset_high = ijb_address >> 16;
-
- ijb[i].pusha_instruction = IJB_PUSHA;
- ijb[i].mov_instruction = IJB_MOV_AL_IMM8;
- ijb[i].mov_value = i;
- ijb[i].jump_instruction = IJB_JMP_REL32;
- ijb[i].jump_destination = com32_irq_wrapper_phys -
- virt_to_phys ( &ijb[i + 1] );
- }
-
/* Copy image to segment */
- buffer = phys_to_user ( COM32_START_PHYS );
memcpy_user ( buffer, 0, image->data, 0, filesz );
return 0;
diff --git a/src/arch/i386/include/comboot.h b/src/arch/i386/include/comboot.h
index b34341398..2d2f04fe1 100644
--- a/src/arch/i386/include/comboot.h
+++ b/src/arch/i386/include/comboot.h
@@ -13,50 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <setjmp.h>
#include <ipxe/in.h>
-/** Descriptor in a 32-bit IDT */
-struct idt_descriptor {
- uint16_t offset_low;
- uint16_t selector;
- uint16_t flags;
- uint16_t offset_high;
-} __attribute__ (( packed ));
-
-/** Operand for the LIDT instruction */
-struct idt_register {
- uint16_t limit;
- uint32_t base;
-} __attribute__ (( packed ));
-
-/** Entry in the interrupt jump buffer */
-struct ijb_entry {
- uint8_t pusha_instruction;
- uint8_t mov_instruction;
- uint8_t mov_value;
- uint8_t jump_instruction;
- uint32_t jump_destination;
-} __attribute__ (( packed ));
-
-/** The x86 opcode for "pushal" */
-#define IJB_PUSHA 0x60
-
-/** The x86 opcode for "movb $imm8,%al" */
-#define IJB_MOV_AL_IMM8 0xB0
-
-/** The x86 opcode for "jmp rel32" */
-#define IJB_JMP_REL32 0xE9
-
-/** Flags that specify a 32-bit interrupt gate with DPL=0 */
-#define IDT_INTERRUPT_GATE_FLAGS 0x8E00
-
-/** Address of COM32 interrupt descriptor table */
-#define COM32_IDT 0x100000
-
-/** Number of entries in a fully populated IDT */
-#define COM32_NUM_IDT_ENTRIES 256
-
-/** Address of COM32 interrupt jump buffer */
-#define COM32_IJB 0x100800
-
/** Segment used for COMBOOT PSP and image */
#define COMBOOT_PSP_SEG 0x07C0
@@ -153,7 +109,6 @@ extern void unhook_comboot_interrupts ( );
extern void com32_intcall_wrapper ( );
extern void com32_farcall_wrapper ( );
extern void com32_cfarcall_wrapper ( );
-extern void com32_irq_wrapper ( );
/* Resolve a hostname to an (IPv4) address */
extern int comboot_resolv ( const char *name, struct in_addr *address );
diff --git a/src/arch/i386/interface/syslinux/com32_call.c b/src/arch/i386/interface/syslinux/com32_call.c
index 8fffd0692..75dcc238f 100644
--- a/src/arch/i386/interface/syslinux/com32_call.c
+++ b/src/arch/i386/interface/syslinux/com32_call.c
@@ -189,20 +189,3 @@ int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz )
return eax;
}
-
-/**
- * IRQ handler
- */
-void __asmcall com32_irq ( uint32_t vector ) {
- uint32_t *ivt_entry = phys_to_virt( vector * 4 );
-
- __asm__ __volatile__ (
- REAL_CODE ( "pushfw\n\t"
- "pushw %%cs\n\t"
- "pushw $com32_irq_return\n\t"
- "pushl %0\n\t"
- "lret\n"
- "com32_irq_return:\n\t" )
- : /* no outputs */
- : "r" ( *ivt_entry ) );
-}
diff --git a/src/arch/i386/interface/syslinux/com32_wrapper.S b/src/arch/i386/interface/syslinux/com32_wrapper.S
index 69cea02e8..c9d1452b4 100644
--- a/src/arch/i386/interface/syslinux/com32_wrapper.S
+++ b/src/arch/i386/interface/syslinux/com32_wrapper.S
@@ -23,26 +23,6 @@ FILE_LICENCE ( GPL2_OR_LATER )
.arch i386
.code32
- /*
- * This code is entered after running the following sequence out of
- * the interrupt jump buffer:
- *
- * pushal
- * movb $vector, %al
- * jmp com32_irq_wrapper
- */
-
- .globl com32_irq_wrapper
-com32_irq_wrapper:
-
- movzbl %al,%eax
- pushl %eax
- movl $com32_irq, %eax
- call com32_wrapper
- popl %eax
- popal
- iret
-
.globl com32_farcall_wrapper
com32_farcall_wrapper:
@@ -69,9 +49,6 @@ com32_wrapper:
/* Switch to internal virtual address space */
call _phys_to_virt
- /* Switch to internal IDT (if we have one for debugging) */
- lidt com32_internal_idtr
-
mov %eax, (com32_helper_function)
/* Save external COM32 stack pointer */
@@ -99,9 +76,6 @@ com32_wrapper:
movl %esp, (com32_internal_esp)
movl (com32_external_esp), %esp
- /* Switch to com32 IDT */
- lidt com32_external_idtr
-
/* Switch to external flat physical address space */
call _virt_to_phys