Skip to content

Commit

Permalink
feat: support basic mutex based on SPIN
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Jun 16, 2024
1 parent fa24d8a commit d1a30fe
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 86 deletions.
9 changes: 0 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ fdt = "0.1.5"
bitflags = "2.0.2"
cfg-if = "1.0.0"
polyhal-macro = { path = "polyhal-macro" }
spin = { version = "0.9.8", features = ["mutex"] }

[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = "0.11.0"
Expand All @@ -29,8 +30,6 @@ sbi-rt = { version = "0.0.2", features = ["legacy"] }
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86 = "0.52"
x86_64 = "0.14"
spin = { version = "0.9.8", features = ["mutex"] }
irq_safety = { git = "https://github.com/theseus-os/irq_safety.git" }
multiboot = "0.8.0"
x2apic = "0.4"
raw-cpuid = "11.0"
Expand All @@ -39,9 +38,7 @@ raw-cpuid = "11.0"
aarch64-cpu = "9.3"
arm_pl011 = { git = "https://github.com/Byte-OS/arm_pl011.git" }
tock-registers = "0.8"
irq_safety = { git = "https://github.com/theseus-os/irq_safety.git" }
arm_gic = { git = "https://github.com/Byte-OS/arm_gic" }

[target.'cfg(target_arch = "loongarch64")'.dependencies]
spin = { version = "0.9.8", features = ["mutex"] }
loongArch64 = "0.2.2"
9 changes: 0 additions & 9 deletions example/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions polyhal-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ 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 @@ -112,11 +111,6 @@ 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
11 changes: 4 additions & 7 deletions polyhal-macro/src/percpu.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
use std::mem::size_of;

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

/// 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 {
// TODO: Move this consts into polyhal crate.
quote! {
let base: usize;
// The first index is SELF_PTR in the x86_64 format
// The first usize is SELF_PTR in the x86_64 format
// The Second usize is VALID_PTR in the x86_64 format
// The Second usize point to the start of the valid area in the x86_64 format
#[cfg(target_arch = "x86_64")]
::core::arch::asm!(
"mov {0}, gs:0",
"mov {0}, gs:1*8",
out(reg) base,
);
#[cfg(target_arch = "aarch64")]
Expand Down
6 changes: 3 additions & 3 deletions src/aarch64/gic.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use aarch64_cpu::registers::{Readable, DAIF};
use arm_gic::gic_v2::{GicCpuInterface, GicDistributor};
use arm_gic::{translate_irq, InterruptType};
use irq_safety::MutexIrqSafe;

use crate::addr::PhysAddr;
use crate::irq::{IRQVector, IRQ};
use crate::utils::MutexNoIrq;

/// The maximum number of IRQs.
#[allow(dead_code)]
Expand All @@ -20,8 +20,8 @@ pub const UART_IRQ_NUM: usize = translate_irq(1, InterruptType::SPI).unwrap();
const GICD_BASE: PhysAddr = PhysAddr::new(0x0800_0000);
const GICC_BASE: PhysAddr = PhysAddr::new(0x0801_0000);

static GICD: MutexIrqSafe<GicDistributor> =
MutexIrqSafe::new(GicDistributor::new(GICD_BASE.get_mut_ptr()));
static GICD: MutexNoIrq<GicDistributor> =
MutexNoIrq::new(GicDistributor::new(GICD_BASE.get_mut_ptr()));

// per-CPU, no lock
static GICC: GicCpuInterface = GicCpuInterface::new(GICC_BASE.get_mut_ptr());
Expand Down
15 changes: 9 additions & 6 deletions src/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ 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};
use crate::{
clear_bss,
debug::{display_info, println},
multicore::MultiCore,
pagetable::PageTable,
percpu::percpu_area_init,
utils::LazyInit,
CPU_NUM, DTB_BIN, MEM_AREA,
};

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

Expand Down
5 changes: 2 additions & 3 deletions src/aarch64/pl011.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
//! PL011 UART.

use arm_pl011::pl011::Pl011Uart;
use irq_safety::MutexIrqSafe;

use crate::{addr::PhysAddr, debug::DebugConsole};
use crate::{addr::PhysAddr, debug::DebugConsole, utils::MutexNoIrq};

const UART_BASE: PhysAddr = PhysAddr(0x0900_0000);

static UART: MutexIrqSafe<Pl011Uart> = MutexIrqSafe::new(Pl011Uart::new(UART_BASE.get_mut_ptr()));
static UART: MutexNoIrq<Pl011Uart> = MutexNoIrq::new(Pl011Uart::new(UART_BASE.get_mut_ptr()));

/// Initialize the UART
pub fn init_early() {
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![feature(cfg_version)]
#![feature(decl_macro)]
#![feature(cfg_match)]
#![feature(offset_of)]
#![feature(used_with_arg)]
#![cfg_attr(not(version("1.79")), feature(stdsimd))]
#![feature(const_mut_refs)]
Expand Down Expand Up @@ -152,10 +153,10 @@ pub mod irq;
pub mod mem;
#[cfg(feature = "multicore")]
pub mod multicore;
pub mod once;
pub mod pagetable;
pub mod percpu;
pub mod time;
pub mod utils;
use core::mem::size_of;

use addr::PhysPage;
Expand All @@ -164,8 +165,8 @@ use alloc::vec::Vec;
use consts::STACK_SIZE;
use fdt::Fdt;
use irq::IRQVector;
use once::LazyInit;
use pagetable::PageTable;
use utils::LazyInit;

#[cfg_attr(target_arch = "riscv64", path = "riscv64/mod.rs")]
#[cfg_attr(target_arch = "aarch64", path = "aarch64/mod.rs")]
Expand Down
4 changes: 3 additions & 1 deletion src/loongarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ mod timer;
mod trap;
mod unaligned;

use crate::{clear_bss, multicore::MultiCore, percpu::percpu_area_init, 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 Down
19 changes: 7 additions & 12 deletions src/percpu.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/// !TIPS: x86_64 will

/// !TIPS: x86_64 will
use core::{alloc::Layout, mem::size_of, ptr::copy_nonoverlapping};

use alloc::alloc::alloc;
Expand All @@ -14,15 +13,8 @@ static BOOT_PERCPU_DATA_AREA: [u8; PAGE_SIZE] = [0; PAGE_SIZE];
#[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>();
const PERCPU_RESERVED: usize = size_of::<crate::currrent_arch::PerCPUReserved>();
#[cfg(not(target_arch = "x86_64"))]
const PERCPU_RESERVED: usize = 0;

Expand Down Expand Up @@ -86,8 +78,11 @@ 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);
// Write cpu_local pointer to the per-CPU data area
core::arch::asm!("mov gs:0, {0}", in(reg) tp);
// Write cpu_local pointer to the first usize of the per-CPU data area
// Write the valid address to the second usize of the per-CPU data area
let percpu_reserved = crate::currrent_arch::PerCPUReserved::mut_from_ptr(tp as _);
percpu_reserved.self_ptr = tp;
percpu_reserved.valid_ptr = tp + PERCPU_RESERVED;
} 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 Down
2 changes: 1 addition & 1 deletion src/riscv64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::{
api::frame_alloc,
debug::{display_info, println},
multicore::MultiCore,
once::LazyInit,
utils::LazyInit,
CPU_NUM, DTB_BIN, MEM_AREA,
};

Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod lazy_init;
mod mutex_no_irq;

pub use lazy_init::LazyInit;
pub use mutex_no_irq::{MutexNoIrq, MutexNoIrqGuard};
95 changes: 95 additions & 0 deletions src/utils/mutex_no_irq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use core::ops::{Deref, DerefMut};
use spin::{Mutex, MutexGuard};

use crate::irq::IRQ;

pub struct MutexNoIrq<T: ?Sized> {
lock: Mutex<T>,
}

/// Irq Status Struct.
/// This structure contains the status of the current IRQ
/// And it will restore irq status after dropping.
struct IrqStatus {
irq_enabled: bool,
}

/// Restore the IRQ status when dropping
impl Drop for IrqStatus {
fn drop(&mut self) {
if self.irq_enabled {
IRQ::int_enable();
}
}
}

unsafe impl<T: ?Sized + Send> Sync for MutexNoIrq<T> {}
unsafe impl<T: ?Sized + Send> Send for MutexNoIrq<T> {}

impl<T> MutexNoIrq<T> {
pub const fn new(data: T) -> MutexNoIrq<T> {
MutexNoIrq {
lock: Mutex::new(data),
}
}

#[inline(always)]
pub fn into_inner(self) -> T {
self.lock.into_inner()
}
}

impl<T: ?Sized> MutexNoIrq<T> {
#[inline]
pub fn lock(&self) -> MutexNoIrqGuard<T> {
loop {
match self.try_lock() {
Some(guard) => return guard,
_ => {}
}
}
}

#[inline]
pub fn is_locked(&self) -> bool {
self.lock.is_locked()
}

pub unsafe fn force_unlock(&self) {
self.lock.force_unlock()
}

#[inline]
pub fn try_lock(&self) -> Option<MutexNoIrqGuard<T>> {
if self.lock.is_locked() {
return None;
}
let _irq_status = IrqStatus {
irq_enabled: IRQ::int_enabled(),
};
IRQ::int_disable();
self.lock
.try_lock()
.map(|guard| MutexNoIrqGuard { guard, _irq_status })
}
}

/// The Mutex Guard.
pub struct MutexNoIrqGuard<'a, T: ?Sized + 'a> {
guard: MutexGuard<'a, T>,
_irq_status: IrqStatus,
}

impl<'a, T: ?Sized> Deref for MutexNoIrqGuard<'a, T> {
type Target = T;

fn deref<'b>(&'b self) -> &'b T {
&*(self.guard)
}
}

impl<'a, T: ?Sized> DerefMut for MutexNoIrqGuard<'a, T> {
fn deref_mut<'b>(&'b mut self) -> &'b mut T {
&mut *(self.guard)
}
}
Loading

0 comments on commit d1a30fe

Please sign in to comment.