Embed ISRs at known address
authorJack Miller <jack@codezen.org>
Tue, 20 Sep 2016 20:25:04 +0000 (15:25 -0500)
committerJack Miller <jack@codezen.org>
Wed, 21 Sep 2016 00:14:38 +0000 (19:14 -0500)
Rather than fixing up the IDT entries at runtime, put the ISRs into
their own section at a known address and generate the IDT entries at
compile time.

This also tightens the "early" part of the kernel (grub sig, .text_early
section) to 2k although it's currently less than half of that.

The price of this change is that we don't have a working IDT until we're
in long mode, but we haven't ever had valid 32-bit ISRs outside of the
realmode stub, so no loss there.

asm/head.asm
asm/idt.asm
asm/realmode.asm-bin
include/asm/idt.h
include/memmap.h
linker.ld

index c86bfef..e080985 100644 (file)
 .extern CODE_SEL_32
 .extern CODE_SEL_64
 
-/* idt.asm */
-.extern populate_idt
-.extern fixup_idtr
-
 /* linker.ld */
 .extern kernel_size
 
@@ -127,8 +123,6 @@ host_gdt:
     mov $(STACK_TOP_PHYS), %esp
     mov %esp, %ebp
 
-    call populate_idt
-
     /* Calculate size of early structures */
 
     /* eax = size of kernel, rounded up to page size */
@@ -406,9 +400,9 @@ cleanup_64:
     mov %rax, %rsp
     mov %rax, %rbp
 
-    /* Move GDTR / IDTR addresses to new 0xFFFF8....... */
+    /* Move GDTR addresses to new 0xFFFF8....... */
     call fixup_gdtr
-    call fixup_idtr
+    lidt IDTR
 
     /* Now that we are executing in 0xF... space, and our
      * stacks are there too, we can clean up the 0x0 kernel
index bfdfadb..cb05bb5 100644 (file)
@@ -1,87 +1,68 @@
-.code32
-.section .text_early, "ax"
-
 #include <memmap.h>
+#include <asm/idt.h>
 
-/* The IDT holds a set of descriptors similar to the GDT, called
- * Interrupt Gates. Call and Trap Gates are also valid here.
- */
+.code64
 
-#include <asm/idt.h>
+.section .isrs, "ax"
+
+/* Generate 256 interrupt routines. */
+
+.macro def_isr num err
+.if \err == 0
+    pushq $0
+.else
+    nop  // pad to keep isrs the same size
+    nop  // push is 2 bytes, nop is 1 byte
+.endif
+    pushq $\num
+    jmp exception
+.endm
+
+isr0:
+def_isr 0,  0
+isr1:
+def_isr 1,  0
+def_isr 2,  0
+def_isr 3,  0
+def_isr 4,  0
+def_isr 5,  0
+def_isr 6,  0
+def_isr 7,  0
+def_isr 8,  1
+def_isr 9,  0
+def_isr 10, 1
+def_isr 11, 1
+def_isr 12, 1
+def_isr 13, 1
+def_isr 14, 1
+def_isr 15, 0
+def_isr 16, 0
+def_isr 17, 1
 
-#define ISR_SIZE (isr1 - isr0)
+.set i, 18
+.rept (IDT_ENTRIES - i)
+    def_isr i, 0
+    .set i, (i +1)
+.endr
+
+.section .text
 
-/* IDTR, just like GDTR */
+.global IDTR
 
 .align 8
 IDTR:
 .word (IDTEND - IDT - 1)
 .quad IDT
 
-/* Use 64-bit IDTE format, even though we assume 32-bit addresses since 
- * we're defining them here.
- */
-
-bigisr:
-.quad isr0
-
 .align 8
 IDT:
 .set i, 0
 .rept IDT_ENTRIES
-IDTENTRY 0
+IDTENTRY(ISRS + (i * (ISR_SIZE)))
 .set i, (i+1)
 .endr
 IDTEND:
 
-.global populate_idt
-populate_idt:
-    mov $IDT, %eax
-    mov (bigisr), %ebx
-    or $(VIRT_BASE & 0xFFFFFFFF), %ebx
-
-idt_init_one:
-    /* Target Low (word) */
-    mov %ebx, %ecx
-    movw %cx, (%eax)
-    add $6, %eax
-
-    /* Target High (word) */
-    shr $16, %ecx
-    movw %cx, (%eax)
-    add $2, %eax
-
-    /* Long Mode Target High 32 */
-    movl $(VIRT_BASE >> 32), (%eax)
-    add $4, %eax
-
-    movl $0, (%eax)
-    add $4, %eax
-
-    add $(ISR_SIZE), %ebx
-
-    cmp $(IDTEND), %eax
-    jl idt_init_one
-
-    lidt IDTR
-    ret
-
-.code64
-
-.global fixup_idtr
-fixup_idtr:
-    movq $(VIRT_BASE + IDTR + 2), %rax
-
-    movq $(VIRT_BASE + IDT), %rbx
-
-    movq %rbx, (%rax)
-
-    sub $2, %rax
-    lidt (%rax)
-    ret
-
-.section ".text"
-
 /* Save/restore order from regs.h */
 
 .macro SAVE_ALL
@@ -120,46 +101,6 @@ fixup_idtr:
     pop %rdi
 .endm
 
-/* Generate 256 interrupt routines. */
-
-.macro def_isr num err
-.if \err == 0
-    pushq $0
-.else
-    nop  // pad to keep isrs the same size
-    nop  // push is 2 bytes, nop is 1 byte
-.endif
-    pushq $\num
-    jmp exception
-.endm
-
-isr0:
-def_isr 0,  0
-isr1:
-def_isr 1,  0
-def_isr 2,  0
-def_isr 3,  0
-def_isr 4,  0
-def_isr 5,  0
-def_isr 6,  0
-def_isr 7,  0
-def_isr 8,  1
-def_isr 9,  0
-def_isr 10, 1
-def_isr 11, 1
-def_isr 12, 1
-def_isr 13, 1
-def_isr 14, 1
-def_isr 15, 0
-def_isr 16, 0
-def_isr 17, 1
-
-.set i, 18
-.rept (IDT_ENTRIES - i)
-    def_isr i, 0
-    .set i, (i +1)
-.endr
-
 /* Common exception handler. An error code has been pushed either by the
  * processor or us, and the interrupt vector has been pushed as well.
  */
index 14dceee..055b39d 100644 (file)
@@ -158,14 +158,14 @@ builtin_gdt_end:
 jmp .
 .endr
 
-#define ISR_SIZE       2
+#define RM_ISR_SIZE    2
 
 .align 8
 RM_IDT:
 .set a, (REALMODE_PA + 0x400)
 .rept 21
-IDTENTRY a
-.set a, (a+ISR_SIZE)
+IDTENTRY(a)
+.set a, (a+RM_ISR_SIZE)
 .endr
 RM_IDTEND:
 
index 58e651a..a1b21a4 100644 (file)
@@ -9,15 +9,15 @@
 #define FLAG_R0                (0 << 5)    // Rings 0 - 3
 #define FLAG_P          (1 << 7)
 #define IDT_ENTRIES     256
+#define ISR_SIZE       9
 
 #ifdef __ASSEMBLY__
-.macro IDTENTRY isr
-    .word (\isr & 0xFFFF)                      /* target low */
-    .word CODE_SEL_64                          /* selector */
-    .byte 0                                    /* IST */
-    .byte (FLAG_P|FLAG_R0|FLAG_INTERRUPT)      /* type */
-    .word (\isr >> 16)                         /* target high */
-    .long 0                                    /* target even higher */
-    .long 0                                    /* reserved */
-.endm
+#define IDTENTRY(isr)                          \
+    .word ((isr) & 0xFFFF);                    \
+    .word CODE_SEL_64;                         \
+    .byte 0;                                   \
+    .byte (FLAG_P|FLAG_R0|FLAG_INTERRUPT);     \
+    .word (((isr) & 0xFFFFFFFF) >> 16);                \
+    .long ((isr) >> 32);                       \
+    .long 0;
 #endif
index 7b7626b..41a2ebb 100644 (file)
 /* Huge space for EFI runtime memory being remapped */
 #define EFI_RUNTIME     0xFFFFFFE000000000
 
+/* Vritual addresses must match up with linker.ld */
 #define VIRT_BASE              0xFFFFFFFF80000000
 #define KERNEL_VIRT            (VIRT_BASE | KERNEL_START)
+#define ISRS            (KERNEL_VIRT + 0x800)
 
 #define STACK_PAGES_ORDER              1
 #define STACK_PAGES                            (1 << STACK_PAGES_ORDER)
index 3af9923..db2f356 100644 (file)
--- a/linker.ld
+++ b/linker.ld
@@ -8,13 +8,15 @@ SECTIONS
     {
         *(.grub_sig)
     }
-    .text_early 0x100080 :
+    .text_early :
     {
         *(.text_early)
     }
-    . = ALIGN(0x8);
-    end_early_text = .;
-    .text (0xFFFFFFFF80000000 + end_early_text): AT (end_early_text)
+    .isrs 0xFFFFFFFF80100800: AT (0x100800)
+    {
+        *(.isrs)
+    }
+    .text :
     {
         *(.text)
     }