Separate arch-specific and arch-agnostic code
This commit is contained in:
parent
b1011b780f
commit
49d6f19516
4 changed files with 120 additions and 105 deletions
16
build.zig
16
build.zig
|
@ -8,7 +8,7 @@ const ArrayList = std.ArrayList;
|
||||||
const warn = std.debug.warn;
|
const warn = std.debug.warn;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
|
||||||
const src_files = [][]const u8{"kernel/kmain"};
|
var src_files: ArrayList([]const u8) = undefined;
|
||||||
|
|
||||||
fn concat(allocator: *std.mem.Allocator, str: []const u8, str2: []const u8) !std.Buffer {
|
fn concat(allocator: *std.mem.Allocator, str: []const u8, str2: []const u8) !std.Buffer {
|
||||||
var b = try std.Buffer.init(allocator, str);
|
var b = try std.Buffer.init(allocator, str);
|
||||||
|
@ -17,6 +17,7 @@ fn concat(allocator: *std.mem.Allocator, str: []const u8, str2: []const u8) !std
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(b: *Builder) void {
|
pub fn build(b: *Builder) void {
|
||||||
|
src_files = ArrayList([]const u8).init(b.allocator);
|
||||||
const debug = b.option(bool, "debug", "build with debug symbols / make qemu wait for a debug connection") orelse false;
|
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 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 src_path = b.option([]const u8, "source-path", "path to source") orelse "src";
|
||||||
|
@ -25,6 +26,13 @@ pub fn build(b: *Builder) void {
|
||||||
|
|
||||||
const iso_path = concat(b.allocator, build_path, "/pluto.iso") catch unreachable;
|
const iso_path = concat(b.allocator, build_path, "/pluto.iso") catch unreachable;
|
||||||
|
|
||||||
|
src_files.append("kernel/kmain") catch unreachable;
|
||||||
|
|
||||||
|
// Add the architecture init file to the source files
|
||||||
|
var arch_init = concat(b.allocator, "kernel/arch/", target) catch unreachable;
|
||||||
|
arch_init.append("/arch") catch unreachable;
|
||||||
|
src_files.append(arch_init.toSlice()) catch unreachable;
|
||||||
|
|
||||||
var objects_steps = buildObjects(b, builtin_target, build_path, src_path);
|
var objects_steps = buildObjects(b, builtin_target, build_path, src_path);
|
||||||
var link_step = buildLink(b, builtin_target, build_path);
|
var link_step = buildLink(b, builtin_target, build_path);
|
||||||
const iso_step = buildISO(b, build_path, iso_path.toSlice());
|
const iso_step = buildISO(b, build_path, iso_path.toSlice());
|
||||||
|
@ -41,7 +49,7 @@ pub fn build(b: *Builder) void {
|
||||||
fn buildTest(b: *Builder, src_path: []const u8) void {
|
fn buildTest(b: *Builder, src_path: []const u8) void {
|
||||||
const step = b.step("test", "Run all tests");
|
const step = b.step("test", "Run all tests");
|
||||||
const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
|
const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
|
||||||
for (src_files) |file| {
|
for (src_files.toSlice()) |file| {
|
||||||
var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
|
var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
|
||||||
file_src.append(".zig") catch unreachable;
|
file_src.append(".zig") catch unreachable;
|
||||||
const tst = b.addTest(file_src.toSlice());
|
const tst = b.addTest(file_src.toSlice());
|
||||||
|
@ -100,7 +108,7 @@ fn buildLink(b: *Builder, target: builtin.Arch, build_path: []const u8) *Step {
|
||||||
exec.setOutputDir(elf_path.toSlice());
|
exec.setOutputDir(elf_path.toSlice());
|
||||||
exec.setLinkerScriptPath("link.ld");
|
exec.setLinkerScriptPath("link.ld");
|
||||||
exec.setTarget(target, builtin.Os.freestanding, builtin.Abi.gnu);
|
exec.setTarget(target, builtin.Os.freestanding, builtin.Abi.gnu);
|
||||||
for (src_files) |file| {
|
for (src_files.toSlice()) |file| {
|
||||||
var file_obj = concat(b.allocator, build_path, "/") catch unreachable;
|
var file_obj = concat(b.allocator, build_path, "/") catch unreachable;
|
||||||
file_obj.append(file) catch unreachable;
|
file_obj.append(file) catch unreachable;
|
||||||
file_obj.append(".o") catch unreachable;
|
file_obj.append(".o") catch unreachable;
|
||||||
|
@ -112,7 +120,7 @@ fn buildLink(b: *Builder, target: builtin.Arch, build_path: []const u8) *Step {
|
||||||
fn buildObjects(b: *Builder, target: builtin.Arch, build_path: []const u8, src_path: []const u8) ArrayList(*Step) {
|
fn buildObjects(b: *Builder, target: builtin.Arch, build_path: []const u8, src_path: []const u8) ArrayList(*Step) {
|
||||||
var objects = ArrayList(*Step).init(b.allocator);
|
var objects = ArrayList(*Step).init(b.allocator);
|
||||||
const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
|
const src_path2 = concat(b.allocator, src_path, "/") catch unreachable;
|
||||||
for (src_files) |file| {
|
for (src_files.toSlice()) |file| {
|
||||||
var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
|
var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable;
|
||||||
file_src.append(".zig") catch unreachable;
|
file_src.append(".zig") catch unreachable;
|
||||||
const obj = b.addObject(file, file_src.toSlice());
|
const obj = b.addObject(file, file_src.toSlice());
|
||||||
|
|
2
src/kernel/arch.zig
Normal file
2
src/kernel/arch.zig
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/// Initialise the architecture
|
||||||
|
pub extern fn init() void;
|
103
src/kernel/arch/x86/arch.zig
Normal file
103
src/kernel/arch/x86/arch.zig
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
extern fn kmain() void;
|
||||||
|
|
||||||
|
const MultiBoot = packed struct {
|
||||||
|
magic: i32,
|
||||||
|
flags: i32,
|
||||||
|
checksum: i32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ALIGN = 1 << 0;
|
||||||
|
const MEMINFO = 1 << 1;
|
||||||
|
const MAGIC = 0x1BADB002;
|
||||||
|
const FLAGS = ALIGN | MEMINFO;
|
||||||
|
|
||||||
|
export var multiboot align(4) linksection(".rodata.boot") = MultiBoot{
|
||||||
|
.magic = MAGIC,
|
||||||
|
.flags = FLAGS,
|
||||||
|
.checksum = -(MAGIC + FLAGS),
|
||||||
|
};
|
||||||
|
|
||||||
|
const KERNEL_ADDR_OFFSET = 0xC0000000;
|
||||||
|
const KERNEL_PAGE_NUMBER = KERNEL_ADDR_OFFSET >> 22;
|
||||||
|
// The number of pages occupied by the kernel, will need to be increased as we add a heap etc.
|
||||||
|
const KERNEL_NUM_PAGES = 1;
|
||||||
|
|
||||||
|
// The initial page directory used for booting into the higher half. Should be overwritten later
|
||||||
|
export var boot_page_directory: [1024]u32 align(4096) linksection(".rodata.boot") = init: {
|
||||||
|
// Increase max number of branches done by comptime evaluator
|
||||||
|
@setEvalBranchQuota(1024);
|
||||||
|
// Temp value
|
||||||
|
var dir: [1024]u32 = undefined;
|
||||||
|
|
||||||
|
// Page for 0 -> 4 MiB. Gets unmapped later
|
||||||
|
dir[0] = 0x00000083;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var idx = 1;
|
||||||
|
|
||||||
|
// Fill preceding pages with zeroes. May be unecessary but incurs no runtime cost
|
||||||
|
while (i < KERNEL_PAGE_NUMBER - 1) : ({
|
||||||
|
i += 1;
|
||||||
|
idx += 1;
|
||||||
|
}) {
|
||||||
|
dir[idx] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the kernel's higher half pages increasing by 4 MiB every time
|
||||||
|
i = 0;
|
||||||
|
while (i < KERNEL_NUM_PAGES) : ({
|
||||||
|
i += 1;
|
||||||
|
idx += 1;
|
||||||
|
}) {
|
||||||
|
dir[idx] = 0x00000083 | (i << 22);
|
||||||
|
}
|
||||||
|
// Fill suceeding pages with zeroes. May be unecessary but incurs no runtime cost
|
||||||
|
i = 0;
|
||||||
|
while (i < 1024 - KERNEL_PAGE_NUMBER - KERNEL_NUM_PAGES) : ({
|
||||||
|
i += 1;
|
||||||
|
idx += 1;
|
||||||
|
}) {
|
||||||
|
dir[idx] = 0;
|
||||||
|
}
|
||||||
|
break :init dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
export var kernel_stack: [16 * 1024]u8 align(16) linksection(".bss.stack") = undefined;
|
||||||
|
|
||||||
|
export nakedcc fn _start() align(16) linksection(".text.boot") noreturn {
|
||||||
|
// Seth the page directory to the boot directory
|
||||||
|
asm volatile (
|
||||||
|
\\.extern boot_page_directory
|
||||||
|
\\mov $boot_page_directory, %%ecx
|
||||||
|
\\mov %%ecx, %%cr3
|
||||||
|
);
|
||||||
|
// Enable 4 MiB pages
|
||||||
|
asm volatile (
|
||||||
|
\\mov %%cr4, %%ecx
|
||||||
|
\\or $0x00000010, %%ecx
|
||||||
|
\\mov %%ecx, %%cr4
|
||||||
|
);
|
||||||
|
// Enable paging
|
||||||
|
asm volatile (
|
||||||
|
\\mov %%cr0, %%ecx
|
||||||
|
\\or $0x80000000, %%ecx
|
||||||
|
\\mov %%ecx, %%cr0
|
||||||
|
);
|
||||||
|
asm volatile ("jmp start_higher_half");
|
||||||
|
while (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export nakedcc fn start_higher_half() noreturn {
|
||||||
|
// Invalidate the page for the first 4MiB as it's no longer needed
|
||||||
|
asm volatile ("invlpg (0)");
|
||||||
|
// Setup the stack
|
||||||
|
asm volatile (
|
||||||
|
\\.extern KERNEL_STACK_END
|
||||||
|
\\mov $KERNEL_STACK_END, %%esp
|
||||||
|
\\mov %%esp, %%ebp
|
||||||
|
);
|
||||||
|
kmain();
|
||||||
|
while (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn init() void {}
|
|
@ -5,106 +5,7 @@
|
||||||
// Date: 2019-03-30
|
// Date: 2019-03-30
|
||||||
//
|
//
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const arch = @import("arch.zig");
|
||||||
const MultiBoot = packed struct {
|
|
||||||
magic: i32,
|
|
||||||
flags: i32,
|
|
||||||
checksum: i32,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ALIGN = 1 << 0;
|
|
||||||
const MEMINFO = 1 << 1;
|
|
||||||
const MAGIC = 0x1BADB002;
|
|
||||||
const FLAGS = ALIGN | MEMINFO;
|
|
||||||
|
|
||||||
export var multiboot align(4) linksection(".rodata.boot") = MultiBoot{
|
|
||||||
.magic = MAGIC,
|
|
||||||
.flags = FLAGS,
|
|
||||||
.checksum = -(MAGIC + FLAGS),
|
|
||||||
};
|
|
||||||
|
|
||||||
const KERNEL_ADDR_OFFSET = 0xC0000000;
|
|
||||||
const KERNEL_PAGE_NUMBER = KERNEL_ADDR_OFFSET >> 22;
|
|
||||||
// The number of pages occupied by the kernel, will need to be increased as we add a heap etc.
|
|
||||||
const KERNEL_NUM_PAGES = 1;
|
|
||||||
|
|
||||||
// The initial page directory used for booting into the higher half. Should be overwritten later
|
|
||||||
export var boot_page_directory: [1024]u32 align(4096) linksection(".rodata.boot") = init: {
|
|
||||||
// Increase max number of branches done by comptime evaluator
|
|
||||||
@setEvalBranchQuota(1024);
|
|
||||||
// Temp value
|
|
||||||
var dir: [1024]u32 = undefined;
|
|
||||||
|
|
||||||
// Page for 0 -> 4 MiB. Gets unmapped later
|
|
||||||
dir[0] = 0x00000083;
|
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
var idx = 1;
|
|
||||||
|
|
||||||
// Fill preceding pages with zeroes. May be unecessary but incurs no runtime cost
|
|
||||||
while (i < KERNEL_PAGE_NUMBER - 1) : ({
|
|
||||||
i += 1;
|
|
||||||
idx += 1;
|
|
||||||
}) {
|
|
||||||
dir[idx] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the kernel's higher half pages increasing by 4 MiB every time
|
|
||||||
i = 0;
|
|
||||||
while (i < KERNEL_NUM_PAGES) : ({
|
|
||||||
i += 1;
|
|
||||||
idx += 1;
|
|
||||||
}) {
|
|
||||||
dir[idx] = 0x00000083 | (i << 22);
|
|
||||||
}
|
|
||||||
// Fill suceeding pages with zeroes. May be unecessary but incurs no runtime cost
|
|
||||||
i = 0;
|
|
||||||
while (i < 1024 - KERNEL_PAGE_NUMBER - KERNEL_NUM_PAGES) : ({
|
|
||||||
i += 1;
|
|
||||||
idx += 1;
|
|
||||||
}) {
|
|
||||||
dir[idx] = 0;
|
|
||||||
}
|
|
||||||
break :init dir;
|
|
||||||
};
|
|
||||||
|
|
||||||
export var kernel_stack: [16 * 1024]u8 align(16) linksection(".bss.stack") = undefined;
|
|
||||||
|
|
||||||
export nakedcc fn _start() align(16) linksection(".text.boot") noreturn {
|
|
||||||
// Seth the page directory to the boot directory
|
|
||||||
asm volatile (
|
|
||||||
\\.extern boot_page_directory
|
|
||||||
\\mov $boot_page_directory, %%ecx
|
|
||||||
\\mov %%ecx, %%cr3
|
|
||||||
);
|
|
||||||
// Enable 4 MiB pages
|
|
||||||
asm volatile (
|
|
||||||
\\mov %%cr4, %%ecx
|
|
||||||
\\or $0x00000010, %%ecx
|
|
||||||
\\mov %%ecx, %%cr4
|
|
||||||
);
|
|
||||||
// Enable paging
|
|
||||||
asm volatile (
|
|
||||||
\\mov %%cr0, %%ecx
|
|
||||||
\\or $0x80000000, %%ecx
|
|
||||||
\\mov %%ecx, %%cr0
|
|
||||||
);
|
|
||||||
asm volatile ("jmp start_higher_half");
|
|
||||||
while (true) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export nakedcc fn start_higher_half() noreturn {
|
|
||||||
// Invalidate the page for the first 4MiB as it's no longer needed
|
|
||||||
asm volatile ("invlpg (0)");
|
|
||||||
// Setup the stack
|
|
||||||
asm volatile (
|
|
||||||
\\.extern KERNEL_STACK_END
|
|
||||||
\\mov $KERNEL_STACK_END, %%esp
|
|
||||||
\\mov %%esp, %%ebp
|
|
||||||
);
|
|
||||||
kmain();
|
|
||||||
while (true) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
|
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
|
@ -113,7 +14,8 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kmain() void {
|
pub export fn kmain() void {
|
||||||
|
arch.init();
|
||||||
terminal.initialize();
|
terminal.initialize();
|
||||||
terminal.write("Hello, kernel World!");
|
terminal.write("Hello, kernel World!");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue