diff --git a/etc/ld/riscv/riscv64-unknown-jh7110.ld b/etc/ld/riscv/riscv64-unknown-jh7110.ld deleted file mode 100644 index 771efc0d..00000000 --- a/etc/ld/riscv/riscv64-unknown-jh7110.ld +++ /dev/null @@ -1,58 +0,0 @@ -ENTRY(__rv64_entry); - -KERNEL_PHYS_BASE = 0x40200000; -KERNEL_VIRT_OFFSET = 0xFFFFFFF000000000; - -SECTIONS { - . = KERNEL_PHYS_BASE; - PROVIDE(__kernel_start = . + KERNEL_VIRT_OFFSET); - - .text.entry : { - *(.text.entry) - } - - . = ALIGN(16); - . = . + KERNEL_VIRT_OFFSET; - - .text : AT(. - KERNEL_VIRT_OFFSET) { - KEEP(*(.text.vectors)); - *(.text*) - } - - . = ALIGN(4K); - .rodata : AT(. - KERNEL_VIRT_OFFSET) { - *(.rodata*) - *(.eh_frame*) - } - - . = ALIGN(4K); - .data.tables : AT (. - KERNEL_VIRT_OFFSET) { - KEEP(*(.data.tables)) - } - - . = ALIGN(4K); - .data : AT(. - KERNEL_VIRT_OFFSET) { - *(.data*) - . = ALIGN(8); - /* PROVIDE(__global_pointer = . + 0x800 - KERNEL_VIRT_OFFSET); */ - - . = ALIGN(16); - PROVIDE(__init_array_start = .); - KEEP(*(.init_array*)) - PROVIDE(__init_array_end = .); - - *(.got*) - } - - . = ALIGN(4K); - PROVIDE(__bss_start_phys = . - KERNEL_VIRT_OFFSET); - .bss : AT(. - KERNEL_VIRT_OFFSET) { - *(COMMON) - *(.bss*) - } - . = ALIGN(4K); - PROVIDE(__bss_end_phys = . - KERNEL_VIRT_OFFSET); - PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys); - - PROVIDE(__kernel_end = .); -}; diff --git a/etc/ld/riscv/riscv64-unknown-qemu.ld b/etc/ld/riscv/riscv64-unknown-qemu.ld deleted file mode 100644 index 8a9547b2..00000000 --- a/etc/ld/riscv/riscv64-unknown-qemu.ld +++ /dev/null @@ -1,59 +0,0 @@ -ENTRY(__rv64_entry); - -KERNEL_PHYS_BASE = 0x80200000; -KERNEL_VIRT_OFFSET = 0xFFFFFFF000000000; - -SECTIONS { - . = KERNEL_PHYS_BASE; - PROVIDE(__kernel_start = . + KERNEL_VIRT_OFFSET); - - .text.entry : { - *(.text.entry) - } - - . = ALIGN(16); - . = . + KERNEL_VIRT_OFFSET; - - .text : AT(. - KERNEL_VIRT_OFFSET) { - KEEP(*(.text.vectors)); - *(.text*) - } - - . = ALIGN(4K); - .rodata : AT(. - KERNEL_VIRT_OFFSET) { - *(.rodata*) - *(.eh_frame*) - } - - . = ALIGN(4K); - .data.tables : AT (. - KERNEL_VIRT_OFFSET) { - KEEP(*(.data.tables)) - } - - . = ALIGN(4K); - .data : AT(. - KERNEL_VIRT_OFFSET) { - *(.data*) - . = ALIGN(8); - /* PROVIDE(__global_pointer = . + 0x800 - KERNEL_VIRT_OFFSET); */ - - . = ALIGN(16); - PROVIDE(__init_array_start = .); - KEEP(*(.init_array*)) - PROVIDE(__init_array_end = .); - - *(.got*) - } - - . = ALIGN(4K); - PROVIDE(__bss_start_phys = . - KERNEL_VIRT_OFFSET); - .bss : AT(. - KERNEL_VIRT_OFFSET) { - *(COMMON) - *(.bss*) - } - . = ALIGN(4K); - PROVIDE(__bss_end_phys = . - KERNEL_VIRT_OFFSET); - PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys); - - PROVIDE(__kernel_end = .); - PROVIDE(__kernel_size = __kernel_end - __kernel_start); -}; diff --git a/etc/ld/riscv64-unknown-none.ld b/etc/ld/riscv64-unknown-none.ld new file mode 100644 index 00000000..4751d1f7 --- /dev/null +++ b/etc/ld/riscv64-unknown-none.ld @@ -0,0 +1,75 @@ +ENTRY(__riscv64_entry); + +SECTIONS { + . = 0x0; + + PROVIDE(__kernel_start = .); + + .text : { + *(.text.entry) + *(.text*) + } + + . = ALIGN(4K); + + .rodata : { + *(.rodata*) + *(.eh_frame*) + + . = ALIGN(16); + PROVIDE(__init_array_start = .); + KEEP(*(.init_array*)); + PROVIDE(__init_array_end = .); + } + + . = ALIGN(4K); + + .rela : { + PROVIDE(__rela_start = .); + *(.rela*) + PROVIDE(__rela_end = .); + } + + .got : { + *(.got*) + } + + .dynamic : { + *(.dynamic) + } + + . = ALIGN(4K); + + .data : { + *(.data*) + } + + . = ALIGN(4K); + PROVIDE(__bss_start = .); + + .bss : { + *(COMMON) + *(.bss*) + } + + . = ALIGN(4K); + PROVIDE(__bss_end = .); + PROVIDE(__kernel_end = .); + PROVIDE(__kernel_size = __kernel_end - __kernel_start); + + .dynsym : { + *(.dynsym) + } + + .gnu.hash : { + *(.gnu.hash) + } + + .hash : { + *(.hash) + } + + .dynstr : { + *(.dynstr) + } +} diff --git a/etc/riscv64-unknown-none.json b/etc/riscv64-unknown-none.json index 5de664f2..2f475cae 100644 --- a/etc/riscv64-unknown-none.json +++ b/etc/riscv64-unknown-none.json @@ -14,6 +14,7 @@ "panic-strategy": "abort", "dynamic-linking": true, "relocation-model": "pic", + "position-independent-executables": true, "code-model": "medium", "eh-frame-header": false, diff --git a/kernel/arch/riscv64/src/context.rs b/kernel/arch/riscv64/src/context.rs index 5a5aacb8..a449c766 100644 --- a/kernel/arch/riscv64/src/context.rs +++ b/kernel/arch/riscv64/src/context.rs @@ -124,8 +124,7 @@ impl> 12)); Ok(Self { diff --git a/kernel/arch/riscv64/src/mem/fixed.rs b/kernel/arch/riscv64/src/mem/fixed.rs new file mode 100644 index 00000000..a1cf112d --- /dev/null +++ b/kernel/arch/riscv64/src/mem/fixed.rs @@ -0,0 +1,32 @@ +use kernel_arch_interface::sync::IrqSafeSpinlock; +use libk_mm_interface::{address::PhysicalAddress, table::EntryLevel}; + +use crate::{ + mem::{ + auto_lower_address, + table::{PageEntry, PageTable, L1}, + KERNEL_VIRT_OFFSET, + }, + ArchitectureImpl, +}; + +pub const IDENTITY_SIZE_L1: usize = 64; + +pub(super) static mut KERNEL_L1: PageTable = const { + let mut table = PageTable::zeroed(); + + let mut index = 0; + while index < IDENTITY_SIZE_L1 { + let entry = PageEntry::identity_block(PhysicalAddress::from_usize(index << L1::SHIFT)); + table.entries[index] = entry; + table.entries[index + ((KERNEL_VIRT_OFFSET >> L1::SHIFT) & 0x1FF)] = entry; + index += 1; + } + + table +}; +pub(super) static LOCK: IrqSafeSpinlock = IrqSafeSpinlock::new(()); + +pub fn table_physical_address() -> PhysicalAddress { + PhysicalAddress::from_usize(auto_lower_address(&raw const KERNEL_L1)) +} diff --git a/kernel/arch/riscv64/src/mem/intrinsics.rs b/kernel/arch/riscv64/src/mem/intrinsics.rs new file mode 100644 index 00000000..210a1e37 --- /dev/null +++ b/kernel/arch/riscv64/src/mem/intrinsics.rs @@ -0,0 +1,51 @@ +use libk_mm_interface::table::{EntryLevel, EntryLevelExt}; + +use crate::mem::table::L3; + +pub fn tlb_flush_global_full() { + tlb_flush_full(); + // TODO send TLB shootdown IPI to other harts +} + +pub fn tlb_flush_global_va(va: usize) { + tlb_flush_va(va); + // TODO send TLB shootdown IPI to other harts +} + +pub fn tlb_flush_range_va(start: usize, size: usize) { + let end = (start + size).page_align_up::(); + let start = start.page_align_down::(); + + for page in (start..end).step_by(L3::SIZE) { + tlb_flush_va(page); + } +} + +pub fn tlb_flush_range_va_asid(asid: usize, start: usize, size: usize) { + let end = (start + size).page_align_up::(); + let start = start.page_align_down::(); + + for page in (start..end).step_by(L3::SIZE) { + tlb_flush_va_asid(page, asid); + } +} + +#[inline] +pub fn tlb_flush_full() { + unsafe { core::arch::asm!("sfence.vma") }; +} + +#[inline] +pub fn tlb_flush_va(va: usize) { + unsafe { core::arch::asm!("sfence.vma {0}, zero", in(reg) va) }; +} + +#[inline] +pub fn tlb_flush_asid(asid: usize) { + unsafe { core::arch::asm!("sfence.vma zero, {0}", in(reg) asid) }; +} + +#[inline] +pub fn tlb_flush_va_asid(va: usize, asid: usize) { + unsafe { core::arch::asm!("sfence.vma {0}, {1}", in(reg) va, in(reg) asid) }; +} diff --git a/kernel/arch/riscv64/src/mem/mod.rs b/kernel/arch/riscv64/src/mem/mod.rs index 34e1ac6f..9d457e47 100644 --- a/kernel/arch/riscv64/src/mem/mod.rs +++ b/kernel/arch/riscv64/src/mem/mod.rs @@ -1,70 +1,26 @@ -use cfg_if::cfg_if; -use kernel_arch_interface::{ - mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, - split_spinlock, +use kernel_arch_interface::mem::{ + DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping, }; use libk_mm_interface::{ address::PhysicalAddress, table::{page_index, EntryLevel, EntryLevelExt}, }; -use memtables::riscv64::PageAttributes; -use static_assertions::{const_assert, const_assert_eq}; -use table::{PageEntry, PageTable, L1, L2, L3}; use tock_registers::interfaces::Writeable; use yggdrasil_abi::error::Error; -pub use memtables::riscv64::FixedTables; +use crate::{ + mem::table::{PageTable, L1, L3}, + registers::SATP, +}; -use crate::registers::SATP; +pub use intrinsics::*; +pub mod fixed; +pub mod intrinsics; pub mod process; pub mod table; -split_spinlock! { - use crate::ArchitectureImpl; - use crate::mem::FixedTables; - use libk_mm_interface::KernelImageObject; - - #[link_section = ".data.tables"] - #[used] - static KERNEL_TABLES: KernelImageObject = - unsafe { KernelImageObject::new(FixedTables::zeroed()) }; -} - -cfg_if! { - if #[cfg(feature = "riscv64_board_virt")] { - pub const KERNEL_PHYS_BASE: usize = 0x80200000; - } else if #[cfg(feature = "riscv64_board_jh7110")] { - pub const KERNEL_PHYS_BASE: usize = 0x40200000; - } else if #[cfg(rust_analyzer)] { - pub const KERNEL_PHYS_BASE: usize = 0x80200000; - } -} - pub const KERNEL_VIRT_OFFSET: usize = kernel_arch_interface::KERNEL_VIRT_OFFSET; -pub const SIGN_EXTEND_MASK: usize = 0xFFFFFF80_00000000; - -pub const KERNEL_START_L1I: usize = page_index::(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); -pub const KERNEL_L2I: usize = page_index::(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); -const_assert_eq!(KERNEL_L2I, 1); - -// Runtime mappings -// 1GiB of device memory space -const DEVICE_MAPPING_L1I: usize = KERNEL_START_L1I + 1; -const DEVICE_MAPPING_L3_COUNT: usize = 4; -// 32GiB of RAM space -const RAM_MAPPING_START_L1I: usize = KERNEL_START_L1I + 2; -const RAM_MAPPING_L1_COUNT: usize = 32; -const_assert!(RAM_MAPPING_START_L1I + RAM_MAPPING_L1_COUNT <= 512); -const_assert!(DEVICE_MAPPING_L1I < 512); - -const DEVICE_MAPPING_OFFSET: usize = (DEVICE_MAPPING_L1I << L1::SHIFT) | SIGN_EXTEND_MASK; -const RAM_MAPPING_OFFSET: usize = (RAM_MAPPING_START_L1I << L1::SHIFT) | SIGN_EXTEND_MASK; - -// Runtime tables -static mut DEVICE_MAPPING_L2: PageTable = PageTable::zeroed(); -static mut DEVICE_MAPPING_L3S: [PageTable; DEVICE_MAPPING_L3_COUNT] = - [const { PageTable::zeroed() }; DEVICE_MAPPING_L3_COUNT]; /// Any VAs above this one are sign-extended pub const USER_BOUNDARY: usize = 0x40_00000000; @@ -75,17 +31,20 @@ pub struct KernelTableManagerImpl; impl KernelTableManager for KernelTableManagerImpl { fn virtualize(address: u64) -> usize { let address = address as usize; - if address >= RAM_MAPPING_OFFSET { - panic!("Invalid physical address: {address:#x}"); + if address < fixed::IDENTITY_SIZE_L1 * L1::SIZE { + address + KERNEL_VIRT_OFFSET + } else { + panic!("Invalid physical address: {address:#x}") } - address + RAM_MAPPING_OFFSET } fn physicalize(address: usize) -> u64 { - if address < RAM_MAPPING_OFFSET { - panic!("Invalid \"physicalized\" virtual address {address:#x}"); + if address < KERNEL_VIRT_OFFSET + || address - KERNEL_VIRT_OFFSET >= fixed::IDENTITY_SIZE_L1 * L1::SIZE + { + panic!("Invalid virtualized address: {address:#x}"); } - (address - RAM_MAPPING_OFFSET) as u64 + (address - KERNEL_VIRT_OFFSET) as u64 } unsafe fn map_device_pages( @@ -93,146 +52,32 @@ impl KernelTableManager for KernelTableManagerImpl { count: usize, attrs: DeviceMemoryAttributes, ) -> Result, Error> { - unsafe { map_device_memory(PhysicalAddress::from_u64(base), count, attrs) } + let _ = attrs; + let _lock = fixed::LOCK.lock(); + let base = PhysicalAddress::from_u64(base); + let l3_aligned_base = base.page_align_down::(); + let l3_aligned_end = base.add(count).page_align_up::(); + let l3_offset = base - l3_aligned_base; + let l3_page_count = (l3_aligned_end - l3_aligned_base).page_count::(); + let l3_aligned_virt = l3_aligned_base.add(KERNEL_VIRT_OFFSET).into_usize(); + + Ok(unsafe { + RawDeviceMemoryMapping::from_raw_parts( + l3_aligned_base.into_u64(), + l3_aligned_virt + l3_offset, + l3_aligned_virt, + l3_page_count, + L3::SIZE, + ) + }) } unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping) { - unsafe { unmap_device_memory(mapping) } + let _ = mapping; } } -// Device mappings -unsafe fn map_device_memory_l3( - base: PhysicalAddress, - count: usize, - _attrs: DeviceMemoryAttributes, -) -> Result { - // TODO don't map pages if already mapped - - 'l0: for i in 0..DEVICE_MAPPING_L3_COUNT * 512 { - for j in 0..count { - let l2i = (i + j) / 512; - let l3i = (i + j) % 512; - - unsafe { - if DEVICE_MAPPING_L3S[l2i][l3i].is_present() { - continue 'l0; - } - } - } - - for j in 0..count { - let l2i = (i + j) / 512; - let l3i = (i + j) % 512; - - unsafe { - DEVICE_MAPPING_L3S[l2i][l3i] = - PageEntry::page(base.add(j * L3::SIZE), PageAttributes::W); - } - } - - let start = DEVICE_MAPPING_OFFSET + i * L3::SIZE; - tlb_flush_range_va(start, count * L3::SIZE); - return Ok(start); - } - - Err(Error::OutOfMemory) -} - -#[allow(unused)] -unsafe fn map_device_memory_l2( - base: PhysicalAddress, - count: usize, - _attrs: DeviceMemoryAttributes, -) -> Result { - 'l0: for i in DEVICE_MAPPING_L3_COUNT..512 { - for j in 0..count { - unsafe { - if DEVICE_MAPPING_L2[i + j].is_present() { - continue 'l0; - } - } - } - - unsafe { - for j in 0..count { - DEVICE_MAPPING_L2[i + j] = - PageEntry::::block(base.add(j * L2::SIZE), PageAttributes::W); - } - } - - let start = DEVICE_MAPPING_OFFSET + i * L2::SIZE; - tlb_flush_range_va(start, count * L2::SIZE); - return Ok(start); - } - - Err(Error::OutOfMemory) -} - -pub(crate) unsafe fn map_device_memory( - base: PhysicalAddress, - size: usize, - attrs: DeviceMemoryAttributes, -) -> Result, Error> { - let l3_aligned = base.page_align_down::(); - let l3_offset = base.page_offset::(); - let page_count = (l3_offset + size).page_count::(); - - if page_count > 256 { - // Large mapping, use L2 mapping instead - let l2_aligned = base.page_align_down::(); - let l2_offset = base.page_offset::(); - let page_count = (l2_offset + size).page_count::(); - - unsafe { - let base_address = map_device_memory_l2(l2_aligned, page_count, attrs)?; - let address = base_address + l2_offset; - - Ok(RawDeviceMemoryMapping::from_raw_parts( - l2_aligned.into_u64(), - address, - base_address, - page_count, - L2::SIZE, - )) - } - } else { - // Just map the pages directly - unsafe { - let base_address = map_device_memory_l3(l3_aligned, page_count, attrs)?; - let address = base_address + l3_offset; - - Ok(RawDeviceMemoryMapping::from_raw_parts( - l3_aligned.into_u64(), - address, - base_address, - page_count, - L3::SIZE, - )) - } - } -} - -pub(crate) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping) { - match map.page_size { - L3::SIZE => { - for i in 0..map.page_count { - let page = map.base_address + i * L3::SIZE; - let l2i = page.page_index::(); - let l3i = page.page_index::(); - unsafe { - assert!(DEVICE_MAPPING_L3S[l2i][l3i].is_present()); - DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::INVALID; - } - } - tlb_flush_range_va(map.base_address, map.page_count * L3::SIZE); - } - L2::SIZE => todo!(), - _ => unimplemented!(), - } -} - -pub fn auto_address(x: *const T) -> usize { +pub fn auto_lower_address(x: *const T) -> usize { let x = x.addr(); if x >= KERNEL_VIRT_OFFSET { x - KERNEL_VIRT_OFFSET @@ -247,113 +92,14 @@ pub fn auto_address(x: *const T) -> usize { /// /// Only meant to be called once per each HART during their early init. pub unsafe fn enable_mmu() { - let l1_phys = auto_address(&raw const KERNEL_TABLES) as u64; + let l1_phys = auto_lower_address(&raw const fixed::KERNEL_L1) as u64; tlb_flush_full(); SATP.write(SATP::PPN.val(l1_phys >> 12) + SATP::MODE::Sv39); } -/// Removes the lower half translation mappings. -/// -/// # Safety -/// -/// Needs to be called once after secondary HARTs are initialized. -pub unsafe fn unmap_lower_half() { - let mut tables = KERNEL_TABLES.lock(); - let kernel_l1i_lower = page_index::(KERNEL_PHYS_BASE); - tables.l1.data[kernel_l1i_lower] = 0; - tlb_flush_range_va(0x0, L1::SIZE); -} - -/// Sets up run-time kernel translation tables. -/// -/// # Safety -/// -/// The caller must ensure MMU is already enabled. -pub unsafe fn setup_fixed_tables() { - let mut tables = KERNEL_TABLES.lock(); - - let device_mapping_l2_phys = auto_address(&raw const DEVICE_MAPPING_L2); - - // Set up static runtime mappings - for i in 0..DEVICE_MAPPING_L3_COUNT { - unsafe { - let device_mapping_l3_phys = PhysicalAddress::from_usize( - (&raw const DEVICE_MAPPING_L3S[i]).addr() - KERNEL_VIRT_OFFSET, - ); - DEVICE_MAPPING_L2[i] = - PageEntry::table(device_mapping_l3_phys, PageAttributes::empty()); - } - } - - assert_eq!(tables.l1.data[DEVICE_MAPPING_L1I], 0); - tables.l1.data[DEVICE_MAPPING_L1I] = - ((device_mapping_l2_phys as u64) >> 2) | PageAttributes::V.bits(); - - for l1i in 0..RAM_MAPPING_L1_COUNT { - let physical = (l1i as u64) << L1::SHIFT; - tables.l1.data[l1i + RAM_MAPPING_START_L1I] = (physical >> 2) - | (PageAttributes::R - | PageAttributes::W - | PageAttributes::A - | PageAttributes::D - | PageAttributes::V) - .bits(); - } - - tlb_flush_full(); -} - -pub fn tlb_flush_global_full() { - tlb_flush_full(); - // TODO send TLB shootdown IPI to other harts -} - -pub fn tlb_flush_global_va(va: usize) { - tlb_flush_va(va); - // TODO send TLB shootdown IPI to other harts -} - -pub fn tlb_flush_range_va(start: usize, size: usize) { - let end = (start + size).page_align_up::(); - let start = start.page_align_down::(); - - for page in (start..end).step_by(L3::SIZE) { - tlb_flush_va(page); - } -} - -pub fn tlb_flush_range_va_asid(asid: usize, start: usize, size: usize) { - let end = (start + size).page_align_up::(); - let start = start.page_align_down::(); - - for page in (start..end).step_by(L3::SIZE) { - tlb_flush_va_asid(page, asid); - } -} - -#[inline] -pub fn tlb_flush_full() { - unsafe { core::arch::asm!("sfence.vma") }; -} - -#[inline] -pub fn tlb_flush_va(va: usize) { - unsafe { core::arch::asm!("sfence.vma {0}, zero", in(reg) va) }; -} - -#[inline] -pub fn tlb_flush_asid(asid: usize) { - unsafe { core::arch::asm!("sfence.vma zero, {0}", in(reg) asid) }; -} - -#[inline] -pub fn tlb_flush_va_asid(va: usize, asid: usize) { - unsafe { core::arch::asm!("sfence.vma {0}, {1}", in(reg) va, in(reg) asid) }; -} - pub fn clone_kernel_tables(dst: &mut PageTable) { - let tables = KERNEL_TABLES.lock(); + let _lock = fixed::LOCK.lock(); for l1i in page_index::(USER_BOUNDARY)..512 { - dst[l1i] = unsafe { PageEntry::from_raw(tables.l1.data[l1i]) }; + dst[l1i] = unsafe { fixed::KERNEL_L1[l1i] }; } } diff --git a/kernel/arch/riscv64/src/mem/table.rs b/kernel/arch/riscv64/src/mem/table.rs index a1add287..cb2934f1 100644 --- a/kernel/arch/riscv64/src/mem/table.rs +++ b/kernel/arch/riscv64/src/mem/table.rs @@ -42,7 +42,7 @@ impl EntryLevel for L1 { #[repr(C, align(0x1000))] pub struct PageTable { - entries: [PageEntry; 512], + pub(crate) entries: [PageEntry; 512], } #[derive(Clone, Copy, Debug, PartialEq)] @@ -204,6 +204,19 @@ impl NextPageTable for PageTable { } impl PageEntry { + pub const fn identity_block(address: PhysicalAddress) -> Self { + Self( + (address.into_u64() >> 2) + | PageAttributes::R.bits() + | PageAttributes::W.bits() + | PageAttributes::X.bits() + | PageAttributes::V.bits() + | PageAttributes::D.bits() + | PageAttributes::A.bits(), + PhantomData, + ) + } + pub fn block(address: PhysicalAddress, attrs: PageAttributes) -> Self { // TODO validate address alignment Self( diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 6260dd1b..119b9c90 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -14,11 +14,11 @@ pub use aarch64::{AArch64 as PlatformImpl, L3, PLATFORM}; // pub mod x86_64; // #[cfg(any(target_arch = "x86_64", rust_analyzer))] // pub use x86_64::{PLATFORM, X86_64 as PlatformImpl}; -// -// #[cfg(any(target_arch = "riscv64", rust_analyzer))] -// pub mod riscv64; -// #[cfg(any(target_arch = "riscv64", rust_analyzer))] -// pub use riscv64::{Riscv64 as PlatformImpl, PLATFORM}; + +#[cfg(any(target_arch = "riscv64", rust_analyzer))] +pub mod riscv64; +#[cfg(any(target_arch = "riscv64", rust_analyzer))] +pub use riscv64::{Riscv64 as PlatformImpl, L3, PLATFORM}; // // #[cfg(not(any( // target_arch = "x86_64", diff --git a/kernel/src/arch/riscv64/boot/entry.S b/kernel/src/arch/riscv64/boot/entry.S index e55d0f95..974b6c1e 100644 --- a/kernel/src/arch/riscv64/boot/entry.S +++ b/kernel/src/arch/riscv64/boot/entry.S @@ -1,82 +1,77 @@ // vi:ft=asm: -.macro LOAD_PCREL label, register, symbol -\label: auipc \register, %pcrel_hi(\symbol) - addi \register, \register, %pcrel_lo(\label) +.global __riscv64_entry +.global __riscv64_ap_entry + +.macro LOAD_PCREL label, reg, sym +\label: auipc \reg, %pcrel_hi(\sym) + addi \reg, \reg, %pcrel_lo(\label) .endm .pushsection .text.entry - -.option push -.option rvc - -.global __rv64_entry -.global __boot_header -.global __rv64_secondary_entry - -.type __rv64_entry, @function -.type __boot_header, @object -__boot_header: -__rv64_entry: - // Look mau-boot, I'm Linux! - .ascii "MZ" // Magic 0 - j __rv64_real_entry // Jump to real entry (if entered by non-Linux bootloader) +__riscv64_entry: + .ascii "MZ" // Magic 0 + j __riscv64_real_entry // Jump to real entry (if entered by non-Linux bootloader) .long 0 - .quad 0x200000 // Offset from RAM start - .quad __kernel_size // Image size - .quad 0 // Kernel flags - .long 0x2 // Header version + .quad 0x200000 // Offset from RAM start + .quad __kernel_size // Image size + .quad 0 // Kernel flags + .long 0x2 // Header version .long 0 .quad 0 - .ascii "RISCV\x00\x00\x00" // Magic 1 - .ascii "RSC\x05" // Magic 2 + .ascii "RISCV\x00\x00\x00" // Magic 1 + .ascii "RSC\x05" // Magic 2 .long 0 -.size __rv64_entry, . - __rv64_entry -.size __boot_header, . - __boot_header -.option pop - -.option push -.option norvc - -.type __rv64_real_entry, @function -__rv64_real_entry: - // a0 - bootstrap HART ID - // a1 - device tree blob - // mhartid == a0 +__riscv64_real_entry: csrw satp, zero mv tp, zero - // Zero the .bss - LOAD_PCREL .L00, t0, __bss_start_phys - LOAD_PCREL .L01, t1, __bss_end_phys + // a0 - bootstrap HART ID + // a1 - device tree blob + LOAD_PCREL .L00, s0, __riscv64_entry + mv s1, a0 + mv s2, a1 + //// Zero the .bss + LOAD_PCREL .L01, t0, __bss_start + LOAD_PCREL .L02, t1, __bss_end 1: bgeu t0, t1, 2f sd zero, (t0) - addi t0, t0, 4 + addi t0, t0, 8 j 1b 2: - // Setup boot stack and entry point - LOAD_PCREL .L02, sp, {boot_stack_bottom} + {boot_stack_size} - {kernel_virt_offset} - LOAD_PCREL .L03, t0, {entry_smode_lower} - {kernel_virt_offset} + //// Store boot parameters + LOAD_PCREL .L03, t0, {kernel_load_base} + LOAD_PCREL .L04, t1, {boot_hart_id} + LOAD_PCREL .L05, t2, {dtb_address} + sd s0, (t0) + sd s1, (t1) + sd s2, (t2) - jr t0 -.size __rv64_real_entry, . - __rv64_real_entry + //// Setup a stack + LOAD_PCREL .L06, sp, {boot_stack_bottom} + {boot_stack_size} -.type __rv64_secondary_entry, @function -__rv64_secondary_entry: + //// Relocate the kernel + mv a0, s0 + LOAD_PCREL .L07, a1, __rela_start + LOAD_PCREL .L08, a2, __rela_end + jal {relocate_kernel} + + //// Enter S-mode kernel + j {bsp_smode_entry} +.popsection // .text.entry + +.pushsection .text +__riscv64_ap_entry: // a1 - context struct csrw satp, zero mv tp, zero - // Setup stack and jump to Rust entry code + // Setup stack and enter Rust code ld sp, (a1) mv a0, a1 mv a1, sp - LOAD_PCREL .L04, t0, {entry_smode_secondary_lower} - {kernel_virt_offset} - jr t0 -.size __rv64_secondary_entry, . - __rv64_secondary_entry - -.option pop -.popsection + j {ap_smode_entry} +.popsection // .text diff --git a/kernel/src/arch/riscv64/boot/mod.rs b/kernel/src/arch/riscv64/boot/mod.rs index f7644b3b..9a471cbf 100644 --- a/kernel/src/arch/riscv64/boot/mod.rs +++ b/kernel/src/arch/riscv64/boot/mod.rs @@ -1,13 +1,13 @@ +//! RISC-V boot code + use core::{ arch::global_asm, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{self, compiler_fence, Ordering}, }; -use kernel_arch::Architecture; -use kernel_arch_riscv64::{ - mem::{self, KERNEL_VIRT_OFFSET}, - ArchitectureImpl, CPU_COUNT, -}; +use elf::{abi, relocation::Elf64_Rela}; +use kernel_arch::{Architecture, ArchitectureImpl}; +use kernel_arch_riscv64::{mem, CPU_COUNT}; use libk::{ debug, fs::{devfs, sysfs}, @@ -18,12 +18,19 @@ use libk_mm::{ PageBox, }; -use crate::{kernel_main, kernel_secondary_main}; - -use super::{smp::SecondaryContext, PLATFORM}; +use crate::{ + arch::{riscv64::smp::SecondaryContext, PLATFORM}, + kernel_main, kernel_secondary_main, + mem::KERNEL_VIRT_OFFSET, +}; const BOOT_STACK_SIZE: usize = 65536; +static mut KERNEL_LOAD_BASE: u64 = 0; +static mut DTB_ADDRESS: PhysicalAddress = PhysicalAddress::ZERO; +static mut BOOT_HART_ID: u64 = 0; +static mut BOOT_STACK: BootStack = BootStack::zeroed(); + #[repr(C, align(0x10))] struct BootStack([u8; N]); @@ -33,35 +40,59 @@ impl BootStack { } } -#[link_section = ".bss"] -static mut BOOT_STACK: BootStack = BootStack::zeroed(); +unsafe extern "C" fn relocate_kernel(image_base: i64, rela_start: usize, rela_end: usize) { + let rela_count = (rela_end - rela_start) / size_of::(); + let rela_ptr: *const Elf64_Rela = core::ptr::with_exposed_provenance(rela_start); + let rela_table = core::slice::from_raw_parts(rela_ptr, rela_count); -unsafe fn long_jump(pc: usize, sp: usize, a0: usize, a1: usize) -> ! { - core::arch::asm!(r#" - mv sp, {sp} - jr {pc} - "#, - in("a0") a0, - in("a1") a1, - pc = in(reg) pc, - sp = in(reg) sp, - options(noreturn) - ); + for rela in rela_table { + let slot: *mut i64 = + core::ptr::with_exposed_provenance_mut(rela.r_offset as usize + image_base as usize); + + let value = match rela.r_info as u32 { + abi::R_RISCV_RELATIVE => rela.r_addend + image_base, + _ => loop {}, + }; + + slot.write_volatile(value); + } } -unsafe extern "C" fn __rv64_bsp_entry_upper(bsp_hart_id: u64, dtb_physical: PhysicalAddress) -> ! { +/// Returns the ID of the bootstrap HART +pub fn boot_hart_id() -> u64 { + unsafe { BOOT_HART_ID } +} + +unsafe fn long_jump(pc: usize, sp: usize, a0: usize) -> ! { + core::arch::asm!("mv sp, {sp}; jr {pc}", in("a0") a0, sp = in(reg) sp, pc = in(reg) pc, options(noreturn)) +} + +unsafe extern "C" fn bsp_entry_upper() -> ! { + // Relocate the kernel again + extern "C" { + static __rela_start: u8; + static __rela_end: u8; + } + + atomic::fence(Ordering::SeqCst); + let rela_start = (&raw const __rela_start).addr(); + let rela_end = (&raw const __rela_end).addr(); + let image_base = (KERNEL_VIRT_OFFSET as u64 + KERNEL_LOAD_BASE) as i64; + relocate_kernel(image_base, rela_start, rela_end); + atomic::fence(Ordering::SeqCst); + debug::init_logger(); super::debug::register_sbi_debug(); log::info!("Starting riscv64 upper half"); - if dtb_physical.is_zero() { + if DTB_ADDRESS.is_zero() { log::error!("No device tree provided"); // No DTB provided ArchitectureImpl::halt(); } - if let Err(error) = PLATFORM.init_memory_management(dtb_physical) { + if let Err(error) = PLATFORM.init_memory_management(DTB_ADDRESS) { log::error!("Failed to initialize memory management: {error:?}"); ArchitectureImpl::halt(); } @@ -71,7 +102,7 @@ unsafe extern "C" fn __rv64_bsp_entry_upper(bsp_hart_id: u64, dtb_physical: Phys runtime::init_task_queue(); - if let Err(error) = PLATFORM.init_platform(bsp_hart_id as _, 0, true) { + if let Err(error) = PLATFORM.init_platform(BOOT_HART_ID as u32, 0, true) { log::error!("Failed to initialize the platform: {error:?}"); ArchitectureImpl::halt(); } @@ -79,7 +110,14 @@ unsafe extern "C" fn __rv64_bsp_entry_upper(bsp_hart_id: u64, dtb_physical: Phys kernel_main() } -unsafe extern "C" fn __rv64_secondary_entry_upper(context: PhysicalAddress) -> ! { +unsafe extern "C" fn bsp_smode_entry() -> ! { + mem::enable_mmu(); + let pc = bsp_entry_upper as usize + KERNEL_VIRT_OFFSET; + let sp = (&raw const BOOT_STACK).addr() + BOOT_STACK_SIZE + KERNEL_VIRT_OFFSET; + long_jump(pc, sp, 0) +} + +unsafe extern "C" fn ap_smode_upper(context: PhysicalAddress) -> ! { let hart_id = { let context = PageBox::::from_physical_raw(context); context.hart_id @@ -94,39 +132,27 @@ unsafe extern "C" fn __rv64_secondary_entry_upper(context: PhysicalAddress) -> ! kernel_secondary_main() } -unsafe extern "C" fn __rv64_bsp_smode_entry_lower(a0: usize, a1: usize) -> ! { - ArchitectureImpl::set_interrupt_mask(true); - +unsafe extern "C" fn ap_smode_entry(context: PhysicalAddress, sp: PhysicalAddress) -> ! { + compiler_fence(Ordering::SeqCst); mem::enable_mmu(); - - let stack = (&raw const BOOT_STACK).addr() + KERNEL_VIRT_OFFSET; - let pc = __rv64_bsp_entry_upper as usize + KERNEL_VIRT_OFFSET; - let sp = stack + BOOT_STACK_SIZE; - - long_jump(pc, sp, a0, a1) -} - -unsafe extern "C" fn __rv64_secondary_smode_entry_lower( - context: PhysicalAddress, - sp: PhysicalAddress, -) -> ! { + compiler_fence(Ordering::SeqCst); + let pc = ap_smode_upper as usize + KERNEL_VIRT_OFFSET; let sp = sp.virtualize(); - - ArchitectureImpl::set_interrupt_mask(true); - - compiler_fence(Ordering::Release); - mem::enable_mmu(); - compiler_fence(Ordering::Acquire); - - let pc = __rv64_secondary_entry_upper as usize + KERNEL_VIRT_OFFSET; - long_jump(pc, sp, context.into_usize(), 0) + long_jump(pc, sp, context.into_usize()) } global_asm!( include_str!("entry.S"), - entry_smode_lower = sym __rv64_bsp_smode_entry_lower, - entry_smode_secondary_lower = sym __rv64_secondary_smode_entry_lower, + + dtb_address = sym DTB_ADDRESS, + kernel_load_base = sym KERNEL_LOAD_BASE, + boot_hart_id = sym BOOT_HART_ID, + boot_stack_bottom = sym BOOT_STACK, - kernel_virt_offset = const KERNEL_VIRT_OFFSET, boot_stack_size = const BOOT_STACK_SIZE, + bsp_smode_entry = sym bsp_smode_entry, + + ap_smode_entry = sym ap_smode_entry, + + relocate_kernel = sym relocate_kernel, ); diff --git a/kernel/src/arch/riscv64/debug.rs b/kernel/src/arch/riscv64/debug.rs index 162e563f..7b1c0e42 100644 --- a/kernel/src/arch/riscv64/debug.rs +++ b/kernel/src/arch/riscv64/debug.rs @@ -1,7 +1,10 @@ +//! Debugging utilties specific to RISC-V + use abi::error::Error; use kernel_arch_riscv64::sbi; use libk::debug::{self, DebugSink, LogLevel}; +/// SBI-based debug sink pub struct SbiDebugConsole; impl DebugSink for SbiDebugConsole { @@ -17,6 +20,7 @@ impl DebugSink for SbiDebugConsole { static SBI_DEBUG: SbiDebugConsole = SbiDebugConsole; +/// Sets up a SBI-based debug log sink pub fn register_sbi_debug() { debug::add_early_sink(&SBI_DEBUG, LogLevel::Debug); } diff --git a/kernel/src/arch/riscv64/exception.rs b/kernel/src/arch/riscv64/exception.rs index b6324e83..5d079176 100644 --- a/kernel/src/arch/riscv64/exception.rs +++ b/kernel/src/arch/riscv64/exception.rs @@ -1,3 +1,4 @@ +//! RISC-V exception handling functions use core::arch::global_asm; use abi::{arch::SavedFrame, primitive_enum, process::Signal, SyscallFunction}; @@ -13,6 +14,7 @@ use crate::syscall; use super::{smp, timer}; primitive_enum! { + #[allow(missing_docs)] pub enum Cause: usize { MisalignedInstruction = 0, InstructionAccessFault = 1, @@ -33,6 +35,7 @@ primitive_enum! { #[derive(Debug)] #[repr(C)] +#[allow(missing_docs)] pub struct TrapFrame { // General-purpose pub ra: usize, @@ -49,6 +52,7 @@ pub struct TrapFrame { pub tp: usize, } +/// Sets up kernel exception handling pub fn init_smode_exceptions() { extern "C" { static __rv64_smode_trap_vectors: u8; diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs index a920802b..a97426a4 100644 --- a/kernel/src/arch/riscv64/mod.rs +++ b/kernel/src/arch/riscv64/mod.rs @@ -1,79 +1,55 @@ -#![allow(missing_docs)] -use core::sync::atomic::{self, AtomicU32, Ordering}; +//! 64-bit RISC-V platform implementation +use core::sync::atomic::{self, Ordering}; use abi::error::Error; -use alloc::sync::Arc; -use device_api::{ - interrupt::{IpiDeliveryTarget, IpiMessage}, - ResetDevice, -}; use device_tree::{ driver::{unflatten_device_tree, InitSequence}, DeviceTree, DeviceTreeNodeExt, }; -use kernel_arch::Architecture; +use kernel_arch::{Architecture, ArchitectureImpl}; use kernel_arch_riscv64::{ - mem::{self, KERNEL_VIRT_OFFSET}, + mem, registers::{SIE, SSTATUS}, - ArchitectureImpl, PerCpuData, + PerCpuData, }; use libk::{arch::Cpu, config}; use libk_mm::{ address::PhysicalAddress, phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, pointer::PhysicalRef, - table::{EntryLevel, EntryLevelExt}, + table::EntryLevelExt, }; use libk_util::OneTimeInit; use tock_registers::interfaces::ReadWriteable; use ygg_driver_pci::PciBusManager; use crate::{ + arch::Platform, device::MACHINE_NAME, fs::{Initrd, INITRD_DATA}, util::call_init_array, }; -use super::Platform; - pub mod boot; pub mod debug; pub mod exception; pub mod smp; pub mod timer; -pub static BOOT_HART_ID: AtomicU32 = AtomicU32::new(u32::MAX); +/// Alias for terminal-level page tables +pub type L3 = mem::table::L3; +/// 64-bit RISC-V platform struct pub struct Riscv64 { dt: OneTimeInit>, initrd: OneTimeInit>, } -pub static PLATFORM: Riscv64 = Riscv64 { - dt: OneTimeInit::new(), - initrd: OneTimeInit::new(), -}; - -#[derive(Debug, Clone, Copy)] -pub struct L3; -impl EntryLevel for L3 { - const SIZE: usize = 4096; - const SHIFT: usize = 12; -} - impl Platform for Riscv64 { - const KERNEL_VIRT_OFFSET: usize = KERNEL_VIRT_OFFSET; - type L3 = L3; - unsafe fn reset(&self) -> ! { ArchitectureImpl::halt(); } - unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result { - smp::send_ipi(target, msg)?; - Ok(true) - } - unsafe fn start_application_processors(&self) { // TODO asymmetric systems with different hart types are not yet supported. // e.g., in JH7110 there're two different types of cores @@ -82,36 +58,37 @@ impl Platform for Riscv64 { log::error!("Couldn't start secondary harts: {error:?}"); } } - - fn register_reset_device(&self, reset: Arc) -> Result<(), Error> { - let _ = reset; - Ok(()) - } } +/// 64-bit RISC-V platform +pub static PLATFORM: Riscv64 = Riscv64 { + dt: OneTimeInit::new(), + initrd: OneTimeInit::new(), +}; + impl Riscv64 { - unsafe fn init_memory_management(&'static self, dtb: PhysicalAddress) -> Result<(), Error> { - // Unmap the lower half - mem::setup_fixed_tables(); + unsafe fn init_memory_management( + &'static self, + dtb_address: PhysicalAddress, + ) -> Result<(), Error> { + let dtb = PhysicalRef::::map_slice(dtb_address, DeviceTree::MIN_HEADER_SIZE); + let dtb_size = DeviceTree::read_totalsize(&dtb[..]).map_err(|_| Error::InvalidArgument)?; - // Extract the size of the device tree - let dtb_size = { - let dtb_header = PhysicalRef::::map_slice(dtb, DeviceTree::MIN_HEADER_SIZE); - DeviceTree::read_totalsize(dtb_header.as_ref()).map_err(|_| Error::InvalidArgument)? - }; + // // Unmap the lower half + // mem::setup_fixed_tables(); - log::debug!("DTB: {:#x?}", dtb..dtb.add(dtb_size)); + log::info!("DTB: {:#x?}", dtb_address..dtb_address.add(dtb_size)); reserve_region( "dtb", PhysicalMemoryRegion { - base: dtb, + base: dtb_address, size: (dtb_size + 0xFFF) & !0xFFF, }, ); - let dtb_slice = PhysicalRef::::map_slice(dtb, dtb_size); - let dt = DeviceTree::from_raw(dtb_slice.as_ptr() as usize)?; + let dtb = PhysicalRef::::map_slice(dtb_address, dtb_size); + let dt = DeviceTree::from_raw(dtb.as_ptr().addr())?; // Reserve memory regions specified in the DTB log::info!("Reserved memory:"); @@ -139,7 +116,7 @@ impl Riscv64 { } // Initialize the physical memory - phys::init_from_iter(dt.memory_regions(), |_, _, _| Ok(()))?; + phys::init_from_iter(dt.memory_regions())?; self.dt.init(dt); @@ -184,8 +161,6 @@ impl Riscv64 { exception::init_smode_exceptions(); if is_bsp { - BOOT_HART_ID.store(hart_id, Ordering::Release); - call_init_array(); atomic::compiler_fence(Ordering::SeqCst); diff --git a/kernel/src/arch/riscv64/smp.rs b/kernel/src/arch/riscv64/smp.rs index b2b53d7c..623aa1bc 100644 --- a/kernel/src/arch/riscv64/smp.rs +++ b/kernel/src/arch/riscv64/smp.rs @@ -1,9 +1,13 @@ +//! RISC-V SMP implementation + use core::{mem::MaybeUninit, sync::atomic::Ordering}; use abi::error::Error; use device_api::interrupt::{IpiDeliveryTarget, IpiMessage}; use device_tree::{DeviceTree, DeviceTreeNodeExt}; -use kernel_arch_riscv64::{mem, registers::SIP, sbi, ArchitectureImpl, CPU_COUNT}; +use kernel_arch_riscv64::{ + mem::auto_lower_address, registers::SIP, sbi, ArchitectureImpl, CPU_COUNT, +}; use libk::arch::Cpu; use libk_mm::{ address::{AsPhysicalAddress, PhysicalAddress}, @@ -11,11 +15,13 @@ use libk_mm::{ }; use tock_registers::interfaces::ReadWriteable; -use crate::{arch::riscv64::BOOT_HART_ID, panic}; +use crate::{arch::riscv64::boot::boot_hart_id, panic}; +#[allow(missing_docs)] pub const SECONDARY_STACK_SIZE: usize = 32768; #[repr(C)] +#[allow(missing_docs)] pub struct SecondaryContext { // 0x00 pub stack_top: PhysicalAddress, @@ -26,10 +32,10 @@ pub struct SecondaryContext { fn start_secondary_hart(hart_id: u64) -> Result<(), Error> { extern "C" { - fn __rv64_secondary_entry(); + fn __riscv64_ap_entry(); } - let start_addr = __rv64_secondary_entry as usize; + let start_addr = auto_lower_address(__riscv64_ap_entry as *const fn()); let stack = PageBox::::new_uninit_slice(SECONDARY_STACK_SIZE)?; let stack_top = unsafe { PageBox::as_physical_address(&stack).add(SECONDARY_STACK_SIZE) }; let context = PageBox::new(SecondaryContext { @@ -56,10 +62,11 @@ fn start_secondary_hart(hart_id: u64) -> Result<(), Error> { Ok(()) } +/// Main function to setup all secondary HARTs pub fn start_secondary_harts(dt: &DeviceTree) -> Result<(), Error> { log::info!("Setting up secondary harts"); - let boot_hart_id = BOOT_HART_ID.load(Ordering::Acquire); + let boot_hart_id = boot_hart_id() as u32; let cpus = dt.find_absolute("/cpus").ok_or(Error::DoesNotExist)?; // Find the boot hart @@ -104,11 +111,12 @@ pub fn start_secondary_harts(dt: &DeviceTree) -> Result<(), Error> { } // Can get rid of lower half now - unsafe { mem::unmap_lower_half() }; + // unsafe { mem::unmap_lower_half() }; Ok(()) } +/// Sends an IPI to the target HART(s) pub fn send_ipi(target: IpiDeliveryTarget, msg: IpiMessage) -> Result<(), Error> { let local = Cpu::local(); @@ -130,6 +138,7 @@ pub fn send_ipi(target: IpiDeliveryTarget, msg: IpiMessage) -> Result<(), Error> sbi::sbi_send_ipi(hart_mask, 0) } +/// Handles received IPIs pub fn handle_ipi() { let local = Cpu::local(); if let Some(message) = local.get_ipi() { diff --git a/kernel/src/arch/riscv64/timer.rs b/kernel/src/arch/riscv64/timer.rs index 4d4cf07c..36280b85 100644 --- a/kernel/src/arch/riscv64/timer.rs +++ b/kernel/src/arch/riscv64/timer.rs @@ -1,3 +1,4 @@ +//! RISC-V system timer driver use core::sync::atomic::{AtomicU64, Ordering}; use abi::time::NANOSECONDS_IN_SECOND; @@ -6,13 +7,16 @@ use kernel_arch_riscv64::{intrinsics, registers::SIE, sbi}; use libk::{arch::Cpu, task::runtime, time}; use tock_registers::interfaces::ReadWriteable; +/// Timer value at last tick pub static LAST_TICK: AtomicU64 = AtomicU64::new(0); +/// Timer frequency pub static FREQUENCY: AtomicU64 = AtomicU64::new(0); // 1kHz const TICK_RATE: u64 = 1000; // TODO use stimecmp instead of sbi calls if sstc extension is available +/// Handles incoming timer interrupts pub fn handle_interrupt() { let frequency = FREQUENCY.load(Ordering::Acquire); @@ -37,6 +41,7 @@ pub fn handle_interrupt() { unsafe { Cpu::local().scheduler().yield_cpu() }; } +/// Sets up a timer for the calling HART pub fn init_hart(is_bsp: bool) { let frequency = FREQUENCY.load(Ordering::Acquire); diff --git a/kernel/src/device/interrupt/riscv_plic.rs b/kernel/src/device/interrupt/riscv_plic.rs index 7c5ebadb..9c3cc067 100644 --- a/kernel/src/device/interrupt/riscv_plic.rs +++ b/kernel/src/device/interrupt/riscv_plic.rs @@ -1,5 +1,4 @@ //! RISC-V PLIC driver -use core::sync::atomic::Ordering; use abi::{error::Error, primitive_enum}; use alloc::{sync::Arc, vec::Vec}; @@ -25,7 +24,7 @@ use tock_registers::{ registers::{ReadOnly, ReadWrite}, }; -use crate::arch::riscv64::BOOT_HART_ID; +use crate::arch::riscv64::boot::boot_hart_id; const MAX_IRQS: usize = 1024; @@ -138,7 +137,7 @@ impl ExternalInterruptController for Plic { fn enable_irq(&self, irq: Irq) -> Result<(), Error> { // TODO balance IRQs between harts? let irq = self.validate_irq(irq)?; - let bsp_hart_id = BOOT_HART_ID.load(Ordering::Acquire); + let bsp_hart_id = boot_hart_id() as u32; let context = self .hart_context(bsp_hart_id) .ok_or(Error::InvalidArgument) @@ -159,7 +158,7 @@ impl ExternalInterruptController for Plic { _options: IrqOptions, handler: Arc, ) -> Result<(), Error> { - let bsp_hart_id = BOOT_HART_ID.load(Ordering::Acquire); + let bsp_hart_id = boot_hart_id() as u32; let irq = self.validate_irq(irq)?; let context = self .hart_context(bsp_hart_id) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a2b25874..4fcec277 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -3,7 +3,6 @@ if_let_guard, step_trait, decl_macro, - naked_functions, optimize_attribute, const_trait_impl, maybe_uninit_slice,