diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e3e692c..04227c3 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/devcontainers/rust:1-1-bookworm RUN apt-get update && apt-get install -y cmake ARG LLVM_URL=https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.0/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4.tar.xz -ARG ZIG_VERSION=zig-linux-x86_64-0.12.1 +ARG ZIG_VERSION=zig-linux-x86_64-0.14.0-dev.2540+f857bf72e ENV PATH="/usr/bin/zig:${PATH}" ENV PATH=/usr/local/llvm/bin:$PATH diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e5f2f22..5041def 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,4 +4,11 @@ "context": "..", "dockerfile": "./Dockerfile" }, + "customizations": { + "vscode": { + "extensions": [ + "ziglang.vscode-zig" + ] + } + }, } diff --git a/.gitignore b/.gitignore index ca8ee09..9ba5fe1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ iso_root/ zig-out/ zig-cache/ +.zig-cache/ build/ virtio-net.pcap disk.tar diff --git a/Dockerfile b/Dockerfile index 08c31d9..090e33f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ghcr.io/mewz-project/wasker:latest -ARG ZIG_VERSION=zig-linux-x86_64-0.12.0-dev.1856+94c63f31f +ARG ZIG_VERSION=zig-linux-x86_64-0.14.0-dev.2540+f857bf72e ENV PATH="/usr/bin/zig:${PATH}" diff --git a/build.zig b/build.zig index b5af2aa..3a69e54 100644 --- a/build.zig +++ b/build.zig @@ -79,49 +79,43 @@ pub fn build(b: *Build) !void { const params = BuildParams.new(b); const options = params.setOptions(b); - const features = Target.x86.Feature; - - var disabled_features = Feature.Set.empty; - var enabled_features = Feature.Set.empty; - - disabled_features.addFeature(@intFromEnum(features.mmx)); - disabled_features.addFeature(@intFromEnum(features.sse)); - disabled_features.addFeature(@intFromEnum(features.sse2)); - disabled_features.addFeature(@intFromEnum(features.avx)); - disabled_features.addFeature(@intFromEnum(features.avx2)); - enabled_features.addFeature(@intFromEnum(features.soft_float)); - - const target = Query{ .cpu_arch = Target.Cpu.Arch.x86_64, .os_tag = Target.Os.Tag.freestanding, .cpu_features_sub = disabled_features, .cpu_features_add = enabled_features }; - const optimize = b.standardOptimizeOption(.{}); const newlib_build_cmd = b.addSystemCommand(&[_][]const u8{"./scripts/build-newlib.sh"}); const lwip_build_cmd = b.addSystemCommand(&[_][]const u8{"./scripts/build-lwip.sh"}); + const target = b.resolveTargetQuery(.{ + .cpu_arch = .x86_64, + .os_tag = .freestanding, + .ofmt = .elf, + }); + const kernel = b.addExecutable(.{ .name = "mewz.elf", - .root_source_file = .{ .path = "src/main.zig" }, + .root_source_file = b.path("src/main.zig"), .optimize = optimize, - .target = b.resolveTargetQuery(target), - .linkage = std.builtin.LinkMode.static, + .target = target, + .linkage = .static, + .code_model = .kernel, }); - kernel.entry = .{ .symbol_name = "boot" }; - kernel.setLinkerScriptPath(.{ .path = "src/x64.ld" }); - kernel.addAssemblyFile(Build.LazyPath{ .path = "src/boot.S" }); - kernel.addAssemblyFile(Build.LazyPath{ .path = "src/interrupt.S" }); - kernel.addObjectFile(Build.LazyPath{ .path = "build/newlib/libc.a" }); - kernel.addObjectFile(Build.LazyPath{ .path = "build/lwip/libtcpip.a" }); - kernel.addObjectFile(Build.LazyPath{ .path = "build/lwip/liblwipcore.a" }); - kernel.addObjectFile(Build.LazyPath{ .path = "build/lwip/liblwipallapps.a" }); - kernel.addCSourceFile(Build.Module.CSourceFile{ .file = Build.LazyPath{ .path = "src/c/newlib_support.c" }, .flags = &[_][]const u8{ "-I", "submodules/newlib/newlib/libc/include" } }); - kernel.addCSourceFile(Build.Module.CSourceFile{ .file = Build.LazyPath{ .path = "src/c/lwip_support.c" }, .flags = &[_][]const u8{ "-I", "submodules/newlib/newlib/libc/include" } }); + + kernel.linker_script = b.path("src/x64.ld"); + kernel.addAssemblyFile(b.path("src/boot.S")); + kernel.addAssemblyFile(b.path("src/interrupt.S")); + kernel.addObjectFile(b.path("build/newlib/libc.a")); + kernel.addObjectFile(b.path("build/lwip/libtcpip.a")); + kernel.addObjectFile(b.path("build/lwip/liblwipcore.a")); + kernel.addObjectFile(b.path("build/lwip/liblwipallapps.a")); + kernel.addCSourceFile(.{ .file = b.path("src/c/newlib_support.c"), .flags = &.{ "-I", "submodules/newlib/newlib/libc/include" } }); + kernel.addCSourceFile(.{ .file = b.path("src/c/lwip_support.c"), .flags = &.{ "-I", "submodules/newlib/newlib/libc/include" } }); if (params.obj_path) |p| { - kernel.addObjectFile(Build.LazyPath{ .path = p }); + kernel.addObjectFile(b.path(p)); } if (params.dir_path) |_| { - kernel.addObjectFile(Build.LazyPath{ .path = "build/disk.o" }); + kernel.addObjectFile(b.path("build/disk.o")); } kernel.root_module.addOptions("options", options); + kernel.entry = .{ .symbol_name = "boot" }; b.installArtifact(kernel); const kernel_step = b.step("kernel", "Build the kernel"); diff --git a/src/drivers/virtio/common.zig b/src/drivers/virtio/common.zig index b093548..5175a33 100644 --- a/src/drivers/virtio/common.zig +++ b/src/drivers/virtio/common.zig @@ -301,7 +301,10 @@ pub const AvailRing = struct { fn new(queue_size: u16, allocator: Allocator) Error!Self { const size = @sizeOf(u16) * queue_size + @sizeOf(u16) * 3; - const data = try allocator.alignedAlloc(u8, 2, size); + const data = allocator.alignedAlloc(u8, 8, size) catch |err| { + log.fatal.printf("failed to allocate avail ring: {}\n", .{err}); + return err; + }; @memset(data, 0); return Self{ .data = data, @@ -535,7 +538,6 @@ pub fn VirtioMmioTransport(comptime DeviceConfigType: type) type { } self.common_config.queue_select = virtq.index; - @fence(std.builtin.AtomicOrder.seq_cst); const offset = self.notify_off_multiplier * self.common_config.queue_notify_off; const addr = self.notify + @as(usize, @intCast(offset)); @as(*volatile u16, @ptrFromInt(addr)).* = virtq.index; diff --git a/src/fs.zig b/src/fs.zig index bb80371..84bd40d 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -7,7 +7,7 @@ const Stream = stream.Stream; const FILES_MAX: usize = 200; -extern const _binary_build_disk_tar_start: [*]u8; +extern var _binary_build_disk_tar_start: [*]u8; pub var files: [FILES_MAX]RegularFile = undefined; pub var dirs: [FILES_MAX]Directory = undefined; diff --git a/src/main.zig b/src/main.zig index a1e8306..a041b5b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -23,22 +23,23 @@ const wasi = @import("wasi.zig"); extern fn wasker_main() void; -export fn bspEarlyInit(boot_magic: u32, boot_params: u64) align(16) callconv(.C) void { - _ = boot_magic; +export fn bspEarlyInit(boot_magic: u32, boot_params: u32) align(16) callconv(.C) void { const bootinfo = @as(*multiboot.BootInfo, @ptrFromInt(boot_params)); const cmdline = util.getString(bootinfo.cmdline); + x64.init(); param.parseFromArgs(cmdline); uart.init(); lapic.init(); ioapic.init(); picirq.init(); - x64.init(); + printBootinfo(boot_magic, bootinfo); timer.init(); interrupt.init(); mem.init(bootinfo); pci.init(); + log.debug.print("pci init finish\n"); if (param.params.isNetworkEnabled()) { virtio_net.init(); } @@ -76,3 +77,15 @@ export fn write(fd: i32, b: *const u8, count: usize) callconv(.C) isize { } return -1; } + +fn printBootinfo(magic: u32, bootinfo: *multiboot.BootInfo) void { + log.debug.print("=== bootinfo ===\n"); + log.debug.printf("magic: {x}\n", .{magic}); + log.debug.printf("bootinfo addr: {x}\n", .{@intFromPtr(bootinfo)}); + log.debug.printf("flags: {b:0>8}\n", .{bootinfo.flags}); + log.debug.printf("mmap_addr: {x}\n", .{bootinfo.mmap_addr}); + log.debug.printf("mmap_length: {x}\n", .{bootinfo.mmap_length}); + const boot_loader_name = @as([*]u8, @ptrFromInt(bootinfo.boot_loader_name))[0..20]; + log.debug.printf("boot_loader_name: {s}\n", .{boot_loader_name}); + log.debug.print("================\n"); +} diff --git a/src/mem.zig b/src/mem.zig index 47b52f5..d0531a2 100644 --- a/src/mem.zig +++ b/src/mem.zig @@ -176,20 +176,20 @@ pub fn init(info: *multiboot.BootInfo) void { // disable alignment checks for mmaps @setRuntimeSafety(false); - // mmap_addr points to the MemoryMap array - // mmap_length is the size of the MemoryMap array in bytes - const mmaps_ptr = @as([*]multiboot.MemoryMap, @ptrFromInt(info.mmap_addr)); - const mmaps = mmaps_ptr[0 .. info.mmap_length / @sizeOf(multiboot.MemoryMap)]; - - for (mmaps) |*mmap| { - if (mmap.type == multiboot.MemoryType.available) { - // exclude the kernel image from available memory, because it's already used - const base = @max(image_end_addr, mmap.base); - const end = mmap.base + mmap.length; - if (end <= base) { - continue; - } - log.info.printf("available memory: {x} - {x}\n", .{ base, end }); + var off: usize = 0; + while (off < info.mmap_length) { + const mmap = @as(*multiboot.MemoryMap, @ptrFromInt(off + info.mmap_addr)); + log.debug.printf("mmap.type: {x}\n", .{@intFromEnum(mmap.type)}); + + // exclude the kernel image from available memory, because it's already used + const base = @max(image_end_addr, mmap.base); + const end = mmap.base + mmap.length; + + log.debug.printf("mmap.base: {x}\n", .{mmap.base}); + log.debug.printf("end: {x}\n", .{end}); + + if (mmap.type == multiboot.MemoryType.available and base < end) { + log.debug.printf("available memory: {x} - {x}\n", .{ base, end }); // align the range to BLOCK_SIZE const aligned_base = util.roundUp(usize, base, BLOCK_SIZE); @@ -201,11 +201,15 @@ pub fn init(info: *multiboot.BootInfo) void { const buf = @as([*]u8, @ptrFromInt(aligned_base))[0..length]; boottime_fba = FixedBufferAllocator.init(buf); boottime_allocator = boottime_fba.?.allocator(); + + log.debug.printf("boottime allocator: addr=0x{x}, len=0x{x}\n", .{ aligned_base, length }); } else { // add the range to the free list initRange(aligned_base, length); } } + + off += mmap.size + @sizeOf(u32); } } } diff --git a/src/param.zig b/src/param.zig index bb769af..b989fb5 100644 --- a/src/param.zig +++ b/src/param.zig @@ -16,9 +16,9 @@ pub var params = Params{}; // TODO: Add tests pub fn parseFromArgs(args: []const u8) void { - var params_itr = std.mem.split(u8, args, " "); + var params_itr = std.mem.splitScalar(u8, args, ' '); while (params_itr.next()) |part| { - var kv = std.mem.split(u8, part, "="); + var kv = std.mem.splitScalar(u8, part, '='); const k = kv.next() orelse continue; const v = kv.next() orelse continue; @@ -36,7 +36,7 @@ pub fn parseFromArgs(args: []const u8) void { } fn parseIp(ip_str: []const u8) void { - var parts = std.mem.split(u8, ip_str, "/"); + var parts = std.mem.splitScalar(u8, ip_str, '/'); const ip = parts.next() orelse @panic("invalid ip format"); const subnet = parts.next() orelse @panic("invalid ip format"); if (parts.next()) |_| { diff --git a/src/pci.zig b/src/pci.zig index 456375e..df3c139 100644 --- a/src/pci.zig +++ b/src/pci.zig @@ -92,7 +92,7 @@ pub const Device = struct { const Self = @This(); fn new(bus: u8, slot: u8, func: u8) (Allocator.Error || Error)!Self { - var config_buffer: [16]u32 align(8) = [16]u32{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + var config_buffer: [16]u32 align(16) = [16]u32{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; for (0..16) |i| { const config_value = readConfig(bus, slot, func, @as(u8, @intCast(i * 4))); config_buffer[i] = config_value; diff --git a/src/rand.zig b/src/rand.zig index 4a9a47f..810550a 100644 --- a/src/rand.zig +++ b/src/rand.zig @@ -1,4 +1,4 @@ -const Random = @import("std").rand.Random; +const Random = @import("std").Random; pub const X64Random = Random{ .ptr = undefined, diff --git a/src/x64.ld b/src/x64.ld index 5d6baf8..3826bad 100644 --- a/src/x64.ld +++ b/src/x64.ld @@ -51,6 +51,8 @@ SECTIONS { .rodata : AT(ADDR(.rodata) - VMA_OFFSET) { *(.rodata); *(.rodata.*); + *(.lrodata); + *(.lrodata.*); . = ALIGN(4096); __cpu_local = .; @@ -63,6 +65,8 @@ SECTIONS { .data : AT(ADDR(.data) - VMA_OFFSET) { *(.data); *(.data.*); + *(.ldata); + *(.ldata.*); *(.got*); @@ -75,6 +79,8 @@ SECTIONS { __bss = .; *(.bss); *(.bss.*); + *(.lbss); + *(.lbss.*); __bss_end = .; /* The kernel page table (physical addresses). */ diff --git a/src/x64.zig b/src/x64.zig index f1fa797..14febfb 100644 --- a/src/x64.zig +++ b/src/x64.zig @@ -4,7 +4,6 @@ pub const EFLAGS_IF = 0x00000200; pub fn init() void { enableSSE(); - @fence(std.builtin.AtomicOrder.seq_cst); enableAVX(); } diff --git a/submodules/lwip b/submodules/lwip index 73fcf72..1cc1536 160000 --- a/submodules/lwip +++ b/submodules/lwip @@ -1 +1 @@ -Subproject commit 73fcf72792a926a4e0ac8b656b29bff70552d927 +Subproject commit 1cc1536e6a7117e23ebaf5546405a843a3e558ae