style: fix clippy warnings
This commit is contained in:
Generated
-8
@@ -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",
|
||||
|
||||
@@ -10,6 +10,5 @@ edition = "2018"
|
||||
[workspace]
|
||||
members = [
|
||||
"kernel",
|
||||
"address",
|
||||
"error"
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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" }
|
||||
@@ -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};
|
||||
@@ -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<usize> for PhysicalAddress {
|
||||
type Output = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn add(self, rhs: usize) -> Self {
|
||||
// Will panic on overflow
|
||||
Self::from(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
impl<A: Into<usize>> AddAssign<A> 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<usize> for PhysicalAddress {
|
||||
type Output = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn sub(self, rhs: usize) -> Self {
|
||||
Self::from(self.0 - rhs)
|
||||
}
|
||||
}
|
||||
impl SubAssign<usize> for PhysicalAddress {
|
||||
#[inline(always)]
|
||||
fn sub_assign(&mut self, rhs: usize) {
|
||||
*self = Self::from(self.0 - rhs);
|
||||
}
|
||||
}
|
||||
|
||||
// Construction
|
||||
impl const From<usize> for PhysicalAddress {
|
||||
fn from(p: usize) -> Self {
|
||||
Self(p)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl const From<u64> 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<T: AddressSpace + TrivialConvert> const From<PhysicalAddress> for VirtualAddress<T> {
|
||||
fn from(p: PhysicalAddress) -> Self {
|
||||
VirtualAddress::from(p.0 + T::OFFSET)
|
||||
}
|
||||
}
|
||||
|
||||
impl const From<PhysicalAddress> for usize {
|
||||
#[inline(always)]
|
||||
fn from(p: PhysicalAddress) -> Self {
|
||||
p.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl const From<PhysicalAddress> 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, "<phys {:#018x}>", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// Step
|
||||
impl Step for PhysicalAddress {
|
||||
#[inline]
|
||||
fn steps_between(_p0: &Self, _p1: &Self) -> Option<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(p: Self, steps: usize) -> Option<Self> {
|
||||
p.0.checked_add(steps).map(Self::from)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(p: Self, steps: usize) -> Option<Self> {
|
||||
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::<S0>::from(p0),
|
||||
VirtualAddress::<S0>::from(0x9234usize)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_virt_convert_invalid() {
|
||||
let p0 = PhysicalAddress::from(0x4321usize);
|
||||
let _v = VirtualAddress::<S0>::from(p0);
|
||||
}
|
||||
}
|
||||
@@ -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<Kind: AddressSpace>(usize, PhantomData<Kind>);
|
||||
|
||||
// Arithmetic
|
||||
impl<T: AddressSpace> Add<usize> for VirtualAddress<T> {
|
||||
type Output = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn add(self, rhs: usize) -> Self {
|
||||
// Will panic on overflow
|
||||
Self::from(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
impl<T: AddressSpace> AddAssign<usize> for VirtualAddress<T> {
|
||||
#[inline(always)]
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
// Will panic on overflow
|
||||
*self = Self::from(self.0 + rhs);
|
||||
}
|
||||
}
|
||||
impl<T: AddressSpace> Sub<usize> for VirtualAddress<T> {
|
||||
type Output = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn sub(self, rhs: usize) -> Self {
|
||||
// Will panic on underflow
|
||||
Self::from(self.0 - rhs)
|
||||
}
|
||||
}
|
||||
impl<T: AddressSpace> SubAssign<usize> for VirtualAddress<T> {
|
||||
#[inline(always)]
|
||||
fn sub_assign(&mut self, rhs: usize) {
|
||||
// Will panic on underflow
|
||||
*self = Self::from(self.0 - rhs);
|
||||
}
|
||||
}
|
||||
|
||||
// Trivial conversion VirtualAddress -> PhysicalAddress
|
||||
impl<T: AddressSpace + TrivialConvert> From<VirtualAddress<T>> for PhysicalAddress {
|
||||
#[inline(always)]
|
||||
fn from(virt: VirtualAddress<T>) -> Self {
|
||||
assert!(virt.0 < T::LIMIT);
|
||||
PhysicalAddress::from(virt.0 - T::OFFSET)
|
||||
}
|
||||
}
|
||||
|
||||
// Formatting
|
||||
impl<T: AddressSpace> fmt::Debug for VirtualAddress<T> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "<{} {:#018x}>", T::NAME, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AddressSpace> VirtualAddress<T> {
|
||||
#[inline(always)]
|
||||
pub const fn null() -> Self {
|
||||
Self(0, PhantomData)
|
||||
}
|
||||
|
||||
pub fn try_subtract(self, p: usize) -> Option<Self> {
|
||||
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<isize> {
|
||||
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<U>(self, count: usize) -> &'static mut [U] {
|
||||
core::slice::from_raw_parts_mut(self.0 as *mut _, count)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_mut_ptr<U>(self) -> *mut U {
|
||||
self.0 as *mut U
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_ptr<U>(self) -> *const U {
|
||||
self.0 as *const U
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn as_mut<U>(self) -> Option<&'static mut U> {
|
||||
(self.0 as *mut U).as_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn from_ptr<U>(r: *const U) -> Self {
|
||||
Self::from(r as usize)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn from_ref<U>(r: &U) -> Self {
|
||||
Self(r as *const U as usize, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// Step
|
||||
impl<T: AddressSpace> Step for VirtualAddress<T> {
|
||||
#[inline]
|
||||
fn steps_between(_p0: &Self, _p1: &Self) -> Option<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(p: Self, steps: usize) -> Option<Self> {
|
||||
p.0.checked_add(steps).map(Self::from)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(p: Self, steps: usize) -> Option<Self> {
|
||||
p.0.checked_sub(steps).map(Self::from)
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion into VirtualAddress
|
||||
impl<T: AddressSpace> const From<usize> for VirtualAddress<T> {
|
||||
#[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<T: AddressSpace> From<u64> for VirtualAddress<T> {
|
||||
#[inline(always)]
|
||||
fn from(p: u64) -> Self {
|
||||
Self::from(p as usize)
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion from VirtualAddress
|
||||
impl<T: AddressSpace> From<VirtualAddress<T>> for usize {
|
||||
#[inline(always)]
|
||||
fn from(p: VirtualAddress<T>) -> Self {
|
||||
p.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl<T: AddressSpace> From<VirtualAddress<T>> for u64 {
|
||||
#[inline(always)]
|
||||
fn from(p: VirtualAddress<T>) -> 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::<S0>::from(i);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_trivial_construct_invalid_0() {
|
||||
let _v = VirtualAddress::<S0>::from(0x1234usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_trivial_construct_invalid_1() {
|
||||
let _v = VirtualAddress::<S0>::from(0xD123usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trivial_convert() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8123usize);
|
||||
assert_eq!(PhysicalAddress::from(v0), PhysicalAddress::from(0x123usize));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_valid() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
assert_eq!(VirtualAddress::<S0>::from(0x8223usize), v0 + 0x123usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_add_overflow() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
let _v = v0 - 0xF123usize;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subtract_valid() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
assert_eq!(VirtualAddress::<S0>::from(0x8023usize), v0 - 0xDDusize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_subtract_overflow() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
let _v = v0 - 0x1234usize;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_subtract() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
assert_eq!(v0.try_subtract(0x1234usize), None);
|
||||
assert_eq!(
|
||||
v0.try_subtract(0x12usize),
|
||||
Some(VirtualAddress::<S0>::from(0x80EEusize))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_assign_valid() {
|
||||
let mut v0 = VirtualAddress::<S0>::from(0x8100usize);
|
||||
v0 += 0x123usize;
|
||||
assert_eq!(v0, VirtualAddress::<S0>::from(0x8223usize));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sub_assign_valid() {
|
||||
let mut v0 = VirtualAddress::<S0>::from(0x8321usize);
|
||||
v0 -= 0x123usize;
|
||||
assert_eq!(v0, VirtualAddress::<S0>::from(0x81FEusize));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_sub_assign_overflow() {
|
||||
let mut v0 = VirtualAddress::<S0>::from(0x8321usize);
|
||||
v0 -= 0x1234usize;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_add_assign_overflow() {
|
||||
let mut v0 = VirtualAddress::<S0>::from(0x8321usize);
|
||||
v0 += 0xF234usize;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8123usize);
|
||||
assert_eq!(&format!("{:?}", v0), "<S0 0x0000000000008123>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_diff() {
|
||||
let v0 = VirtualAddress::<S0>::from(0x8123usize);
|
||||
let v1 = VirtualAddress::<S0>::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::<S1>::from(0usize);
|
||||
let v1 = VirtualAddress::<S1>::from(usize::MAX);
|
||||
|
||||
let _v = VirtualAddress::diff(v0, v1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_step() {
|
||||
let mut count = 0;
|
||||
for _ in VirtualAddress::<S0>::from(0x8000usize)..VirtualAddress::<S0>::from(0x8300usize) {
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(count, 0x300);
|
||||
|
||||
let mut count = 0;
|
||||
for _ in (VirtualAddress::<S0>::from(0x8000usize)..VirtualAddress::<S0>::from(0x8300usize))
|
||||
.step_by(0x100)
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(count, 3);
|
||||
|
||||
let mut count = 0;
|
||||
for _ in
|
||||
(VirtualAddress::<S0>::from(0x8000usize)..VirtualAddress::<S0>::from(0x8300usize)).rev()
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(count, 0x300);
|
||||
|
||||
let mut count = 0;
|
||||
for _ in (VirtualAddress::<S0>::from(0x8000usize)..VirtualAddress::<S0>::from(0x8300usize))
|
||||
.rev()
|
||||
.step_by(0x100)
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(count, 3);
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -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:");
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -86,7 +86,7 @@ impl GpioDevice for Gpio {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn get_pin_config(&self, _pin: u32) -> Result<PinConfig, Errno> {
|
||||
fn get_pin_config(&self, _pin: u32) -> Result<PinConfig, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -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<IrqNumber = IrqNumber> {
|
||||
&GIC
|
||||
|
||||
@@ -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<IrqNumber = IrqNumber> {
|
||||
&GIC
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<PinConfig, Errno>;
|
||||
fn get_pin_config(&self, pin: u32) -> Result<PinConfig, Errno>;
|
||||
|
||||
/// Sets `pin` to HIGH state
|
||||
fn set_pin(&self, pin: u32);
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user