Commonize ISR handling as much as possible
This commit is contained in:
parent
edc9b2c3ff
commit
0efe8af5aa
209
src/hulk/idt.d
209
src/hulk/idt.d
@ -13,6 +13,27 @@ import hulk.cpu;
|
||||
import hulk.kfont;
|
||||
import hulk.thread;
|
||||
|
||||
static foreach(isr; 0 .. Idt.N_ISRS)
|
||||
{
|
||||
mixin(`private extern(C) void isr_`, isr, `();`);
|
||||
}
|
||||
|
||||
private string isrs_list(int index = 0)()
|
||||
{
|
||||
static if (index < 256)
|
||||
{
|
||||
return "&isr_" ~ index.stringof ~ ",\n" ~ isrs_list!(index + 1)();
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
mixin(`private static __gshared extern(C) void function()[Idt.N_ISRS] isrs = [`,
|
||||
isrs_list(),
|
||||
`];`);
|
||||
|
||||
struct Idt
|
||||
{
|
||||
/** Interrupt stack frame indices. */
|
||||
@ -65,18 +86,43 @@ struct Idt
|
||||
"SS",
|
||||
];
|
||||
|
||||
public static enum ulong EXC_PAGE_FAULT = 14;
|
||||
public enum ulong EXC_PAGE_FAULT = 14;
|
||||
|
||||
/* The I/O APIC is configured to map IRQ 0 to interrupt 64 (0x40). */
|
||||
public static enum ulong INT_APIC_BASE = 0x40u; /* IRQ 0 */
|
||||
public static enum ulong INT_APIC_COUNT = 24u;
|
||||
public enum ulong INT_APIC_BASE = 0x40u; /* IRQ 0 */
|
||||
public enum ulong INT_APIC_COUNT = 24u;
|
||||
|
||||
public static enum ulong INT_APIC_TIMER = 0x70u;
|
||||
public static enum ulong INT_APIC_LINT0 = 0x71u;
|
||||
public static enum ulong INT_APIC_LINT1 = 0x72u;
|
||||
public static enum ulong INT_KERNEL_SWINT = 0x80u;
|
||||
public static enum ulong INT_APIC_SPURIOUS = 0xFFu;
|
||||
public enum ulong INT_APIC_TIMER = 0x70u;
|
||||
public enum ulong INT_APIC_LINT0 = 0x71u;
|
||||
public enum ulong INT_APIC_LINT1 = 0x72u;
|
||||
public enum ulong INT_KERNEL_SWINT = 0x80u;
|
||||
public enum ulong INT_APIC_SPURIOUS = 0xFFu;
|
||||
|
||||
private enum N_ISRS = 256;
|
||||
|
||||
/**
|
||||
* IDT descriptor entry type.
|
||||
*/
|
||||
struct descriptor_t
|
||||
{
|
||||
ulong[2] descriptor;
|
||||
|
||||
this(T)(size_t index, ulong dpl, bool trap, T offset)
|
||||
{
|
||||
descriptor[0] =
|
||||
0x0000_8E_00_0000_0000u |
|
||||
((cast(ulong)offset & 0xFFFF_0000u) << 32u) |
|
||||
(dpl << 45u) |
|
||||
((trap ? 1uL : 0uL) << 40u) |
|
||||
(Gdt.SELECTOR_KERNEL_CODE << 16u) |
|
||||
(cast(ulong)offset & 0xFFFFu);
|
||||
descriptor[1] = cast(ulong)offset >> 32u;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IDTR register format.
|
||||
*/
|
||||
struct idtr_t
|
||||
{
|
||||
ushort limit;
|
||||
@ -84,11 +130,9 @@ struct Idt
|
||||
}
|
||||
static assert(idtr_t.sizeof == 10u);
|
||||
|
||||
alias descriptor_t = ulong[2];
|
||||
|
||||
static __gshared align(0x10) descriptor_t[256] idt;
|
||||
static assert(idt.sizeof == (256u * 16u));
|
||||
static __gshared idtr_t idtr;
|
||||
private static __gshared idtr_t idtr;
|
||||
private static __gshared align(0x10) descriptor_t[N_ISRS] idt;
|
||||
static assert(idt.sizeof == (N_ISRS * 16u));
|
||||
|
||||
public static void initialize()
|
||||
{
|
||||
@ -103,87 +147,80 @@ struct Idt
|
||||
__asm("lidt $0", "*m", idtr);
|
||||
}
|
||||
|
||||
private static bool isr_has_error_code(size_t isr)
|
||||
{
|
||||
return (isr == 8) ||
|
||||
((10 <= isr) && (isr <= 14)) ||
|
||||
(isr == 17) ||
|
||||
(isr == 21) ||
|
||||
(isr == 29) ||
|
||||
(isr == 30);
|
||||
}
|
||||
|
||||
private static bool isr_is_trap(size_t isr)
|
||||
{
|
||||
return (isr < 32u) && (isr != 2u);
|
||||
}
|
||||
|
||||
private static void set_isrs()
|
||||
{
|
||||
ulong isr_address;
|
||||
static foreach(isr; 0 .. 256)
|
||||
static bool isr_has_error_code(size_t isr)
|
||||
{
|
||||
mixin("isr_address = __asm!ulong(`
|
||||
movabs $$1f, %rax
|
||||
jmp 2f
|
||||
1:
|
||||
return (isr == 8) ||
|
||||
((10 <= isr) && (isr <= 14)) ||
|
||||
(isr == 17) ||
|
||||
(isr == 21) ||
|
||||
(isr == 29) ||
|
||||
(isr == 30);
|
||||
}
|
||||
|
||||
static bool isr_is_trap(size_t isr)
|
||||
{
|
||||
return (isr < 32u) && (isr != 2u);
|
||||
}
|
||||
|
||||
__asm("jmp 1f", "");
|
||||
static foreach(isr; 0 .. N_ISRS)
|
||||
{
|
||||
mixin("__asm(`isr_", isr, ":
|
||||
" ~ (isr_has_error_code(isr) ? "" : "pushq $$0") ~ "
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %rbp
|
||||
mov %rsp, %rbp
|
||||
mov %rsp, %rsi
|
||||
and $$0xFFFFFFFFFFFFFFF0, %rsp
|
||||
mov $$", isr, ", %rdi
|
||||
movabs $$isr, %rax
|
||||
callq *%rax
|
||||
mov %rax, %rsp
|
||||
popq %rbp
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rax
|
||||
add $$8, %rsp
|
||||
iretq
|
||||
2:`, `={rax}`);");
|
||||
mixin("set_descriptor(", isr, ", 0u, " ~
|
||||
(isr_is_trap(isr) ? "true" : "false") ~ ", isr_address);");
|
||||
mov $$", isr, ", %rax
|
||||
jmp isr_common`, ``);");
|
||||
}
|
||||
|
||||
__asm(`isr_common:
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %rbp
|
||||
mov %rsp, %rbp
|
||||
mov %rsp, %rsi
|
||||
and $$0xFFFFFFFFFFFFFFF0, %rsp
|
||||
mov %rax, %rdi
|
||||
movabs $$isr, %rax
|
||||
callq *%rax
|
||||
mov %rax, %rsp
|
||||
popq %rbp
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rax
|
||||
add $$8, %rsp
|
||||
iretq
|
||||
1:`, ``);
|
||||
|
||||
for (size_t isr = 0; isr < N_ISRS; isr++)
|
||||
{
|
||||
idt[isr] = descriptor_t(isr, 0u, isr_is_trap(isr), isrs[isr]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void set_descriptor(size_t index, ulong dpl, bool trap, ulong offset)
|
||||
{
|
||||
idt[index][0] =
|
||||
0x0000_8E_00_0000_0000u |
|
||||
((offset & 0xFFFF_0000u) << 32u) |
|
||||
(dpl << 45u) |
|
||||
((trap ? 1uL : 0uL) << 40u) |
|
||||
(Gdt.SELECTOR_KERNEL_CODE << 16u) |
|
||||
(offset & 0xFFFFu);
|
||||
idt[index][1] = offset >> 32u;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user