From 2b61ad947c64d76875311e6af08c87a5592055b3 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Fri, 26 Aug 2022 19:49:13 -0700 Subject: SpinLocks --- src/_arch/arm/cpu/boot.rs | 51 ++++++++ src/_arch/arm/cpu/boot.s | 136 +++++++++++++------- src/bsp/raspberrypi/linker.ld | 7 +- src/kernel.rs | 8 +- src/mem/alloc.rs | 289 ------------------------------------------ src/mem/types.rs | 54 -------- src/util/mem/alloc.rs | 3 + 7 files changed, 157 insertions(+), 391 deletions(-) delete mode 100644 src/mem/alloc.rs delete mode 100644 src/mem/types.rs (limited to 'src') diff --git a/src/_arch/arm/cpu/boot.rs b/src/_arch/arm/cpu/boot.rs index b81a16a..1b4ed74 100644 --- a/src/_arch/arm/cpu/boot.rs +++ b/src/_arch/arm/cpu/boot.rs @@ -18,3 +18,54 @@ global_asm!(include_str!("boot.s")); pub unsafe fn _start_rust() -> ! { crate::kernel_init() } + +/// # Rust entry for other cores of the `kernel` binary. +/// +/// This function is unmangled so that the +/// ASM boot code can switch to Rust safely. +#[no_mangle] +pub extern "C" fn _start_other_core(_core: u32) -> ! { + loop { + use crate::INITIALIZED_BOOL; + use core::sync::atomic::Ordering; + if let Ok(true) = + INITIALIZED_BOOL.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) + { + crate::serial_println!("Ran core {}!", _core); + let u = crate::Box::::new(42); + crate::serial_println!("{}", u); + INITIALIZED_BOOL.store(true, Ordering::Release); + break; + } + } + #[allow(unreachable_code)] + loop {} +} + +/// # Prefetch +#[no_mangle] +pub extern "C" fn prefetch() -> ! { + crate::serial_println!("Prefetch handler"); + loop {} +} + +/// # Data +#[no_mangle] +pub extern "C" fn data() -> ! { + crate::serial_println!("Data handler"); + loop {} +} + +/// # IRQ +#[no_mangle] +pub extern "C" fn irq() -> ! { + crate::serial_println!("IRQ handler"); + loop {} +} + +/// # FIQ +#[no_mangle] +pub extern "C" fn fiq() -> ! { + crate::serial_println!("FIQ handler"); + loop {} +} diff --git a/src/_arch/arm/cpu/boot.s b/src/_arch/arm/cpu/boot.s index fd2a652..0151386 100644 --- a/src/_arch/arm/cpu/boot.s +++ b/src/_arch/arm/cpu/boot.s @@ -1,84 +1,130 @@ .equ _core_id_mask, 0b11 .section .text.boot +.macro init_core coreid + // set vector address. + ldr r0, =vector + mcr p15, 0, r0, c12, c0, 0 + cps #0x12 // Setup sp in IRQ mode. + ldr sp, =irq_stack_core\coreid + cps #0x11 // Setup sp in FIQ mode. + ldr sp, =fiq_stack_core\coreid + cps #0x1B // Setup sp in UNDEF mode. + ldr sp, =undefined_stack_core\coreid + cps #0x17 // Setup sp in ABORT mode. + ldr sp, =data_stack_core\coreid + cps #0x1f // Setup sp in USR/SYS mode. + ldr sp, =sys_stack_core\coreid + cps #0x13 // Setup sp in SVC mode. + ldr sp, =svc_stack_core\coreid +.endm + +.macro core_stacks coreid + .space 4096 +undefined_stack_core\coreid: + .space 4096 +svc_stack_core\coreid: + .space 4096 +data_stack_core\coreid: + .space 4096 +irq_stack_core\coreid: + .space 4096 +fiq_stack_core\coreid: + .space 4096 +sys_stack_core\coreid: +.endm + .global _start _start: reset: cpsid aif + + // Exit Hypervisor Mode + mrs r0, cpsr + and r1, r0, #0x1F + cmp r1, #0x1A + bne 1f + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr spsr_cxsf, r0 + add r0, pc, #4 + msr ELR_hyp, r0 + eret + +1: + // disable core0,1,2. mrc p15, #0, r1, c0, c0, #5 - and r1, r1, #_core_id_mask + and r1, r1, #3 cmp r1, #1 - beq core1run + beq runcore1 cmp r1, #2 - beq core2run + beq runcore2 cmp r1, #3 - beq core3run + bge runcore3 - ldr r0, =vector - mcr p15, 0, r0, c12, c0, 0 - cps #0x12 - ldr sp, =core0_irq_stack - cps #0x11 - ldr sp, =core0_fiq_stack - cps #0x1B - ldr sp, =core0_undefined_stack - cps #0x17 - ldr sp, =core0_data_stack - cps #0x1f - ldr sp, =core0_sys_stack - cps #0x13 - ldr sp, =core0_svc_stack + init_core 0 + // Clear out bss. ldr r4, =__bss_start ldr r9, =__bss_end mov r5, #0 mov r6, #0 mov r7, #0 mov r8, #0 - b 2f -1: + b 2f + +1: // store multiple at r4. stmia r4!, {{r5-r8}} -2: + +2: // If we are still below bss_end, loop. cmp r4, r9 blo 1b ldr r3, =_start_rust blx r3 -core1run: -core2run: -core3run: -.global io_halt +runcore1: + init_core 1 + mov r0, #1 + b _start_other_core +runcore2: + init_core 2 + mov r0, #2 + b _start_other_core +runcore3: + init_core 3 + mov r0, #3 + b _start_other_core undefined: +.global io_halt io_halt: wfi b io_halt + .align 5 vector: ldr pc, reset_handler ldr pc, undefined_handler - ldr pc, undefined_handler - ldr pc, undefined_handler - ldr pc, undefined_handler - ldr pc, undefined_handler - ldr pc, undefined_handler - ldr pc, undefined_handler + ldr pc, svc_handler + ldr pc, prefetch_handler + ldr pc, data_handler + ldr pc, unused_handler + ldr pc, irq_handler + ldr pc, fiq_handler -reset_handler: .word reset -undefined_handler: .word undefined +reset_handler: .word reset +undefined_handler: .word undefined +svc_handler: .word svc +prefetch_handler: .word prefetch +data_handler: .word data +unused_handler: .word io_halt +irq_handler: .word irq +fiq_handler: .word fiq .section .bss.sysstacks .align 4 - .space 4096 -core0_undefined_stack: - .space 4096 -core0_svc_stack: - .space 4096 -core0_data_stack: - .space 4096 -core0_irq_stack: - .space 4096 -core0_fiq_stack: - .space 4096 -core0_sys_stack: +core_stacks 0 +core_stacks 1 +core_stacks 2 +core_stacks 3 diff --git a/src/bsp/raspberrypi/linker.ld b/src/bsp/raspberrypi/linker.ld index 2541a88..515245d 100644 --- a/src/bsp/raspberrypi/linker.ld +++ b/src/bsp/raspberrypi/linker.ld @@ -18,12 +18,15 @@ SECTIONS __data_start = .; .data : { - *(.data*) + KEEP(*(.data)) + . = 0x300000; + __alloc_start = .; KEEP(*(.data.alloc)) + . = 0x400000; __stacks_start = .; KEEP(*(.data.stacks)) } - . = ALIGN(4096); + . = 0x500000; __data_end = .; __bss_start = .; diff --git a/src/kernel.rs b/src/kernel.rs index 8c7ab58..4017b5a 100644 --- a/src/kernel.rs +++ b/src/kernel.rs @@ -26,6 +26,8 @@ mod util; use crate::lib::console::console; use crate::util::mem::alloc::allocator; use crate::util::mem::{format, Box, String}; +use core::sync::atomic::AtomicBool; +use core::sync::atomic::Ordering; /// # Initialization Code /// @@ -48,6 +50,7 @@ unsafe fn kernel_init() -> ! { util::mem::mmu_init(); console().init().unwrap(); allocator().init().unwrap(); + INITIALIZED_BOOL.store(true, Ordering::Release); kernel_main() } @@ -133,10 +136,13 @@ fn run_verbose() { #[no_mangle] /// # SVC Handler -pub fn svc_handler(code: u32) { +pub fn svc(code: u32) { match code { _ => { serial_println!("Unhandled Service Call!"); } } } + +/// # Static for other cores +pub static INITIALIZED_BOOL: AtomicBool = AtomicBool::new(false); diff --git a/src/mem/alloc.rs b/src/mem/alloc.rs deleted file mode 100644 index 514f34f..0000000 --- a/src/mem/alloc.rs +++ /dev/null @@ -1,289 +0,0 @@ -//! # Allocate crate -//! -//! Provides the Global allocator and methods -//! to create special purpose allocators. -use super::types::*; -use crate::sync::interface::Mutex; -use crate::sync::NullLock; -use crate::serial_vprintln; -use alloc::alloc::{GlobalAlloc, Layout}; -use os_pic::init_lifo_queue; -use os_pic::util::lifo_queue::LifoQueue; -use os_pic::util::node::Node; -use os_pic::util::queue::Queue; - -/// # Grand Allocator -/// -/// The structure that uses different sized pools and allocates memory chunks -pub struct GrandAllocator {} - -/// # The number of elements of each size -const GRAND_ALLOC_SIZE: usize = 64; - -init_lifo_queue!(U8_GRAND_ALLOC, GRAND_ALLOC_SIZE, 0, u8); -init_lifo_queue!(U16_GRAND_ALLOC, GRAND_ALLOC_SIZE, 0, u16); -init_lifo_queue!(U32_GRAND_ALLOC, GRAND_ALLOC_SIZE, 0, u32); -init_lifo_queue!(U64_GRAND_ALLOC, GRAND_ALLOC_SIZE, 0, u64); -init_lifo_queue!(U128_GRAND_ALLOC, GRAND_ALLOC_SIZE, 0, u128); -init_lifo_queue!(U256_GRAND_ALLOC, GRAND_ALLOC_SIZE, { U256::new() }, U256); -init_lifo_queue!(U512_GRAND_ALLOC, GRAND_ALLOC_SIZE, { U512::new() }, U512); -init_lifo_queue!(U1024_GRAND_ALLOC, GRAND_ALLOC_SIZE, { U1024::new() }, U1024); -init_lifo_queue!(U2048_GRAND_ALLOC, GRAND_ALLOC_SIZE, { U2048::new() }, U2048); -init_lifo_queue!(U4096_GRAND_ALLOC, GRAND_ALLOC_SIZE, { U4096::new() }, U4096); - -impl GrandAllocator { - pub fn init(&self) -> Result<(), &'static str> { - serial_vprintln!("GA: \x1b[93mInit U8 Pool\x1b[0m"); - U8_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U16 Pool\x1b[0m"); - U16_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U32 Pool\x1b[0m"); - U32_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U64 Pool\x1b[0m"); - U64_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U128 Pool\x1b[0m"); - U128_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U256 Pool\x1b[0m"); - U256_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U512 Pool\x1b[0m"); - U512_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U1024 Pool\x1b[0m"); - U1024_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U2048 Pool\x1b[0m"); - U2048_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[93mInit U4096 Pool\x1b[0m"); - U4096_GRAND_ALLOC.init(); - serial_vprintln!("GA: \x1b[94mPools Initialized!\x1b[0m"); - Ok(()) - } -} - -unsafe impl GlobalAlloc for GrandAllocator { - /// # Allocator - /// - /// Allocate the fixed size chunks - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - serial_vprintln!("GA: Allocating chunk of size {}!", layout.size()); - match layout.size() { - 1 => match U8_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 2 => match U16_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 3..=4 => match U32_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 5..=8 => match U64_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 9..=16 => match U128_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 17..=32 => match U256_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 33..=64 => match U512_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 65..=128 => match U1024_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 129..=256 => match U2048_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - 257..=512 => match U4096_GRAND_ALLOC.pop() { - None => { - panic!("No cells to allocate!"); - } - Some(elem) => { - return (*elem).ptr(); - } - }, - _ => { - panic!("No allocators for size {}!", layout.size()); - } - } - } - - /// # Deallocate - /// - /// Deallocate the fixed size chunks by searching for them - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - serial_vprintln!("GA: Deallocating chunk of size {}!", layout.size()); - match layout.size() { - 1 => { - U8_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U8_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 2 => { - U16_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U16_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 3..=4 => { - U32_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U32_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 5..=8 => { - U64_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U64_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 9..=16 => { - U128_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U128_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 17..=32 => { - U256_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U256_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 33..=64 => { - U512_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U512_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 65..=128 => { - U1024_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U1024_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 129..=256 => { - U2048_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U2048_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - 257..=512 => { - U4096_GRAND_ALLOC.inner.lock(|pool| { - let spacing: usize = (pool[2].ptr() as usize) - (pool[1].ptr() as usize); - let diff: usize = (ptr as usize) - (pool[1].ptr() as usize); - let index: usize = diff/spacing; - assert!(index < GRAND_ALLOC_SIZE, "{} is out of the allocation bounds ({})", index, GRAND_ALLOC_SIZE); - assert_eq!(diff % spacing, 0, "{} is not aligned with the spacings and so it must not have been allocated by the Grand Allocator", diff % spacing); - U4096_GRAND_ALLOC.push(&mut pool[index+1]); - serial_vprintln!("GA: Freeing ({}, {}, {})", index, diff, spacing); - }); - } - _ => { - panic!("No deallocators for size {}!", layout.size()); - } - } - } -} - -/// # Grand Allocator -/// -/// The allocator of allocators. It hands out fixed sized memory chunks. -#[global_allocator] -pub static ALLOCATOR: GrandAllocator = GrandAllocator {}; - -/// # Global Allocator -/// -/// Returns a borrow for the Global Allocator -pub fn allocator() -> &'static crate::mem::alloc::GrandAllocator { - serial_vprintln!("AL: Getting global allocator!"); - &crate::mem::alloc::ALLOCATOR -} diff --git a/src/mem/types.rs b/src/mem/types.rs deleted file mode 100644 index ed22132..0000000 --- a/src/mem/types.rs +++ /dev/null @@ -1,54 +0,0 @@ -/// # u256 struct -/// -/// 256 bit size field -#[derive(Copy, Clone)] -pub struct U256(u128, u128); -impl U256 { - pub const fn new() -> Self { - U256(0, 0) - } -} - -/// # u512 struct -/// -/// 512 bit size field -#[derive(Copy, Clone)] -pub struct U512(U256, U256); -impl U512 { - pub const fn new() -> Self { - U512(U256::new(), U256::new()) - } -} - -/// # u1024 struct -/// -/// 1024 bit size field -#[derive(Copy, Clone)] -pub struct U1024(U512, U512); -impl U1024 { - pub const fn new() -> Self { - U1024(U512::new(), U512::new()) - } -} - -/// # u2048 struct -/// -/// 2048 bit size field -#[derive(Copy, Clone)] -pub struct U2048(U1024, U1024); -impl U2048 { - pub const fn new() -> Self { - U2048(U1024::new(), U1024::new()) - } -} - -/// # u4096 struct -/// -/// 4096 bit size field -#[derive(Copy, Clone)] -pub struct U4096(U2048, U2048); -impl U4096 { - pub const fn new() -> Self { - U4096(U2048::new(), U2048::new()) - } -} diff --git a/src/util/mem/alloc.rs b/src/util/mem/alloc.rs index dfe8c60..ac67a72 100644 --- a/src/util/mem/alloc.rs +++ b/src/util/mem/alloc.rs @@ -8,7 +8,10 @@ use crate::lib::lifo_queue::LifoQueue; use crate::lib::node::Node; use crate::lib::queue::Queue; use crate::lib::sync::interface::Mutex; +#[allow(unused_imports)] use crate::lib::sync::NullLock; +#[allow(unused_imports)] +use crate::lib::sync::SpinLock; use crate::serial_vprintln; use crate::util::mem::{GlobalAlloc, Layout}; -- cgit v1.2.1