From c3d59bc9a4fe6083399f16723438e9a9c9c8494e Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Sat, 23 Mar 2024 21:05:33 +0800 Subject: [PATCH] feat: provide infrastructure for TLS --- kernel/src/arch/riscv/cpu.rs | 9 --------- kernel/src/arch/riscv/entry.rs | 26 +++++++++++++------------- kernel/src/arch/riscv/layout.rs | 22 ++++++++++++++++++++++ kernel/src/arch/riscv/linker.ld | 19 +++++++++++++++++++ kernel/src/arch/riscv/mod.rs | 2 +- kernel/src/arch/riscv/tls.rs | 17 +++++++++++++++++ kernel/src/arch/riscv/trap.rs | 2 +- kernel/src/entry.rs | 7 +++++++ kernel/src/main.rs | 1 + kernel/src/utils/extern_addr.rs | 4 ++++ 10 files changed, 85 insertions(+), 24 deletions(-) delete mode 100644 kernel/src/arch/riscv/cpu.rs create mode 100644 kernel/src/arch/riscv/tls.rs diff --git a/kernel/src/arch/riscv/cpu.rs b/kernel/src/arch/riscv/cpu.rs deleted file mode 100644 index 998902f..0000000 --- a/kernel/src/arch/riscv/cpu.rs +++ /dev/null @@ -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) } -} diff --git a/kernel/src/arch/riscv/entry.rs b/kernel/src/arch/riscv/entry.rs index ce1e18a..890cfd9 100644 --- a/kernel/src/arch/riscv/entry.rs +++ b/kernel/src/arch/riscv/entry.rs @@ -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() { - unsafe { - let cur = addr_of_mut!(__boot_stack_end); - let end = addr_of_mut!(__bss_end); + fn clear_range(bgn: *mut T, end: *mut T) { + unsafe { + 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()); } } diff --git a/kernel/src/arch/riscv/layout.rs b/kernel/src/arch/riscv/layout.rs index 8f3239d..d1fe240 100644 --- a/kernel/src/arch/riscv/layout.rs +++ b/kernel/src/arch/riscv/layout.rs @@ -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; } diff --git a/kernel/src/arch/riscv/linker.ld b/kernel/src/arch/riscv/linker.ld index 923af0e..2d99c53 100644 --- a/kernel/src/arch/riscv/linker.ld +++ b/kernel/src/arch/riscv/linker.ld @@ -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 = .; diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index ca181c6..0ba73f4 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -12,9 +12,9 @@ cfg_if! { } } -mod cpu; mod entry; pub mod layout; mod lowlevel; mod timer; +mod tls; pub mod trap; diff --git a/kernel/src/arch/riscv/tls.rs b/kernel/src/arch/riscv/tls.rs new file mode 100644 index 0000000..2706e15 --- /dev/null +++ b/kernel/src/arch/riscv/tls.rs @@ -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) } +} diff --git a/kernel/src/arch/riscv/trap.rs b/kernel/src/arch/riscv/trap.rs index bca78d6..3321ceb 100644 --- a/kernel/src/arch/riscv/trap.rs +++ b/kernel/src/arch/riscv/trap.rs @@ -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}; diff --git a/kernel/src/entry.rs b/kernel/src/entry.rs index 4163480..bce2a9b 100644 --- a/kernel/src/entry.rs +++ b/kernel/src/entry.rs @@ -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 = 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)] diff --git a/kernel/src/main.rs b/kernel/src/main.rs index f25797a..941e983 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -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)] diff --git a/kernel/src/utils/extern_addr.rs b/kernel/src/utils/extern_addr.rs index 94c1395..91f237b 100644 --- a/kernel/src/utils/extern_addr.rs +++ b/kernel/src/utils/extern_addr.rs @@ -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 }