70 lines
2.3 KiB
Zig
70 lines
2.3 KiB
Zig
//! Thread-local storage implementation.
|
|
|
|
const builtin = @import("builtin");
|
|
|
|
const vmm = @import("vmm.zig");
|
|
const phys_memory = @import("phys.zig");
|
|
const kernel = @import("../kernel.zig");
|
|
|
|
const PAGE_SIZE = vmm.PAGE_SIZE;
|
|
const log = kernel.debug.log;
|
|
|
|
/// Thread-local storage layout variant used by this target platform.
|
|
pub const TLS_VARIANT: enum {
|
|
/// Variant I:
|
|
///
|
|
/// [ TCB ] [ pad to p_align ] [ MODULE 0 ] [ MODULE 1 ] ...
|
|
/// | | |
|
|
/// | | |
|
|
/// tp off1 off2
|
|
variant1,
|
|
/// Variant II:
|
|
///
|
|
/// ... [ MODULE 1 ] [ MODULE 0 ] [ TCB ]
|
|
/// | | |
|
|
/// | | |
|
|
/// off2 off1 tp
|
|
variant2,
|
|
} = switch (builtin.cpu.arch) {
|
|
.riscv64, .aarch64 => .variant1,
|
|
// x86-64 uses variant 2
|
|
else => @panic("Unsupported CPU architecture"),
|
|
};
|
|
|
|
extern var __tdata_start: u8;
|
|
extern var __tdata_end: u8;
|
|
extern var __tbss_start: u8;
|
|
extern var __tbss_end: u8;
|
|
|
|
/// Allocates a storage for one per-CPU TLS block, clones the TLS image
|
|
/// (as described by .tbss/.tdata sections) and returns the result.
|
|
pub fn load_kernel_tls_image() []u8 {
|
|
// Assume .tbss follows .tdata
|
|
const tdata_start = @intFromPtr(&__tdata_start);
|
|
const tdata_end = @intFromPtr(&__tdata_end);
|
|
const tdata_size = tdata_end - tdata_start;
|
|
const tbss_start = @intFromPtr(&__tbss_start);
|
|
const tbss_end = @intFromPtr(&__tbss_end);
|
|
const tbss_size = tbss_end - tbss_start;
|
|
|
|
const tdata_data = @as([*]u8, @ptrFromInt(tdata_start))[0..tdata_size];
|
|
|
|
switch (comptime TLS_VARIANT) {
|
|
.variant1 => {
|
|
const tls_size = tdata_size + tbss_size;
|
|
const tls_page_count = (tls_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
|
// Variant I: TLS block 0 follows TP after a certain displacement
|
|
const tls_address = phys_memory.alloc_pages(tls_page_count).?.virtualize();
|
|
const tls_data = @as([*]u8, @ptrFromInt(tls_address))[0..tls_size];
|
|
|
|
log.info("Allocated TLS @ {*}", .{tls_data});
|
|
|
|
@memcpy(tls_data[0..tdata_size], tdata_data);
|
|
@memset(tls_data[tdata_size..], 0);
|
|
|
|
return tls_data;
|
|
},
|
|
.variant2 => @panic("TODO: TLS variant II"),
|
|
}
|
|
}
|