Zig 124 lines
// Trace I/O helpers — output via PL011 UART for tracing.
// Layouts come from src/task_layout.zig.
const layout = @import("task_layout");
const TaskStruct = layout.TaskStruct;
pub const PL: i32 = 1;
const ID_MAP_PAGES: usize = 3;
const HIGH_MAP_PAGES: usize = 6;
const ENTRIES_PER_TABLE: usize = 512;
extern fn pl011_uart_send_string(str: [*:0]const u8) void;
extern fn pl011_uart_recv() u8;
extern var id_pg_dir: u64;
extern var high_pg_dir: u64;
export fn trace_output(interface: i32, str: [*:0]const u8) void {
switch (interface) {
PL => pl011_uart_send_string(str),
else => trace_output(PL, "trace_output bad interface\n"),
}
}
export fn trace_u64_to_char_array(in: u64, buf: [*]u8) void {
var i: u32 = 0;
while (i < 16) : (i += 1) {
const shift: u6 = @intCast((15 - i) * 4);
const tmp: u8 = @intCast((in >> shift) & 0xF);
buf[i] = if (tmp <= 9) tmp + '0' else tmp - 10 + 'a';
}
}
export fn trace_char_to_char_array(ch: u8, buf: [*]u8) void {
buf[0] = ch;
}
export fn trace_output_char(interface: i32, ch: u8) void {
var printable: [2]u8 = undefined;
printable[0] = ch;
printable[1] = 0;
trace_output(interface, @ptrCast(&printable[0]));
}
export fn trace_output_u64(interface: i32, in: u64) void {
var printable: [17]u8 = undefined;
printable[16] = 0;
trace_u64_to_char_array(in, @ptrCast(&printable[0]));
trace_output(interface, @ptrCast(&printable[0]));
}
export fn trace_output_process(interface: i32, p: *TaskStruct) void {
trace_output(interface, "task address: ");
trace_output_u64(interface, @intFromPtr(p));
trace_output(interface, ", state: ");
trace_output_u64(interface, @bitCast(p.state));
trace_output(interface, ", counter: ");
trace_output_u64(interface, @bitCast(p.counter));
trace_output(interface, ", priority: ");
trace_output_u64(interface, @bitCast(p.priority));
trace_output(interface, ", preempt_count: ");
trace_output_u64(interface, @bitCast(p.preempt_count));
trace_output(interface, ", pgd: ");
trace_output_u64(interface, p.mm.pgd);
trace_output(interface, "\n");
}
export fn trace_output_insn(interface: i32, addr_in: u64) void {
const addr: u64 = addr_in & ~@as(u64, 0x7);
trace_output(interface, "instruction address: ");
trace_output_u64(interface, addr);
trace_output(interface, ", instruction: ");
const ptr: *const volatile u64 = @ptrFromInt(addr);
trace_output_u64(interface, ptr.*);
trace_output(interface, "\n");
}
export fn trace_output_pt(interface: i32, page: [*]u64) void {
var i: usize = 0;
while (i < ENTRIES_PER_TABLE) : (i += 1) {
trace_output_u64(interface, @intFromPtr(&page[i]));
trace_output(interface, ": ");
trace_output_u64(interface, page[i]);
if ((i % 2) != 0) {
trace_output(interface, "\n");
} else {
trace_output(interface, " ");
}
}
}
export fn trace_output_kernel_pts(interface: i32) void {
_ = interface;
var pt: [*]u64 = @ptrCast(&id_pg_dir);
var i: usize = 0;
while (i < ID_MAP_PAGES) : (i += 1) {
trace_output(PL, "pt = ");
trace_output_u64(PL, @intFromPtr(pt));
trace_output(PL, "\n");
trace_output_pt(PL, pt);
pt += ENTRIES_PER_TABLE;
}
pt = @ptrCast(&high_pg_dir);
i = 0;
while (i < HIGH_MAP_PAGES) : (i += 1) {
trace_output(PL, "pt = ");
trace_output_u64(PL, @intFromPtr(pt));
trace_output(PL, "\n");
trace_output_pt(PL, pt);
pt += ENTRIES_PER_TABLE;
}
}
export fn trace_recv(interface: i32) u8 {
switch (interface) {
PL => return pl011_uart_recv(),
else => {
trace_output(PL, "main_recv bad interface\n");
return 0;
},
}
}