Add aarch64 target
This commit is contained in:
@@ -1,5 +1,86 @@
|
||||
const std = @import("std");
|
||||
|
||||
const DEFAULT_ARCH = "riscv64";
|
||||
|
||||
const SupportedArch = enum {
|
||||
aarch64,
|
||||
riscv64,
|
||||
|
||||
fn fromStr(s: []const u8) ?SupportedArch {
|
||||
return if (std.mem.eql(u8, s, "riscv64")) //
|
||||
.riscv64
|
||||
else if (std.mem.eql(u8, s, "aarch64")) //
|
||||
.aarch64
|
||||
else //
|
||||
null;
|
||||
}
|
||||
|
||||
fn makeTarget(self: SupportedArch, b: *std.Build) std.Build.ResolvedTarget {
|
||||
return switch (self) {
|
||||
.riscv64 => b.standardTargetOptions(.{ .default_target = .{
|
||||
.cpu_arch = .riscv64,
|
||||
.os_tag = .freestanding,
|
||||
.abi = .none,
|
||||
} }),
|
||||
.aarch64 => b.standardTargetOptions(.{ .default_target = .{
|
||||
.cpu_arch = .aarch64,
|
||||
.os_tag = .freestanding,
|
||||
.abi = .none,
|
||||
} }),
|
||||
};
|
||||
}
|
||||
|
||||
fn addTargetSpecific(self: SupportedArch, b: *std.Build, kernel: *std.Build.Step.Compile) anyerror!*std.Build.Step {
|
||||
switch (self) {
|
||||
.riscv64 => {
|
||||
kernel.entry = .{ .symbol_name = "__rv64_entry" };
|
||||
|
||||
kernel.setLinkerScript(b.path("etc/riscv64-unknown-none.ld"));
|
||||
kernel.addCSourceFiles(.{
|
||||
.files = &.{"src/arch/riscv64/entry.S"},
|
||||
.flags = &.{},
|
||||
});
|
||||
},
|
||||
.aarch64 => {
|
||||
kernel.entry = .{ .symbol_name = "__aa64_entry" };
|
||||
|
||||
kernel.setLinkerScript(b.path("etc/aarch64-unknown-none.ld"));
|
||||
kernel.addCSourceFiles(.{
|
||||
.files = &.{"src/arch/aarch64/entry.S"},
|
||||
.flags = &.{},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
b.installArtifact(kernel);
|
||||
|
||||
if (self == .riscv64 or self == .aarch64) {
|
||||
const fakeLinuxHeader: *std.Build.Step = try b.allocator.create(std.Build.Step);
|
||||
fakeLinuxHeader.* = std.Build.Step.init(.{
|
||||
.id = std.Build.Step.Id.custom,
|
||||
.name = "insert fake linux header",
|
||||
.owner = kernel.step.owner,
|
||||
.makeFn = insertFakeLinuxImageHeader,
|
||||
});
|
||||
|
||||
const elf2bin = b.addSystemCommand(&.{
|
||||
"llvm-objcopy",
|
||||
"-O",
|
||||
"binary",
|
||||
"zig-out/bin/kernel",
|
||||
"zig-out/bin/kernel.bin",
|
||||
});
|
||||
|
||||
fakeLinuxHeader.dependOn(b.getInstallStep());
|
||||
elf2bin.step.dependOn(fakeLinuxHeader);
|
||||
|
||||
return &elf2bin.step;
|
||||
} else {
|
||||
@panic("Unreachable + don't care");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn insertFakeLinuxImageHeader(step: *std.Build.Step, opts: std.Build.Step.MakeOptions) anyerror!void {
|
||||
const RISCV_MAGIC1 = "RISCV\x00\x00\x00";
|
||||
const RISCV_MAGIC2 = "RSC\x05";
|
||||
@@ -46,53 +127,72 @@ fn insertFakeLinuxImageHeader(step: *std.Build.Step, opts: std.Build.Step.MakeOp
|
||||
_ = opts;
|
||||
}
|
||||
|
||||
fn build_riscv64(b: *std.Build) anyerror!void {
|
||||
_ = b;
|
||||
}
|
||||
|
||||
pub fn build(b: *std.Build) anyerror!void {
|
||||
const maybeArchOption = b.option([]const u8, "arch", "Architecture to use");
|
||||
|
||||
const archOption = maybeArchOption orelse DEFAULT_ARCH;
|
||||
|
||||
const sTarget = SupportedArch.fromStr(archOption) orelse {
|
||||
std.debug.print("Unsupported target arch: '{s}'", .{archOption});
|
||||
return error.InvalidArgument;
|
||||
};
|
||||
|
||||
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast });
|
||||
const target = b.standardTargetOptions(.{ .default_target = .{
|
||||
.cpu_arch = .riscv64,
|
||||
.os_tag = .freestanding,
|
||||
.abi = .none,
|
||||
} });
|
||||
const target = sTarget.makeTarget(b);
|
||||
|
||||
const kernel_module = b.addModule("kernel", .{ .optimize = optimize, .target = target, .pic = true, .red_zone = false, .code_model = .medium, .root_source_file = b.path("src/kernel.zig") });
|
||||
|
||||
const kernel = b.addExecutable(.{ .name = "kernel", .root_module = kernel_module, .pic = true });
|
||||
const codeModel: std.builtin.CodeModel = switch (sTarget) {
|
||||
.riscv64 => .medium,
|
||||
.aarch64 => .small,
|
||||
};
|
||||
const kernelModule = b.addModule("kernel", .{
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
.pic = true,
|
||||
.red_zone = false,
|
||||
.code_model = codeModel,
|
||||
.root_source_file = b.path("src/kernel.zig"),
|
||||
});
|
||||
const kernel = b.addExecutable(.{
|
||||
.name = "kernel",
|
||||
.root_module = kernelModule,
|
||||
.pic = true,
|
||||
});
|
||||
kernel.pie = true;
|
||||
|
||||
kernel.entry = .{ .symbol_name = "__rv64_entry" };
|
||||
|
||||
kernel.setLinkerScript(b.path("etc/riscv64-unknown-none.ld"));
|
||||
kernel.addCSourceFiles(.{
|
||||
.files = &.{"src/arch/riscv64/entry.S"},
|
||||
.flags = &.{},
|
||||
});
|
||||
b.installArtifact(kernel);
|
||||
|
||||
const fakeLinuxHeader: *std.Build.Step = try b.allocator.create(std.Build.Step);
|
||||
fakeLinuxHeader.* = std.Build.Step.init(.{
|
||||
.id = std.Build.Step.Id.custom,
|
||||
.name = "insert fake linux header",
|
||||
.owner = kernel.step.owner,
|
||||
.makeFn = insertFakeLinuxImageHeader,
|
||||
});
|
||||
|
||||
const elf2bin = b.addSystemCommand(&.{ "llvm-objcopy", "-O", "binary", "zig-out/bin/kernel", "zig-out/bin/kernel.bin" });
|
||||
const kernelStep = try sTarget.addTargetSpecific(b, kernel);
|
||||
|
||||
// TODO QEMU binary override
|
||||
const qemu_info = switch (target.result.cpu.arch) {
|
||||
.riscv64 => .{ "qemu-system-riscv64", "rv64" },
|
||||
.aarch64 => .{ "qemu-system-aarch64", "cortex-a72" },
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const qemu_cmd = b.addSystemCommand(&.{ qemu_info[0], "-M", "virt", "-kernel", "zig-out/bin/kernel.bin", "-m", "256M", "-cpu", qemu_info[1], "-serial", "mon:stdio", "-display", "none" });
|
||||
const qemu_cmd = b.addSystemCommand(&.{
|
||||
qemu_info[0],
|
||||
"-M",
|
||||
"virt",
|
||||
"-kernel",
|
||||
"zig-out/bin/kernel.bin",
|
||||
"-m",
|
||||
"256M",
|
||||
"-cpu",
|
||||
qemu_info[1],
|
||||
"-serial",
|
||||
"mon:stdio",
|
||||
"-display",
|
||||
"none",
|
||||
});
|
||||
|
||||
if (target.result.cpu.arch == .riscv64) {
|
||||
qemu_cmd.addArgs(&.{ "-bios", "etc/boot/rv64_fw_jump.bin" });
|
||||
}
|
||||
|
||||
fakeLinuxHeader.dependOn(b.getInstallStep());
|
||||
elf2bin.step.dependOn(fakeLinuxHeader);
|
||||
qemu_cmd.step.dependOn(&elf2bin.step);
|
||||
qemu_cmd.step.dependOn(kernelStep);
|
||||
if (b.args) |args| qemu_cmd.addArgs(args);
|
||||
const run_step = b.step("run", "Start the OS in qemu");
|
||||
run_step.dependOn(&qemu_cmd.step);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
SECTIONS {
|
||||
. = 0x0;
|
||||
|
||||
PROVIDE(__kernel_start = .);
|
||||
|
||||
.text : ALIGN(4K) {
|
||||
*(.text.entry*)
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
.rodata : ALIGN(4K) {
|
||||
*(.rodata*)
|
||||
*(.srodata*)
|
||||
*(.got*)
|
||||
*(.plt*)
|
||||
}
|
||||
|
||||
.dynamic : ALIGN(4K) {
|
||||
*(.dynamic*)
|
||||
}
|
||||
|
||||
.tdata : ALIGN(4K) {
|
||||
PROVIDE(__tdata_start = .);
|
||||
*(.tdata*)
|
||||
PROVIDE(__tdata_end = .);
|
||||
}
|
||||
|
||||
.rela : ALIGN(4K) {
|
||||
PROVIDE(__rela_start = .);
|
||||
*(.rela*)
|
||||
PROVIDE(__rela_end = .);
|
||||
}
|
||||
|
||||
.data : ALIGN(4K) {
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__bss_start = .);
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
*(.sbss*)
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__bss_end = .);
|
||||
}
|
||||
|
||||
.tbss : {
|
||||
PROVIDE(__tbss_start = .);
|
||||
*(.tbss*)
|
||||
PROVIDE(__tbss_end = .);
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__kernel_end = .);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
gdb-remote localhost:1234
|
||||
|
||||
target modules add zig-out/bin/kernel
|
||||
# target modules load -f zig-out/bin/kernel -s 0xFFFFFFF000200000
|
||||
target modules load -f zig-out/bin/kernel -s 0x40080000
|
||||
|
||||
# breakpoint set -H -a 0x80200000
|
||||
# process continue
|
||||
|
||||
# breakpoint set -H -n arch.riscv64.boot.rv64BspEntryLower
|
||||
# process continue
|
||||
@@ -5,6 +5,9 @@ pub fn arch() type {
|
||||
.riscv64 => {
|
||||
return @import("arch/riscv64.zig");
|
||||
},
|
||||
.aarch64 => {
|
||||
return @import("arch/aarch64.zig");
|
||||
},
|
||||
else => {
|
||||
@panic("Architecture is not supported");
|
||||
},
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
const boot = @import("aarch64/boot.zig");
|
||||
|
||||
export const _ = boot.aa64BspLowerEntry;
|
||||
|
||||
pub const Context = struct {
|
||||
pub fn idle() Context {
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
pub fn kernel(pc: usize, arg: usize) Context {
|
||||
_ = pc;
|
||||
_ = arg;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
pub fn enter(self: *Context) noreturn {
|
||||
_ = self;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
pub fn switchFrom(self: *Context, from: *Context) void {
|
||||
_ = self;
|
||||
_ = from;
|
||||
@panic("TODO");
|
||||
}
|
||||
};
|
||||
|
||||
pub fn halt() noreturn {
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
pub fn spinHint() void {
|
||||
// TODO
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub export fn aa64BspLowerEntry() callconv(.C) noreturn {
|
||||
while (true) {}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
.global __aa64_entry
|
||||
|
||||
.pushsection .text.entry
|
||||
__aa64_entry:
|
||||
// x0 -- DTB physical address
|
||||
mrs x1, mpidr_el1
|
||||
ands x1, x1, #0xF
|
||||
bne .parking_lot
|
||||
|
||||
mrs x1, CurrentEL
|
||||
and x1, x1, #~0x3
|
||||
adr x2, .el_jump_table
|
||||
add x2, x2, x1
|
||||
br x2
|
||||
|
||||
.el_jump_table:
|
||||
b . // EL0 impossible
|
||||
b .bsp_el1 // EL1
|
||||
b . // EL2 not implemented
|
||||
b . // EL3 not implemented
|
||||
|
||||
.bsp_el1:
|
||||
// Zero out the .bss
|
||||
adr x1, __bss_start
|
||||
adr x2, __bss_end
|
||||
1:
|
||||
cmp x1, x2
|
||||
beq 2f
|
||||
str xzr, [x1], #8
|
||||
b 1b
|
||||
2:
|
||||
|
||||
// Setup a stack
|
||||
adr x1, __aa64_bsp_stack_top
|
||||
mov sp, x1
|
||||
|
||||
b aa64BspLowerEntry
|
||||
|
||||
.parking_lot:
|
||||
wfe
|
||||
b .parking_lot
|
||||
.popsection // .text.entry
|
||||
|
||||
.pushsection .bss
|
||||
.p2align 4
|
||||
__aa64_bsp_stack_bottom:
|
||||
.skip 65536
|
||||
__aa64_bsp_stack_top:
|
||||
.popsection // .bss
|
||||
Reference in New Issue
Block a user