Browse Source

[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>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
aaf276ccd4

+ 6
- 46
src/arch/i386/image/com32.c View File

41
 #include <ipxe/init.h>
41
 #include <ipxe/init.h>
42
 #include <ipxe/io.h>
42
 #include <ipxe/io.h>
43
 
43
 
44
-struct idt_register com32_external_idtr = {
45
-	.limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
46
-	.base = COM32_IDT
47
-};
48
-
49
-struct idt_register com32_internal_idtr;
50
-
51
 /**
44
 /**
52
  * Execute COMBOOT image
45
  * Execute COMBOOT image
53
  *
46
  *
95
 		unregister_image ( image );
88
 		unregister_image ( image );
96
 
89
 
97
 		__asm__ __volatile__ (
90
 		__asm__ __volatile__ (
98
-			"sidt com32_internal_idtr\n\t"
99
-			"lidt com32_external_idtr\n\t"	       /* Set up IDT */
100
 			"movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
91
 			"movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
101
 			"movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
92
 			"movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
102
 			"call _virt_to_phys\n\t"               /* Switch to flat physical address space */
93
 			"call _virt_to_phys\n\t"               /* Switch to flat physical address space */
110
 			"pushl $6\n\t"                         /* Number of additional arguments */
101
 			"pushl $6\n\t"                         /* Number of additional arguments */
111
 			"call *%6\n\t"                         /* Execute image */
102
 			"call *%6\n\t"                         /* Execute image */
112
 			"cli\n\t"			       /* Disable interrupts */
103
 			"cli\n\t"			       /* Disable interrupts */
113
-			"call _phys_to_virt\n\t"	       /* Switch back to internal virtual address space */
114
-			"lidt com32_internal_idtr\n\t"	       /* Switch back to internal IDT (for debugging) */
104
+			"call _phys_to_virt\n\t"               /* Switch back to internal virtual address space */
115
 			"movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
105
 			"movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
116
 		:
106
 		:
117
 		:
107
 		:
201
 
191
 
202
 
192
 
203
 /**
193
 /**
204
- * Load COM32 image into memory and set up the IDT
194
+ * Load COM32 image into memory
205
  * @v image		COM32 image
195
  * @v image		COM32 image
206
  * @ret rc		Return status code
196
  * @ret rc		Return status code
207
  */
197
  */
208
 static int com32_load_image ( struct image *image ) {
198
 static int com32_load_image ( struct image *image ) {
209
-	physaddr_t com32_irq_wrapper_phys;
210
-	struct idt_descriptor *idt;
211
-	struct ijb_entry *ijb;
212
 	size_t filesz, memsz;
199
 	size_t filesz, memsz;
213
 	userptr_t buffer;
200
 	userptr_t buffer;
214
-	int rc, i;
215
-
216
-	/* The interrupt descriptor table, interrupt jump buffer, and
217
-	 * image data are all contiguous in memory. Prepare them all at once.
218
-	 */
219
-	filesz = image->len +
220
-		COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) +
221
-		COM32_NUM_IDT_ENTRIES * sizeof ( struct ijb_entry );
201
+	int rc;
202
+
203
+	filesz = image->len;
222
 	memsz = filesz;
204
 	memsz = filesz;
223
-	buffer = phys_to_user ( COM32_IDT );
205
+	buffer = phys_to_user ( COM32_START_PHYS );
224
 	if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
206
 	if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
225
 		DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
207
 		DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
226
 		       image, strerror ( rc ) );
208
 		       image, strerror ( rc ) );
227
 		return rc;
209
 		return rc;
228
 	}
210
 	}
229
 
211
 
230
-	/* Write the IDT and IJB */
231
-	idt = phys_to_virt ( COM32_IDT );
232
-	ijb = phys_to_virt ( COM32_IJB );
233
-	com32_irq_wrapper_phys = virt_to_phys ( com32_irq_wrapper );
234
-
235
-	for ( i = 0; i < COM32_NUM_IDT_ENTRIES; i++ ) {
236
-		uint32_t ijb_address = virt_to_phys ( &ijb[i] );
237
-
238
-		idt[i].offset_low = ijb_address & 0xFFFF;
239
-		idt[i].selector = PHYSICAL_CS;
240
-		idt[i].flags = IDT_INTERRUPT_GATE_FLAGS;
241
-		idt[i].offset_high = ijb_address >> 16;
242
-
243
-		ijb[i].pusha_instruction = IJB_PUSHA;
244
-		ijb[i].mov_instruction = IJB_MOV_AL_IMM8;
245
-		ijb[i].mov_value = i;
246
-		ijb[i].jump_instruction = IJB_JMP_REL32;
247
-		ijb[i].jump_destination = com32_irq_wrapper_phys -
248
-			virt_to_phys ( &ijb[i + 1] );
249
-	}
250
-
251
 	/* Copy image to segment */
212
 	/* Copy image to segment */
252
-	buffer = phys_to_user ( COM32_START_PHYS );
253
 	memcpy_user ( buffer, 0, image->data, 0, filesz );
213
 	memcpy_user ( buffer, 0, image->data, 0, filesz );
254
 
214
 
255
 	return 0;
215
 	return 0;

+ 0
- 45
src/arch/i386/include/comboot.h View File

13
 #include <setjmp.h>
13
 #include <setjmp.h>
14
 #include <ipxe/in.h>
14
 #include <ipxe/in.h>
15
 
15
 
16
-/** Descriptor in a 32-bit IDT */
17
-struct idt_descriptor {
18
-	uint16_t offset_low;
19
-	uint16_t selector;
20
-	uint16_t flags;
21
-	uint16_t offset_high;
22
-} __attribute__ (( packed ));
23
-
24
-/** Operand for the LIDT instruction */
25
-struct idt_register {
26
-	uint16_t limit;
27
-	uint32_t base;
28
-} __attribute__ (( packed ));
29
-
30
-/** Entry in the interrupt jump buffer */
31
-struct ijb_entry {
32
-	uint8_t pusha_instruction;
33
-	uint8_t mov_instruction;
34
-	uint8_t mov_value;
35
-	uint8_t jump_instruction;
36
-	uint32_t jump_destination;
37
-} __attribute__ (( packed ));
38
-
39
-/** The x86 opcode for "pushal" */
40
-#define IJB_PUSHA 0x60
41
-
42
-/** The x86 opcode for "movb $imm8,%al" */
43
-#define IJB_MOV_AL_IMM8 0xB0
44
-
45
-/** The x86 opcode for "jmp rel32" */
46
-#define IJB_JMP_REL32 0xE9
47
-
48
-/** Flags that specify a 32-bit interrupt gate with DPL=0 */
49
-#define IDT_INTERRUPT_GATE_FLAGS 0x8E00
50
-
51
-/** Address of COM32 interrupt descriptor table */
52
-#define COM32_IDT 0x100000
53
-
54
-/** Number of entries in a fully populated IDT */
55
-#define COM32_NUM_IDT_ENTRIES 256
56
-
57
-/** Address of COM32 interrupt jump buffer */
58
-#define COM32_IJB 0x100800
59
-
60
 /** Segment used for COMBOOT PSP and image */
16
 /** Segment used for COMBOOT PSP and image */
61
 #define COMBOOT_PSP_SEG 0x07C0
17
 #define COMBOOT_PSP_SEG 0x07C0
62
 
18
 
153
 extern void com32_intcall_wrapper ( );
109
 extern void com32_intcall_wrapper ( );
154
 extern void com32_farcall_wrapper ( );
110
 extern void com32_farcall_wrapper ( );
155
 extern void com32_cfarcall_wrapper ( );
111
 extern void com32_cfarcall_wrapper ( );
156
-extern void com32_irq_wrapper ( );
157
 
112
 
158
 /* Resolve a hostname to an (IPv4) address */
113
 /* Resolve a hostname to an (IPv4) address */
159
 extern int comboot_resolv ( const char *name, struct in_addr *address );
114
 extern int comboot_resolv ( const char *name, struct in_addr *address );

+ 0
- 17
src/arch/i386/interface/syslinux/com32_call.c View File

189
 
189
 
190
 	return eax;
190
 	return eax;
191
 }
191
 }
192
-
193
-/**
194
- * IRQ handler
195
- */
196
-void __asmcall com32_irq ( uint32_t vector ) {
197
-	uint32_t *ivt_entry = phys_to_virt( vector * 4 );
198
-
199
-	__asm__ __volatile__ (
200
-		REAL_CODE ( "pushfw\n\t"
201
-			    "pushw %%cs\n\t"
202
-			    "pushw $com32_irq_return\n\t"
203
-			    "pushl %0\n\t"
204
-			    "lret\n"
205
-			    "com32_irq_return:\n\t" )
206
-		: /* no outputs */
207
-		: "r" ( *ivt_entry ) );
208
-}

+ 0
- 26
src/arch/i386/interface/syslinux/com32_wrapper.S View File

23
 	.arch i386
23
 	.arch i386
24
 	.code32
24
 	.code32
25
 
25
 
26
-	/*
27
-	 * This code is entered after running the following sequence out of
28
-	 * the interrupt jump buffer:
29
-	 *
30
-	 * pushal
31
-	 * movb $vector, %al
32
-	 * jmp com32_irq_wrapper
33
-	 */
34
-
35
-	.globl com32_irq_wrapper
36
-com32_irq_wrapper:
37
-
38
-	movzbl %al,%eax
39
-	pushl %eax
40
-	movl $com32_irq, %eax
41
-	call com32_wrapper
42
-	popl %eax
43
-	popal
44
-	iret
45
-
46
 	.globl com32_farcall_wrapper
26
 	.globl com32_farcall_wrapper
47
 com32_farcall_wrapper:
27
 com32_farcall_wrapper:
48
 
28
 
69
 	/* Switch to internal virtual address space */
49
 	/* Switch to internal virtual address space */
70
 	call _phys_to_virt
50
 	call _phys_to_virt
71
 
51
 
72
-	/* Switch to internal IDT (if we have one for debugging) */
73
-	lidt com32_internal_idtr
74
-
75
 	mov %eax, (com32_helper_function)
52
 	mov %eax, (com32_helper_function)
76
 
53
 
77
 	/* Save external COM32 stack pointer */
54
 	/* Save external COM32 stack pointer */
99
 	movl %esp, (com32_internal_esp)
76
 	movl %esp, (com32_internal_esp)
100
 	movl (com32_external_esp), %esp
77
 	movl (com32_external_esp), %esp
101
 
78
 
102
-	/* Switch to com32 IDT */
103
-	lidt com32_external_idtr
104
-
105
 	/* Switch to external flat physical address space */
79
 	/* Switch to external flat physical address space */
106
 	call _virt_to_phys
80
 	call _virt_to_phys
107
 
81
 

Loading…
Cancel
Save