Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
6a46d26
Merge pull request #119 from SamTebbs33/hotfix/callconv-changes
SamTebbs33 Jan 7, 2020
7043ccd
Add a physical memory manager
Sep 9, 2019
a095fd3
Merge pull request #104 from SamTebbs33/feature/phys-mem-manager
SamTebbs33 Jan 9, 2020
0746048
Run unit tests under the building architecture
DrDeano Jan 9, 2020
c581db8
Merge pull request #122 from SamTebbs33/feature/unittest-in-build-arch
DrDeano Jan 9, 2020
9332fc6
Add Format set to build
DrDeano Jan 15, 2020
96da426
Merge pull request #124 from SamTebbs33/feature/add-fmt-setp-to-build
DrDeano Jan 15, 2020
7ab180f
Added RTC
DrDeano Jan 15, 2020
aca2cc1
Merge pull request #123 from SamTebbs33/feature/real-time-clock
DrDeano Jan 15, 2020
2352a04
Update zig code
SamTebbs33 Feb 1, 2020
a4f2de4
Merge pull request #127 from SamTebbs33/zig-update
SamTebbs33 Feb 1, 2020
ee42565
Keep stack section
SamTebbs33 Feb 1, 2020
d17381c
Merge pull request #126 from SamTebbs33/keep-stack-section
SamTebbs33 Feb 1, 2020
1f97a5c
Updating to zig master
DrDeano Apr 12, 2020
638ad81
Merge pull request #130 from SamTebbs33/feature/update_zig_version
DrDeano Apr 12, 2020
02ce6a5
Add virtual memory manager
SamTebbs33 Jan 9, 2020
7f470a4
Merge pull request #128 from SamTebbs33/feature/virtual-mem-manager
SamTebbs33 Apr 14, 2020
98268ff
Run CI checks on pull requests and pushes
SamTebbs33 Apr 14, 2020
b2b6616
Merge pull request #132 from SamTebbs33/feature/pr-status-checks
SamTebbs33 Apr 14, 2020
825cfe0
use /usr/bin/env bash instead of /bin/bash
marler8997 Apr 13, 2020
8523bcf
Merge pull request #131 from marler8997/shebang
SamTebbs33 Apr 14, 2020
cf11b17
Add start to alloc result
SamTebbs33 Apr 22, 2020
2646f8b
Start kernel VMM at second block
SamTebbs33 Apr 22, 2020
ed8087a
Merge pull request #137 from SamTebbs33/bugfix/vmm-add-start-to-alloc
SamTebbs33 Apr 24, 2020
16b07bf
Log CPU state on page fault
DrDeano May 6, 2020
dac57fc
Merge pull request #140 from SamTebbs33/feature/log-cpu-state-on-page…
DrDeano May 6, 2020
f5a22fd
Add heap allocator
SamTebbs33 Jan 9, 2020
9cf4858
Merge pull request #133 from SamTebbs33/feature/heap-allocator
SamTebbs33 May 6, 2020
a432e45
zig fmt
DrDeano May 14, 2020
76ff52b
Merge pull request #148 from SamTebbs33/feature/update-to-zig-master
DrDeano May 15, 2020
39fd5a1
Make some integers usize
SamTebbs33 May 12, 2020
fe0b2ff
Merge pull request #146 from SamTebbs33/bugfix/fix-integer-types
SamTebbs33 May 15, 2020
397cd44
Write full symbol name to kernel symbol file
SamTebbs33 May 11, 2020
0ca3542
Merge pull request #144 from SamTebbs33/bugfix/stacktrace-full-symbol…
SamTebbs33 May 15, 2020
554b970
Abstract away boot modules and memory map
SamTebbs33 May 14, 2020
122adab
Merge pull request #149 from SamTebbs33/feature/arch-boot-payload
SamTebbs33 May 30, 2020
368ecd3
Remove start.asm and start.s
SamTebbs33 Jun 1, 2020
10a629c
Merge pull request #151 from SamTebbs33/remove-unused-files
SamTebbs33 Jun 2, 2020
a9589c2
Add architecture option to build.zig
SamTebbs33 Jun 2, 2020
c2a9622
Add info to README
SamTebbs33 Jun 2, 2020
72269c2
Merge pull request #155 from SamTebbs33/feature/add-arch-option
SamTebbs33 Jun 4, 2020
cec5d3c
Move linker script
SamTebbs33 Jun 2, 2020
e7770d0
Merge pull request #153 from SamTebbs33/feature/move-linker-script
SamTebbs33 Jun 4, 2020
ecc3de4
Make serial arch-dependent
SamTebbs33 Jun 4, 2020
4f7e7a7
Merge pull request #157 from SamTebbs33/feature/abstract-serial
SamTebbs33 Jun 7, 2020
256e5fe
Set arch in rt-test.py
SamTebbs33 Jun 9, 2020
de1c87e
Merge pull request #161 from SamTebbs33/bugfix/rt-test-arch
SamTebbs33 Jun 10, 2020
5101990
Pass boot payload to serial init
SamTebbs33 Jun 9, 2020
c4083b0
Merge pull request #159 from SamTebbs33/feature/serial-init-payload
SamTebbs33 Jun 13, 2020
e2533a2
Move tty to arch
SamTebbs33 Jun 12, 2020
fb82dbb
Merge pull request #163 from SamTebbs33/feature/abstract-tty
SamTebbs33 Jun 18, 2020
951ef07
Fix x86 payload passing
SamTebbs33 Jun 20, 2020
fd4c614
Merge pull request #167 from SamTebbs33/bugfix/x86-payload-argument
SamTebbs33 Jun 22, 2020
28128dd
Add virtual filesystem
SamTebbs33 Apr 24, 2020
d6d99ef
Merge pull request #139 from SamTebbs33/feature/virtual-fs
SamTebbs33 Jun 22, 2020
2c91e6f
Remove the old and in with the new
DrDeano Jun 23, 2020
10bf243
Merge pull request #164 from SamTebbs33/feature/replace-python-rt-wit…
DrDeano Jun 23, 2020
1b32fd3
Use the standardTargetOptions for built targets
DrDeano Jun 22, 2020
2d3ea3a
Merge pull request #168 from SamTebbs33/feature/add-standardTargetOpt…
DrDeano Jun 23, 2020
e763514
Fix the kernel VMM start address
SamTebbs33 Jun 24, 2020
e9fd88c
Merge pull request #175 from SamTebbs33/bugfix/vmm-start-address
SamTebbs33 Jun 24, 2020
04896f1
Update to new allocator interface
SamTebbs33 Jul 1, 2020
7204c42
Merge pull request #180 from SamTebbs33/feature/update-allocator-inte…
SamTebbs33 Jul 1, 2020
d60164b
Update for latest zig
SamTebbs33 Jul 6, 2020
34d7bb6
Merge pull request #181 from SamTebbs33/feature/zig-update
SamTebbs33 Jul 6, 2020
36a0f24
Insert the correct address into the allocations map
SamTebbs33 Jun 30, 2020
676232a
Merge pull request #179 from SamTebbs33/bugfix/vmm-correct-addr-in-al…
SamTebbs33 Jul 6, 2020
f3ba8c3
Fix heap freeing one too many blocks
SamTebbs33 Jun 30, 2020
f0add19
Merge pull request #177 from SamTebbs33/bugfix/heap-free-too-many
SamTebbs33 Jul 8, 2020
afcaf96
Replace var with anytype
SamTebbs33 Jul 12, 2020
c164f5e
Merge pull request #186 from SamTebbs33/feature/zig-update
SamTebbs33 Jul 12, 2020
8acf4e0
A comptime bitmap
DrDeano Jul 13, 2020
17f0892
Merge pull request #188 from SamTebbs33/feature/comptime-bitmap
DrDeano Jul 14, 2020
6d4b3e9
Replace buddy allocator with free list allocator
SamTebbs33 Jul 11, 2020
2082654
Merge pull request #183 from SamTebbs33/feature/free-list-allocator
SamTebbs33 Jul 14, 2020
d600be8
Initial scheduler
DrDeano Jul 18, 2020
7e0c1fd
Merge pull request #138 from SamTebbs33/feature/initial_multitasking
DrDeano Jul 18, 2020
3ced37b
Merge branch 'master' into release/v0.2
SamTebbs33 Jul 20, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
name: CI

on: [push]
on:
push:
branches: "*"
pull_request:
branches: "*"

jobs:
test:
name: Build mode ${{ matrix.build_mode }}
runs-on: ubuntu-latest
strategy:
matrix:
build_mode: ["", -Drelease-fast=true, -Drelease-safe=true, -Drelease-small=true]
build_mode: ["", -Drelease-fast, -Drelease-safe, -Drelease-small]

steps:
- uses: actions/checkout@v1
Expand All @@ -19,15 +23,19 @@ jobs:
wget $(curl -s 'https://ziglang.org/download/index.json' | python3 -c "import sys, json; print(json.load(sys.stdin)['master']['x86_64-linux']['tarball'])")
sudo apt-get install mtools
tar -xvf zig*
- name: Build kernel
run: zig*/zig build ${{ matrix.build_mode }}
- name: Run unit tests
run: zig*/zig build test ${{ matrix.build_mode }}
- name: Install qemu
run: |
sudo apt-get update
sudo apt-get install qemu qemu-system --fix-missing
- name: Run runtime tests
run: zig*/zig build test -Drt-test=true ${{ matrix.build_mode }}
- name: Check formatting
run: zig*/zig fmt --check src
- name: Build kernel
run: zig*/zig build ${{ matrix.build_mode }}
- name: Run unit tests
run: zig*/zig build test ${{ matrix.build_mode }}
- name: Run runtime test - Initialisation
run: zig*/zig build rt-test -Ddisable-display -Dtest-mode=Initialisation ${{ matrix.build_mode }}
- name: Run runtime test - Panic
run: zig*/zig build rt-test -Ddisable-display -Dtest-mode=Panic ${{ matrix.build_mode }}
- name: Run runtime test - Scheduler
run: zig*/zig build rt-test -Ddisable-display -Dtest-mode=Scheduler ${{ matrix.build_mode }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
# Intellij
.idea/

# VSCode
.vscode/

# Zig
zig-cache

Expand Down
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,52 @@ zig build
```Shell
zig build run
```

or if you want to wait for a gdb connection:

```Shell
zig build debug-run
```

## Debug

Launch a gdb instance and connect to qemu.
Launch a gdb-multiarch instance and connect to qemu.

```Shell
zig build debug
```

## Test
## Unit testing

Run the unit tests or runtime tests.
Run the unit tests.

```Shell
zig build test
```

## Runtime testing

Run the runtime tests.

```Shell
zig build rt-test -Dtest-mode=<MODE>
```

Available test modes:

* `None`: This is the default, this will run the OS normally.
* `Initialisation`: Run the OS's initialisation runtime tests to ensure the OS is properly set up.
* `Panic`: Run the panic runtime test.

## Options

* `-Drt-test=`: Boolean (default `false`).
* **build**: Build with runtime testing enabled. Makes the kernel bigger and slower but tests important functionality.
* **test**: Run the runtime testing script instead of the unittests. Checks for the expected log statements and fails if any are missing.
* `-D[build-mode]=`: Boolean (default `false`).
* **build**: Build a certain build mode (*release-safe*, *release-fast*, *release-small*). Don't set in order to use the *debug* build mode.
* **test**: Test a certain build mode (*release-safe*, *release-fast*, *release-small*). Don't set in order to use the *debug* build mode.
* `-Dtarget=`: String (default `i386-freestanding`). The standard target options for building with zig. Currently supported targets:
* `i386-freestanding`
* `-Ddisable-display`: Boolean (default `false`)
* This disables the display output of QEMU.

## Contribution

Expand Down
185 changes: 105 additions & 80 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,122 +1,147 @@
const std = @import("std");
const builtin = @import("builtin");
const rt = @import("test/runtime_test.zig");
const RuntimeStep = rt.RuntimeStep;
const Builder = std.build.Builder;
const LibExeObjStep = std.build.LibExeObjStep;
const Step = std.build.Step;
const Target = std.build.Target;
const Target = std.Target;
const CrossTarget = std.zig.CrossTarget;
const fs = std.fs;
const Mode = builtin.Mode;
const TestMode = rt.TestMode;
const ArrayList = std.ArrayList;

pub fn build(b: *Builder) !void {
const target = Target{
.Cross = std.build.CrossTarget{
.arch = .i386,
.os = .freestanding,
.abi = .gnu,
},
};
const x86_i686 = CrossTarget{
.cpu_arch = .i386,
.os_tag = .freestanding,
.cpu_model = .{ .explicit = &Target.x86.cpu._i686 },
};

const target_str = switch (target.getArch()) {
pub fn build(b: *Builder) !void {
const target = b.standardTargetOptions(.{ .whitelist = &[_]CrossTarget{x86_i686}, .default_target = x86_i686 });
const arch = switch (target.getCpuArch()) {
.i386 => "x86",
else => unreachable,
};

const build_mode = b.standardReleaseOptions();
const rt_test = b.option(bool, "rt-test", "enable/disable runtime testing") orelse false;
const fmt_step = b.addFmt(&[_][]const u8{
"build.zig",
"src",
"test",
});
b.default_step.dependOn(&fmt_step.step);

const main_src = "src/kernel/kmain.zig";
const arch_root = "src/kernel/arch";
const constants_path = try fs.path.join(b.allocator, &[_][]const u8{ arch_root, arch, "constants.zig" });
const linker_script_path = try fs.path.join(b.allocator, &[_][]const u8{ arch_root, arch, "link.ld" });
const output_iso = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "pluto.iso" });
const iso_dir_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso" });
const boot_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "boot" });
const modules_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "modules" });

const build_mode = b.standardReleaseOptions();
comptime var test_mode_desc: []const u8 = "\n ";
inline for (@typeInfo(TestMode).Enum.fields) |field| {
const tm = @field(TestMode, field.name);
test_mode_desc = test_mode_desc ++ field.name ++ " (" ++ TestMode.getDescription(tm) ++ ")";
test_mode_desc = test_mode_desc ++ "\n ";
}

const test_mode = b.option(TestMode, "test-mode", "Run a specific runtime test. This option is for the rt-test step. Available options: " ++ test_mode_desc) orelse .None;
const disable_display = b.option(bool, "disable-display", "Disable the qemu window") orelse false;

const exec = b.addExecutable("pluto", main_src);
const constants_path = try fs.path.join(b.allocator, &[_][]const u8{ "src/kernel/arch", target_str, "constants.zig" });
const exec = b.addExecutable("pluto.elf", main_src);
exec.addPackagePath("constants", constants_path);
exec.setOutputDir(b.cache_root);
exec.addBuildOption(TestMode, "test_mode", test_mode);
exec.setBuildMode(build_mode);
exec.addBuildOption(bool, "rt_test", rt_test);
exec.setLinkerScriptPath("link.ld");
exec.setTheTarget(target);
exec.setLinkerScriptPath(linker_script_path);
exec.setTarget(target);

const iso_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "pluto.iso" });
const grub_build_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "boot" });
const iso_dir_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso" });
const make_iso = switch (target.getCpuArch()) {
.i386 => b.addSystemCommand(&[_][]const u8{ "./makeiso.sh", boot_path, modules_path, iso_dir_path, exec.getOutputPath(), output_iso }),
else => unreachable,
};
make_iso.step.dependOn(&exec.step);

const mkdir_cmd = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", fs.path.dirname(grub_build_path).? });
b.default_step.dependOn(&make_iso.step);

const grub_cmd = b.addSystemCommand(&[_][]const u8{ "cp", "-r", "grub", grub_build_path });
grub_cmd.step.dependOn(&mkdir_cmd.step);
const test_step = b.step("test", "Run tests");
const mock_path = "\"../../test/mock/kernel/\"";
const arch_mock_path = "\"../../../../test/mock/kernel/\"";
const unit_tests = b.addTest(main_src);
unit_tests.setBuildMode(build_mode);
unit_tests.setMainPkgPath(".");
unit_tests.addPackagePath("constants", constants_path);
unit_tests.addBuildOption(TestMode, "test_mode", test_mode);
unit_tests.addBuildOption([]const u8, "mock_path", mock_path);
unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path);

if (builtin.os.tag != .windows) {
unit_tests.enable_qemu = true;
}

const cp_elf_cmd = b.addSystemCommand(&[_][]const u8{"cp"});
const elf_path = try fs.path.join(b.allocator, &[_][]const u8{ grub_build_path, "pluto.elf" });
cp_elf_cmd.addArtifactArg(exec);
cp_elf_cmd.addArg(elf_path);
cp_elf_cmd.step.dependOn(&grub_cmd.step);
cp_elf_cmd.step.dependOn(&exec.step);
unit_tests.setTarget(.{ .cpu_arch = target.cpu_arch });
test_step.dependOn(&unit_tests.step);

const modules_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "modules" });
const mkdir_modules_cmd = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", modules_path });
const rt_test_step = b.step("rt-test", "Run runtime tests");
const build_mode_str = switch (build_mode) {
.Debug => "",
.ReleaseSafe => "-Drelease-safe",
.ReleaseFast => "-Drelease-fast",
.ReleaseSmall => "-Drelease-small",
};

var qemu_args_al = ArrayList([]const u8).init(b.allocator);
defer qemu_args_al.deinit();

switch (target.getCpuArch()) {
.i386 => try qemu_args_al.append("qemu-system-i386"),
else => unreachable,
}
try qemu_args_al.append("-serial");
try qemu_args_al.append("stdio");
switch (target.getCpuArch()) {
.i386 => {
try qemu_args_al.append("-boot");
try qemu_args_al.append("d");
try qemu_args_al.append("-cdrom");
try qemu_args_al.append(output_iso);
},
else => unreachable,
}
if (disable_display) {
try qemu_args_al.append("-display");
try qemu_args_al.append("none");
}

const map_file_path = try fs.path.join(b.allocator, &[_][]const u8{ modules_path, "kernel.map" });
const map_file_cmd = b.addSystemCommand(&[_][]const u8{ "./make_map.sh", elf_path, map_file_path });
map_file_cmd.step.dependOn(&cp_elf_cmd.step);
map_file_cmd.step.dependOn(&mkdir_modules_cmd.step);
var qemu_args = qemu_args_al.toOwnedSlice();

const iso_cmd = b.addSystemCommand(&[_][]const u8{ "grub-mkrescue", "-o", iso_path, iso_dir_path });
iso_cmd.step.dependOn(&map_file_cmd.step);
b.default_step.dependOn(&iso_cmd.step);
const rt_step = RuntimeStep.create(b, test_mode, qemu_args);
rt_step.step.dependOn(&make_iso.step);
rt_test_step.dependOn(&rt_step.step);

const run_step = b.step("run", "Run with qemu");
const run_debug_step = b.step("debug-run", "Run with qemu and wait for a gdb connection");

const qemu_bin = switch (target.getArch()) {
.i386 => "qemu-system-i386",
else => unreachable,
};
const qemu_args = &[_][]const u8{
qemu_bin,
"-cdrom",
iso_path,
"-boot",
"d",
"-serial",
"stdio",
};
const qemu_cmd = b.addSystemCommand(qemu_args);
const qemu_debug_cmd = b.addSystemCommand(qemu_args);
qemu_debug_cmd.addArgs(&[_][]const u8{ "-s", "-S" });

if (rt_test) {
const qemu_rt_test_args = &[_][]const u8{ "-display", "none" };
qemu_cmd.addArgs(qemu_rt_test_args);
qemu_debug_cmd.addArgs(qemu_rt_test_args);
}

qemu_cmd.step.dependOn(&iso_cmd.step);
qemu_debug_cmd.step.dependOn(&iso_cmd.step);
qemu_cmd.step.dependOn(&make_iso.step);
qemu_debug_cmd.step.dependOn(&make_iso.step);

run_step.dependOn(&qemu_cmd.step);
run_debug_step.dependOn(&qemu_debug_cmd.step);

const test_step = b.step("test", "Run tests");
if (rt_test) {
const script = b.addSystemCommand(&[_][]const u8{ "python3", "test/rt-test.py", "x86", b.zig_exe });
test_step.dependOn(&script.step);
} else {
const mock_path = "\"../../test/mock/kernel/\"";
const arch_mock_path = "\"../../../../test/mock/kernel/\"";
const unit_tests = b.addTest(main_src);
unit_tests.setBuildMode(build_mode);
unit_tests.setMainPkgPath(".");
unit_tests.addPackagePath("constants", constants_path);
unit_tests.addBuildOption(bool, "rt_test", rt_test);
unit_tests.addBuildOption([]const u8, "mock_path", mock_path);
unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path);
test_step.dependOn(&unit_tests.step);
}

const debug_step = b.step("debug", "Debug with gdb and connect to a running qemu instance");
const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", elf_path });
const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", exec.getOutputPath() });
const debug_cmd = b.addSystemCommand(&[_][]const u8{
"gdb",
"gdb-multiarch",
"-ex",
symbol_file_arg,
"-ex",
"set architecture auto",
});
debug_cmd.addArgs(&[_][]const u8{
"-ex",
Expand Down
4 changes: 0 additions & 4 deletions make_map.sh

This file was deleted.

31 changes: 31 additions & 0 deletions makeiso.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

BOOT_DIR=$1
MODULES_DIR=$2
ISO_DIR=$3
PLUTO_ELF=$4
OUTPUT_FILE=$5

MAP_FILE=$MODULES_DIR/'kernel.map'

exit_missing() {
printf "$_ must be installed\n";
exit 1;
}

# Check dependencies
which xorriso > /dev/null || exit_missing
which grub-mkrescue > /dev/null || exit_missing
which readelf > /dev/null || exit_missing

mkdir -p $BOOT_DIR
mkdir -p $MODULES_DIR

cp -r grub $BOOT_DIR
cp $PLUTO_ELF $BOOT_DIR/"pluto.elf"

# Read the symbols from the binary, remove all the unnecessary columns with awk and emit to a map file
readelf -s --wide $PLUTO_ELF | grep -F "FUNC" | awk '{$1=$3=$4=$5=$6=$7=""; print $0}' | sort -k 1 > $MAP_FILE
echo "" >> $MAP_FILE

grub-mkrescue -o $OUTPUT_FILE $ISO_DIR
4 changes: 3 additions & 1 deletion src/kernel/arch.zig
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const std = @import("std");
const builtin = @import("builtin");
const is_test = builtin.is_test;
const build_options = @import("build_options");
const mock_path = build_options.mock_path;

pub const internals = if (is_test) @import(build_options.mock_path ++ "arch_mock.zig") else switch (builtin.arch) {
pub const internals = if (is_test) @import(mock_path ++ "arch_mock.zig") else switch (builtin.arch) {
.i386 => @import("arch/x86/arch.zig"),
else => unreachable,
};
Expand Down
Loading