feat: provide infrastructure for TLS

This commit is contained in:
Paul Pan 2024-03-23 21:05:33 +08:00
parent c210a049cd
commit c3d59bc9a4
10 changed files with 85 additions and 24 deletions

View File

@ -1,9 +0,0 @@
pub fn get_hart_id() -> usize {
let id;
unsafe { core::arch::asm!("mv {}, tp", out(reg) id) }
id
}
pub fn set_hart_id(id: usize) {
unsafe { core::arch::asm!("mv tp, {}", in(reg) id) }
}

View File

@ -1,6 +1,5 @@
use core::ptr::addr_of_mut;
use super::cpu::set_hart_id;
use super::layout::{__boot_stack_end, __bss_end, __tbss_end, __tbss_start};
use super::tls::set_hart_id;
#[naked]
#[no_mangle]
@ -16,6 +15,8 @@ unsafe extern "C" fn _start(hart_id: usize, device_tree_addr: usize) -> ! {
core::arch::asm!(
"csrw sie, 0",
"csrw sip, 0",
"la gp, __global_pointer$",
"la tp, __tss_start",
"la sp, {stack} + {stack_size}",
"j {main}",
stack_size = const STACK_SIZE,
@ -29,24 +30,23 @@ extern "C" fn pre_main(hart_id: usize, device_tree_addr: usize) -> ! {
// TODO: multiboot
zero_bss();
set_hart_id(hart_id);
// TODO: initialize page table
crate::entry::rust_main(hart_id, device_tree_addr);
}
extern "C" {
static mut __boot_stack_end: u8;
static mut __bss_end: u8;
}
#[inline(always)]
fn zero_bss() {
fn clear_range<T: Clone>(bgn: *mut T, end: *mut T) {
unsafe {
let cur = addr_of_mut!(__boot_stack_end);
let end = addr_of_mut!(__bss_end);
core::slice::from_raw_parts_mut(bgn, end.offset_from(bgn) as usize)
.fill(core::mem::zeroed())
}
}
core::slice::from_raw_parts_mut(cur, end.offset_from(cur) as usize).fill(0);
unsafe {
clear_range(__boot_stack_end.as_mut_ptr(), __bss_end.as_mut_ptr());
clear_range(__tbss_start.as_mut_ptr(), __tbss_end.as_mut_ptr());
}
}

View File

@ -3,4 +3,26 @@ use crate::utils::extern_addr::ExternSymbol;
extern "C" {
static __kernel_start: ExternSymbol;
static __kernel_end: ExternSymbol;
static __text_start: ExternSymbol;
static __text_end: ExternSymbol;
static __rodata_start: ExternSymbol;
static __rodata_end: ExternSymbol;
static __data_start: ExternSymbol;
static __data_end: ExternSymbol;
static __bss_start: ExternSymbol;
pub(crate) static __boot_stack_end: ExternSymbol;
pub(crate) static __bss_end: ExternSymbol;
static __tss_start: ExternSymbol;
static __tss_end: ExternSymbol;
static __tdata_start: ExternSymbol;
static __tdata_end: ExternSymbol;
pub(crate) static __tbss_start: ExternSymbol;
pub(crate) static __tbss_end: ExternSymbol;
}

View File

@ -27,6 +27,8 @@ SECTIONS {
. = ALIGN(8);
__data_start = .;
*(.data .data.*)
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
__data_end = .;
}
@ -42,6 +44,23 @@ SECTIONS {
__bss_end = .;
}
.tss : {
. = ALIGN(8);
__tss_start = .;
. = ALIGN(8);
__tdata_start = .;
*(.tdata .tdata.*)
__tdata_end = .;
. = ALIGN(8);
__tbss_start = .;
*(.tbss .tbss.*)
__tbss_end = .;
__tss_end = .;
}
. = ALIGN(PAGE_SIZE);
__kernel_end = .;

View File

@ -12,9 +12,9 @@ cfg_if! {
}
}
mod cpu;
mod entry;
pub mod layout;
mod lowlevel;
mod timer;
mod tls;
pub mod trap;

View File

@ -0,0 +1,17 @@
// Documentations:
// - RISC-V ELF psABI: 8.5. Thread Local Storage
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc
// - Rust #[thread_local] feature
// https://github.com/rust-lang/rust/issues/29594
// TODO: use TLS for per-hart data
pub fn get_hart_id() -> usize {
let id;
unsafe { core::arch::asm!("mv {}, tp", out(reg) id) }
id
}
pub fn set_hart_id(id: usize) {
unsafe { core::arch::asm!("mv tp, {}", in(reg) id) }
}

View File

@ -3,7 +3,7 @@ use log::trace;
use riscv::register::scause::{Interrupt as I, Trap as T};
use riscv::register::stvec::TrapMode;
use super::cpu::get_hart_id;
use super::tls::get_hart_id;
use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapContextOps, TrapOps};

View File

@ -1,3 +1,5 @@
use core::cell::Cell;
use fdt::Fdt;
use log::{debug, error, info};
use crate::arch::BOOT_HART_ID;
@ -6,8 +8,13 @@ use crate::plat::lowlevel::{Hardware, LowLevel};
use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapOps};
#[thread_local]
static HART_ID: Cell<usize> = Cell::new(0);
#[no_mangle]
pub extern "C" fn rust_main(hart_id: usize, device_tree_addr: usize) -> ! {
HART_ID.set(hart_id);
crate::logging::init();
#[cfg(test)]

View File

@ -8,6 +8,7 @@
#![feature(naked_functions)]
#![feature(panic_info_message)]
#![feature(stmt_expr_attributes)]
#![feature(thread_local)]
// Test Infrastructure
#![feature(custom_test_frameworks)]
#![test_runner(test_runner::runner)]

View File

@ -9,6 +9,10 @@ impl ExternSymbol {
self as *const Self as *const u8
}
pub fn as_mut_ptr(&'static self) -> *mut u8 {
self as *const Self as *mut u8
}
pub fn as_usize(&'static self) -> usize {
self.as_ptr() as usize
}