Merge pull request #108 from SamTebbs33/full-isr-irq-zig-code

No more assembly
This commit is contained in:
Edward Dean 2019-11-06 21:34:03 +00:00 committed by GitHub
commit 87f33a4c0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 120 additions and 278 deletions

View file

@ -33,13 +33,6 @@ pub fn build(b: *Builder) !void {
exec.addBuildOption(bool, "rt_test", rt_test);
exec.setLinkerScriptPath("link.ld");
exec.setTheTarget(target);
switch (target.getArch()) {
.i386 => {
exec.addAssemblyFile("src/kernel/arch/x86/irq_asm.s");
exec.addAssemblyFile("src/kernel/arch/x86/isr_asm.s");
},
else => unreachable,
}
const iso_path = try fs.path.join(b.allocator, [_][]const u8{ b.exe_dir, "pluto.iso" });
const grub_build_path = try fs.path.join(b.allocator, [_][]const u8{ b.exe_dir, "iso", "boot" });

View file

@ -48,7 +48,7 @@ pub const IdtPtr = packed struct {
base: u32,
};
pub const InterruptHandler = extern fn () void;
pub const InterruptHandler = nakedcc fn () void;
/// The error set for the IDT
pub const IdtError = error{
@ -189,8 +189,8 @@ pub fn init() void {
if (build_options.rt_test) runtimeTests();
}
extern fn testHandler0() void {}
extern fn testHandler1() void {}
nakedcc fn testHandler0() void {}
nakedcc fn testHandler1() void {}
fn mock_lidt(ptr: *const IdtPtr) void {
expectEqual(TABLE_SIZE, ptr.limit);

View file

@ -0,0 +1,86 @@
const arch = @import("arch.zig");
const syscalls = @import("syscalls.zig");
const irq = @import("irq.zig");
const idt = @import("idt.zig");
extern fn irqHandler(ctx: *arch.InterruptContext) void;
extern fn isrHandler(ctx: *arch.InterruptContext) void;
///
/// The main handler for all exceptions and interrupts. This will then go and call the correct
/// handler for an ISR or IRQ.
///
/// Arguments:
/// IN ctx: *arch.InterruptContext - Pointer to the exception context containing the contents
/// of the registers at the time of a exception.
///
export fn handler(ctx: *arch.InterruptContext) void {
if (ctx.int_num < irq.IRQ_OFFSET or ctx.int_num == syscalls.INTERRUPT) {
isrHandler(ctx);
} else {
irqHandler(ctx);
}
}
///
/// The common assembly that all exceptions and interrupts will call.
///
export nakedcc fn commonStub() void {
asm volatile (
\\pusha
\\push %%ds
\\push %%es
\\push %%fs
\\push %%gs
\\mov $0x10, %%ax
\\mov %%ax, %%ds
\\mov %%ax, %%es
\\mov %%ax, %%fs
\\mov %%ax, %%gs
\\mov %%esp, %%eax
\\push %%eax
\\call handler
\\pop %%eax
\\pop %%gs
\\pop %%fs
\\pop %%es
\\pop %%ds
\\popa
\\add $0x8, %%esp
\\iret
);
}
///
/// Generate the function that is the entry point for each exception/interrupt. This will then be
/// used as the handler for the corresponding IDT entry.
///
/// Arguments:
/// IN interrupt_num: u32 - The interrupt number to generate the function for.
///
/// Return: idt.InterruptHandler
/// The stub function that is called for each interrupt/exception.
///
pub fn getInterruptStub(comptime interrupt_num: u32) idt.InterruptHandler {
return struct {
nakedcc fn func() void {
asm volatile (
\\ cli
);
// These interrupts don't push an error code onto the stack, so will push a zero.
if (interrupt_num != 8 and !(interrupt_num >= 10 and interrupt_num <= 14) and interrupt_num != 17) {
asm volatile (
\\ pushl $0
);
}
asm volatile (
\\ pushl %[nr]
\\ jmp commonStub
:
: [nr] "n" (interrupt_num)
);
}
}.func;
}

View file

@ -11,6 +11,7 @@ const idt = if (is_test) @import(mock_path ++ "idt_mock.zig") else @import("idt.
const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig");
const log = if (is_test) @import(mock_path ++ "log_mock.zig") else @import("../../log.zig");
const pic = if (is_test) @import(mock_path ++ "pic_mock.zig") else @import("pic.zig");
const interrupts = @import("interrupts.zig");
/// The error set for the IRQ. This will be from installing a IRQ handler.
pub const IrqError = error{
@ -24,33 +25,15 @@ pub const IrqError = error{
/// The total number of IRQ.
const NUMBER_OF_ENTRIES: u16 = 16;
// The offset from the interrupt number where the IRQs are.
const IRQ_OFFSET: u16 = 32;
/// The type of a IRQ handler. A function that takes a interrupt context and returns void.
const IrqHandler = fn (*arch.InterruptContext) void;
// The offset from the interrupt number where the IRQs are.
pub const IRQ_OFFSET: u16 = 32;
/// The list of IRQ handlers initialised to unhandled.
var irq_handlers: [NUMBER_OF_ENTRIES]?IrqHandler = [_]?IrqHandler{null} ** NUMBER_OF_ENTRIES;
// The external assembly that is fist called to set up the interrupt handler.
extern fn irq0() void;
extern fn irq1() void;
extern fn irq2() void;
extern fn irq3() void;
extern fn irq4() void;
extern fn irq5() void;
extern fn irq6() void;
extern fn irq7() void;
extern fn irq8() void;
extern fn irq9() void;
extern fn irq10() void;
extern fn irq11() void;
extern fn irq12() void;
extern fn irq13() void;
extern fn irq14() void;
extern fn irq15() void;
///
/// The IRQ handler that each of the IRQs will call when a interrupt happens.
///
@ -60,6 +43,10 @@ extern fn irq15() void;
///
export fn irqHandler(ctx: *arch.InterruptContext) void {
// Get the IRQ index, by getting the interrupt number and subtracting the offset.
if (ctx.int_num < IRQ_OFFSET) {
panic(@errorReturnTrace(), "Not an IRQ number: {}\n", ctx.int_num);
}
const irq_offset = ctx.int_num - IRQ_OFFSET;
if (isValidIrq(irq_offset)) {
// IRQ index is valid so can truncate
@ -143,30 +130,17 @@ pub fn registerIrq(irq_num: u8, handler: IrqHandler) IrqError!void {
pub fn init() void {
log.logInfo("Init irq\n");
// Open all the IRQs
openIrq(32, irq0);
openIrq(33, irq1);
openIrq(34, irq2);
openIrq(35, irq3);
openIrq(36, irq4);
openIrq(37, irq5);
openIrq(38, irq6);
openIrq(39, irq7);
openIrq(40, irq8);
openIrq(41, irq9);
openIrq(42, irq10);
openIrq(43, irq11);
openIrq(44, irq12);
openIrq(45, irq13);
openIrq(46, irq14);
openIrq(47, irq15);
comptime var i = IRQ_OFFSET;
inline while (i < IRQ_OFFSET + 16) : (i += 1) {
openIrq(i, interrupts.getInterruptStub(i));
}
log.logInfo("Done\n");
if (build_options.rt_test) runtimeTests();
}
extern fn testFunction0() void {}
nakedcc fn testFunction0() void {}
fn testFunction1(ctx: *arch.InterruptContext) void {}
fn testFunction2(ctx: *arch.InterruptContext) void {}

View file

@ -1,70 +0,0 @@
.macro irqGenerator n
.align 4
.type irq\n, @function
.global irq\n
irq\n:
cli
push $0
push $\n+32
jmp irqCommonStub
.endmacro
irqCommonStub:
// Push all the registers
pusha
// Push the additional segment regiters
push %ds
push %es
push %fs
push %gs
// Set the kernel data segment
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
// Push the stack, this is where all the registers are sported, points the interuptContect
mov %esp, %eax
push %eax
// Call the handler
call irqHandler
// Pop stack pointer to point to the registers pushed
pop %eax
// Pop segment regiters inorder
pop %gs
pop %fs
pop %es
pop %ds
// Pop all general registers
popa
// Pop the error code and interrupt number
add $0x8, %esp
// Pops 5 things at once: cs, eip, eflags, ss, and esp
iret
.type irqCommonStub, @function
irqGenerator 0
irqGenerator 1
irqGenerator 2
irqGenerator 3
irqGenerator 4
irqGenerator 5
irqGenerator 6
irqGenerator 7
irqGenerator 8
irqGenerator 9
irqGenerator 10
irqGenerator 11
irqGenerator 12
irqGenerator 13
irqGenerator 14
irqGenerator 15

View file

@ -11,6 +11,7 @@ const panic = if (is_test) @import(mock_path ++ "panic_mock.zig").panic else @im
const idt = if (is_test) @import(mock_path ++ "idt_mock.zig") else @import("idt.zig");
const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig");
const log = if (is_test) @import(mock_path ++ "log_mock.zig") else @import("../../log.zig");
const interrupts = @import("interrupts.zig");
/// The error set for the ISR. This will be from installing a ISR handler.
pub const IsrError = error{
@ -132,41 +133,6 @@ var isr_handlers: [NUMBER_OF_ENTRIES]?IsrHandler = [_]?IsrHandler{null} ** NUMBE
/// The syscall hander.
var syscall_handler: ?IsrHandler = null;
// The external assembly that is fist called to set up the exception handler.
extern fn isr0() void;
extern fn isr1() void;
extern fn isr2() void;
extern fn isr3() void;
extern fn isr4() void;
extern fn isr5() void;
extern fn isr6() void;
extern fn isr7() void;
extern fn isr8() void;
extern fn isr9() void;
extern fn isr10() void;
extern fn isr11() void;
extern fn isr12() void;
extern fn isr13() void;
extern fn isr14() void;
extern fn isr15() void;
extern fn isr16() void;
extern fn isr17() void;
extern fn isr18() void;
extern fn isr19() void;
extern fn isr20() void;
extern fn isr21() void;
extern fn isr22() void;
extern fn isr23() void;
extern fn isr24() void;
extern fn isr25() void;
extern fn isr26() void;
extern fn isr27() void;
extern fn isr28() void;
extern fn isr29() void;
extern fn isr30() void;
extern fn isr31() void;
extern fn isr128() void;
///
/// The exception handler that each of the exceptions will call when a exception happens.
///
@ -270,46 +236,19 @@ pub fn registerIsr(isr_num: u16, handler: IsrHandler) IsrError!void {
pub fn init() void {
log.logInfo("Init isr\n");
openIsr(0, isr0);
openIsr(1, isr1);
openIsr(2, isr2);
openIsr(3, isr3);
openIsr(4, isr4);
openIsr(5, isr5);
openIsr(6, isr6);
openIsr(7, isr7);
openIsr(8, isr8);
openIsr(9, isr9);
openIsr(10, isr10);
openIsr(11, isr11);
openIsr(12, isr12);
openIsr(13, isr13);
openIsr(14, isr14);
openIsr(15, isr15);
openIsr(16, isr16);
openIsr(17, isr17);
openIsr(18, isr18);
openIsr(19, isr19);
openIsr(20, isr20);
openIsr(21, isr21);
openIsr(22, isr22);
openIsr(23, isr23);
openIsr(24, isr24);
openIsr(25, isr25);
openIsr(26, isr26);
openIsr(27, isr27);
openIsr(28, isr28);
openIsr(29, isr29);
openIsr(30, isr30);
openIsr(31, isr31);
openIsr(syscalls.INTERRUPT, isr128);
comptime var i = 0;
inline while (i < 32) : (i += 1) {
openIsr(i, interrupts.getInterruptStub(i));
}
openIsr(syscalls.INTERRUPT, interrupts.getInterruptStub(syscalls.INTERRUPT));
log.logInfo("Done\n");
if (build_options.rt_test) runtimeTests();
}
extern fn testFunction0() void {}
nakedcc fn testFunction0() void {}
fn testFunction1(ctx: *arch.InterruptContext) void {}
fn testFunction2(ctx: *arch.InterruptContext) void {}
fn testFunction3(ctx: *arch.InterruptContext) void {}

View file

@ -1,90 +0,0 @@
.macro isrGenerator n
.align 4
.type isr\n, @function
.global isr\n
isr\n:
cli
// Push 0 if there is no interrupt error code
.if (\n != 8 && !(\n >= 10 && \n <= 14) && \n != 17)
push $0
.endif
push $\n
jmp isrCommonStub
.endmacro
isrCommonStub:
// Push all the registers
pusha
// Push the additional segment regiters
push %ds
push %es
push %fs
push %gs
// Set the kernel data segment
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
// Push the stack, this is where all the registers are sported, points the interuptContect
mov %esp, %eax
push %eax
// Call the handler
call isrHandler
// Pop stack pointer to point to the registers pushed
pop %eax
// Pop segment regiters inorder
pop %gs
pop %fs
pop %es
pop %ds
// Pop all general registers
popa
// Pop the error code and interrupt number
add $0x8, %esp
// Pops 5 things at once: cs, eip, eflags, ss, and esp
iret
.type isrCommonStub, @function
isrGenerator 0
isrGenerator 1
isrGenerator 2
isrGenerator 3
isrGenerator 4
isrGenerator 5
isrGenerator 6
isrGenerator 7
isrGenerator 8
isrGenerator 9
isrGenerator 10
isrGenerator 11
isrGenerator 12
isrGenerator 13
isrGenerator 14
isrGenerator 15
isrGenerator 16
isrGenerator 17
isrGenerator 18
isrGenerator 19
isrGenerator 20
isrGenerator 21
isrGenerator 22
isrGenerator 23
isrGenerator 24
isrGenerator 25
isrGenerator 26
isrGenerator 27
isrGenerator 28
isrGenerator 29
isrGenerator 30
isrGenerator 31
isrGenerator 128

View file

@ -22,6 +22,7 @@ const DataElementType = enum {
PTR_CONST_IdtPtr,
ERROR_IDTERROR_VOID,
EFN_OVOID,
NFN_OVOID,
FN_OVOID,
FN_OUSIZE,
FN_OU16,
@ -34,6 +35,7 @@ const DataElementType = enum {
FN_IU16_IU8_OVOID,
FN_IU16_IU16_OVOID,
FN_IU8_IEFNOVOID_OERRORIDTERRORVOID,
FN_IU8_INFNOVOID_OERRORIDTERRORVOID,
FN_IPTRCONSTGDTPTR_OVOID,
FN_IPTRCONSTIDTPTR_OVOID,
};
@ -53,6 +55,7 @@ const DataElement = union(DataElementType) {
PTR_CONST_IdtPtr: *const idt.IdtPtr,
ERROR_IDTERROR_VOID: idt.IdtError!void,
EFN_OVOID: extern fn () void,
NFN_OVOID: nakedcc fn () void,
FN_OVOID: fn () void,
FN_OUSIZE: fn () usize,
FN_OU16: fn () u16,
@ -65,6 +68,7 @@ const DataElement = union(DataElementType) {
FN_IU16_IU8_OVOID: fn (u16, u8) void,
FN_IU16_IU16_OVOID: fn (u16, u16) void,
FN_IU8_IEFNOVOID_OERRORIDTERRORVOID: fn (u8, extern fn () void) idt.IdtError!void,
FN_IU8_INFNOVOID_OERRORIDTERRORVOID: fn (u8, nakedcc fn () void) idt.IdtError!void,
FN_IPTRCONSTGDTPTR_OVOID: fn (*const gdt.GdtPtr) void,
FN_IPTRCONSTIDTPTR_OVOID: fn (*const idt.IdtPtr) void,
};
@ -151,6 +155,7 @@ fn Mock() type {
*const idt.IdtPtr => DataElement{ .PTR_CONST_IdtPtr = arg },
idt.IdtError!void => DataElement{ .ERROR_IDTERROR_VOID = arg },
extern fn () void => DataElement{ .EFN_OVOID = arg },
nakedcc fn () void => DataElement{ .NFN_OVOID = arg },
fn () void => DataElement{ .FN_OVOID = arg },
fn () usize => DataElement{ .FN_OUSIZE = arg },
fn () u16 => DataElement{ .FN_OU16 = arg },
@ -165,6 +170,7 @@ fn Mock() type {
fn (*const gdt.GdtPtr) void => DataElement{ .FN_IPTRCONSTGDTPTR_OVOID = arg },
fn (*const idt.IdtPtr) void => DataElement{ .FN_IPTRCONSTIDTPTR_OVOID = arg },
fn (u8, extern fn () void) idt.IdtError!void => DataElement{ .FN_IU8_IEFNOVOID_OERRORIDTERRORVOID = arg },
fn (u8, nakedcc fn () void) idt.IdtError!void => DataElement{ .FN_IU8_INFNOVOID_OERRORIDTERRORVOID = arg },
else => @compileError("Type not supported: " ++ @typeName(@typeOf(arg))),
};
}
@ -189,6 +195,7 @@ fn Mock() type {
*const idt.IdtPtr => DataElement.PTR_CONST_IdtPtr,
idt.IdtError!void => DataElement.ERROR_IDTERROR_VOID,
extern fn () void => DataElementType.EFN_OVOID,
nakedcc fn () void => DataElementType.NFN_OVOID,
fn () void => DataElementType.FN_OVOID,
fn () u16 => DataElementType.FN_OU16,
fn (u8) bool => DataElementType.FN_IU8_OBOOL,
@ -202,6 +209,7 @@ fn Mock() type {
fn (*const gdt.GdtPtr) void => DataElementType.FN_IPTRCONSTGDTPTR_OVOID,
fn (*const idt.IdtPtr) void => DataElementType.FN_IPTRCONSTIDTPTR_OVOID,
fn (u8, extern fn () void) idt.IdtError!void => DataElementType.FN_IU8_IEFNOVOID_OERRORIDTERRORVOID,
fn (u8, nakedcc fn () void) idt.IdtError!void => DataElementType.FN_IU8_INFNOVOID_OERRORIDTERRORVOID,
else => @compileError("Type not supported: " ++ @typeName(T)),
};
}
@ -228,6 +236,7 @@ fn Mock() type {
*const idt.IdtPtr => element.PTR_CONST_IdtPtr,
idt.IdtError!void => element.ERROR_IDTERROR_VOID,
extern fn () void => element.EFN_OVOID,
nakedcc fn () void => element.NFN_OVOID,
fn () void => element.FN_OVOID,
fn () u16 => element.FN_OU16,
fn (u8) bool => element.FN_IU8_OBOOL,
@ -241,6 +250,7 @@ fn Mock() type {
fn (*const gdt.GdtPtr) void => element.FN_IPTRCONSTGDTPTR_OVOID,
fn (*const idt.IdtPtr) void => element.FN_IPTRCONSTIDTPTR_OVOID,
fn (u8, extern fn () void) idt.IdtError!void => element.FN_IU8_IEFNOVOID_OERRORIDTERRORVOID,
fn (u8, nakedcc fn () void) idt.IdtError!void => element.FN_IU8_INFNOVOID_OERRORIDTERRORVOID,
else => @compileError("Type not supported: " ++ @typeName(T)),
};
}