137 lines
3.9 KiB
Zig
137 lines
3.9 KiB
Zig
const kernel = @import("../../kernel.zig");
|
|
const vmm = @import("vmm.zig");
|
|
const dtb = @import("../../util/dtb.zig");
|
|
const exception = @import("exception.zig");
|
|
const tls = @import("../../mem/tls.zig");
|
|
|
|
const arch = kernel.arch;
|
|
const mem = kernel.mem;
|
|
const log = kernel.debug.log;
|
|
const phys_memory = mem.phys;
|
|
|
|
extern const __aa64_bsp_stack_top: u8;
|
|
|
|
var g_dtb_address: u64 = undefined;
|
|
|
|
fn early_debug_print(byte: u8) void {
|
|
const address = 0x9000000;
|
|
@as(*volatile u32, @ptrFromInt(address)).* = byte;
|
|
}
|
|
|
|
fn reloc_address_to_upper(ptr: *const anyopaque) usize {
|
|
const p = @intFromPtr(ptr);
|
|
if (p >= vmm.KERNEL_VIRTUAL_BASE) {
|
|
return p;
|
|
} else {
|
|
return p + vmm.KERNEL_VIRTUAL_BASE;
|
|
}
|
|
}
|
|
|
|
fn reloc_address_to_lower(ptr: *const anyopaque) usize {
|
|
const p = @intFromPtr(ptr);
|
|
if (p >= vmm.KERNEL_VIRTUAL_BASE) {
|
|
return p - vmm.KERNEL_VIRTUAL_BASE;
|
|
} else {
|
|
return p;
|
|
}
|
|
}
|
|
|
|
fn aa64_bsp_upper_entry(real_address: u64) callconv(.C) noreturn {
|
|
// Relocate the kernel yet again
|
|
const rela_start = reloc_address_to_upper(&__rela_start);
|
|
const rela_end = reloc_address_to_upper(&__rela_end);
|
|
const rel_offset = vmm.KERNEL_VIRTUAL_BASE + real_address;
|
|
|
|
arch.barrier(.acq_rel);
|
|
aa64_relocate_kernel(rel_offset, rela_start, rela_end);
|
|
arch.barrier(.acq_rel);
|
|
|
|
log.set_write_fn(&early_debug_print);
|
|
|
|
exception.init();
|
|
|
|
mem.PhysicalAddress.g_virtualize_base = 0;
|
|
mem.PhysicalAddress.g_virtualize_size = 16 << 30;
|
|
|
|
setup_memory_from_fdt(real_address);
|
|
|
|
setup_per_cpu();
|
|
|
|
kernel.kernel_main();
|
|
}
|
|
|
|
pub export fn aa64_bsp_lower_entry(real_address: u64, dtb_address: u64) callconv(.C) noreturn {
|
|
g_dtb_address = dtb_address;
|
|
|
|
vmm.map_early(real_address);
|
|
|
|
const pc = @intFromPtr(&aa64_bsp_upper_entry) + vmm.KERNEL_VIRTUAL_BASE;
|
|
const sp = @intFromPtr(&__aa64_bsp_stack_top) + vmm.KERNEL_VIRTUAL_BASE;
|
|
|
|
long_jump(pc, sp, real_address);
|
|
}
|
|
|
|
// Functions used by the boot process
|
|
|
|
extern const __rela_start: u8;
|
|
extern const __rela_end: u8;
|
|
extern var __kernel_start: u8;
|
|
extern var __kernel_end: u8;
|
|
|
|
export fn aa64_relocate_kernel(image_base: usize, rela_start: usize, rela_end: usize) void {
|
|
const elf = @import("std").elf;
|
|
|
|
const rela_table_ptr = @as([*]elf.Rela, @ptrFromInt(rela_start));
|
|
const rela_count = (rela_end - rela_start) / @sizeOf(elf.Rela);
|
|
const rela_table = rela_table_ptr[0..rela_count];
|
|
for (rela_table) |entry| {
|
|
const rela_type: elf.R_AARCH64 = @enumFromInt(entry.r_type());
|
|
switch (rela_type) {
|
|
.RELATIVE => {
|
|
const value = @as(*isize, @ptrFromInt(image_base + entry.r_offset));
|
|
value.* = @as(isize, @bitCast(image_base)) + entry.r_addend;
|
|
},
|
|
else => {
|
|
arch.halt();
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
inline fn long_jump(pc: usize, sp: usize, a0: usize) noreturn {
|
|
asm volatile (
|
|
\\ mov sp, %[sp]
|
|
\\ br %[pc]
|
|
:
|
|
: [sp] "r" (sp),
|
|
[pc] "r" (pc),
|
|
[a0] "{x0}" (a0),
|
|
: "memory"
|
|
);
|
|
unreachable;
|
|
}
|
|
|
|
fn setup_memory_from_fdt(real_address: usize) void {
|
|
_ = real_address;
|
|
|
|
const kernel_start = reloc_address_to_lower(&__kernel_start); // 0
|
|
const kernel_end = reloc_address_to_lower(&__kernel_end); // whatever
|
|
|
|
const fdt = dtb.Fdt.from_physical_address(.{ .raw = g_dtb_address }) catch |err| {
|
|
log.panic("Cannot initialize raw DTB: {}", .{err});
|
|
};
|
|
fdt.add_physical_memory_to_system();
|
|
|
|
phys_memory.add_reserved_region("kernel", kernel_start, kernel_end - kernel_start);
|
|
phys_memory.add_reserved_region("fdt", g_dtb_address, vmm.L3.align_up(fdt.bytes.len));
|
|
|
|
phys_memory.init();
|
|
}
|
|
|
|
fn setup_per_cpu() void {
|
|
const tls_data = tls.load_kernel_tls_image();
|
|
const tp = @intFromPtr(tls_data.ptr);
|
|
log.info("Set TP = 0x{x}", .{tp});
|
|
arch.set_thread_pointer(tp);
|
|
}
|