Update to zig master and simplify build script
This commit is contained in:
		
							parent
							
								
									b2ce5f6310
								
							
						
					
					
						commit
						798b1c1d34
					
				
					 9 changed files with 143 additions and 636 deletions
				
			
		| 
						 | 
				
			
			@ -15,7 +15,7 @@ pool:
 | 
			
		|||
  vmImage: 'ubuntu-latest'
 | 
			
		||||
 | 
			
		||||
variables:
 | 
			
		||||
  zig_version: 0.4.0
 | 
			
		||||
  zig_version: master
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
- script: |
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +37,5 @@ steps:
 | 
			
		|||
  displayName: 'Download qemu'
 | 
			
		||||
  
 | 
			
		||||
- script: |
 | 
			
		||||
    zig*/zig build -Drt-test=true
 | 
			
		||||
    zig*/zig build test -Drt-test=true -Dzig-path=zig*/zig
 | 
			
		||||
    zig*/zig build test -Drt-test=true
 | 
			
		||||
  displayName: 'Runtime tests'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										230
									
								
								build.zig
									
										
									
									
									
								
							
							
						
						
									
										230
									
								
								build.zig
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,187 +1,93 @@
 | 
			
		|||
// Zig version: 0.4.0
 | 
			
		||||
 | 
			
		||||
const Builder = @import("std").build.Builder;
 | 
			
		||||
const Step = @import("std").build.Step;
 | 
			
		||||
const builtin = @import("builtin");
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const os = std.os;
 | 
			
		||||
const ArrayList = std.ArrayList;
 | 
			
		||||
const warn = std.debug.warn;
 | 
			
		||||
const mem = std.mem;
 | 
			
		||||
const builtin = @import("builtin");
 | 
			
		||||
const Builder = std.build.Builder;
 | 
			
		||||
const Step = std.build.Step;
 | 
			
		||||
const Target = std.build.Target;
 | 
			
		||||
const fs = std.fs;
 | 
			
		||||
 | 
			
		||||
var src_files: ArrayList([]const u8) = undefined;
 | 
			
		||||
var src_files_asm: ArrayList([]const u8) = undefined;
 | 
			
		||||
 | 
			
		||||
fn concat(allocator: *std.mem.Allocator, str: []const u8, str2: []const u8) !std.Buffer {
 | 
			
		||||
    var b = try std.Buffer.init(allocator, str);
 | 
			
		||||
    try b.append(str2);
 | 
			
		||||
    return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn build(b: *Builder) void {
 | 
			
		||||
    src_files = ArrayList([]const u8).init(b.allocator);
 | 
			
		||||
    src_files_asm = ArrayList([]const u8).init(b.allocator);
 | 
			
		||||
pub fn build(b: *Builder) !void {
 | 
			
		||||
    const target = Target{
 | 
			
		||||
        .Cross = std.build.CrossTarget{
 | 
			
		||||
            .arch = .i386,
 | 
			
		||||
            .os = .freestanding,
 | 
			
		||||
            .abi = .gnu,
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
    const debug = b.option(bool, "debug", "build with debug symbols / make qemu wait for a debug connection") orelse false;
 | 
			
		||||
    var build_path = b.option([]const u8, "build-path", "path to build to") orelse "bin";
 | 
			
		||||
    var src_path = b.option([]const u8, "source-path", "path to source") orelse "src";
 | 
			
		||||
    var target = b.option([]const u8, "target", "target to build/run for") orelse "x86";
 | 
			
		||||
    const rt_test = b.option(bool, "rt-test", "enable/disable runtime testing") orelse false;
 | 
			
		||||
    const builtin_target = if (mem.eql(u8, target, "x86")) builtin.Arch.i386 else unreachable;
 | 
			
		||||
    const zig_path = b.option([]const u8, "zig-path", "the path to the zig binary to use for rt testing") orelse "/snap/bin/zig";
 | 
			
		||||
 | 
			
		||||
    b.makePath(build_path) catch unreachable;
 | 
			
		||||
    var grub_path = concat(b.allocator, build_path, "/iso/boot/grub") catch unreachable;
 | 
			
		||||
    var kern_path = concat(b.allocator, build_path, "/kernel") catch unreachable;
 | 
			
		||||
    var a_path = concat(b.allocator, build_path, "/kernel/arch/") catch unreachable;
 | 
			
		||||
    a_path = concat(b.allocator, a_path.toSlice(), target) catch unreachable;
 | 
			
		||||
    b.makePath(grub_path.toSlice()) catch unreachable;
 | 
			
		||||
    b.makePath(kern_path.toSlice()) catch unreachable;
 | 
			
		||||
    b.makePath(a_path.toSlice()) catch unreachable;
 | 
			
		||||
    b.makePath("zig-cache/kernel") catch unreachable;
 | 
			
		||||
 | 
			
		||||
    src_files.append("kernel/kmain") catch unreachable;
 | 
			
		||||
 | 
			
		||||
    // Add the assemblies
 | 
			
		||||
    switch (builtin_target) {
 | 
			
		||||
        builtin.Arch.i386 => {
 | 
			
		||||
            src_files_asm.append("kernel/arch/x86/irq_asm") catch unreachable;
 | 
			
		||||
            src_files_asm.append("kernel/arch/x86/isr_asm") catch unreachable;
 | 
			
		||||
    const main_src = "src/kernel/kmain.zig";
 | 
			
		||||
    const exec = b.addExecutable("pluto", main_src);
 | 
			
		||||
    exec.setMainPkgPath(".");
 | 
			
		||||
    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 => {},
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var arch_boot = concat(b.allocator, "kernel/arch/", target) catch unreachable;
 | 
			
		||||
    arch_boot.append("/boot") catch unreachable;
 | 
			
		||||
    src_files.append(arch_boot.toSlice()) catch unreachable;
 | 
			
		||||
    const iso_path = fs.path.join(b.allocator, [_][]const u8{ b.exe_dir, "pluto.iso" }) catch unreachable;
 | 
			
		||||
    const grub_build_path = fs.path.join(b.allocator, [_][]const u8{ b.exe_dir, "iso", "boot" }) catch unreachable;
 | 
			
		||||
    const iso_dir_path = fs.path.join(b.allocator, [_][]const u8{ b.exe_dir, "iso" }) catch unreachable;
 | 
			
		||||
 | 
			
		||||
    const iso_path = concat(b.allocator, build_path, "/pluto.iso") catch unreachable;
 | 
			
		||||
    var objects = buildObjects(b, builtin_target, build_path, src_path);
 | 
			
		||||
    var link_step = buildLink(b, builtin_target, build_path);
 | 
			
		||||
    const iso_step = buildISO(b, build_path, iso_path.toSlice());
 | 
			
		||||
    const mkdir_cmd = b.addSystemCommand([_][]const u8{ "mkdir", "-p", fs.path.dirname(grub_build_path).? });
 | 
			
		||||
 | 
			
		||||
    for (objects.toSlice()) |obj| {
 | 
			
		||||
        if (std.mem.eql(u8, obj.name, "kernel/kmain")) {
 | 
			
		||||
            // Add build options here
 | 
			
		||||
            obj.addBuildOption(bool, "rt_test", rt_test);
 | 
			
		||||
        }
 | 
			
		||||
        b.default_step.dependOn(&obj.step);
 | 
			
		||||
    }
 | 
			
		||||
    b.default_step.dependOn(link_step);
 | 
			
		||||
    for (iso_step.toSlice()) |step| b.default_step.dependOn(step);
 | 
			
		||||
    const grub_cmd = b.addSystemCommand([_][]const u8{ "cp", "-r", "grub", grub_build_path });
 | 
			
		||||
    grub_cmd.step.dependOn(&mkdir_cmd.step);
 | 
			
		||||
 | 
			
		||||
    buildRun(b, builtin_target, build_path, iso_path.toSlice(), debug, rt_test);
 | 
			
		||||
    buildDebug(b);
 | 
			
		||||
    buildTest(b, src_path, rt_test, target, zig_path);
 | 
			
		||||
}
 | 
			
		||||
    const cp_elf_cmd = b.addSystemCommand([_][]const u8{"cp"});
 | 
			
		||||
    cp_elf_cmd.addArtifactArg(exec);
 | 
			
		||||
    cp_elf_cmd.addArg(try fs.path.join(b.allocator, [_][]const u8{ grub_build_path, "pluto.elf" }));
 | 
			
		||||
    cp_elf_cmd.step.dependOn(&grub_cmd.step);
 | 
			
		||||
    cp_elf_cmd.step.dependOn(&exec.step);
 | 
			
		||||
 | 
			
		||||
fn buildTest(b: *Builder, src_path: []const u8, rt_test: bool, target: []const u8, zig_path: []const u8) void {
 | 
			
		||||
    const step = b.step("test", "Run tests");
 | 
			
		||||
    if (rt_test) {
 | 
			
		||||
        const script = b.addSystemCommand([][]const u8{ "python3", "test/rt-test.py", target, zig_path});
 | 
			
		||||
        step.dependOn(&script.step);
 | 
			
		||||
    } else {
 | 
			
		||||
        const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
 | 
			
		||||
        for (src_files.toSlice()) |file| {
 | 
			
		||||
            var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
 | 
			
		||||
            file_src.append(".zig") catch unreachable;
 | 
			
		||||
            const tst = b.addTest(file_src.toSlice());
 | 
			
		||||
            tst.setMainPkgPath(".");
 | 
			
		||||
            step.dependOn(&tst.step);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
    const iso_cmd = b.addSystemCommand([_][]const u8{ "grub-mkrescue", "-o", iso_path, iso_dir_path });
 | 
			
		||||
    iso_cmd.step.dependOn(&cp_elf_cmd.step);
 | 
			
		||||
    b.default_step.dependOn(&iso_cmd.step);
 | 
			
		||||
 | 
			
		||||
fn buildDebug(b: *Builder) void {
 | 
			
		||||
    const step = b.step("debug", "Debug with gdb");
 | 
			
		||||
    const cmd = b.addSystemCommand([][]const u8{
 | 
			
		||||
        "gdb",
 | 
			
		||||
        "-ex",
 | 
			
		||||
        "symbol-file bin/iso/boot/pluto.elf",
 | 
			
		||||
        "-ex",
 | 
			
		||||
        "target remote localhost:1234",
 | 
			
		||||
    });
 | 
			
		||||
    step.dependOn(&cmd.step);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn buildRun(b: *Builder, target: builtin.Arch, build_path: []const u8, iso_path: []const u8, debug: bool, rt_test: bool) void {
 | 
			
		||||
    const step = b.step("run", "Run with qemu");
 | 
			
		||||
    const qemu = if (target == builtin.Arch.i386) "qemu-system-i386" else unreachable;
 | 
			
		||||
    var qemu_flags = ArrayList([]const u8).init(b.allocator);
 | 
			
		||||
    qemu_flags.appendSlice([][]const u8{
 | 
			
		||||
        qemu,
 | 
			
		||||
    const run_step = b.step("run", "Run with qemu");
 | 
			
		||||
    const qemu_bin = if (target.getArch() == builtin.Arch.i386) "qemu-system-i386" else unreachable;
 | 
			
		||||
    const qemu_cmd = b.addSystemCommand([_][]const u8{
 | 
			
		||||
        qemu_bin,
 | 
			
		||||
        "-cdrom",
 | 
			
		||||
        iso_path,
 | 
			
		||||
        "-boot",
 | 
			
		||||
        "d",
 | 
			
		||||
        "-serial",
 | 
			
		||||
        "stdio",
 | 
			
		||||
    }) catch unreachable;
 | 
			
		||||
    });
 | 
			
		||||
    if (debug)
 | 
			
		||||
        qemu_flags.appendSlice([][]const u8{
 | 
			
		||||
            "-s",
 | 
			
		||||
            "-S",
 | 
			
		||||
        }) catch unreachable;
 | 
			
		||||
        qemu_cmd.addArgs([_][]const u8{ "-s", "-S" });
 | 
			
		||||
    if (rt_test)
 | 
			
		||||
        qemu_flags.appendSlice([][]const u8{
 | 
			
		||||
            "-display",
 | 
			
		||||
            "none"
 | 
			
		||||
        }) catch unreachable;
 | 
			
		||||
    const cmd = b.addSystemCommand(qemu_flags.toSlice());
 | 
			
		||||
    step.dependOn(&cmd.step);
 | 
			
		||||
}
 | 
			
		||||
        qemu_cmd.addArgs([_][]const u8{ "-display", "none" });
 | 
			
		||||
    run_step.dependOn(&qemu_cmd.step);
 | 
			
		||||
    qemu_cmd.step.dependOn(&iso_cmd.step);
 | 
			
		||||
 | 
			
		||||
fn buildISO(b: *Builder, build_path: []const u8, iso_path: []const u8) ArrayList(*Step) {
 | 
			
		||||
    const grub_build_path = concat(b.allocator, build_path, "/iso/boot/") catch unreachable;
 | 
			
		||||
    const iso_dir_path = concat(b.allocator, build_path, "/iso") catch unreachable;
 | 
			
		||||
    const grub_cmd = b.addSystemCommand([][]const u8{ "cp", "-r", "grub", grub_build_path.toSlice() });
 | 
			
		||||
    const iso_cmd = b.addSystemCommand([][]const u8{ "grub-mkrescue", "-o", iso_path, iso_dir_path.toSlice() });
 | 
			
		||||
    var steps = ArrayList(*Step).init(b.allocator);
 | 
			
		||||
    steps.append(&grub_cmd.step) catch unreachable;
 | 
			
		||||
    steps.append(&iso_cmd.step) catch unreachable;
 | 
			
		||||
    return steps;
 | 
			
		||||
}
 | 
			
		||||
    const test_step = b.step("test", "Run tests");
 | 
			
		||||
    if (rt_test) {
 | 
			
		||||
        const script = b.addSystemCommand([_][]const u8{ "python3", "test/rt-test.py", "x86", b.zig_exe });
 | 
			
		||||
        test_step.dependOn(&script.step);
 | 
			
		||||
    } else {
 | 
			
		||||
        const unit_tests = b.addTest(main_src);
 | 
			
		||||
        unit_tests.setMainPkgPath(".");
 | 
			
		||||
        unit_tests.addBuildOption(bool, "rt_test", rt_test);
 | 
			
		||||
        test_step.dependOn(&unit_tests.step);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
fn buildLink(b: *Builder, target: builtin.Arch, build_path: []const u8) *Step {
 | 
			
		||||
    const exec = b.addExecutable("pluto.elf", null);
 | 
			
		||||
    const elf_path = concat(b.allocator, build_path, "/iso/boot") catch unreachable;
 | 
			
		||||
    exec.setOutputDir(elf_path.toSlice());
 | 
			
		||||
    exec.setLinkerScriptPath("link.ld");
 | 
			
		||||
    exec.setTarget(target, builtin.Os.freestanding, builtin.Abi.gnu);
 | 
			
		||||
    for (src_files.toSlice()) |file| {
 | 
			
		||||
        var file_obj = concat(b.allocator, build_path, "/") catch unreachable;
 | 
			
		||||
        file_obj.append(file) catch unreachable;
 | 
			
		||||
        file_obj.append(".o") catch unreachable;
 | 
			
		||||
        exec.addObjectFile(file_obj.toSlice());
 | 
			
		||||
        exec.setMainPkgPath(".");
 | 
			
		||||
    }
 | 
			
		||||
    for (src_files_asm.toSlice()) |file| {
 | 
			
		||||
        var file_obj = concat(b.allocator, build_path, "/") catch unreachable;
 | 
			
		||||
        file_obj.append(file) catch unreachable;
 | 
			
		||||
        file_obj.append(".o") catch unreachable;
 | 
			
		||||
        exec.addObjectFile(file_obj.toSlice());
 | 
			
		||||
    }
 | 
			
		||||
    return &exec.step;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn buildObjects(b: *Builder, target: builtin.Arch, build_path: []const u8, src_path: []const u8) ArrayList(*std.build.LibExeObjStep) {
 | 
			
		||||
    var objects = ArrayList(*std.build.LibExeObjStep).init(b.allocator);
 | 
			
		||||
    const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
 | 
			
		||||
    for (src_files.toSlice()) |file| {
 | 
			
		||||
        var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
 | 
			
		||||
        file_src.append(".zig") catch unreachable;
 | 
			
		||||
        const obj = b.addObject(file, file_src.toSlice());
 | 
			
		||||
        obj.setMainPkgPath(".");
 | 
			
		||||
        obj.setOutputDir(build_path);
 | 
			
		||||
        obj.setTarget(target, builtin.Os.freestanding, builtin.Abi.gnu);
 | 
			
		||||
        objects.append(obj) catch unreachable;
 | 
			
		||||
    }
 | 
			
		||||
    for (src_files_asm.toSlice()) |file| {
 | 
			
		||||
        var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
 | 
			
		||||
        file_src.append(".s") catch unreachable;
 | 
			
		||||
        const obj = b.addAssemble(file, file_src.toSlice());
 | 
			
		||||
        obj.setOutputDir(build_path);
 | 
			
		||||
        obj.setTarget(target, builtin.Os.freestanding, builtin.Abi.gnu);
 | 
			
		||||
        objects.append(obj) catch unreachable;
 | 
			
		||||
    }
 | 
			
		||||
    return objects;
 | 
			
		||||
    const debug_step = b.step("debug", "Debug with gdb");
 | 
			
		||||
    const debug_cmd = b.addSystemCommand([_][]const u8{
 | 
			
		||||
        "gdb",
 | 
			
		||||
        "-ex",
 | 
			
		||||
        "symbol-file",
 | 
			
		||||
    });
 | 
			
		||||
    debug_cmd.addArtifactArg(exec);
 | 
			
		||||
    debug_cmd.addArgs([_][]const u8{
 | 
			
		||||
        "-ex",
 | 
			
		||||
        "target remote localhost:1234",
 | 
			
		||||
    });
 | 
			
		||||
    debug_step.dependOn(&debug_cmd.step);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ const USER_DATA_INDEX: u16      = 0x04;
 | 
			
		|||
/// The index of the task state segment GDT entry.
 | 
			
		||||
const TSS_INDEX: u16 = 0x05;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// The offsets into the GDT where each segment resides.
 | 
			
		||||
 | 
			
		||||
/// The offset of the NULL GDT entry.
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +60,6 @@ const PRIVILEGE_RING_3          = 0x60; // 01100000
 | 
			
		|||
 | 
			
		||||
const PRESENT_BIT = 0x80; // 10000000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const KERNEL_SEGMENT = PRESENT_BIT | PRIVILEGE_RING_0 | DESCRIPTOR_BIT;
 | 
			
		||||
const USER_SEGMENT = PRESENT_BIT | PRIVILEGE_RING_3 | DESCRIPTOR_BIT;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +68,6 @@ const DATA_SEGMENT = WRITABLE_BIT;
 | 
			
		|||
 | 
			
		||||
const TSS_SEGMENT = PRESENT_BIT | EXECUTABLE_BIT | ACCESSED_BIT;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// The flag bits
 | 
			
		||||
const IS_64_BIT = 0x02; // 0010
 | 
			
		||||
const IS_32_BIT = 0x04; // 0100
 | 
			
		||||
| 
						 | 
				
			
			@ -213,7 +210,7 @@ const TtsEntry = packed struct {
 | 
			
		|||
///     A new GDT entry with the give access and flag bits set with the base at 0x00000000 and limit at 0xFFFFF.
 | 
			
		||||
///
 | 
			
		||||
fn makeEntry(base: u32, limit: u20, access: u8, flags: u4) GdtEntry {
 | 
			
		||||
    return GdtEntry {
 | 
			
		||||
    return GdtEntry{
 | 
			
		||||
        .limit_low = @truncate(u16, limit),
 | 
			
		||||
        .base_low = @truncate(u24, base),
 | 
			
		||||
        .access = access,
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +221,7 @@ fn makeEntry(base: u32, limit: u20, access: u8, flags: u4) GdtEntry {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/// The GDT entry table of NUMBER_OF_ENTRIES entries.
 | 
			
		||||
var gdt_entries: [NUMBER_OF_ENTRIES]GdtEntry = []GdtEntry {
 | 
			
		||||
var gdt_entries: [NUMBER_OF_ENTRIES]GdtEntry = [_]GdtEntry{
 | 
			
		||||
    // Null descriptor
 | 
			
		||||
    makeEntry(0, 0, 0, 0),
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -246,13 +243,13 @@ var gdt_entries: [NUMBER_OF_ENTRIES]GdtEntry = []GdtEntry {
 | 
			
		|||
 | 
			
		||||
/// The GDT pointer that the CPU is loaded with that contains the base address of the GDT and the
 | 
			
		||||
/// size.
 | 
			
		||||
const gdt_ptr: GdtPtr = GdtPtr {
 | 
			
		||||
const gdt_ptr: GdtPtr = GdtPtr{
 | 
			
		||||
    .limit = TABLE_SIZE,
 | 
			
		||||
    .base = &gdt_entries[0],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// The task state segment entry.
 | 
			
		||||
var tss: TtsEntry = TtsEntry {
 | 
			
		||||
var tss: TtsEntry = TtsEntry{
 | 
			
		||||
    .prev_tss = 0,
 | 
			
		||||
    .esp0 = undefined,
 | 
			
		||||
    .ss0 = KERNEL_DATA_OFFSET,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,11 +58,11 @@ pub const IdtPtr = packed struct {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/// The IDT entry table of NUMBER_OF_ENTRIES entries.
 | 
			
		||||
var idt: [NUMBER_OF_ENTRIES]IdtEntry = []IdtEntry{makeEntry(0, 0, 0, 0, 0)} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
var idt: [NUMBER_OF_ENTRIES]IdtEntry = [_]IdtEntry{makeEntry(0, 0, 0, 0, 0)} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
 | 
			
		||||
/// The IDT pointer that the CPU is loaded with that contains the base address of the IDT and the
 | 
			
		||||
/// size.
 | 
			
		||||
const idt_ptr: IdtPtr = IdtPtr {
 | 
			
		||||
const idt_ptr: IdtPtr = IdtPtr{
 | 
			
		||||
    .limit = TABLE_SIZE,
 | 
			
		||||
    .base = &idt[0],
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ const idt_ptr: IdtPtr = IdtPtr {
 | 
			
		|||
///     A new IDT entry.
 | 
			
		||||
///
 | 
			
		||||
fn makeEntry(base: u32, selector: u16, gate_type: u4, privilege: u2, present: u1) IdtEntry {
 | 
			
		||||
    return IdtEntry {
 | 
			
		||||
    return IdtEntry{
 | 
			
		||||
        .base_low = @truncate(u16, base),
 | 
			
		||||
        .selector = selector,
 | 
			
		||||
        .zero = 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +102,7 @@ fn makeEntry(base: u32, selector: u16, gate_type: u4, privilege: u2, present: u1
 | 
			
		|||
///     IN index: u8             - The interrupt number to close.
 | 
			
		||||
///     IN base: extern fn()void - The function handler for the interrupt.
 | 
			
		||||
///
 | 
			
		||||
pub fn openInterruptGate(index: u8, base: extern fn()void) void {
 | 
			
		||||
pub fn openInterruptGate(index: u8, base: extern fn () void) void {
 | 
			
		||||
    idt[index] = makeEntry(@ptrToInt(base), gdt.KERNEL_CODE_OFFSET, INTERRUPT_GATE_32BIT, PRIVILEGE_RING_0, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ extern fn irq14() void;
 | 
			
		|||
extern fn irq15() void;
 | 
			
		||||
 | 
			
		||||
/// The list of IRQ handlers initialised to unhandled.
 | 
			
		||||
var irq_handlers: [NUMBER_OF_ENTRIES]fn(*arch.InterruptContext)void = []fn(*arch.InterruptContext)void {unhandled} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
var irq_handlers: [NUMBER_OF_ENTRIES]fn (*arch.InterruptContext) void = [_]fn (*arch.InterruptContext) void{unhandled} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
/// A dummy handler that will make a call to panic as it is a unhandled interrupt.
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ export fn irqHandler(context: *arch.InterruptContext) void {
 | 
			
		|||
/// Arguments:
 | 
			
		||||
///     IN irq_num: u16 - The IRQ number to register.
 | 
			
		||||
///
 | 
			
		||||
pub fn registerIrq(irq_num: u16, handler: fn(*arch.InterruptContext)void) void {
 | 
			
		||||
pub fn registerIrq(irq_num: u16, handler: fn (*arch.InterruptContext) void) void {
 | 
			
		||||
    irq_handlers[irq_num] = handler;
 | 
			
		||||
    pic.clearMask(irq_num);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ extern fn isr31() void;
 | 
			
		|||
extern fn isr128() void;
 | 
			
		||||
 | 
			
		||||
/// The exception messaged that is printed when a exception happens
 | 
			
		||||
const exception_msg: [NUMBER_OF_ENTRIES][]const u8 = [NUMBER_OF_ENTRIES][]const u8 {
 | 
			
		||||
const exception_msg: [NUMBER_OF_ENTRIES][]const u8 = [NUMBER_OF_ENTRIES][]const u8{
 | 
			
		||||
    "Divide By Zero",
 | 
			
		||||
    "Single Step (Debugger)",
 | 
			
		||||
    "Non Maskable Interrupt",
 | 
			
		||||
| 
						 | 
				
			
			@ -75,20 +75,18 @@ const exception_msg: [NUMBER_OF_ENTRIES][]const u8 = [NUMBER_OF_ENTRIES][]const
 | 
			
		|||
    "Reserved",
 | 
			
		||||
    "Reserved",
 | 
			
		||||
    "Security",
 | 
			
		||||
    "Reserved"
 | 
			
		||||
    "Reserved",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Errors that an isr function can return
 | 
			
		||||
pub const IsrError = error {
 | 
			
		||||
    UnrecognisedIsr
 | 
			
		||||
};
 | 
			
		||||
pub const IsrError = error{UnrecognisedIsr};
 | 
			
		||||
 | 
			
		||||
/// An isr handler. Takes an interrupt context and returns void.
 | 
			
		||||
/// Should finish quickly to avoid delaying further interrupts and the previously running code
 | 
			
		||||
pub const IsrHandler = fn(*arch.InterruptContext)void;
 | 
			
		||||
pub const IsrHandler = fn (*arch.InterruptContext) void;
 | 
			
		||||
 | 
			
		||||
// The of exception handlers initialised to unhandled.
 | 
			
		||||
var isr_handlers: [NUMBER_OF_ENTRIES]IsrHandler = []IsrHandler{unhandled} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
var isr_handlers: [NUMBER_OF_ENTRIES]IsrHandler = [_]IsrHandler{unhandled} ** NUMBER_OF_ENTRIES;
 | 
			
		||||
var syscall_handler: IsrHandler = unhandled;
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +139,7 @@ export fn isrHandler(context: *arch.InterruptContext) void {
 | 
			
		|||
/// Errors:
 | 
			
		||||
///     IsrError.UnrecognisedIsr - If `isr_num` is invalid (see isValidIsr)
 | 
			
		||||
///
 | 
			
		||||
pub fn registerIsr(isr_num: u16, handler: fn(*arch.InterruptContext)void) !void {
 | 
			
		||||
pub fn registerIsr(isr_num: u16, handler: fn (*arch.InterruptContext) void) !void {
 | 
			
		||||
    if (isr_num == syscalls.INTERRUPT) {
 | 
			
		||||
        syscall_handler = handler;
 | 
			
		||||
    } else if (isValidIsr(isr_num)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,13 @@ pub const NUM_HANDLERS: u16 = 256;
 | 
			
		|||
pub const SyscallHandler = fn (ctx: *arch.InterruptContext) u32;
 | 
			
		||||
 | 
			
		||||
/// Errors that syscall utility functions can throw
 | 
			
		||||
pub const SyscallError = error {
 | 
			
		||||
pub const SyscallError = error{
 | 
			
		||||
    SyscallExists,
 | 
			
		||||
    InvalidSyscall
 | 
			
		||||
    InvalidSyscall,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// The array of registered syscalls
 | 
			
		||||
var handlers: [NUM_HANDLERS]?SyscallHandler = []?SyscallHandler{null} ** NUM_HANDLERS;
 | 
			
		||||
var handlers: [NUM_HANDLERS]?SyscallHandler = [_]?SyscallHandler{null} ** NUM_HANDLERS;
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
/// Returns true if the syscall is valid, else false.
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ inline fn syscall0(syscall: u32) u32 {
 | 
			
		|||
    return asm volatile (
 | 
			
		||||
        \\int $0x80
 | 
			
		||||
        : [ret] "={eax}" (-> u32)
 | 
			
		||||
        : [syscall] "{eax}" (syscall),
 | 
			
		||||
        : [syscall] "{eax}" (syscall)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ inline fn syscall1(syscall: u32, arg: u32) u32 {
 | 
			
		|||
        \\int $0x80
 | 
			
		||||
        : [ret] "={eax}" (-> u32)
 | 
			
		||||
        : [syscall] "{eax}" (syscall),
 | 
			
		||||
          [arg1] "{ebx}" (arg),
 | 
			
		||||
          [arg1] "{ebx}" (arg)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ inline fn syscall2(syscall: u32, arg1: u32, arg2: u32) u32 {
 | 
			
		|||
        : [ret] "={eax}" (-> u32)
 | 
			
		||||
        : [syscall] "{eax}" (syscall),
 | 
			
		||||
          [arg1] "{ebx}" (arg1),
 | 
			
		||||
          [arg2] "{ecx}" (arg2),
 | 
			
		||||
          [arg2] "{ecx}" (arg2)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +138,7 @@ inline fn syscall3(syscall: u32, arg1: u32, arg2: u32, arg3: u32) u32 {
 | 
			
		|||
        : [syscall] "{eax}" (syscall),
 | 
			
		||||
          [arg1] "{ebx}" (arg1),
 | 
			
		||||
          [arg2] "{ecx}" (arg2),
 | 
			
		||||
          [arg3] "{edx}" (arg3),
 | 
			
		||||
          [arg3] "{edx}" (arg3)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +160,7 @@ inline fn syscall4(syscall: u32, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32
 | 
			
		|||
          [arg1] "{ebx}" (arg1),
 | 
			
		||||
          [arg2] "{ecx}" (arg2),
 | 
			
		||||
          [arg3] "{edx}" (arg3),
 | 
			
		||||
          [arg4] "{esi}" (arg4),
 | 
			
		||||
          [arg4] "{esi}" (arg4)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +184,7 @@ inline fn syscall5(syscall: u32, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg
 | 
			
		|||
          [arg2] "{ecx}" (arg2),
 | 
			
		||||
          [arg3] "{edx}" (arg3),
 | 
			
		||||
          [arg4] "{esi}" (arg4),
 | 
			
		||||
          [arg5] "{edi}" (arg5),
 | 
			
		||||
          [arg5] "{edi}" (arg5)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ inline fn syscallArg(ctx: *arch.InterruptContext, comptime arg_idx: u32) u32 {
 | 
			
		|||
        2 => ctx.edx,
 | 
			
		||||
        3 => ctx.esi,
 | 
			
		||||
        4 => ctx.edi,
 | 
			
		||||
        else => @compileError("Arg index must be between 0 and 4")
 | 
			
		||||
        else => @compileError("Arg index must be between 0 and 4"),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +217,6 @@ pub fn init(comptime options: type) void {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/// Tests
 | 
			
		||||
 | 
			
		||||
var testInt: u32 = 0;
 | 
			
		||||
 | 
			
		||||
fn testHandler0(ctx: *arch.InterruptContext) u32 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,13 @@ const serial = @import("serial.zig");
 | 
			
		|||
const mem = @import("mem.zig");
 | 
			
		||||
const options = @import("build_options");
 | 
			
		||||
 | 
			
		||||
comptime {
 | 
			
		||||
    switch (builtin.arch) {
 | 
			
		||||
        .i386 => _ = @import("arch/x86/boot.zig"),
 | 
			
		||||
        else => {},
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Need to import this as we need the panic to be in the root source file, or zig will just use the
 | 
			
		||||
// builtin panic and just loop, which is what we don't want
 | 
			
		||||
const panic_root = @import("panic.zig");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue