Skip to content

Commit

Permalink
feat: new new percpu design for all arch
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Jun 15, 2024
1 parent b4dc936 commit fa24d8a
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 193 deletions.
14 changes: 0 additions & 14 deletions example/linker/linker-aarch64.ld
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ SECTIONS
_ebss = .;
}

. = ALIGN(4K);
_percpu_start = .;
.percpu 0x0 : AT(_percpu_start) {
_percpu_load_start = .;
*(.percpu .percpu.*)
_percpu_load_end = .;
. = ALIGN(64);
_percpu_size_aligned = .;

. = _percpu_load_start + _percpu_size_aligned * 1;
}
. = _percpu_start + SIZEOF(.percpu);
_percpu_end = .;

PROVIDE(end = .);
/DISCARD/ : {
*(.comment) *(.gnu*) *(.note*) *(.eh_frame*)
Expand Down
14 changes: 0 additions & 14 deletions example/linker/linker-loongarch64.ld
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ SECTIONS
_ebss = .;
}

. = ALIGN(4K);
_percpu_start = .;
.percpu 0x0 : AT(_percpu_start) {
_percpu_load_start = .;
*(.percpu .percpu.*)
_percpu_load_end = .;
. = ALIGN(64);
_percpu_size_aligned = .;

. = _percpu_load_start + _percpu_size_aligned * 1;
}
. = _percpu_start + SIZEOF(.percpu);
_percpu_end = .;

PROVIDE(end = .);
/DISCARD/ : {
*(.comment) *(.gnu*) *(.note*) *(.eh_frame*)
Expand Down
14 changes: 0 additions & 14 deletions example/linker/linker-x86_64.ld
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ SECTIONS
_ebss = .;
}

. = ALIGN(4K);
_percpu_start = .;
.percpu 0x0 : AT(_percpu_start) {
_percpu_load_start = .;
*(.percpu .percpu.*)
_percpu_load_end = .;
. = ALIGN(64);
_percpu_size_aligned = .;

. = _percpu_load_start + _percpu_size_aligned * 1;
}
. = _percpu_start + SIZEOF(.percpu);
_percpu_end = .;

PROVIDE(end = .);
/DISCARD/ : {
*(.comment) *(.gnu*) *(.note*) *(.eh_frame*)
Expand Down
15 changes: 6 additions & 9 deletions polyhal-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::{format_ident, quote};
use syn::{parse_macro_input, Error, ItemFn, ItemStatic};
use percpu::PERCPU_RESERVED;

#[proc_macro_attribute]
pub fn arch_entry(_input: TokenStream, annotated_item: TokenStream) -> TokenStream {
Expand Down Expand Up @@ -111,6 +112,11 @@ pub fn def_percpu(attr: TokenStream, item: TokenStream) -> TokenStream {
extern "Rust" {
fn __start_percpu();
}
#[cfg(target_arch = "x86_64")]
unsafe {
&#inner_symbol_name as *const _ as usize - __start_percpu as usize + #PERCPU_RESERVED
}
#[cfg(not(target_arch = "x86_64"))]
unsafe {
&#inner_symbol_name as *const _ as usize - __start_percpu as usize
}
Expand Down Expand Up @@ -162,15 +168,6 @@ pub fn def_percpu(attr: TokenStream, item: TokenStream) -> TokenStream {
.into()
}

#[doc(hidden)]
#[proc_macro]
pub fn percpu_symbol_offset(item: TokenStream) -> TokenStream {
let symbol = &format_ident!("{}", item.to_string());
let offset = percpu::gen_offset(symbol);
quote!({ #offset }).into()
}


fn compiler_error(err: Error) -> TokenStream {
err.to_compile_error().into()
}
78 changes: 18 additions & 60 deletions polyhal-macro/src/percpu.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,27 @@
use std::mem::size_of;

use quote::quote;
use syn::{Ident, Type};

pub fn gen_offset(symbol: &Ident) -> proc_macro2::TokenStream {
quote! {
let value: usize;
unsafe {
cfg_match! {
cfg(target_arch = "x86_64") => {
::core::arch::asm!(
"movabs {0}, offset {VAR}",
out(reg) value,
VAR = sym #symbol,
);
}
cfg(target_arch = "aarch64") => {
::core::arch::asm!(
"movz {0}, #:abs_g0_nc:{VAR}",
out(reg) value,
VAR = sym #symbol,
);
}
cfg(any(target_arch = "riscv32", target_arch = "riscv64")) => {
::core::arch::asm!(
"lui {0}, %hi({VAR})",
"addi {0}, {0}, %lo({VAR})",
out(reg) value,
VAR = sym #symbol,
);
}
cfg(target_arch = "loongarch64") => {
::core::arch::asm!(
"la.abs {0}, {VAR}",
out(reg) value,
VAR = sym #symbol,
);
}
}
}
value
}
}
/// Reserved for default usage, Just for x86_64 now.
pub const PERCPU_RESERVED: usize = 4 * size_of::<usize>();

pub fn gen_current_ptr(symbol: &Ident, ty: &Type) -> proc_macro2::TokenStream {
pub fn gen_current_ptr(_symbol: &Ident, ty: &Type) -> proc_macro2::TokenStream {
// TODO: Move this consts into polyhal crate.
quote! {
let base: usize;
// The first index is SELF_PTR in the x86_64 format
#[cfg(target_arch = "x86_64")]
{
// `__PERCPU_SELF_PTR` stores GS_BASE, which is defined in crate `percpu`.
::core::arch::asm!(
"mov {0}, gs:[offset __PERCPU_SELF_PTR]",
"add {0}, offset {VAR}",
out(reg) base,
VAR = sym #symbol,
);
base as *const #ty
}
#[cfg(not(target_arch = "x86_64"))]
{
#[cfg(target_arch = "aarch64")]
::core::arch::asm!("mrs {}, TPIDR_EL1", out(reg) base);
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
::core::arch::asm!("mv {}, gp", out(reg) base);
#[cfg(target_arch = "loongarch64")]
::core::arch::asm!("move {}, $r21", out(reg) base);
(base + self.offset()) as *const #ty
}
::core::arch::asm!(
"mov {0}, gs:0",
out(reg) base,
);
#[cfg(target_arch = "aarch64")]
::core::arch::asm!("mrs {}, TPIDR_EL1", out(reg) base);
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
::core::arch::asm!("mv {}, gp", out(reg) base);
#[cfg(target_arch = "loongarch64")]
::core::arch::asm!("move {}, $r21", out(reg) base);
(base + self.offset()) as *const #ty
}
}
6 changes: 6 additions & 0 deletions src/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,25 @@ use fdt::Fdt;
pub use kcontext::{context_switch, context_switch_pt, read_current_tp, KContext};

pub use page_table::*;
use polyhal_macro::def_percpu;
pub use psci::system_off as shutdown;
pub use trap::run_user_task;

use crate::debug::{display_info, println};
use crate::multicore::MultiCore;
use crate::once::LazyInit;
use crate::pagetable::PageTable;
use crate::percpu::percpu_area_init;
use crate::{clear_bss, CPU_NUM, DTB_BIN, MEM_AREA};

static DTB_PTR: LazyInit<usize> = LazyInit::new();

#[def_percpu]
static CPU_ID: usize = 0;

pub fn rust_tmp_main(hart_id: usize, device_tree: usize) {
clear_bss();
percpu_area_init(hart_id);
pl011::init_early();
trap::init();
gic::init();
Expand Down
4 changes: 2 additions & 2 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) macro println {
$crate::debug::print(format_args!("\n"))
},
($fmt: expr $(, $($arg: tt)+)?) => {
$crate::debug::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?))
$crate::debug::print(format_args!("{}\n", format_args!($fmt $(, $($arg)+)?)))
},
}

Expand All @@ -33,7 +33,7 @@ pub(crate) macro display_info{
$crate::debug::print(format_args!("\n"))
},
($item:literal,$fmt: expr $(, $($arg: tt)+)?) => {
$crate::debug::print(format_args!(concat!("{:<26}: ", $fmt, "\n"),$item $(, $($arg)+)?))
$crate::debug::print(format_args!("{:<26}: {}\n", $item, format_args!($fmt $(, $($arg)+)?)))
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/loongarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod timer;
mod trap;
mod unaligned;

use crate::{clear_bss, multicore::MultiCore, CPU_NUM, DTB_BIN, MEM_AREA};
use crate::{clear_bss, multicore::MultiCore, percpu::percpu_area_init, CPU_NUM, DTB_BIN, MEM_AREA};
use alloc::vec::Vec;
pub use consts::*;
pub use context::TrapFrame;
Expand All @@ -23,6 +23,7 @@ pub use trap::{disable_irq, enable_external_irq, enable_irq, run_user_task};

pub fn rust_tmp_main(hart_id: usize) {
clear_bss();
percpu_area_init(hart_id);
console::init();
trap::set_trap_vector_base();
sigtrx::init();
Expand Down
78 changes: 26 additions & 52 deletions src/percpu.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
use core::{alloc::Layout, cell::UnsafeCell, mem::size_of, ptr::copy_nonoverlapping};
/// !TIPS: x86_64 will

use core::{alloc::Layout, mem::size_of, ptr::copy_nonoverlapping};

use alloc::alloc::alloc;

use crate::{debug::println, PAGE_SIZE};
use crate::PAGE_SIZE;

static BOOT_PERCPU_DATA_AREA: [u8; PAGE_SIZE] = [0; PAGE_SIZE];

/// This is a empty seat for percpu section.
/// Force the linker to create the percpu section.
#[link_section = "percpu"]
#[used(linker)]
static _PERCPU_SEAT: [usize; 0] = [0; 0];

/// Reserved for default usage.
/// This is related to the [polyhal_macro::percpu::PERCPU_RESERVED]
/// Just for x86_64 now.
/// 0: SELF_PTR
/// 1: USER_RSP
/// 2: KERNEL_RSP
/// 3: USER_CONTEXT
#[cfg(target_arch = "x86_64")]
const PERCPU_RESERVED: usize = 4 * size_of::<usize>();
#[cfg(not(target_arch = "x86_64"))]
const PERCPU_RESERVED: usize = 0;

/// Returns the base address of the per-CPU data area on the given CPU.
///
/// if `cpu_id` is 0, it returns the base address of all per-CPU data areas.
Expand All @@ -16,12 +36,7 @@ pub fn percpu_area_init(cpu_id: usize) -> usize {
fn __stop_percpu();
}
let start = __start_percpu as usize;
let size = __stop_percpu as usize - start;
// use polyhal_macro::percpu_symbol_offset;
// let start = percpu_symbol_offset!(__start_percpu);
// let size = percpu_symbol_offset!(__stop_percpu) - percpu_symbol_offset!(__start_percpu);

println!("start: {:#x} size: {:#x}", start, size);
let size = __stop_percpu as usize - start + PERCPU_RESERVED;

// Get the base address of the per-CPU data area
// If cpu_id is boot,core then use BOOT_PERCPU_DATA_AREA.
Expand All @@ -36,7 +51,7 @@ pub fn percpu_area_init(cpu_id: usize) -> usize {

// Init the area with original data.
unsafe {
copy_nonoverlapping(start as *const u8, dst, size);
copy_nonoverlapping(start as *const u8, dst.add(PERCPU_RESERVED), size);
}

dst as usize
Expand Down Expand Up @@ -71,7 +86,8 @@ pub fn set_local_thread_pointer(cpu_id: usize) {
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
x86::msr::wrmsr(x86::msr::IA32_GS_BASE, tp as u64);
SELF_PTR.write_current_raw(tp);
// Write cpu_local pointer to the per-CPU data area
core::arch::asm!("mov gs:0, {0}", in(reg) tp);
} else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
core::arch::asm!("mv gp, {}", in(reg) tp)
} else if #[cfg(target_arch = "aarch64")] {
Expand All @@ -82,45 +98,3 @@ pub fn set_local_thread_pointer(cpu_id: usize) {
}
}
}

/// On x86, we use `gs:SELF_PTR` to store the address of the per-CPU data area base.
#[cfg(target_arch = "x86_64")]
#[no_mangle]
#[polyhal_macro::def_percpu]
static SELF_PTR: usize = 0;

// 思路: 这里存放的 usize 数据,如果是 u8, u16, u32, u64, 或者 size 小于等于 u64 的直接存取
// 否则这里仅表示指针。
pub struct PerCpu<T> {
value: UnsafeCell<T>,
}

unsafe impl<T> Sync for PerCpu<T> {}

impl<T> PerCpu<T> {
pub const fn new(value: T) -> Self {
PerCpu {
value: UnsafeCell::new(value),
}
}

pub fn get(&self) -> &T {
unsafe { &*self.value.get() }
}

pub fn write(&self, value: T) {
unsafe {
core::ptr::write_volatile(self.value.get(), value);
}
}

// pub fn offset(&self) -> usize {
// extern "Rust" {
// #[link_name = "__start_per_cpu"]
// fn SECION_START();
// }
// self.value.get() as usize - SECION_START as usize
// }
}

pub fn init_per_cpu() {}
7 changes: 7 additions & 0 deletions src/x86_64/consts.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
use core::mem::size_of;

pub const VIRT_ADDR_START: usize = 0xffff_ff80_0000_0000;

pub const SYSCALL_VECTOR: usize = 0x33445566;
/// The offset of the pic irq.
pub(super) const PIC_VECTOR_OFFSET: u8 = 0x20;

/// Reserved percpu index
pub(super) const PERCPU_USER_RSP_OFFSET: usize = 1 * size_of::<usize>();
pub(super) const PERCPU_KERNEL_RSP_OFFSET: usize = 2 * size_of::<usize>();
pub(super) const PERCPU_USER_CONTEXT_OFFSET: usize = 3 * size_of::<usize>();
Loading

0 comments on commit fa24d8a

Please sign in to comment.