Xenon/src/start.zig

109 lines
3.5 KiB
Zig

const builtin = @import("builtin");
const std = @import("std");
const assert = std.debug.assert;
usingnamespace @import("panic.zig");
const apic = @import("apic.zig");
const bootboot = @import("bootboot.zig");
const cpu = @import("cpu.zig");
const framebuffer = @import("framebuffer.zig");
const global = @import("global.zig");
const kernel = @import("kernel.zig");
const lock = @import("lock.zig");
const log = @import("logger.zig").log;
const memory = @import("memory.zig");
const panic_mod = @import("panic.zig");
const paging = @import("paging.zig");
const types = @import("types.zig");
const kernel_stack_size: usize = 8 * 4096;
var ap_lock: lock.SpinLock = lock.SpinLock.init();
var init_stack: [8192]u8 align(std.Target.stack_align) = undefined;
fn init() noreturn {
// Initialize framebuffer
// TODO Possible bootboot bug
const fb_size = if (bootboot.bootboot.fb_size != 0) bootboot.bootboot.fb_size else bootboot.bootboot.fb_width * bootboot.bootboot.fb_height * 4;
global.framebuffer = framebuffer.Framebuffer.init(
@ptrCast([*]volatile u8, &bootboot.fb)[0..fb_size],
bootboot.bootboot.fb_width,
bootboot.bootboot.fb_height,
bootboot.framebuffer_pixel_type() catch @panic("Unsupported framebuffer pixel type"),
);
global.framebuffer.?.clear();
global.framebuffer_stream = global.framebuffer.?.outStream();
global.log_target = &global.framebuffer_stream.?.stream;
log(.Debug, "Framebuffer ({}x{} {}) initialized", .{
bootboot.bootboot.fb_width,
bootboot.bootboot.fb_height,
@tagName(bootboot.framebuffer_pixel_type() catch unreachable),
});
log(.Debug, "Logging initialized", .{});
// Initrd
global.initrd = @intToPtr([*]const u8, bootboot.bootboot.initrd_ptr)[0..bootboot.bootboot.initrd_size];
// Establish CPU capabilities
global.cpu_capabilities.initialize();
// Initialize memory management
log(.Debug, "Initializing memory management", .{});
const mmap = bootboot.memory_map();
const page_table = paging.PageMapLevel4.fromCr3(cpu.register.cr3());
const kernel_dynamic_data_address = 0 -% std.math.pow(usize, 2, global.cpu_capabilities.virtual_address_width - 1);
global.physical_memory = memory.PhysicalMemory.init(mmap);
global.kernel_memory = memory.VirtualMemory.init(page_table, kernel_dynamic_data_address);
paging.initialize(page_table);
// Initialize panic memory
panic_mod.initialize();
// Setup complete, allow AP's to continue
ap_lock.release();
// Call main kernel function
global.bp_stack = global.kernel_memory.?.alloc(.{ .writeable = true }, kernel_stack_size, std.Target.stack_align) catch @panic("Unable to allocate kernel stack");
const new_stack_address = @ptrToInt(&global.bp_stack.?[0]) + kernel_stack_size;
asm volatile (
\\movq %[addr], %%rsp
\\movq %%rsp, %%rbp
:
: [addr] "r" (new_stack_address)
: "memory"
);
@call(.{ .modifier = .never_inline }, kernel.main, .{});
}
fn init_ap() noreturn {
ap_lock.wait();
@call(.{ .modifier = .never_inline }, kernel.main_ap, .{});
}
export fn _start() noreturn {
assert(std.mem.eql(u8, &bootboot.bootboot.magic, "BOOT"));
@atomicStore(u8, &ap_lock.lock, 1, .SeqCst);
if (!apic.bootstrapCpuCore()) {
@call(.{ .modifier = .never_inline }, init_ap, .{});
}
@call(.{ .stack = &init_stack, .modifier = .never_inline }, init, .{});
}
comptime {
assert(builtin.arch == .x86_64);
}