Implement thread-locals for per-CPU data

This commit is contained in:
2025-03-17 17:26:40 +02:00
parent 856c7b273e
commit c803a3e2b2
5 changed files with 64 additions and 13 deletions
+12
View File
@@ -21,6 +21,12 @@ SECTIONS {
*(.dynamic*)
}
.tdata : ALIGN(4K) {
PROVIDE(__tdata_start = .);
*(.tdata*)
PROVIDE(__tdata_end = .);
}
.rela : ALIGN(4K) {
PROVIDE(__rela_start = .);
*(.rela*)
@@ -42,6 +48,12 @@ SECTIONS {
PROVIDE(__bss_end = .);
}
.tbss : {
PROVIDE(__tbss_start = .);
*(.tbss*)
PROVIDE(__tbss_end = .);
}
. = ALIGN(4K);
PROVIDE(__kernel_end = .);
}
+6
View File
@@ -14,6 +14,8 @@ extern fn __rv64_task_enter_kernel() callconv(.C) noreturn;
pub fn arch() type {
return struct {
pub threadlocal var tHartId: u32 = 0;
pub const Context = extern struct {
const STACK_SIZE: usize = 8192;
@@ -101,5 +103,9 @@ pub fn arch() type {
}
asm volatile ("":::"memory");
}
pub inline fn setThreadPointer(tp: usize) void {
asm volatile ("mv tp, %[tp]"::[tp]"r"(tp):"memory");
}
};
}
+14 -7
View File
@@ -18,7 +18,7 @@ extern const __kernel_start: u8;
extern const __kernel_end: u8;
var gDtbAddress: usize = 0;
var gBspHartId: usize = 0;
var gBspHartId: u32 = 0;
pub export fn rv64RelocateKernel(imageBase: usize, relaStart: usize, relaEnd: usize) void {
const elf = @import("std").elf;
@@ -27,11 +27,15 @@ pub export fn rv64RelocateKernel(imageBase: usize, relaStart: usize, relaEnd: us
const relaCount = (relaEnd - relaStart) / @sizeOf(elf.Rela);
const relaTable = relaTablePtr[0..relaCount];
for (relaTable) |entry| {
if (entry.r_type() == 0x03) {
const value = @as(*isize, @ptrFromInt(imageBase + entry.r_offset));
value.* = @as(isize, @bitCast(imageBase)) + entry.r_addend;
} else {
arch.halt();
const relaType: elf.R_RISCV = @enumFromInt(entry.r_type());
switch (relaType) {
.RELATIVE => {
const value = @as(*isize, @ptrFromInt(imageBase + entry.r_offset));
value.* = @as(isize, @bitCast(imageBase)) + entry.r_addend;
},
else => {
arch.halt();
},
}
}
}
@@ -94,6 +98,9 @@ fn bspUpperEntry(realAddress: usize, unused: usize) callconv(.C) noreturn {
// Setup physical memory management
setupMemoryFromFdt(realAddress);
kernel.thread.setupCurrentCpu();
arch.tHartId = gBspHartId;
kernel.kernel_main();
}
@@ -115,7 +122,7 @@ pub export fn rv64BspLowerEntry(realAddress: usize, bspHartId: usize, dtbAddress
debug.log.setWriteFn(&sbi.debugPrintByte);
gDtbAddress = dtbAddress;
gBspHartId = bspHartId;
gBspHartId = @truncate(bspHartId);
vmm.mapEarly(realAddress);
-6
View File
@@ -34,12 +34,6 @@ pub export fn kernel_main() callconv(.C) noreturn {
thread.addThread(t);
}
const ptr: *const u32 = @ptrFromInt(0x1111111111111114);
const z = ptr.*;
_ = z;
while (true) {}
thread.enter();
arch.halt();
+32
View File
@@ -1,3 +1,5 @@
const std = @import("std");
const arena = @import("arena.zig");
const arch = @import("kernel.zig").arch;
const log = @import("debug.zig").log;
@@ -90,3 +92,33 @@ pub fn yield() void {
next.switchFrom(curr);
}
}
extern var __tdata_start: u8;
extern var __tdata_end: u8;
extern var __tbss_start: u8;
extern var __tbss_end: u8;
pub fn setupCurrentCpu() void {
// Assume .tbss follows .tdata
const tdataStart = @intFromPtr(&__tdata_start);
const tdataEnd = @intFromPtr(&__tdata_end);
const tdataSize = tdataEnd - tdataStart;
const tbssStart = @intFromPtr(&__tbss_start);
const tbssEnd = @intFromPtr(&__tbss_end);
const tbssSize = tbssEnd - tbssStart;
const tdataData = @as([*]u8, @ptrFromInt(tdataStart))[0..tdataSize];
const tlsSize = tdataSize + tbssSize;
const tlsPageCount = (tlsSize + mem.vmm.PAGE_SIZE - 1) / mem.vmm.PAGE_SIZE;
// Variant I: TLS block 0 follows TP after a certain displacement
const tlsAddress = mem.phys.alloc_pages(tlsPageCount).?.virtualize();
const tlsData = @as([*]u8, @ptrFromInt(tlsAddress))[0..tlsSize];
log.info("Allocated TLS @ {*}", .{ tlsData });
@memcpy(tlsData[0..tdataSize], tdataData);
@memset(tlsData[tdataSize..], 0);
arch.setThreadPointer(tlsAddress);
}