diff --git a/Cargo.lock b/Cargo.lock index 72028ae..169e274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "address" -version = "0.1.0" -dependencies = [ - "error", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -32,7 +25,6 @@ version = "0.1.0" name = "kernel" version = "0.1.0" dependencies = [ - "address", "cfg-if", "cortex-a", "error", diff --git a/Cargo.toml b/Cargo.toml index 93d5d57..702d0db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,5 @@ edition = "2018" [workspace] members = [ "kernel", - "address", "error" ] diff --git a/Makefile b/Makefile index 98324d2..8bb3f30 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,9 @@ endif clean: cargo clean +clippy: + cd kernel && cargo clippy $(CARGO_BUILD_OPTS) + qemu: all $(QEMU_PREFIX)qemu-system-$(ARCH) $(QEMU_OPTS) diff --git a/address/Cargo.toml b/address/Cargo.toml deleted file mode 100644 index 73486c9..0000000 --- a/address/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "address" -version = "0.1.0" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -error = { path = "../error" } diff --git a/address/src/base/mod.rs b/address/src/base/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/address/src/lib.rs b/address/src/lib.rs deleted file mode 100644 index d92c555..0000000 --- a/address/src/lib.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Type-safe wrappers for different address kinds -#![no_std] -#![feature(step_trait, const_fn_trait_bound, const_trait_impl, const_panic)] - -#[cfg(test)] -#[macro_use] -extern crate std; - -#[deny(missing_docs)] -pub mod phys; -pub mod virt; - -trait Address {} - -pub use phys::PhysicalAddress; -pub use virt::{AddressSpace, NoTrivialConvert, TrivialConvert, VirtualAddress}; diff --git a/address/src/phys.rs b/address/src/phys.rs deleted file mode 100644 index 3099d22..0000000 --- a/address/src/phys.rs +++ /dev/null @@ -1,183 +0,0 @@ -//! Module for handling physical memory addresses - -use crate::{AddressSpace, TrivialConvert, VirtualAddress}; -use core::convert::TryFrom; -use core::fmt; -use core::iter::Step; -use core::ops::{Add, AddAssign, Sub, SubAssign}; - -/// Wrapper struct for representing a physical address -#[repr(transparent)] -#[derive(PartialEq, PartialOrd, Copy, Clone)] -pub struct PhysicalAddress(usize); - -// Arithmetic -impl const Add for PhysicalAddress { - type Output = Self; - - #[inline(always)] - fn add(self, rhs: usize) -> Self { - // Will panic on overflow - Self::from(self.0 + rhs) - } -} -impl> AddAssign for PhysicalAddress { - #[inline(always)] - fn add_assign(&mut self, rhs: A) { - // Will panic on overflow - *self = Self::from(self.0 + rhs.into()); - } -} -impl const Sub for PhysicalAddress { - type Output = Self; - - #[inline(always)] - fn sub(self, rhs: usize) -> Self { - Self::from(self.0 - rhs) - } -} -impl SubAssign for PhysicalAddress { - #[inline(always)] - fn sub_assign(&mut self, rhs: usize) { - *self = Self::from(self.0 - rhs); - } -} - -// Construction -impl const From for PhysicalAddress { - fn from(p: usize) -> Self { - Self(p) - } -} - -#[cfg(target_pointer_width = "64")] -impl const From for PhysicalAddress { - fn from(p: u64) -> Self { - Self(p as usize) - } -} - -impl PhysicalAddress { - /// Computes a signed difference between `start` and `end` - /// addresses. Will panic if the result cannot be represented due to - /// overflow. - #[inline(always)] - pub fn diff(start: PhysicalAddress, end: PhysicalAddress) -> isize { - if end >= start { - isize::try_from(end.0 - start.0).expect("Address subtraction overflowed") - } else { - -isize::try_from(start.0 - end.0).expect("Address subtraction overflowed") - } - } - - /// Computes a signed difference between `start` and `end`, does not check for - /// overflow condition. - /// - /// # Safety - /// - /// Does not check for signed integer overflow. - #[inline(always)] - pub unsafe fn diff_unchecked(start: PhysicalAddress, end: PhysicalAddress) -> isize { - end.0 as isize - start.0 as isize - } - - /// Returns `true` if the address is page-aligned - #[inline(always)] - pub const fn is_paligned(self) -> bool { - self.0 & 0xFFF == 0 - } - - /// Returns the index of the 4K page containing the address - #[inline(always)] - pub const fn page_index(self) -> usize { - self.0 >> 12 - } -} - -// Trivial conversion PhysicalAddress -> VirtualAddress -impl const From for VirtualAddress { - fn from(p: PhysicalAddress) -> Self { - VirtualAddress::from(p.0 + T::OFFSET) - } -} - -impl const From for usize { - #[inline(always)] - fn from(p: PhysicalAddress) -> Self { - p.0 as usize - } -} - -#[cfg(target_pointer_width = "64")] -impl const From for u64 { - #[inline(always)] - fn from(p: PhysicalAddress) -> Self { - p.0 as u64 - } -} - -// Formatting -impl fmt::Debug for PhysicalAddress { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "", self.0) - } -} - -// Step -impl Step for PhysicalAddress { - #[inline] - fn steps_between(_p0: &Self, _p1: &Self) -> Option { - todo!() - } - - #[inline] - fn forward_checked(p: Self, steps: usize) -> Option { - p.0.checked_add(steps).map(Self::from) - } - - #[inline] - fn backward_checked(p: Self, steps: usize) -> Option { - p.0.checked_sub(steps).map(Self::from) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{AddressSpace, NoTrivialConvert, TrivialConvert, VirtualAddress}; - - #[derive(Copy, Clone, PartialEq, PartialOrd)] - struct S0; - impl AddressSpace for S0 { - const NAME: &'static str = "S0"; - const OFFSET: usize = 0x8000; - const LIMIT: usize = Self::OFFSET + 0x4000; - } - impl TrivialConvert for S0 {} - - #[derive(Copy, Clone, PartialEq, PartialOrd)] - struct S1; - impl AddressSpace for S1 { - const NAME: &'static str = "S1"; - const OFFSET: usize = 0; - const LIMIT: usize = 0; - } - impl NoTrivialConvert for S1 {} - - #[test] - fn test_virt_convert_valid() { - let p0 = PhysicalAddress::from(0x1234usize); - assert_eq!( - VirtualAddress::::from(p0), - VirtualAddress::::from(0x9234usize) - ); - } - - #[test] - #[should_panic] - fn test_virt_convert_invalid() { - let p0 = PhysicalAddress::from(0x4321usize); - let _v = VirtualAddress::::from(p0); - } -} diff --git a/address/src/virt.rs b/address/src/virt.rs deleted file mode 100644 index f6d006f..0000000 --- a/address/src/virt.rs +++ /dev/null @@ -1,361 +0,0 @@ -use super::PhysicalAddress; -use core::convert::TryFrom; -use core::fmt; -use core::iter::Step; -use core::marker::PhantomData; -use core::ops::{Add, AddAssign, Neg, Sub, SubAssign}; - -pub trait AddressSpace: Copy + Clone + PartialEq + PartialOrd { - const NAME: &'static str; - const OFFSET: usize; - const LIMIT: usize; -} - -pub trait NoTrivialConvert {} -pub trait TrivialConvert {} - -#[repr(transparent)] -#[derive(Copy, Clone, PartialOrd, PartialEq)] -pub struct VirtualAddress(usize, PhantomData); - -// Arithmetic -impl Add for VirtualAddress { - type Output = Self; - - #[inline(always)] - fn add(self, rhs: usize) -> Self { - // Will panic on overflow - Self::from(self.0 + rhs) - } -} -impl AddAssign for VirtualAddress { - #[inline(always)] - fn add_assign(&mut self, rhs: usize) { - // Will panic on overflow - *self = Self::from(self.0 + rhs); - } -} -impl Sub for VirtualAddress { - type Output = Self; - - #[inline(always)] - fn sub(self, rhs: usize) -> Self { - // Will panic on underflow - Self::from(self.0 - rhs) - } -} -impl SubAssign for VirtualAddress { - #[inline(always)] - fn sub_assign(&mut self, rhs: usize) { - // Will panic on underflow - *self = Self::from(self.0 - rhs); - } -} - -// Trivial conversion VirtualAddress -> PhysicalAddress -impl From> for PhysicalAddress { - #[inline(always)] - fn from(virt: VirtualAddress) -> Self { - assert!(virt.0 < T::LIMIT); - PhysicalAddress::from(virt.0 - T::OFFSET) - } -} - -// Formatting -impl fmt::Debug for VirtualAddress { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "<{} {:#018x}>", T::NAME, self.0) - } -} - -impl VirtualAddress { - #[inline(always)] - pub const fn null() -> Self { - Self(0, PhantomData) - } - - pub fn try_subtract(self, p: usize) -> Option { - let (res, overflow) = self.0.overflowing_sub(p); - if overflow || res < T::OFFSET || res >= T::LIMIT { - None - } else { - Some(Self(res, PhantomData)) - } - } - - #[inline] - pub fn diff(start: Self, end: Self) -> isize { - if end >= start { - isize::try_from(end.0 - start.0).expect("Address subtraction overflowed") - } else { - -isize::try_from(start.0 - end.0).expect("Address subtraction overflowed") - } - } - - #[inline(always)] - pub fn try_diff(start: Self, end: Self) -> Option { - if end >= start { - isize::try_from(end.0 - start.0).ok() - } else { - isize::try_from(start.0 - end.0).map(Neg::neg).ok() - } - } - - #[inline(always)] - pub unsafe fn as_slice_mut(self, count: usize) -> &'static mut [U] { - core::slice::from_raw_parts_mut(self.0 as *mut _, count) - } - - #[inline(always)] - pub fn as_mut_ptr(self) -> *mut U { - self.0 as *mut U - } - - #[inline(always)] - pub fn as_ptr(self) -> *const U { - self.0 as *const U - } - - #[inline(always)] - pub unsafe fn as_mut(self) -> Option<&'static mut U> { - (self.0 as *mut U).as_mut() - } - - #[inline(always)] - pub unsafe fn from_ptr(r: *const U) -> Self { - Self::from(r as usize) - } - - #[inline(always)] - pub unsafe fn from_ref(r: &U) -> Self { - Self(r as *const U as usize, PhantomData) - } -} - -// Step -impl Step for VirtualAddress { - #[inline] - fn steps_between(_p0: &Self, _p1: &Self) -> Option { - todo!() - } - - #[inline] - fn forward_checked(p: Self, steps: usize) -> Option { - p.0.checked_add(steps).map(Self::from) - } - - #[inline] - fn backward_checked(p: Self, steps: usize) -> Option { - p.0.checked_sub(steps).map(Self::from) - } -} - -// Conversion into VirtualAddress -impl const From for VirtualAddress { - #[inline(always)] - fn from(p: usize) -> Self { - if T::LIMIT > 0 { - assert!(p >= T::OFFSET && p < T::LIMIT); - } - Self(p, PhantomData) - } -} - -#[cfg(target_pointer_width = "64")] -impl From for VirtualAddress { - #[inline(always)] - fn from(p: u64) -> Self { - Self::from(p as usize) - } -} - -// Conversion from VirtualAddress -impl From> for usize { - #[inline(always)] - fn from(p: VirtualAddress) -> Self { - p.0 - } -} - -#[cfg(target_pointer_width = "64")] -impl From> for u64 { - #[inline(always)] - fn from(p: VirtualAddress) -> Self { - p.0 as u64 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::PhysicalAddress; - - #[derive(Copy, Clone, PartialEq, PartialOrd)] - struct S0; - impl AddressSpace for S0 { - const NAME: &'static str = "S0"; - const OFFSET: usize = 0x8000; - const LIMIT: usize = Self::OFFSET + 0x4000; - } - impl TrivialConvert for S0 {} - - #[derive(Copy, Clone, PartialEq, PartialOrd)] - struct S1; - impl AddressSpace for S1 { - const NAME: &'static str = "S1"; - const OFFSET: usize = 0; - const LIMIT: usize = 0; - } - impl NoTrivialConvert for S1 {} - - #[test] - fn test_trivial_construct_valid() { - for i in 0x8000usize..0xC000 { - VirtualAddress::::from(i); - } - } - - #[test] - #[should_panic] - fn test_trivial_construct_invalid_0() { - let _v = VirtualAddress::::from(0x1234usize); - } - - #[test] - #[should_panic] - fn test_trivial_construct_invalid_1() { - let _v = VirtualAddress::::from(0xD123usize); - } - - #[test] - fn test_trivial_convert() { - let v0 = VirtualAddress::::from(0x8123usize); - assert_eq!(PhysicalAddress::from(v0), PhysicalAddress::from(0x123usize)); - } - - #[test] - fn test_add_valid() { - let v0 = VirtualAddress::::from(0x8100usize); - assert_eq!(VirtualAddress::::from(0x8223usize), v0 + 0x123usize); - } - - #[test] - #[should_panic] - fn test_add_overflow() { - let v0 = VirtualAddress::::from(0x8100usize); - let _v = v0 - 0xF123usize; - } - - #[test] - fn test_subtract_valid() { - let v0 = VirtualAddress::::from(0x8100usize); - assert_eq!(VirtualAddress::::from(0x8023usize), v0 - 0xDDusize); - } - - #[test] - #[should_panic] - fn test_subtract_overflow() { - let v0 = VirtualAddress::::from(0x8100usize); - let _v = v0 - 0x1234usize; - } - - #[test] - fn test_try_subtract() { - let v0 = VirtualAddress::::from(0x8100usize); - assert_eq!(v0.try_subtract(0x1234usize), None); - assert_eq!( - v0.try_subtract(0x12usize), - Some(VirtualAddress::::from(0x80EEusize)) - ); - } - - #[test] - fn test_add_assign_valid() { - let mut v0 = VirtualAddress::::from(0x8100usize); - v0 += 0x123usize; - assert_eq!(v0, VirtualAddress::::from(0x8223usize)); - } - - #[test] - fn test_sub_assign_valid() { - let mut v0 = VirtualAddress::::from(0x8321usize); - v0 -= 0x123usize; - assert_eq!(v0, VirtualAddress::::from(0x81FEusize)); - } - - #[test] - #[should_panic] - fn test_sub_assign_overflow() { - let mut v0 = VirtualAddress::::from(0x8321usize); - v0 -= 0x1234usize; - } - - #[test] - #[should_panic] - fn test_add_assign_overflow() { - let mut v0 = VirtualAddress::::from(0x8321usize); - v0 += 0xF234usize; - } - - #[test] - fn test_format() { - let v0 = VirtualAddress::::from(0x8123usize); - assert_eq!(&format!("{:?}", v0), ""); - } - - #[test] - fn test_diff() { - let v0 = VirtualAddress::::from(0x8123usize); - let v1 = VirtualAddress::::from(0x8321usize); - - // Ok - assert_eq!(VirtualAddress::diff(v0, v1), 510); - assert_eq!(VirtualAddress::diff(v1, v0), -510); - assert_eq!(VirtualAddress::diff(v0, v0), 0); - assert_eq!(VirtualAddress::diff(v1, v1), 0); - } - - #[test] - #[should_panic] - fn test_diff_overflow() { - let v0 = VirtualAddress::::from(0usize); - let v1 = VirtualAddress::::from(usize::MAX); - - let _v = VirtualAddress::diff(v0, v1); - } - - #[test] - fn test_step() { - let mut count = 0; - for _ in VirtualAddress::::from(0x8000usize)..VirtualAddress::::from(0x8300usize) { - count += 1; - } - assert_eq!(count, 0x300); - - let mut count = 0; - for _ in (VirtualAddress::::from(0x8000usize)..VirtualAddress::::from(0x8300usize)) - .step_by(0x100) - { - count += 1; - } - assert_eq!(count, 3); - - let mut count = 0; - for _ in - (VirtualAddress::::from(0x8000usize)..VirtualAddress::::from(0x8300usize)).rev() - { - count += 1; - } - assert_eq!(count, 0x300); - - let mut count = 0; - for _ in (VirtualAddress::::from(0x8000usize)..VirtualAddress::::from(0x8300usize)) - .rev() - .step_by(0x100) - { - count += 1; - } - assert_eq!(count, 3); - } -} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index b5c40a3..e226233 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,7 +12,6 @@ test = false [dependencies] cfg-if = "1.x.x" error = { path = "../error" } -address = { path = "../address" } tock-registers = "0.7.x" [target.'cfg(target_arch = "aarch64")'.dependencies] diff --git a/kernel/src/arch/aarch64/exception.rs b/kernel/src/arch/aarch64/exception.rs index 4f58982..293504f 100644 --- a/kernel/src/arch/aarch64/exception.rs +++ b/kernel/src/arch/aarch64/exception.rs @@ -72,6 +72,7 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) { debugln!("Unhandled exception at ELR={:#018x}", exc.elr); + #[allow(clippy::single_match)] match err_code { EC_DATA_ABORT_ELX => { debugln!("Data Abort:"); diff --git a/kernel/src/arch/aarch64/irq/gic/mod.rs b/kernel/src/arch/aarch64/irq/gic/mod.rs index 3262a74..c5de99b 100644 --- a/kernel/src/arch/aarch64/irq/gic/mod.rs +++ b/kernel/src/arch/aarch64/irq/gic/mod.rs @@ -20,7 +20,7 @@ pub const MAX_IRQ: usize = 300; #[derive(Copy, Clone)] pub struct IrqNumber(usize); -/// ARM Generic Interrupt Controller +/// ARM Generic Interrupt Controller, version 2 pub struct Gic { gicc: Gicc, gicd: Gicd, @@ -34,7 +34,7 @@ impl IrqNumber { self.0 } - /// + /// Checks and wraps an IRQ number #[inline(always)] pub const fn new(v: usize) -> Self { assert!(v < MAX_IRQ); @@ -98,7 +98,11 @@ impl IntController for Gic { } impl Gic { + /// Constructs an instance of GICv2. /// + /// # Safety + /// + /// Does not perform `gicd_base` and `gicc_base` validation. pub const unsafe fn new(gicd_base: usize, gicc_base: usize) -> Self { Self { gicc: Gicc::new(gicc_base), diff --git a/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs b/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs index f92e213..8d6e7b6 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs @@ -86,7 +86,7 @@ impl GpioDevice for Gpio { Ok(()) } - unsafe fn get_pin_config(&self, _pin: u32) -> Result { + fn get_pin_config(&self, _pin: u32) -> Result { todo!() } diff --git a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs index 3d248de..31cec7b 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs @@ -51,7 +51,7 @@ pub fn local_timer() -> &'static impl TimestampSource { &LOCAL_TIMER } -/// +/// Returns CPU's interrupt controller device #[inline] pub fn intc() -> &'static impl IntController { &GIC diff --git a/kernel/src/arch/aarch64/mach_qemu/mod.rs b/kernel/src/arch/aarch64/mach_qemu/mod.rs index 8a68aed..d1dcedc 100644 --- a/kernel/src/arch/aarch64/mach_qemu/mod.rs +++ b/kernel/src/arch/aarch64/mach_qemu/mod.rs @@ -41,7 +41,7 @@ pub fn local_timer() -> &'static impl TimestampSource { &LOCAL_TIMER } -/// +/// Returns CPU's interrupt controller device #[inline] pub fn intc() -> &'static impl IntController { &GIC diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 4445bb0..51fcac5 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -22,6 +22,10 @@ cfg_if! { } /// Masks IRQs and returns previous IRQ mask state +/// +/// # Safety +/// +/// Unsafe: disables IRQ handling temporarily #[inline(always)] pub unsafe fn irq_mask_save() -> u64 { let state = DAIF.get(); @@ -30,6 +34,11 @@ pub unsafe fn irq_mask_save() -> u64 { } /// Restores IRQ mask state +/// +/// # Safety +/// +/// Unsafe: modifies interrupt behavior. Must only be used in +/// conjunction with [irq_mask_save] #[inline(always)] pub unsafe fn irq_restore(state: u64) { DAIF.set(state); diff --git a/kernel/src/dev/gpio.rs b/kernel/src/dev/gpio.rs index fb586d8..5bd99be 100644 --- a/kernel/src/dev/gpio.rs +++ b/kernel/src/dev/gpio.rs @@ -41,9 +41,13 @@ pub struct PinConfig { /// Generic GPIO controller interface pub trait GpioDevice: Device { /// Initializes configuration for given pin + /// + /// # Safety + /// + /// Unsafe: changes physical pin configuration unsafe fn set_pin_config(&self, pin: u32, cfg: &PinConfig) -> Result<(), Errno>; /// Returns current configuration of given pin - unsafe fn get_pin_config(&self, pin: u32) -> Result; + fn get_pin_config(&self, pin: u32) -> Result; /// Sets `pin` to HIGH state fn set_pin(&self, pin: u32); diff --git a/kernel/src/dev/irq.rs b/kernel/src/dev/irq.rs index 6c59c56..a6efefd 100644 --- a/kernel/src/dev/irq.rs +++ b/kernel/src/dev/irq.rs @@ -35,7 +35,11 @@ pub trait IntSource: Device { } impl<'q> IrqContext<'q> { + /// Constructs an IRQ context token /// + /// # Safety + /// + /// Only allowed to be constructed in top-level IRQ handlers #[inline(always)] pub unsafe fn new() -> Self { Self { _0: PhantomData }