mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
feat(pl/ke): initial amd64 support
This commit is contained in:
@@ -150,6 +150,7 @@ fn targetQueryForPlatform(plat: config.Platform) std.Target.Query {
|
|||||||
switch (plat.arch) {
|
switch (plat.arch) {
|
||||||
.x86_64 => {
|
.x86_64 => {
|
||||||
const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.x86.Feature);
|
const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.x86.Feature);
|
||||||
|
q.cpu_features_add = f.featureSet(&.{.soft_float});
|
||||||
q.cpu_features_sub = f.featureSet(&.{ .x87, .mmx, .sse, .sse2 });
|
q.cpu_features_sub = f.featureSet(&.{ .x87, .mmx, .sse, .sse2 });
|
||||||
},
|
},
|
||||||
.aarch64 => {
|
.aarch64 => {
|
||||||
@@ -169,7 +170,14 @@ fn addKernel(b: *std.Build, plat: config.Platform, optimize: std.builtin.Optimiz
|
|||||||
|
|
||||||
const name = b.fmt("kernel-{s}", .{@tagName(plat.arch)});
|
const name = b.fmt("kernel-{s}", .{@tagName(plat.arch)});
|
||||||
|
|
||||||
const root_source_file = if (plat.os == .freestanding) "src/main.zig" else "src/platform/um/entry.zig";
|
const platform_name = if (plat.bootloader) |bl|
|
||||||
|
switch (bl) {
|
||||||
|
.Limine => "limine",
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@tagName(plat.arch);
|
||||||
|
|
||||||
|
const root_source_file = b.fmt("src/platform/{s}/entry.zig", .{platform_name});
|
||||||
|
|
||||||
const kernel = b.addExecutable(.{
|
const kernel = b.addExecutable(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
@@ -191,12 +199,8 @@ fn addKernel(b: *std.Build, plat: config.Platform, optimize: std.builtin.Optimiz
|
|||||||
if (plat.os == .freestanding) {
|
if (plat.os == .freestanding) {
|
||||||
kernel.linkage = .static;
|
kernel.linkage = .static;
|
||||||
kernel.pie = false;
|
kernel.pie = false;
|
||||||
kernel.bundle_compiler_rt = false;
|
|
||||||
kernel.bundle_ubsan_rt = false;
|
|
||||||
|
|
||||||
kernel.root_module.link_libc = false;
|
|
||||||
kernel.root_module.pic = false;
|
kernel.root_module.pic = false;
|
||||||
kernel.root_module.single_threaded = true;
|
|
||||||
kernel.root_module.strip = false;
|
kernel.root_module.strip = false;
|
||||||
kernel.root_module.stack_check = false;
|
kernel.root_module.stack_check = false;
|
||||||
kernel.root_module.stack_protector = false;
|
kernel.root_module.stack_protector = false;
|
||||||
|
|||||||
+24
-4
@@ -3,9 +3,15 @@ const builtin = @import("builtin");
|
|||||||
|
|
||||||
pub const Config = std.StringHashMap([]const u8);
|
pub const Config = std.StringHashMap([]const u8);
|
||||||
|
|
||||||
|
pub const Bootloader = enum {
|
||||||
|
Limine,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Platform = struct {
|
pub const Platform = struct {
|
||||||
arch: std.Target.Cpu.Arch,
|
arch: std.Target.Cpu.Arch,
|
||||||
os: std.Target.Os.Tag,
|
os: std.Target.Os.Tag,
|
||||||
|
|
||||||
|
bootloader: ?Bootloader = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parseConfig(b: *std.Build) !Config {
|
pub fn parseConfig(b: *std.Build) !Config {
|
||||||
@@ -73,11 +79,25 @@ pub fn getPlatform(config: Config) !Platform {
|
|||||||
.{ "CONFIG_ARCH_UM", Platform{ .arch = builtin.cpu.arch, .os = .linux } },
|
.{ "CONFIG_ARCH_UM", Platform{ .arch = builtin.cpu.arch, .os = .linux } },
|
||||||
};
|
};
|
||||||
|
|
||||||
inline for (keys) |entry| {
|
var ret = blk: {
|
||||||
if (config.get(entry[0])) |val| {
|
inline for (keys) |entry| {
|
||||||
if (std.mem.eql(u8, val, "y")) return entry[1];
|
if (config.get(entry[0])) |val| {
|
||||||
|
if (std.mem.eql(u8, val, "y")) break :blk entry[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return error.NoArchConfigured;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ret.arch == .x86_64 or ret.arch == .aarch64) {
|
||||||
|
ret.bootloader = blk: {
|
||||||
|
if (config.get("CONFIG_BOOT_LIMINE")) |val| {
|
||||||
|
if (std.mem.eql(u8, val, "y")) break :blk .Limine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.NoBootloaderConfigured;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.NoArchConfigured;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ pub fn addIso(
|
|||||||
mkiso.addArg("-o");
|
mkiso.addArg("-o");
|
||||||
const iso_out = mkiso.addOutputFileArg(b.fmt("{s}.iso", .{image_name}));
|
const iso_out = mkiso.addOutputFileArg(b.fmt("{s}.iso", .{image_name}));
|
||||||
mkiso.step.dependOn(&prep.step);
|
mkiso.step.dependOn(&prep.step);
|
||||||
|
_ = mkiso.captureStdErr(.{});
|
||||||
|
|
||||||
if (arch == .x86_64) {
|
if (arch == .x86_64) {
|
||||||
const bios_install = b.addRunArtifact(limine_tool);
|
const bios_install = b.addRunArtifact(limine_tool);
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ SECTIONS
|
|||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
|
.percpu_init_array : {
|
||||||
|
__init_array_percpu_start = .;
|
||||||
|
KEEP(*(.percpu_init_array))
|
||||||
|
__init_array_percpu_end = .;
|
||||||
|
} :rodata
|
||||||
|
|
||||||
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
||||||
/* linker command. */
|
/* linker command. */
|
||||||
.note.gnu.build-id : {
|
.note.gnu.build-id : {
|
||||||
@@ -57,6 +63,12 @@ SECTIONS
|
|||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
|
.data.percpu : {
|
||||||
|
__percpu_start = .;
|
||||||
|
*(.data.percpu)
|
||||||
|
__percpu_end = .;
|
||||||
|
} :data
|
||||||
|
|
||||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||||
/* unnecessary zeros will be written to the binary. */
|
/* unnecessary zeros will be written to the binary. */
|
||||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
qemu.addArgs(&.{
|
qemu.addArgs(&.{
|
||||||
"-serial", "stdio",
|
|
||||||
"-d", "int",
|
"-d", "int",
|
||||||
"-D", "qemu.log",
|
"-D", "qemu.log",
|
||||||
"-no-reboot", "-no-shutdown",
|
"-no-reboot", "-no-shutdown",
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
const b = @import("base");
|
||||||
|
const ke = b.ke;
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Cpu = struct {
|
||||||
|
self_ptr: *Cpu,
|
||||||
|
percpu_offset: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ThreadContext = struct {
|
||||||
|
rdi: u64,
|
||||||
|
rsi: u64,
|
||||||
|
rbx: u64,
|
||||||
|
rsp: u64,
|
||||||
|
rbp: u64,
|
||||||
|
r12: u64,
|
||||||
|
r13: u64,
|
||||||
|
r14: u64,
|
||||||
|
r15: u64,
|
||||||
|
|
||||||
|
fn thread_trampoline(entry: usize, arg: usize) callconv(.c) void {
|
||||||
|
const entry_fn: *const fn (?*anyopaque) void = @ptrFromInt(entry);
|
||||||
|
entry_fn(@ptrFromInt(arg));
|
||||||
|
// TODO: This shouldn't be reached!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(stack: b.VAddr, stack_size: usize, entry: *const fn (?*anyopaque) void, arg: ?*anyopaque) @This() {
|
||||||
|
var ctx: @This() = undefined;
|
||||||
|
ctx.rdi = @intFromPtr(entry);
|
||||||
|
ctx.rsi = @intFromPtr(arg);
|
||||||
|
|
||||||
|
var sp = stack + stack_size;
|
||||||
|
{
|
||||||
|
sp -= @sizeOf(usize);
|
||||||
|
@as(*usize, @ptrFromInt(sp)).* = 0;
|
||||||
|
|
||||||
|
sp -= @sizeOf(usize);
|
||||||
|
@as(*usize, @ptrFromInt(sp)).* = @intFromPtr(&thread_trampoline);
|
||||||
|
}
|
||||||
|
ctx.rsp = sp;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn do_switch_to() callconv(.naked) void {
|
||||||
|
const asm_template = std.fmt.comptimePrint(
|
||||||
|
\\movq %%rbx, {d}(%%rdi)
|
||||||
|
\\movq %%rsp, {d}(%%rdi)
|
||||||
|
\\movq %%rbp, {d}(%%rdi)
|
||||||
|
\\movq %%r12, {d}(%%rdi)
|
||||||
|
\\movq %%r13, {d}(%%rdi)
|
||||||
|
\\movq %%r14, {d}(%%rdi)
|
||||||
|
\\movq %%r15, {d}(%%rdi)
|
||||||
|
\\
|
||||||
|
\\movq {d}(%%rsi), %%rbx
|
||||||
|
\\movq {d}(%%rsi), %%rsp
|
||||||
|
\\movq {d}(%%rsi), %%rbp
|
||||||
|
\\movq {d}(%%rsi), %%r12
|
||||||
|
\\movq {d}(%%rsi), %%r13
|
||||||
|
\\movq {d}(%%rsi), %%r14
|
||||||
|
\\movq {d}(%%rsi), %%r15
|
||||||
|
\\movq {d}(%%rsi), %%rdi
|
||||||
|
\\movq {d}(%%rsi), %%rsi
|
||||||
|
\\
|
||||||
|
\\ret
|
||||||
|
, .{
|
||||||
|
@offsetOf(ThreadContext, "rbx"),
|
||||||
|
@offsetOf(ThreadContext, "rsp"),
|
||||||
|
@offsetOf(ThreadContext, "rbp"),
|
||||||
|
@offsetOf(ThreadContext, "r12"),
|
||||||
|
@offsetOf(ThreadContext, "r13"),
|
||||||
|
@offsetOf(ThreadContext, "r14"),
|
||||||
|
@offsetOf(ThreadContext, "r15"),
|
||||||
|
|
||||||
|
@offsetOf(ThreadContext, "rbx"),
|
||||||
|
@offsetOf(ThreadContext, "rsp"),
|
||||||
|
@offsetOf(ThreadContext, "rbp"),
|
||||||
|
@offsetOf(ThreadContext, "r12"),
|
||||||
|
@offsetOf(ThreadContext, "r13"),
|
||||||
|
@offsetOf(ThreadContext, "r14"),
|
||||||
|
@offsetOf(ThreadContext, "r15"),
|
||||||
|
@offsetOf(ThreadContext, "rdi"),
|
||||||
|
@offsetOf(ThreadContext, "rsi"),
|
||||||
|
});
|
||||||
|
|
||||||
|
asm volatile (asm_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn switch_to(self: *ThreadContext, new: *ThreadContext) callconv(.c) void {
|
||||||
|
asm volatile (
|
||||||
|
\\call do_switch_to
|
||||||
|
:
|
||||||
|
: [_] "{rdi}" (self),
|
||||||
|
[_] "{rsi}" (new),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn curcpu() *ke.Cpu {
|
||||||
|
const asm_template = std.fmt.comptimePrint("movq %%gs:{d}, %[ret]", .{@offsetOf(Cpu, "self_ptr")});
|
||||||
|
const impl_cpu = asm volatile (asm_template
|
||||||
|
: [ret] "=r" (-> *Cpu),
|
||||||
|
);
|
||||||
|
|
||||||
|
return @fieldParentPtr("impl", impl_cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn percpu_ptr_for(variable: anytype, cpu: *ke.Cpu) @TypeOf(variable) {
|
||||||
|
return @ptrFromInt(@intFromPtr(variable) +% cpu.impl.percpu_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn percpu_ptr_other(variable: anytype, id: usize) @TypeOf(variable) {
|
||||||
|
return percpu_ptr_for(variable, ke.cpus[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn percpu_ptr(variable: anytype) @TypeOf(variable) {
|
||||||
|
return percpu_ptr_for(variable, curcpu());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn set_hardware_ipl(_: ke.Ipl) void {}
|
||||||
|
|
||||||
|
pub inline fn enable_interrupts() void {
|
||||||
|
asm volatile ("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn disable_interrupts() bool {
|
||||||
|
const rflags = asm volatile (
|
||||||
|
\\cli
|
||||||
|
\\pushfq
|
||||||
|
\\popq %[rflags]
|
||||||
|
: [rflags] "=r" (-> usize),
|
||||||
|
);
|
||||||
|
|
||||||
|
return rflags & (1 << 9) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn restore_interrupts(state: bool) void {
|
||||||
|
if (state) {
|
||||||
|
enable_interrupts();
|
||||||
|
} else {
|
||||||
|
_ = disable_interrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn send_resched_ipi(_: *ke.Cpu) void {
|
||||||
|
@panic("TODO send_resched_ipi");
|
||||||
|
}
|
||||||
|
|||||||
+12
-3
@@ -14,8 +14,17 @@ fn handler(_: ?*anyopaque) void {
|
|||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var temp_stack1: [8192]u8 align(16) = undefined;
|
||||||
|
var temp_stack2: [8192]u8 align(16) = undefined;
|
||||||
|
var temp_stack3: [8192]u8 align(16) = undefined;
|
||||||
|
|
||||||
|
var stacks: []const []u8 = &.{&temp_stack1, &temp_stack2, &temp_stack3};
|
||||||
|
var which_stack: usize = 0;
|
||||||
|
|
||||||
fn make_thread(entry: *const fn (?*anyopaque) void, td: *ke.Thread, arg: ?*anyopaque) void {
|
fn make_thread(entry: *const fn (?*anyopaque) void, td: *ke.Thread, arg: ?*anyopaque) void {
|
||||||
const _stack = std.heap.page_allocator.alloc(u8, 16384) catch @panic("wtf");
|
std.debug.assert(which_stack < 3);
|
||||||
|
const _stack = stacks[which_stack];
|
||||||
|
which_stack += 1;
|
||||||
|
|
||||||
td.init(@intFromPtr(_stack.ptr), 16384, entry, arg);
|
td.init(@intFromPtr(_stack.ptr), 16384, entry, arg);
|
||||||
}
|
}
|
||||||
@@ -49,8 +58,8 @@ pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
|||||||
|
|
||||||
ke.ipl.lower(ipl);
|
ke.ipl.lower(ipl);
|
||||||
} else {
|
} else {
|
||||||
make_thread(&b.ex.fireworks.start, &threads[0], boot_info);
|
// make_thread(&b.ex.fireworks.start, &threads[0], boot_info);
|
||||||
ke.sched.enqueue(&threads[0]);
|
// ke.sched.enqueue(&threads[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
|
|||||||
+2
-2
@@ -31,7 +31,7 @@ pub fn raise(new: Ipl) Ipl {
|
|||||||
const old = cpu.ipl;
|
const old = cpu.ipl;
|
||||||
|
|
||||||
if (@intFromEnum(new) < @intFromEnum(old)) {
|
if (@intFromEnum(new) < @intFromEnum(old)) {
|
||||||
ke.panic("ke.ipl.raise(): Target IPL ({}) is lower than current IPL ({})\n", .{ new, old });
|
std.debug.panic("ke.ipl.raise(): Target IPL ({}) is lower than current IPL ({})", .{ new, old });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@intFromEnum(new) > @intFromEnum(Ipl.get_max_software())) {
|
if (@intFromEnum(new) > @intFromEnum(Ipl.get_max_software())) {
|
||||||
@@ -53,7 +53,7 @@ pub fn lower(new: Ipl) void {
|
|||||||
const old = cpu.ipl;
|
const old = cpu.ipl;
|
||||||
|
|
||||||
if (@intFromEnum(new) > @intFromEnum(old)) {
|
if (@intFromEnum(new) > @intFromEnum(old)) {
|
||||||
ke.panic("ke.ipl.lower(): Target IPL ({}) is higher than current IPL ({})\n", .{ new, old });
|
std.debug.panic("ke.ipl.lower(): Target IPL ({}) is higher than current IPL ({})", .{ new, old });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@intFromEnum(new) <= @intFromEnum(Ipl.get_max_software()) and @intFromEnum(old) > @intFromEnum(Ipl.get_max_software())) {
|
if (@intFromEnum(new) <= @intFromEnum(Ipl.get_max_software()) and @intFromEnum(old) > @intFromEnum(Ipl.get_max_software())) {
|
||||||
|
|||||||
+7
-4
@@ -3,10 +3,13 @@ const b = @import("base");
|
|||||||
const ke = b.ke;
|
const ke = b.ke;
|
||||||
const ki = ke.private;
|
const ki = ke.private;
|
||||||
|
|
||||||
/// Panics!
|
pub fn panic(
|
||||||
pub fn panic(comptime fmt: []const u8, args: anytype) noreturn {
|
msg: []const u8,
|
||||||
// FIXME: this is probably broken.
|
first_trace_addr: ?usize,
|
||||||
std.log.err("KERNEL PANIC: " ++ fmt, args);
|
) noreturn {
|
||||||
|
_ = first_trace_addr;
|
||||||
|
|
||||||
|
std.log.err("KERNEL PANIC: {s}", .{msg});
|
||||||
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn set_signals(enabled: bool) bool {
|
|||||||
const how = if (enabled) c.SIG_UNBLOCK else c.SIG_BLOCK;
|
const how = if (enabled) c.SIG_UNBLOCK else c.SIG_BLOCK;
|
||||||
|
|
||||||
if (c.pthread_sigmask(how, &newmask, &oldmask) != 0) {
|
if (c.pthread_sigmask(how, &newmask, &oldmask) != 0) {
|
||||||
ke.panic("pthread_sigmask failed", .{});
|
@panic("pthread_sigmask failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.sigismember(&oldmask, c.SIGUSR1) == 0;
|
return c.sigismember(&oldmask, c.SIGUSR1) == 0;
|
||||||
@@ -67,7 +67,7 @@ pub const ThreadContext = struct {
|
|||||||
var new: ThreadContext = .{ .ucontext = undefined };
|
var new: ThreadContext = .{ .ucontext = undefined };
|
||||||
|
|
||||||
if (c.getcontext(&new.ucontext) == -1) {
|
if (c.getcontext(&new.ucontext) == -1) {
|
||||||
ke.panic("getcontext() failed", .{});
|
@panic("getcontext() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
new.ucontext.uc_stack.ss_sp = @ptrFromInt(stack);
|
new.ucontext.uc_stack.ss_sp = @ptrFromInt(stack);
|
||||||
@@ -99,7 +99,7 @@ pub const ThreadContext = struct {
|
|||||||
thread.lock.release_no_ipl();
|
thread.lock.release_no_ipl();
|
||||||
|
|
||||||
if (c.swapcontext(&self.ucontext, &new.ucontext) == -1) {
|
if (c.swapcontext(&self.ucontext, &new.ucontext) == -1) {
|
||||||
ke.panic("swapcontext() failed", .{});
|
@panic("swapcontext() failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const ksyms = @import("ksyms");
|
|
||||||
const pl = @import("base").pl;
|
|
||||||
pub const rtl = @import("rtl");
|
|
||||||
|
|
||||||
const DebugWriter = struct {
|
|
||||||
pub const Error = error{};
|
|
||||||
pub const Writer = std.io.GenericWriter(*DebugWriter, Error, write);
|
|
||||||
|
|
||||||
fn write(self: *DebugWriter, bytes: []const u8) Error!usize {
|
|
||||||
_ = self;
|
|
||||||
for (bytes) |c| pl.debug_write(c);
|
|
||||||
return bytes.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn writer(self: *DebugWriter) Writer {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var debug_writer = DebugWriter{};
|
|
||||||
|
|
||||||
export fn kmain() callconv(.c) void {
|
|
||||||
print("hello from kernel!\n", .{});
|
|
||||||
|
|
||||||
for (ksyms.ksyms) |sym| {
|
|
||||||
print(" 0x{x:0>16} {s}\n", .{ sym.addr, sym.name });
|
|
||||||
}
|
|
||||||
|
|
||||||
pl.first_init();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
asm volatile ("hlt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn memset(dest: [*]u8, c: u8, n: usize) [*]u8 {
|
|
||||||
for (dest[0..n]) |*b| b.* = c;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn memcpy(dest: [*]u8, src: [*]const u8, n: usize) [*]u8 {
|
|
||||||
for (0..n) |i| dest[i] = src[i];
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn memmove(dest: [*]u8, src: [*]const u8, n: usize) [*]u8 {
|
|
||||||
if (@intFromPtr(dest) < @intFromPtr(src)) {
|
|
||||||
for (0..n) |i| dest[i] = src[i];
|
|
||||||
} else {
|
|
||||||
var i = n;
|
|
||||||
while (i > 0) {
|
|
||||||
i -= 1;
|
|
||||||
dest[i] = src[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
const b = @import("base");
|
|
||||||
|
|
||||||
pub fn first_init() linksection(b.init) void {}
|
|
||||||
@@ -1,6 +1,25 @@
|
|||||||
const entry = @import("entry.zig");
|
const b = @import("base");
|
||||||
|
const ki = b.ke.private;
|
||||||
|
|
||||||
pub const first_init = entry.first_init;
|
pub const name = "AMD64";
|
||||||
|
|
||||||
|
pub fn first_init() void {}
|
||||||
|
|
||||||
|
pub fn early_init() void {
|
||||||
|
const impl_cpu = &ki.bootstrap_cpu.impl;
|
||||||
|
impl_cpu.self_ptr = impl_cpu;
|
||||||
|
impl_cpu.percpu_offset = 0;
|
||||||
|
|
||||||
|
const impl_cpu_ptr = @intFromPtr(impl_cpu);
|
||||||
|
asm volatile ("wrmsr"
|
||||||
|
:
|
||||||
|
: [_] "{eax}" (@as(u32, @intCast(impl_cpu_ptr & 0xFFFFFFFF))),
|
||||||
|
[_] "{edx}" (@as(u32, @truncate(impl_cpu_ptr >> 32))),
|
||||||
|
[_] "{ecx}" (0xC000_0101),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn late_init() void {}
|
||||||
|
|
||||||
pub fn devices_init() void {}
|
pub fn devices_init() void {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
const b = @import("base");
|
||||||
|
const ksyms = @import("ksyms");
|
||||||
|
|
||||||
|
const pl = b.pl;
|
||||||
|
const ke = b.ke;
|
||||||
|
|
||||||
|
pub const std_options = b.std_options;
|
||||||
|
pub const panic = b.panic;
|
||||||
|
|
||||||
|
pub const rtl = @import("rtl");
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
var boot_info: pl.BootInfo = undefined;
|
||||||
|
|
||||||
|
export fn kmain() callconv(.c) void {
|
||||||
|
std.log.info("hello from kernel!", .{});
|
||||||
|
|
||||||
|
for (ksyms.ksyms) |sym| {
|
||||||
|
std.log.info(" 0x{x:0>16} {s}", .{ sym.addr, sym.name });
|
||||||
|
}
|
||||||
|
|
||||||
|
boot_info.memory_map.entry_count = 0;
|
||||||
|
|
||||||
|
var cpus: [1]*ke.Cpu = .{&ke.private.bootstrap_cpu};
|
||||||
|
|
||||||
|
ke.ncpus = 1;
|
||||||
|
ke.cpus = &cpus;
|
||||||
|
|
||||||
|
ke.private.init(&boot_info);
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@ else if (@hasDecl(config, "CONFIG_ARCH_UM"))
|
|||||||
else
|
else
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
|
||||||
|
pub inline fn first_init() void {
|
||||||
|
return impl.first_init();
|
||||||
|
}
|
||||||
|
|
||||||
/// Early platform-specific initialization, called before anything else.
|
/// Early platform-specific initialization, called before anything else.
|
||||||
pub inline fn early_init() void {
|
pub inline fn early_init() void {
|
||||||
return impl.early_init();
|
return impl.early_init();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const b = @import("base");
|
const b = @import("base");
|
||||||
|
|
||||||
pub const std_options = b.std_options;
|
pub const std_options = b.std_options;
|
||||||
|
pub const panic = b.panic;
|
||||||
|
|
||||||
pub const rtl = @import("rtl");
|
pub const rtl = @import("rtl");
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub fn arm_timer(ns: b.Nanoseconds) void {
|
|||||||
}, .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 } };
|
}, .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 } };
|
||||||
|
|
||||||
if (c.timer_settime(timerid, 0, &value, null) == -1) {
|
if (c.timer_settime(timerid, 0, &value, null) == -1) {
|
||||||
ke.panic("timer_settime failed", .{});
|
@panic("timer_settime failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +68,6 @@ pub fn init_cpu() void {
|
|||||||
sev._sigev_un._tid = linux.gettid();
|
sev._sigev_un._tid = linux.gettid();
|
||||||
|
|
||||||
if (c.timer_create(c.CLOCK_MONOTONIC, &sev, &timerid) == -1) {
|
if (c.timer_create(c.CLOCK_MONOTONIC, &sev, &timerid) == -1) {
|
||||||
ke.panic("timer_create failed", .{});
|
@panic("timer_create failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,3 +40,5 @@ pub fn tib(comptime N: u32) usize {
|
|||||||
pub const std_options = std.Options{
|
pub const std_options = std.Options{
|
||||||
.logFn = ke.log.log,
|
.logFn = ke.log.log,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const panic = std.debug.FullPanic(ke.panic);
|
||||||
|
|||||||
Reference in New Issue
Block a user