Skip to content

Commit

Permalink
mrriw
Browse files Browse the repository at this point in the history
Signed-off-by: TalonFloof <[email protected]>
  • Loading branch information
TalonFloof committed Nov 23, 2024
1 parent b633af9 commit c1ac523
Show file tree
Hide file tree
Showing 27 changed files with 218 additions and 109 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ iso: build_pc64
mkdir -p /tmp/kobold_iso/EFI/BOOT
cp -f /tmp/limine/BOOTX64.EFI /tmp/limine/limine-uefi-cd.bin /tmp/limine/limine-bios-cd.bin /tmp/limine/limine-bios.sys boot/x86_64/* kobold/zig-out/bin/* /tmp/kobold_iso
mv /tmp/kobold_iso/BOOTX64.EFI /tmp/kobold_iso/EFI/BOOT/BOOTX64.EFI
python3 scripts/appendPersonalities.py
xorriso -as mkisofs -b limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label /tmp/kobold_iso -o kobold.iso
zig cc /tmp/limine/limine.c -o /tmp/limine/limine
/tmp/limine/limine bios-install kobold.iso
rm -r -f /tmp/limine
rm -r -f /tmp/kobold_iso

run_pc64: iso
qemu-system-x86_64 -enable-kvm -cpu host,migratable=off -m 8M -serial stdio -device pcie-pci-bridge -cdrom kobold.iso -smp 2 -no-hpet -no-shutdown -no-reboot
qemu-system-x86_64 -enable-kvm -cpu host,migratable=off -m 8M -serial stdio -device pcie-pci-bridge -cdrom kobold.iso -smp 2 -no-shutdown -no-reboot

run_rv64: build_rv64
qemu-system-riscv64 -machine virt -m 128M -serial stdio -device ramfb -device virtio-keyboard-device -device virtio-mouse-device -kernel kobold/zig-out/bin/kernel
Expand Down
15 changes: 0 additions & 15 deletions boot/x86_64/limine.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,7 @@ default_entry: 1
timeout: 5
verbose: yes
graphics: yes
interface_resolution: 1024x768
term_palette: 292D3E;F07178;62DE84;FFCB6B;75A1FF;F580FF;60BAEC;ABB2BF
term_bright_palette: 959DCB;0xF07178;C3E88D;FF5572;82AAFF;FFCB6B;676E95;FFFEFE
term_background: 000e0f15
term_foreground: BFC7D5

/Kobold
comment: Kobold for ${ARCH}
protocol: limine
kernel_path: boot():/kernel
paging_mode: 4level
kaslr: no

module_path: boot():/kernel.dbg
module_cmdline: KernelDebug
module_path: boot():/ipc.o
module_cmdline: IPC
module_path: boot():/vfs.o
module_cmdline: VFS
42 changes: 21 additions & 21 deletions kobold/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,28 @@ pub fn build(b: *std.Build) void {
halMod.addObjectFile(b.path("../lowlevel.o"));
}

const ipcMod = b.addObject(.{
.name = "ipc",
.root_source_file = b.path("personalities/IPC/main.zig"),
.target = resolvedModTarget,
.optimize = optimize,
.code_model = .large,
.strip = true,
});
const vfsMod = b.addObject(.{
.name = "vfs",
.root_source_file = b.path("personalities/VFS/main.zig"),
.target = resolvedModTarget,
.optimize = optimize,
.code_model = .large,
.strip = true,
});
if (getArch(board) == .riscv64) {
ipcMod.root_module.code_model = .medium;
vfsMod.root_module.code_model = .medium;
const personalityDir = std.fs.cwd().openDir("personalities", .{ .iterate = true }) catch @panic("Couldn't retrieve personalities!");
var iter = personalityDir.iterate();
while (iter.next() catch @panic("Personality Iteration Failure")) |entry| {
if (entry.kind == .directory) {
const mainZig = b.fmt("personalities/{s}/main.zig", .{entry.name});
_ = std.fs.cwd().access(mainZig, .{}) catch continue;
const personality = b.addObject(.{
.name = entry.name,
.root_source_file = b.path(mainZig),
.target = resolvedModTarget,
.optimize = optimize,
.code_model = .large,
.strip = true,
});
if (getArch(board) == .riscv64) {
personality.root_module.code_model = .medium;
}
personality.root_module.addImport("perlib", perlibMod);
b.getInstallStep().dependOn(addInstallObjectFile(b, personality, entry.name));
}
}

kernel.want_lto = false;
kernel.root_module.omit_frame_pointer = false;
kernel.entry = std.Build.Step.Compile.Entry.disabled;
Expand All @@ -157,6 +159,4 @@ pub fn build(b: *std.Build) void {
kernel.root_module.addImport("perlib", perlibMod);
kernel.setLinkerScript(b.path(b.fmt("hal/link/{s}.ld", .{@tagName(board)})));
b.getInstallStep().dependOn(&b.addInstallArtifact(kernel, .{}).step);
b.getInstallStep().dependOn(addInstallObjectFile(b, ipcMod, "ipc"));
b.getInstallStep().dependOn(addInstallObjectFile(b, vfsMod, "vfs"));
}
2 changes: 1 addition & 1 deletion kobold/hal/x86_64/apic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn setup() void {
if (x2apicSupport()) {
if (hal.arch.getHart().hartID == 0) {
lapic_ptr = 0xffffffff;
std.log.info("X2APIC is enabled or required by system, switching to X2APIC operations", .{});
std.log.scoped(.X64APIC).info("X2APIC is enabled or required by system, switching to X2APIC operations", .{});
}
hal.archData.wrmsr(0x1b, (hal.archData.rdmsr(0x1b) | 0x800 | 0x400)); // Enable the X2APIC
} else {
Expand Down
7 changes: 4 additions & 3 deletions kobold/hal/x86_64/hart.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ const physmem = @import("root").physmem;

export var smp_request: limine.SmpRequest = .{ .flags = 0 };
pub var hartData: usize = 0;
pub const hart_log = std.log.scoped(.X64MultiHart);

pub fn startSMP() void {
if (smp_request.response) |response| {
hal.hiList = @as([*]*hal.HartInfo, @ptrCast(@alignCast(physmem.AllocateC(response.cpu_count * @sizeOf(usize)))))[0..response.cpu_count];
hal.hiList.?[0] = hal.arch.getHart();
var hartCount: i32 = 1;
std.log.info("{} Hart System (MultiHart Kernel)", .{hal.hiList.?.len});
hart_log.info("{} Hart System (MultiHart Kernel)", .{hal.hiList.?.len});
for (response.cpus()) |hart| {
if (hart.lapic_id != response.bsp_lapic_id) {
var hi: *hal.HartInfo = @ptrCast(@alignCast(physmem.AllocateC(@sizeOf(hal.HartInfo))));
Expand All @@ -24,7 +25,7 @@ pub fn startSMP() void {
while (hartData != 0) {
cycles += 1;
if (cycles >= 50000000) {
std.log.err("Hart #{} took too long (potential triple fault on hart!)", .{hartCount});
hart_log.err("Hart #{} took too long (potential triple fault on hart!)", .{hartCount});
hal.HALOops("X86-64 HAL Initialization Failure");
}
std.atomic.spinLoopHint();
Expand All @@ -33,6 +34,6 @@ pub fn startSMP() void {
}
}
} else {
std.log.info("1 Hart System (MultiHart Kernel)", .{});
hart_log.info("1 Hart System (MultiHart Kernel)", .{});
}
}
105 changes: 59 additions & 46 deletions kobold/hal/x86_64/timer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,72 @@ pub fn rdtsc() u64 {
}

var ticksPerSecond: u64 = 0;
pub const timer_log = std.log.scoped(.X64Timer);

pub fn init() void {
if (ticksPerSecond == 0) {
if ((hal.archData.cpuid(0x80000007).edx & (1 << 8)) == 0) {
std.log.warn("TSC isn't invariant, reverting to discrete timer for timekeeping", .{});
}
if (acpi.HPETAddr != null) {
const addr: usize = acpi.HPETAddr.?.address;
const hpetAddr: [*]align(1) volatile u64 = @as([*]align(1) volatile u64, @ptrFromInt(addr));
const clock = hpetAddr[0] >> 32;

apic.hpetPeriod = @floatFromInt(clock);
apic.hpetNSPeriod = apic.hpetPeriod / 1000000.0;
apic.hpetTicksPer100NS = 100000000.0 / apic.hpetPeriod;
hpetAddr[2] = 0;
hpetAddr[30] = 0;
hpetAddr[2] = 1;

const hz = 1000000000000000.0 / @as(f64, @floatFromInt(clock));
const interval = @as(usize, @intFromFloat(apic.hpetTicksPer100NS * 10000.0 * 1000.0));
std.log.info("HPET @ {d} MHz for APIC Timer Calibration", .{hz / 1000 / 1000});
apic.write(0x320, 0x10000);
apic.write(0x3e0, 0xb);
const duration = hpetAddr[30] + interval;
apic.write(0x380, 0xffffffff);
while (hpetAddr[30] < duration) {
std.atomic.spinLoopHint();
const hvTest = hal.archData.cpuid(0x40000000);
if (hvTest.ebx == 0x7263694D and hvTest.ecx == 0x666F736F and hvTest.edx == 0x76482074) { // "Microsoft Hv"
if (hal.archData.cpuid(0x40000003).edx & (1 << 8) != 0) {
const freq = hal.archData.rdmsr(0x40000023); // HV_X64_MSR_APIC_FREQUENCY
timer_log.info("Microsoft Hyper-V reported {} APIC Ticks/s", .{freq});
ticksPerSecond = freq;
} else {
hal.HALOops("Microsoft Hyper-V doesn't give APIC Frequency, cannot calibrate LAPIC Timer");
}
apic.write(0x320, 0x10000);
const count = 0xffffffff - apic.read(0x390);
ticksPerSecond = count;
} else {
std.log.info("PIT @ 64 Hz for APIC Timer Calibration", .{});
var speakerControlByte = io.inb(0x61);
speakerControlByte &= ~@as(u8, 2);
io.outb(0x61, speakerControlByte);
io.outb(0x43, 0x80 | 0x00 | 0x30);
const sleepDivisor = 0x48d3; // 64 Hz
io.outb(0x42, sleepDivisor & 0xFF);
io.outb(0x42, sleepDivisor >> 8);
const pitControlByte = io.inb(0x61);
io.outb(0x61, pitControlByte & ~@as(u8, 1));
apic.write(0x320, 0x10000);
apic.write(0x3e0, 0xb);
apic.write(0x380, 0xffffffff);
while (io.inb(0x61) & 0x20 == 0) {
std.atomic.spinLoopHint();
if ((hal.archData.cpuid(0x80000007).edx & (1 << 8)) == 0) {
timer_log.warn("TSC isn't invariant, reverting to discrete timer for timekeeping", .{});
}
if (acpi.HPETAddr != null) {
const addr: usize = acpi.HPETAddr.?.address;
const hpetAddr: [*]align(1) volatile u64 = @as([*]align(1) volatile u64, @ptrFromInt(addr));
const clock = hpetAddr[0] >> 32;

apic.hpetPeriod = @floatFromInt(clock);
apic.hpetNSPeriod = apic.hpetPeriod / 1000000.0;
apic.hpetTicksPer100NS = 100000000.0 / apic.hpetPeriod;
hpetAddr[2] = 0;
hpetAddr[30] = 0;
hpetAddr[2] = 1;

const hz = 1000000000000000.0 / @as(f64, @floatFromInt(clock));
const interval = @as(usize, @intFromFloat(apic.hpetTicksPer100NS * 10000.0 * 1000.0));
timer_log.info("HPET @ {d} MHz for APIC Timer Calibration", .{hz / 1000 / 1000});
apic.write(0x320, 0x10000);
apic.write(0x3e0, 0xb);
const duration = hpetAddr[30] + interval;
apic.write(0x380, 0xffffffff);
while (hpetAddr[30] < duration) {
std.atomic.spinLoopHint();
}
apic.write(0x320, 0x10000);
const count = 0xffffffff - apic.read(0x390);
ticksPerSecond = count;
} else {
const freq: f64 = 105000000.0 / 88.0 / 65536.0;
timer_log.info("PIT @ ~18.2065 Hz for APIC Timer Calibration", .{});
var speakerControlByte = io.inb(0x61);
speakerControlByte &= ~@as(u8, 2);
io.outb(0x61, speakerControlByte);
io.outb(0x43, 0x80 | 0x00 | 0x30);
const sleepDivisor = 0xffff;
io.outb(0x42, sleepDivisor & 0xFF);
io.outb(0x42, sleepDivisor >> 8);
const pitControlByte = io.inb(0x61);
io.outb(0x61, pitControlByte & ~@as(u8, 1));
apic.write(0x320, 0x10000);
apic.write(0x3e0, 0xb);
apic.write(0x380, 0xffffffff);
while (io.inb(0x61) & 0x20 == 0) {
std.atomic.spinLoopHint();
}
apic.write(0x320, 0x10000);
const count = 0xffffffff - apic.read(0x390);
ticksPerSecond = @intFromFloat(@as(f64, @floatFromInt(count)) * freq);
}
apic.write(0x320, 0x10000);
const count = 0xffffffff - apic.read(0x390);
ticksPerSecond = count * 64;
timer_log.info("{} APIC Ticks/s", .{ticksPerSecond});
}
std.log.info("{} APIC Ticks/s", .{ticksPerSecond});
}
apic.write(0x3e0, 0xb);
apic.write(0x320, 0x20);
Expand Down
46 changes: 33 additions & 13 deletions kobold/kernel/vfs.zig
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
const std = @import("std");

pub const Metadata = extern struct {
deviceID: u64 = 0,
ID: u64 = 0,
mode: u32 = 0,
nlinks: u32 = 0,
uid: u32 = 1,
gid: u32 = 1,
rdev: u64 = 0, // Device ID (Optional)
size: u64 = 0,
atime: i64 = 0,
reserved1: u64 = 0,
mtime: i64 = 0,
reserved2: u64 = 0,
ctime: i64 = 0,
reserved3: u64 = 0,
blksize: u64 = 0,
blocks: u64 = 0,
};

pub const VNode = extern struct {
name: [256]u8 = [_]u8{0} ** 256.
name: [256]u8 = [_]u8{0} ** 256,
stat: Metadata = Metadata{ .ID = 0 },

unreferenced: ?*fn (*VNode) callconv(.C) c_long = null,
open: ?*fn(*VNode) callconv(.C) c_long = null,
close: ?*fn(*VNode) callconv(.C) c_long = null,
readDir: ?*fn(*VNode, u32, *DirEntry) callconv(.C) c_long = null,
findDir: ?*fn(*VNode, [*c]const u8, *?*VNode) callconv(.C) c_long = null,
truncate: ?*fn(*VNode, usize) callconv(.C) c_long = null,
create: ?*fn(*VNode, [*c]const u8, usize) callconv(.C) c_long = null,
unlink: ?*fn(*VNode, [*c]const u8) callconv(.C) c_long = null,
rename: ?*fn(*VNode, [*c]const u8, *VNode, [*c]const u8) callconv(.C) c_long = null,
ioctl: ?*fn(*VNode, c_ulong, ?*anyopaque) callconv(.C) c_long = null,
open: ?*fn (*VNode) callconv(.C) c_long = null,
close: ?*fn (*VNode) callconv(.C) c_long = null,
readDir: ?*fn (*VNode, u32, *DirEntry) callconv(.C) c_long = null,
findDir: ?*fn (*VNode, [*c]const u8, *?*VNode) callconv(.C) c_long = null,
truncate: ?*fn (*VNode, usize) callconv(.C) c_long = null,
create: ?*fn (*VNode, [*c]const u8, usize) callconv(.C) c_long = null,
unlink: ?*fn (*VNode, [*c]const u8) callconv(.C) c_long = null,
rename: ?*fn (*VNode, [*c]const u8, *VNode, [*c]const u8) callconv(.C) c_long = null,
ioctl: ?*fn (*VNode, c_ulong, ?*anyopaque) callconv(.C) c_long = null,

read: ?*fn(*VNode, usize, *anyopaque, usize) callconv(.C) c_long = null,
write: ?*fn(*VNode, usize, *anyopaque, usize) callconv(.C) c_long = null,
};
read: ?*fn (*VNode, usize, *anyopaque, usize) callconv(.C) c_long = null,
write: ?*fn (*VNode, usize, *anyopaque, usize) callconv(.C) c_long = null,
};
16 changes: 7 additions & 9 deletions kobold/perLib/perlib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub const RedBlackTree = @import("rbtree.zig").RedBlackTree;

pub const KernelCall = enum {
Log,
Panic,
TriggerOops,
SpawnKThread,
MemAlloc,
MemFree,
Expand All @@ -14,15 +14,10 @@ pub const KernelCall = enum {
FindPersonality,
GetDeviceTree, // ACPI-based systems will return the RSDP when you use this, otherwise return a parsed device tree
IsACPIBased,
RegisterSyscall,
Sleep,
Stall,

RegisterHook,
FreeHook,
};

pub const HookTypes = enum {
ThreadSpawnHook,
ThreadDeathHook,
RegisterFilesystem,
};

pub const PersonalityHeader = struct {
Expand All @@ -35,3 +30,6 @@ pub const PersonalityHeader = struct {
customInterface: ?*void = null,
dependencies: [][]const u8,
};

// PersonalityLoad is defined here to allow us to setup some stuff for the convience of the developer implementing the driver in question
export fn PersonalityLoad() void {}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
Empty file.
Empty file.
Empty file.
22 changes: 22 additions & 0 deletions kobold/personalities/PCI/pci.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const PCI_VENDOR_ID: u16 = 0x00;
const PCI_DEVICE_ID: u16 = 0x02;
const PCI_COMMAND: u16 = 0x04;
const PCI_STATUS: u16 = 0x06;
const PCI_REVISION_ID: u16 = 0x08;
const PCI_SUBSYSTEM_ID: u16 = 0x2e;
const PCI_PROG_IF: u16 = 0x09;
const PCI_SUBCLASS: u16 = 0x0a;
const PCI_CLASS: u16 = 0x0b;
const PCI_CACHE_LINE_SIZE: u16 = 0x0c;
const PCI_LATENCY_TIMER: u16 = 0x0d;
const PCI_HEADER_TYPE: u16 = 0x0e;
const PCI_BIST: u16 = 0x0f;
const PCI_BAR0: u16 = 0x10;
const PCI_BAR1: u16 = 0x14;
const PCI_BAR2: u16 = 0x18;
const PCI_BAR3: u16 = 0x1c;
const PCI_BAR4: u16 = 0x20;
const PCI_BAR5: u16 = 0x24;
const PCI_INTERRUPT_LINE: u16 = 0x3c;
const PCI_INTERRUPT_PIN: u16 = 0x3d;
const PCI_SECONDARY_BUS: u16 = 0x19;
Empty file.
Loading

0 comments on commit c1ac523

Please sign in to comment.