From 5697664e17abb3e1b922b72f5928479634d11db8 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:06 +0800 Subject: [PATCH 01/70] feat(asm): add tlbi support and rewrite barrier static methods --- src/asm.rs | 1 + src/asm/barrier.rs | 45 +++++++++++++-------------------------------- src/asm/tlb.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 32 deletions(-) create mode 100644 src/asm/tlb.rs diff --git a/src/asm.rs b/src/asm.rs index 8e0749d..87f3a13 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -10,6 +10,7 @@ pub mod barrier; pub mod random; +pub mod tlb; /// The classic no-op #[inline(always)] diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index c3e9373..c696455 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -9,15 +9,19 @@ mod sealed { pub trait Dmb { - fn __dmb(&self); + fn dmb(); } pub trait Dsb { - fn __dsb(&self); + fn dsb(); } pub trait Isb { - fn __isb(&self); + fn isb(); + } + + pub trait Tlbi { + fn __tlbi(); } } @@ -25,7 +29,7 @@ macro_rules! dmb_dsb { ($A:ident) => { impl sealed::Dmb for $A { #[inline(always)] - fn __dmb(&self) { + fn dmb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -39,7 +43,7 @@ macro_rules! dmb_dsb { } impl sealed::Dsb for $A { #[inline(always)] - fn __dsb(&self) { + fn dsb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -54,6 +58,9 @@ macro_rules! dmb_dsb { }; } + + + pub struct SY; pub struct ST; pub struct LD; @@ -82,7 +89,7 @@ dmb_dsb!(OSHLD); impl sealed::Isb for SY { #[inline(always)] - fn __isb(&self) { + fn isb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, @@ -93,29 +100,3 @@ impl sealed::Isb for SY { } } -/// Data Memory Barrier. -#[inline(always)] -pub fn dmb(arg: A) -where - A: sealed::Dmb, -{ - arg.__dmb() -} - -/// Data Synchronization Barrier. -#[inline(always)] -pub fn dsb(arg: A) -where - A: sealed::Dsb, -{ - arg.__dsb() -} - -/// Instruction Synchronization Barrier. -#[inline(always)] -pub fn isb(arg: A) -where - A: sealed::Isb, -{ - arg.__isb() -} diff --git a/src/asm/tlb.rs b/src/asm/tlb.rs new file mode 100644 index 0000000..62e311d --- /dev/null +++ b/src/asm/tlb.rs @@ -0,0 +1,30 @@ +mod sealed { + pub trait Tlbi { + fn invalidate(); + } +} + +macro_rules! tlbi{ + ($A: ident) => { + pub struct $A; + impl sealed::Tlbi for $A { + #[inline(always)] + fn invalidate(){ + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("tlbi ", stringify!($A)), options(nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + } +} + + +tlbi!(VMALLE1IS); +tlbi!(VMALLE2IS); +tlbi!(VMALLE3IS); From 56c73aa0587d94973bc45aa598c6d597479520b4 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:32 +0800 Subject: [PATCH 02/70] feat: init mmu modules --- src/mmu.rs | 2 ++ src/mmu/entry.rs | 1 + src/mmu/table.rs | 0 3 files changed, 3 insertions(+) create mode 100644 src/mmu.rs create mode 100644 src/mmu/entry.rs create mode 100644 src/mmu/table.rs diff --git a/src/mmu.rs b/src/mmu.rs new file mode 100644 index 0000000..f5d6eb0 --- /dev/null +++ b/src/mmu.rs @@ -0,0 +1,2 @@ +pub mod entry; +pub mod table; diff --git a/src/mmu/entry.rs b/src/mmu/entry.rs new file mode 100644 index 0000000..834fca2 --- /dev/null +++ b/src/mmu/entry.rs @@ -0,0 +1 @@ +use tock_registers::{register_bitfields, interfaces::{Readable,Writeable}}; diff --git a/src/mmu/table.rs b/src/mmu/table.rs new file mode 100644 index 0000000..e69de29 From 632788428075f0ac66a68bbc5b9adacb9422a150 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:44 +0800 Subject: [PATCH 03/70] feat: add TTBR1_EL2 module --- src/registers/ttbr1_el2.rs | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/registers/ttbr1_el2.rs diff --git a/src/registers/ttbr1_el2.rs b/src/registers/ttbr1_el2.rs new file mode 100644 index 0000000..55e897d --- /dev/null +++ b/src/registers/ttbr1_el2.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2023 by the author(s) +// +// Author(s): +// - Yiyang Wu + +//! Translation Table Base Register 1 - EL2 +//! +//! Holds the base address of the translation table for the initial lookup for stage 1 of the +//! translation of an address from the higher VA range in the EL2&0 translation regime, and other +//! information for this translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TTBR1_EL2 [ + /// An ASID for the translation table base address. The TCR_EL2.A1 field selects either + /// TTBR0_EL2.ASID or TTBR1_EL1.ASID. + /// + /// If the implementation has only 8 bits of ASID, then the upper 8 bits of this field are + /// RES 0. + ASID OFFSET(48) NUMBITS(16) [], + + /// Translation table base address + BADDR OFFSET(1) NUMBITS(47) [], + + /// Common not Private + CnP OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = TTBR1_EL2::Register; + + sys_coproc_read_raw!(u64, "TTBR1_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TTBR1_EL2::Register; + + sys_coproc_write_raw!(u64, "TTBR1_EL2", "x"); +} + +impl Reg { + #[inline(always)] + pub fn get_baddr(&self) -> u64 { + self.read(TTBR1_EL2::BADDR) << 1 + } + + #[inline(always)] + pub fn set_baddr(&self, addr: u64) { + self.write(TTBR1_EL2::BADDR.val(addr >> 1)); + } +} + +pub const TTBR1_EL2: Reg = Reg {}; From 3a8977059683bb90bf3cba81df2b488fb59a9d29 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:54 +0800 Subject: [PATCH 04/70] deps: bmp Cargo deps --- Cargo.toml | 2 +- rust-toolchain.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 965df68..1dd0a25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,4 +20,4 @@ exclude = [ ] [dependencies] -tock-registers = { version = "0.8.x", default-features = false } # Use it as interface-only library. +tock-registers = { version = "0.9.0", default-features = false } # Use it as interface-only library. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1a43ef9..b442dc7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] -targets = ["aarch64-unknown-none-softfloat"] +channel = "nightly" +targets = ["aarch64-unknown-none"] From afa614157e4bb63a745a80b32d7a6e32049738ef Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 24 Jan 2024 23:28:58 +0800 Subject: [PATCH 05/70] fix(barrier): wrap barrier --- src/asm/barrier.rs | 80 +++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index c696455..8091e0f 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -9,27 +9,26 @@ mod sealed { pub trait Dmb { - fn dmb(); + fn dmb(&self); } pub trait Dsb { - fn dsb(); + fn dsb(&self); } pub trait Isb { - fn isb(); - } - - pub trait Tlbi { - fn __tlbi(); + fn isb(&self); } } macro_rules! dmb_dsb { - ($A:ident) => { - impl sealed::Dmb for $A { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::Dmb for $T { #[inline(always)] - fn dmb() { + fn dmb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -41,9 +40,9 @@ macro_rules! dmb_dsb { } } } - impl sealed::Dsb for $A { + impl sealed::Dsb for $T { #[inline(always)] - fn dsb() { + fn dsb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -58,38 +57,22 @@ macro_rules! dmb_dsb { }; } - - - -pub struct SY; -pub struct ST; -pub struct LD; -pub struct ISH; -pub struct ISHST; -pub struct ISHLD; -pub struct NSH; -pub struct NSHST; -pub struct NSHLD; -pub struct OSH; -pub struct OSHST; -pub struct OSHLD; - -dmb_dsb!(SY); -dmb_dsb!(ST); -dmb_dsb!(LD); -dmb_dsb!(ISH); -dmb_dsb!(ISHST); -dmb_dsb!(ISHLD); -dmb_dsb!(NSH); -dmb_dsb!(NSHST); -dmb_dsb!(NSHLD); -dmb_dsb!(OSH); -dmb_dsb!(OSHST); -dmb_dsb!(OSHLD); - -impl sealed::Isb for SY { +dmb_dsb!(SY, Sy); +dmb_dsb!(ST, St); +dmb_dsb!(LD, Ld); +dmb_dsb!(ISH, Ish); +dmb_dsb!(ISHST, Ishst); +dmb_dsb!(ISHLD, Ishld); +dmb_dsb!(NSH, Nsh); +dmb_dsb!(NSHST, Nshst); +dmb_dsb!(NSHLD, Nshld); +dmb_dsb!(OSH, Osh); +dmb_dsb!(OSHST, Oshst); +dmb_dsb!(OSHLD, Oshld); + +impl sealed::Isb for Sy { #[inline(always)] - fn isb() { + fn isb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, @@ -100,3 +83,14 @@ impl sealed::Isb for SY { } } +pub fn isb(_arg: impl sealed::Isb) { + _arg.isb() +} + +pub fn dmb(_arg: impl sealed::Dmb) { + _arg.dmb() +} + +pub fn dsb(_arg: impl sealed::Dsb){ + _arg.dsb() +} From 57b293024ab4c0749674a160a53aca5f14442cee Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 24 Jan 2024 23:29:12 +0800 Subject: [PATCH 06/70] feat: impl mmu features --- src/lib.rs | 2 + src/mmu.rs | 4 +- src/mmu/address.rs | 49 ++++++++++++++++++ src/mmu/descriptor.rs | 118 ++++++++++++++++++++++++++++++++++++++++++ src/mmu/entry.rs | 1 - src/mmu/table.rs | 0 6 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/mmu/address.rs create mode 100644 src/mmu/descriptor.rs delete mode 100644 src/mmu/entry.rs delete mode 100644 src/mmu/table.rs diff --git a/src/lib.rs b/src/lib.rs index 52c7402..80be80d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,5 +55,7 @@ #![no_std] +#![feature(concat_idents)] pub mod asm; +pub mod mmu; pub mod registers; diff --git a/src/mmu.rs b/src/mmu.rs index f5d6eb0..5538bb6 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,2 +1,2 @@ -pub mod entry; -pub mod table; +pub mod descriptor; +pub mod address; diff --git a/src/mmu/address.rs b/src/mmu/address.rs new file mode 100644 index 0000000..bed24ab --- /dev/null +++ b/src/mmu/address.rs @@ -0,0 +1,49 @@ +use tock_registers::register_bitfields; +register_bitfields!{u64, + VADescriptor [ + L0 OFFSET(39) NUMBITS(9) [], + L1 OFFSET(30) NUMBITS(9) [], + L2 OFFSET(21) NUMBITS(9) [], + L3 OFFSET(12) NUMBITS(9) [], + OFFSET OFFSET(0) NUMBITS(12) [] + ] +} + +#[derive(Clone,Copy)] +#[repr(transparent)] +pub struct VirtAddress(pub u64); + +#[derive(Clone,Copy)] +#[repr(transparent)] +pub struct PhyAddress(pub u64); + +pub struct VirtLayout{ + pub indexes: [u64;4], + pub offset: u64 +} + +impl VirtAddress { + pub fn layout(&self) -> VirtLayout { + VirtLayout { + indexes: [ + VADescriptor::L0.read(self.0), + VADescriptor::L1.read(self.0), + VADescriptor::L2.read(self.0), + VADescriptor::L3.read(self.0) + ], + offset: VADescriptor::OFFSET.read(self.0) + } + } +} + +impl From for VirtAddress{ + fn from(value: u64) -> Self { + VirtAddress(value) + } +} + +impl From for PhyAddress { + fn from(value: u64) -> Self { + PhyAddress(value) + } +} diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs new file mode 100644 index 0000000..3c35349 --- /dev/null +++ b/src/mmu/descriptor.rs @@ -0,0 +1,118 @@ +use tock_registers::{ + register_bitfields, + fields::{FieldValue, Field}, + RegisterLongName, +}; + +register_bitfields! {u64, + pub BlockDescriptor [ + UXN_XN OFFSET(54) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + PXN OFFSET(53) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + CONTIGUOUS OFFSET(52) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + L1OUTPUT OFFSET(30) NUMBITS(18) [], + L2OUTPUT OFFSET(21) NUMBITS(27) [], + L3OUTPUT OFFSET(12) NUMBITS(36) [], + NSE_NG OFFSET(11) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + AF OFFSET(10) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + SH OFFSET(8) NUMBITS(2) [ + NS = 0b00, + RESERVED = 0b01, + OS = 0b10, + IS = 0b11 + ], + AP OFFSET(6) NUMBITS(2) [ + RW_ELx_None_EL0 = 0b00, + RW_ELx_RW_EL0 = 0b01, + RO_ELx_None_EL0 = 0b10, + RO_ELx_RO_EL0 = 0b11 + ], + NS OFFSET(5) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + ATTR OFFSET(2) NUMBITS(2) [], + TYPE OFFSET(1) NUMBITS(1) [ + BLOCK = 0b0, + PAGE = 0b1 + ], + VALID OFFSET(0) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ] + ] +} + +register_bitfields! {u64, + pub TableDescriptor [ + NS OFFSET(63) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + AP OFFSET(61) NUMBITS(2) [ + NO_EFFECT = 0b00, + UNPRIV_RESTRICTED = 0b01, + WR_RESTRICTED = 0b10, + WR_UNPRIV_RD_RESTRICTED = 0b11 + ], + UXN_XN OFFSET(60) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + PXN OFFSET(59) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + OUTPUT OFFSET(12) NUMBITS(36) [], + TYPE OFFSET(1) NUMBITS(1) [ + TABLE = 0b1, + BLOCK = 0b0 + ], + VALID OFFSET(0) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ] + ] +} + +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct VADescriptor(pub u64); + +impl VADescriptor { + pub fn read(&self) -> u64 { + self.0 + } + + pub fn read_field(&self, field: Field) -> u64 + where + T: RegisterLongName, + { + field.read(self.0) + } + + pub fn write(&mut self, val: u64) { + self.0 = val; + } + + pub fn write_field(&mut self, field_value: FieldValue) + where + T: RegisterLongName, + { + self.0 = field_value.modify(self.0); + } +} diff --git a/src/mmu/entry.rs b/src/mmu/entry.rs deleted file mode 100644 index 834fca2..0000000 --- a/src/mmu/entry.rs +++ /dev/null @@ -1 +0,0 @@ -use tock_registers::{register_bitfields, interfaces::{Readable,Writeable}}; diff --git a/src/mmu/table.rs b/src/mmu/table.rs deleted file mode 100644 index e69de29..0000000 From e9bfd4c474f450ecac86ab6f0a515f19769a8418 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:10:41 +0800 Subject: [PATCH 07/70] fix(tlb): fix missing vmalle2is --- src/asm/tlb.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/asm/tlb.rs b/src/asm/tlb.rs index 62e311d..91747fe 100644 --- a/src/asm/tlb.rs +++ b/src/asm/tlb.rs @@ -1,6 +1,6 @@ mod sealed { pub trait Tlbi { - fn invalidate(); + fn invalidate(&self); } } @@ -9,11 +9,11 @@ macro_rules! tlbi{ pub struct $A; impl sealed::Tlbi for $A { #[inline(always)] - fn invalidate(){ + fn invalidate(&self){ match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("tlbi ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("TLBI ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -26,5 +26,10 @@ macro_rules! tlbi{ tlbi!(VMALLE1IS); -tlbi!(VMALLE2IS); -tlbi!(VMALLE3IS); +tlbi!(ALLE2IS); +tlbi!(ALLE3IS); + +#[inline(always)] +pub fn tlb_inv(_arg: impl sealed::Tlbi){ + _arg.invalidate(); +} From a2c35d2a48ab3b39acaa829a17b3e171f69f5e36 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:10:58 +0800 Subject: [PATCH 08/70] feat(barrier): add barrier with no option support --- src/asm/barrier.rs | 53 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index 8091e0f..9691677 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -32,7 +32,7 @@ macro_rules! dmb_dsb { match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("DMB ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("dmb ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -46,7 +46,7 @@ macro_rules! dmb_dsb { match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("DSB ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("dsb ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -75,7 +75,7 @@ impl sealed::Isb for Sy { fn isb(&self) { match () { #[cfg(target_arch = "aarch64")] - () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, + () => unsafe { core::arch::asm!("isb sy", options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] () => unimplemented!(), @@ -83,14 +83,59 @@ impl sealed::Isb for Sy { } } +pub struct None; +pub const NONE: None = None {}; + +impl sealed::Dsb for None { + #[inline(always)] + fn dsb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("dsb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +impl sealed::Dmb for None { + #[inline(always)] + fn dmb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("dmb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +impl sealed::Isb for None { + #[inline(always)] + fn isb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("isb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +#[inline(always)] pub fn isb(_arg: impl sealed::Isb) { _arg.isb() } +#[inline(always)] pub fn dmb(_arg: impl sealed::Dmb) { _arg.dmb() } -pub fn dsb(_arg: impl sealed::Dsb){ +#[inline(always)] +pub fn dsb(_arg: impl sealed::Dsb) { _arg.dsb() } From 3079c68151ff785edf8ceebfa21e283de3d3465c Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:11:13 +0800 Subject: [PATCH 09/70] feat(cache): add cache invalidation support --- src/asm.rs | 1 + src/asm/cache.S | 62 +++++++++++++++++++++++++ src/asm/cache.rs | 75 +++++++++++++++++++++++++++++++ src/cache.rs | 97 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- src/mmu.rs | 1 + src/mmu/address.rs | 28 ++++++++---- src/registers/tcr_el2.rs | 4 ++ 8 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 src/asm/cache.S create mode 100644 src/asm/cache.rs create mode 100644 src/cache.rs diff --git a/src/asm.rs b/src/asm.rs index 87f3a13..f070b3b 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -10,6 +10,7 @@ pub mod barrier; pub mod random; +pub mod cache; pub mod tlb; /// The classic no-op diff --git a/src/asm/cache.S b/src/asm/cache.S new file mode 100644 index 0000000..499c738 --- /dev/null +++ b/src/asm/cache.S @@ -0,0 +1,62 @@ + +.macro dcache op + dsb sy + mrs x0, clidr_el1 + and x3, x0, #0x7000000 + lsr x3, x3, #23 + + cbz x3, finished_\op + mov x10, #0 + + loop1_\op: + add x2, x10, x10, lsr #1 + lsr x1, x0, x2 + and x1, x1, #7 + cmp x1, #2 + b.lt skip_\op + + msr csselr_el1, x10 + isb + + mrs x1, ccsidr_el1 + and x2, x1, #7 + add x2, x2, #4 + mov x4, #0x3ff + and x4, x4, x1, lsr #3 + clz w5, w4 + mov x7, #0x7fff + and x7, x7, x1, lsr #13 + + loop2_\op: + mov x9, x4 + + loop3_\op: + lsl x6, x9, x5 + orr x11, x10, x6 + lsl x6, x7, x2 + orr x11, x11, x6 + dc \op, x11 + subs x9, x9, #1 + b.ge loop3_\op + subs x7, x7, #1 + b.ge loop2_\op + + skip_\op: + add x10, x10, #2 + cmp x3, x10 + b.gt loop1_\op + + finished_\op: + mov x10, #0 + msr csselr_el1, x10 + dsb sy + isb +.endm + + +.global dcache_invall; +.type dcache_invall, %function; +dcache_invall: + dcache isw + ret +.size dcache_invall, .-dcache_invall diff --git a/src/asm/cache.rs b/src/asm/cache.rs new file mode 100644 index 0000000..9d751a7 --- /dev/null +++ b/src/asm/cache.rs @@ -0,0 +1,75 @@ +use crate::mmu::address::Segment; + +mod sealed { + + use crate::mmu::address::Segment; + + pub trait Ic { + fn ic(&self); + } + + pub trait Dc { + fn dc(&self, seg: Segment); + } +} + +macro_rules! ic { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::Ic for $T { + #[inline(always)] + fn ic(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("ic ", stringify!($A)), options(nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + }; +} + +macro_rules! dc { + ($A: ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T{}; + impl sealed::Dc for $T { + #[inline(always)] + fn dc(&self, mut seg: Segment){ + seg.round(64); + match() { + #[cfg(target_arch = "aarch64")] + () => unsafe { + for i in(seg.0 .. seg.1).step_by(64){ + core::arch::asm!(concat!("dc ",stringify!($A), ",{}"), in(reg) i, options(nostack)) + } + }, + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + } +} + +ic!(IALLU, Iallu); +ic!(IALLUIS, Ialluis); +dc!(CVAC, CVac); +dc!(IVAC, IVac); +dc!(CIVAC, CIVac); + +#[inline(always)] +pub fn ic(_arg: impl sealed::Ic) { + _arg.ic(); +} + +#[inline(always)] +pub fn dc(_arg: impl sealed::Dc, seg: Segment){ + _arg.dc(seg); +} diff --git a/src/cache.rs b/src/cache.rs new file mode 100644 index 0000000..4758302 --- /dev/null +++ b/src/cache.rs @@ -0,0 +1,97 @@ + +use core::arch::global_asm; +use super::asm::barrier::{NONE, isb, dsb, NSH}; +use super::asm::cache::{ic, IALLUIS}; +use crate::asm::cache::{dc, CVAC, IVAC, CIVAC}; +use crate::mmu::address::Segment; + +global_asm!(include_str!("./asm/cache.S")); + +mod sealed { + use crate::mmu::address::Segment; + pub trait Cache { + fn clean(&self, seg: Segment); + fn inv(&self, seg: Segment); + fn inv_all(&self); + fn inv_clean(&self, seg: Segment); + } +} + +extern "C" { + pub fn dcache_invall(); +} + +pub struct ICache {} +pub struct DCache {} + +pub const ICACHE: ICache = ICache {}; +pub const DCACHE: DCache = DCache {}; + +impl sealed::Cache for DCache { + + #[inline(always)] + fn clean(&self, seg: Segment) { + dc(IVAC, seg) + } + + #[inline(always)] + fn inv(&self, seg: Segment) { + dc(CVAC, seg) + } + + #[inline(always)] + fn inv_all(&self) { + unsafe { + dcache_invall(); + } + } + + #[inline(always)] + fn inv_clean(&self, seg: Segment) { + dc(CIVAC, seg); + } +} + +impl sealed::Cache for ICache{ + #[inline(always)] + fn clean(&self, seg: Segment){ + } + + #[inline(always)] + fn inv(&self, seg:Segment){ + + } + + #[inline(always)] + fn inv_all(&self){ + ic(IALLUIS); + } + + #[inline(always)] + fn inv_clean(&self, seg: Segment) { + + } + +} + +pub enum CacheFlush { + INV, + CLEAN, + INVCLEAN, +} + +pub fn flush_cache_area(_cache: impl sealed::Cache, seg: Segment, mode: CacheFlush) { + match mode { + CacheFlush::INV => _cache.inv(seg), + CacheFlush::INVCLEAN => _cache.inv_clean(seg), + CacheFlush::CLEAN => _cache.clean(seg), + } + dsb(NSH); + isb(NONE); +} + +pub fn flush_cache_all(_cache: impl sealed::Cache) { + _cache.inv_all(); + dsb(NSH); + isb(NONE); +} diff --git a/src/lib.rs b/src/lib.rs index 80be80d..f8f4240 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,8 +54,7 @@ //! profile](https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf?_ga=2.266626254.1122218691.1534883460-1326731866.1530967873). #![no_std] - -#![feature(concat_idents)] pub mod asm; pub mod mmu; pub mod registers; +pub mod cache; diff --git a/src/mmu.rs b/src/mmu.rs index 5538bb6..17b4adf 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,2 +1,3 @@ pub mod descriptor; pub mod address; + diff --git a/src/mmu/address.rs b/src/mmu/address.rs index bed24ab..9151199 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -1,5 +1,5 @@ use tock_registers::register_bitfields; -register_bitfields!{u64, +register_bitfields! {u64, VADescriptor [ L0 OFFSET(39) NUMBITS(9) [], L1 OFFSET(30) NUMBITS(9) [], @@ -9,19 +9,22 @@ register_bitfields!{u64, ] } -#[derive(Clone,Copy)] +#[derive(Clone, Copy)] #[repr(transparent)] pub struct VirtAddress(pub u64); -#[derive(Clone,Copy)] +#[derive(Clone, Copy)] #[repr(transparent)] pub struct PhyAddress(pub u64); -pub struct VirtLayout{ - pub indexes: [u64;4], - pub offset: u64 +pub struct VirtLayout { + pub indexes: [u64; 4], + pub offset: u64, } +#[derive(Clone, Copy)] +pub struct Segment(pub u64, pub u64); + impl VirtAddress { pub fn layout(&self) -> VirtLayout { VirtLayout { @@ -29,14 +32,21 @@ impl VirtAddress { VADescriptor::L0.read(self.0), VADescriptor::L1.read(self.0), VADescriptor::L2.read(self.0), - VADescriptor::L3.read(self.0) + VADescriptor::L3.read(self.0), ], - offset: VADescriptor::OFFSET.read(self.0) + offset: VADescriptor::OFFSET.read(self.0), } } } -impl From for VirtAddress{ +impl Segment { + pub fn round(&mut self, sz: u64) { + self.0 = self.0 & (!(sz - 1)); + self.1 = (self.1 + sz - 1) & (!(sz - 1)); + } +} + +impl From for VirtAddress { fn from(value: u64) -> Self { VirtAddress(value) } diff --git a/src/registers/tcr_el2.rs b/src/registers/tcr_el2.rs index d32dcea..92da8db 100644 --- a/src/registers/tcr_el2.rs +++ b/src/registers/tcr_el2.rs @@ -18,6 +18,10 @@ use tock_registers::{ register_bitfields! {u64, pub TCR_EL2 [ + AS OFFSET(36) NUMBITS(1) [ + Disable = 0, + Enable = 1, + ], /// When FEAT_HAFDBS is implemented hardware can update the dirty flags in the stage1 /// descriptors HD OFFSET(22) NUMBITS(1) [ From 3532cfdd6f6bdae45e8a00a4793398b18ad68476 Mon Sep 17 00:00:00 2001 From: varia Date: Thu, 8 Feb 2024 20:12:11 +0800 Subject: [PATCH 10/70] feat: add at instruction --- src/asm.rs | 1 + src/asm/at.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/asm/at.rs diff --git a/src/asm.rs b/src/asm.rs index f070b3b..50224ab 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,6 +12,7 @@ pub mod barrier; pub mod random; pub mod cache; pub mod tlb; +pub mod at; /// The classic no-op #[inline(always)] diff --git a/src/asm/at.rs b/src/asm/at.rs new file mode 100644 index 0000000..d16ede3 --- /dev/null +++ b/src/asm/at.rs @@ -0,0 +1,34 @@ +mod sealed { + pub trait At { + fn at(&self, va: u64); + } +} + +macro_rules! at { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::At for $T { + #[inline(always)] + fn at(&self, va: u64) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("at ", stringify!($A), ", {0}"), in(reg) va, options(nomem, nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + }; +} + +at!(S1E1R, S1e1r); + +#[inline(always)] +pub fn at(_arg:impl sealed::At , va:u64){ + _arg.at(va); +} From 6368eb1222e660d85bb235423dff69cd799b5fd3 Mon Sep 17 00:00:00 2001 From: varia Date: Thu, 8 Feb 2024 20:35:13 +0800 Subject: [PATCH 11/70] feat(reg): add hpfar_el2 register --- src/registers.rs | 2 ++ src/registers/hpfar_el2.rs | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/registers/hpfar_el2.rs diff --git a/src/registers.rs b/src/registers.rs index 79bae6a..d09a0ea 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -51,6 +51,7 @@ mod far_el2; mod far_el3; mod fp; mod hcr_el2; +mod hpfar_el2; mod id_aa64isar0_el1; mod id_aa64mmfr0_el1; mod id_aa64mmfr1_el1; @@ -138,6 +139,7 @@ pub use far_el2::FAR_EL2; pub use far_el3::FAR_EL3; pub use fp::FP; pub use hcr_el2::HCR_EL2; +pub use hpfar_el2::HPFAR_EL2; pub use id_aa64isar0_el1::ID_AA64ISAR0_EL1; pub use id_aa64mmfr0_el1::ID_AA64MMFR0_EL1; pub use id_aa64mmfr1_el1::ID_AA64MMFR1_EL1; diff --git a/src/registers/hpfar_el2.rs b/src/registers/hpfar_el2.rs new file mode 100644 index 0000000..1572908 --- /dev/null +++ b/src/registers/hpfar_el2.rs @@ -0,0 +1,40 @@ +//! Hypervisor IPA Fault Address Register +//! +//! Holds the faulting IPA for some aborts on a stage 2 translation taken to EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub HPFAR_EL2 [ + /// Faulting IPA address space + NS OFFSET(63) NUMBITS(1) [ + Secure = 0, + NonSecure = 1 + ], + /// Faulting Intermediate Physical Address + /// 40 bits, 40 = 52 - 12. 12 is the size of the page. + /// For implementations with fewer than 52 physical address bits, the corresponding upper bits in this field are RES0. + FIPA OFFSET(4) NUMBITS(40) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = HPFAR_EL2::Register; + + sys_coproc_read_raw!(u64, "HPFAR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = HPFAR_EL2::Register; + + sys_coproc_write_raw!(u64, "HPFAR_EL2", "x"); +} + +pub const HPFAR_EL2: Reg = Reg {}; From 7f18a5651f0930617c162133d54d2df71cf50471 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 8 Feb 2024 21:27:21 +0800 Subject: [PATCH 12/70] fix(descriptor): fix offset for address --- src/mmu/descriptor.rs | 6 ++---- src/registers/ttbr0_el2.rs | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 3c35349..8cb466c 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -18,9 +18,7 @@ register_bitfields! {u64, TRUE = 0b1, FALSE = 0b0 ], - L1OUTPUT OFFSET(30) NUMBITS(18) [], - L2OUTPUT OFFSET(21) NUMBITS(27) [], - L3OUTPUT OFFSET(12) NUMBITS(36) [], + OUTPUT OFFSET(0) NUMBITS(48) [], NSE_NG OFFSET(11) NUMBITS(1) [ TRUE = 0b1, FALSE = 0b0 @@ -77,7 +75,7 @@ register_bitfields! {u64, TRUE = 0b1, FALSE = 0b0 ], - OUTPUT OFFSET(12) NUMBITS(36) [], + OUTPUT OFFSET(0) NUMBITS(48) [], TYPE OFFSET(1) NUMBITS(1) [ TABLE = 0b1, BLOCK = 0b0 diff --git a/src/registers/ttbr0_el2.rs b/src/registers/ttbr0_el2.rs index 66e73e7..749f963 100644 --- a/src/registers/ttbr0_el2.rs +++ b/src/registers/ttbr0_el2.rs @@ -22,7 +22,7 @@ register_bitfields! {u64, RES0 OFFSET(48) NUMBITS(16) [], /// Translation table base address - BADDR OFFSET(1) NUMBITS(48) [], + BADDR OFFSET(0) NUMBITS(48) [], /// Common not Private CnP OFFSET(0) NUMBITS(1) [] From 5fa44b8b847af79346312de86c84d40adfaf31b4 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Tue, 13 Feb 2024 01:54:18 +0800 Subject: [PATCH 13/70] refactor(cache): refactor all cache flush operations --- src/asm/cache.S | 62 ------------------- src/asm/cache.rs | 26 ++++---- src/cache.rs | 150 +++++++++++++++++++++++---------------------- src/mmu/address.rs | 65 +++++++++++--------- 4 files changed, 123 insertions(+), 180 deletions(-) delete mode 100644 src/asm/cache.S diff --git a/src/asm/cache.S b/src/asm/cache.S deleted file mode 100644 index 499c738..0000000 --- a/src/asm/cache.S +++ /dev/null @@ -1,62 +0,0 @@ - -.macro dcache op - dsb sy - mrs x0, clidr_el1 - and x3, x0, #0x7000000 - lsr x3, x3, #23 - - cbz x3, finished_\op - mov x10, #0 - - loop1_\op: - add x2, x10, x10, lsr #1 - lsr x1, x0, x2 - and x1, x1, #7 - cmp x1, #2 - b.lt skip_\op - - msr csselr_el1, x10 - isb - - mrs x1, ccsidr_el1 - and x2, x1, #7 - add x2, x2, #4 - mov x4, #0x3ff - and x4, x4, x1, lsr #3 - clz w5, w4 - mov x7, #0x7fff - and x7, x7, x1, lsr #13 - - loop2_\op: - mov x9, x4 - - loop3_\op: - lsl x6, x9, x5 - orr x11, x10, x6 - lsl x6, x7, x2 - orr x11, x11, x6 - dc \op, x11 - subs x9, x9, #1 - b.ge loop3_\op - subs x7, x7, #1 - b.ge loop2_\op - - skip_\op: - add x10, x10, #2 - cmp x3, x10 - b.gt loop1_\op - - finished_\op: - mov x10, #0 - msr csselr_el1, x10 - dsb sy - isb -.endm - - -.global dcache_invall; -.type dcache_invall, %function; -dcache_invall: - dcache isw - ret -.size dcache_invall, .-dcache_invall diff --git a/src/asm/cache.rs b/src/asm/cache.rs index 9d751a7..698750f 100644 --- a/src/asm/cache.rs +++ b/src/asm/cache.rs @@ -1,15 +1,11 @@ -use crate::mmu::address::Segment; - mod sealed { - use crate::mmu::address::Segment; - pub trait Ic { fn ic(&self); } pub trait Dc { - fn dc(&self, seg: Segment); + fn dc(&self, addr: u64); } } @@ -41,14 +37,11 @@ macro_rules! dc { pub const $A: $T = $T{}; impl sealed::Dc for $T { #[inline(always)] - fn dc(&self, mut seg: Segment){ - seg.round(64); + fn dc(&self, addr:u64){ match() { #[cfg(target_arch = "aarch64")] () => unsafe { - for i in(seg.0 .. seg.1).step_by(64){ - core::arch::asm!(concat!("dc ",stringify!($A), ",{}"), in(reg) i, options(nostack)) - } + core::arch::asm!(concat!("dc ",stringify!($A), ",{}"), in(reg) addr, options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] () => unimplemented!(), @@ -60,9 +53,12 @@ macro_rules! dc { ic!(IALLU, Iallu); ic!(IALLUIS, Ialluis); -dc!(CVAC, CVac); -dc!(IVAC, IVac); -dc!(CIVAC, CIVac); +dc!(CVAC, Cvac); +dc!(IVAC, Ivac); +dc!(CIVAC, Civac); +dc!(CISW, Cisw); +dc!(ISW, Isw); +dc!(CSW, Csw); #[inline(always)] pub fn ic(_arg: impl sealed::Ic) { @@ -70,6 +66,6 @@ pub fn ic(_arg: impl sealed::Ic) { } #[inline(always)] -pub fn dc(_arg: impl sealed::Dc, seg: Segment){ - _arg.dc(seg); +pub fn dc(_arg: impl sealed::Dc, addr: u64) { + _arg.dc(addr); } diff --git a/src/cache.rs b/src/cache.rs index 4758302..78c2eb1 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,25 +1,10 @@ - -use core::arch::global_asm; -use super::asm::barrier::{NONE, isb, dsb, NSH}; -use super::asm::cache::{ic, IALLUIS}; -use crate::asm::cache::{dc, CVAC, IVAC, CIVAC}; -use crate::mmu::address::Segment; - -global_asm!(include_str!("./asm/cache.S")); - -mod sealed { - use crate::mmu::address::Segment; - pub trait Cache { - fn clean(&self, seg: Segment); - fn inv(&self, seg: Segment); - fn inv_all(&self); - fn inv_clean(&self, seg: Segment); - } -} - -extern "C" { - pub fn dcache_invall(); -} +use super::asm::barrier::{dsb, isb, NSH, SY}; +use crate::{ + asm::cache::{ic, dc, CIVAC, CVAC, IALLU, IVAC}, + irq::IRQ, + mmu::address::{MMRegion, MMSegment}, + registers::{Readable, Writeable, CCSIDR_EL1, CLIDR_EL1, CSSELR_EL1}, +}; pub struct ICache {} pub struct DCache {} @@ -27,71 +12,88 @@ pub struct DCache {} pub const ICACHE: ICache = ICache {}; pub const DCACHE: DCache = DCache {}; -impl sealed::Cache for DCache { - - #[inline(always)] - fn clean(&self, seg: Segment) { - dc(IVAC, seg) - } - - #[inline(always)] - fn inv(&self, seg: Segment) { - dc(CVAC, seg) - } - - #[inline(always)] - fn inv_all(&self) { - unsafe { - dcache_invall(); - } - } +pub enum FlushMode { + INV, + CLEAN, + INVCLEAN, +} - #[inline(always)] - fn inv_clean(&self, seg: Segment) { - dc(CIVAC, seg); - } +pub enum AddressMode { + WAYSET, + VIRTUAL, } -impl sealed::Cache for ICache{ - #[inline(always)] - fn clean(&self, seg: Segment){ +impl DCache { + fn get_flush_func(&self, flush_mode: FlushMode, address_mode: AddressMode) -> impl Fn(u64) { + match address_mode { + AddressMode::WAYSET => match flush_mode { + FlushMode::INV => move |addr: u64| dc(IVAC, addr), + FlushMode::CLEAN => move |addr: u64| dc(CVAC, addr), + FlushMode::INVCLEAN => move |addr: u64| dc(CIVAC, addr), + }, + AddressMode::VIRTUAL => match flush_mode { + FlushMode::INV => move |addr: u64| dc(IVAC, addr), + FlushMode::CLEAN => move |addr: u64| dc(CVAC, addr), + FlushMode::INVCLEAN => move |addr: u64| dc(CIVAC, addr), + }, + } } #[inline(always)] - fn inv(&self, seg:Segment){ - + pub fn flush(&self, addr: u64, mode: FlushMode) { + self.get_flush_func(mode, AddressMode::VIRTUAL)(addr); + dsb(SY); + isb(SY); } - #[inline(always)] - fn inv_all(&self){ - ic(IALLUIS); + pub fn flush_region(&self, virt: MMSegment, mode: FlushMode) { + MMRegion::new(virt, CCSIDR_EL1.read(CCSIDR_EL1::LineSize) + 4) + .into_iter() + .for_each(self.get_flush_func(mode, AddressMode::VIRTUAL)); + dsb(SY); + isb(SY); } - #[inline(always)] - fn inv_clean(&self, seg: Segment) { + pub fn flush_all(&self, mode: FlushMode) { + dsb(SY); + let loc = CLIDR_EL1.read(CLIDR_EL1::LoC); + let clidr = CLIDR_EL1.get(); + let _flush = self.get_flush_func(mode, AddressMode::WAYSET); + let mut irq = IRQ::new(); + + if loc != 0 { + for level in (0..loc).step_by(2) { + if (clidr >> (level + level >> 1)) & 0b111 < 2 { + continue; + } + + irq.save_and_disable(); + CSSELR_EL1.set(level); + isb(SY); + let ls = CCSIDR_EL1.read(CCSIDR_EL1::LineSize) + 4; // Notice that linesize needs taken special care of since CCSIDR_EL1 + // only offers log2(Words of Cache) instead of granularity of bytes + let m = CCSIDR_EL1.read(CCSIDR_EL1::AssociativityWithoutCCIDX); + let n = CCSIDR_EL1.read(CCSIDR_EL1::NumSetsWithoutCCIDX); + let k = m.leading_zeros(); + + irq.restore_and_enable(); + + (0..m + 1) + .flat_map(move |i| (0..n + 1).map(move |j| (i << k) | (j << ls))) + .for_each(&_flush); + } + } + CSSELR_EL1.set(0); + dsb(SY); + isb(SY); } - } -pub enum CacheFlush { - INV, - CLEAN, - INVCLEAN, -} - -pub fn flush_cache_area(_cache: impl sealed::Cache, seg: Segment, mode: CacheFlush) { - match mode { - CacheFlush::INV => _cache.inv(seg), - CacheFlush::INVCLEAN => _cache.inv_clean(seg), - CacheFlush::CLEAN => _cache.clean(seg), +impl ICache { + pub fn flush_all(&self) { + ic(IALLU); + dsb(NSH); + isb(SY); } - dsb(NSH); - isb(NONE); -} - -pub fn flush_cache_all(_cache: impl sealed::Cache) { - _cache.inv_all(); - dsb(NSH); - isb(NONE); } diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 9151199..9f1ff8a 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -9,51 +9,58 @@ register_bitfields! {u64, ] } -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct VirtAddress(pub u64); - -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct PhyAddress(pub u64); - pub struct VirtLayout { pub indexes: [u64; 4], pub offset: u64, } +pub type MMSegment = (u64, u64); + #[derive(Clone, Copy)] -pub struct Segment(pub u64, pub u64); +pub struct MMRegion { + pub mem: MMSegment, + pub granule: u64, +} -impl VirtAddress { - pub fn layout(&self) -> VirtLayout { - VirtLayout { - indexes: [ - VADescriptor::L0.read(self.0), - VADescriptor::L1.read(self.0), - VADescriptor::L2.read(self.0), - VADescriptor::L3.read(self.0), - ], - offset: VADescriptor::OFFSET.read(self.0), +impl MMRegion { + pub fn new(segment: MMSegment, granule: u64) -> Self { + MMRegion { + mem: ( + segment.0 & (!(granule - 1)), + (segment.1 + granule - 1) & (!(granule - 1)), + ), + granule, } } -} -impl Segment { - pub fn round(&mut self, sz: u64) { - self.0 = self.0 & (!(sz - 1)); - self.1 = (self.1 + sz - 1) & (!(sz - 1)); + pub fn inbound(&self, addr: u64) -> bool { + return self.mem.0 <= addr && addr < self.mem.1; } } -impl From for VirtAddress { - fn from(value: u64) -> Self { - VirtAddress(value) +impl Iterator for MMRegion { + type Item = u64; + fn next(&mut self) -> Option { + let ret = self.mem.0; + if self.inbound(ret) { + self.mem.0 += self.granule; + Some(ret) + } else { + None + } } } -impl From for PhyAddress { +impl From for VirtLayout { fn from(value: u64) -> Self { - PhyAddress(value) + Self { + indexes: [ + VADescriptor::L0.read(value), + VADescriptor::L1.read(value), + VADescriptor::L2.read(value), + VADescriptor::L3.read(value), + ], + offset: VADescriptor::OFFSET.read(value), + } } } From faea5e29dc5bdb3b3587e9c7fa4841072466ecb8 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Tue, 13 Feb 2024 01:54:28 +0800 Subject: [PATCH 14/70] feat(irq): add irq support --- src/irq.rs | 33 +++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/irq.rs diff --git a/src/irq.rs b/src/irq.rs new file mode 100644 index 0000000..92d34f2 --- /dev/null +++ b/src/irq.rs @@ -0,0 +1,33 @@ +#[repr(transparent)] +pub struct IRQ(u64); + +impl IRQ { + pub fn new() -> Self { + IRQ(0) + } + #[inline(always)] + unsafe fn enable(&self) { + unsafe { core::arch::asm!("msr daifclr, #2", options(nostack)) } + } + + #[inline(always)] + unsafe fn disable(&self) { + unsafe { core::arch::asm!("msr daifclr, #2", options(nostack)) } + } + + #[inline(always)] + pub fn save_and_disable(&mut self) { + unsafe { + core::arch::asm!("mrs {}, daif", out(reg) self.0, options(nostack)); + self.disable(); + } + } + + #[inline(always)] + pub fn restore_and_enable(&self) { + unsafe { + core::arch::asm!("msr daif, {}", in(reg) self.0, options(nostack)); + self.enable(); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index f8f4240..525c047 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,5 +56,6 @@ #![no_std] pub mod asm; pub mod mmu; -pub mod registers; +pub mod irq; pub mod cache; +pub mod registers; From 0dc1e39da3eaf6feae16b712763fea355ea51410 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Tue, 13 Feb 2024 02:12:23 +0800 Subject: [PATCH 15/70] fix: fix typo --- src/cache.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cache.rs b/src/cache.rs index 78c2eb1..f8f330d 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,6 +1,6 @@ use super::asm::barrier::{dsb, isb, NSH, SY}; use crate::{ - asm::cache::{ic, dc, CIVAC, CVAC, IALLU, IVAC}, + asm::cache::{dc, ic, CISW, CIVAC, CSW, CVAC, IALLU, ISW, IVAC}, irq::IRQ, mmu::address::{MMRegion, MMSegment}, registers::{Readable, Writeable, CCSIDR_EL1, CLIDR_EL1, CSSELR_EL1}, @@ -27,9 +27,9 @@ impl DCache { fn get_flush_func(&self, flush_mode: FlushMode, address_mode: AddressMode) -> impl Fn(u64) { match address_mode { AddressMode::WAYSET => match flush_mode { - FlushMode::INV => move |addr: u64| dc(IVAC, addr), - FlushMode::CLEAN => move |addr: u64| dc(CVAC, addr), - FlushMode::INVCLEAN => move |addr: u64| dc(CIVAC, addr), + FlushMode::INV => move |addr: u64| dc(ISW, addr), + FlushMode::CLEAN => move |addr: u64| dc(CSW, addr), + FlushMode::INVCLEAN => move |addr: u64| dc(CISW, addr), }, AddressMode::VIRTUAL => match flush_mode { FlushMode::INV => move |addr: u64| dc(IVAC, addr), From 9ee5d78a9ffa19ed4eba16d06c9c7925a525ab58 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 14 Feb 2024 00:26:55 +0800 Subject: [PATCH 16/70] feat: update exception reason enum --- src/exception.rs | 14 ++++++++++++++ src/lib.rs | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/exception.rs diff --git a/src/exception.rs b/src/exception.rs new file mode 100644 index 0000000..2766b0a --- /dev/null +++ b/src/exception.rs @@ -0,0 +1,14 @@ +#[derive(Copy, Clone)] +pub enum ExceptionReason { + DataAbort = 0x24, + Unimplemented = 0xff, +} + +impl From for ExceptionReason{ + fn from(value: u64) -> Self { + match value { + x if x == Self::DataAbort as u64 => Self::DataAbort, + _ => Self::Unimplemented + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 525c047..4e35ed8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,4 +58,5 @@ pub mod asm; pub mod mmu; pub mod irq; pub mod cache; +pub mod exception; pub mod registers; From edf1591d587a01a711dae446867c01d4bfb5b54d Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 22 Feb 2024 16:56:13 +0800 Subject: [PATCH 17/70] feat(mmu): update mmtype/mmprot abstraction --- src/mmu/address.rs | 129 +++++++++++++++++++++++++++++++++++++++--- src/mmu/descriptor.rs | 4 +- 2 files changed, 123 insertions(+), 10 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 9f1ff8a..c393b15 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -1,4 +1,9 @@ use tock_registers::register_bitfields; +use tock_registers::fields::FieldValue; +use super::descriptor::BlockDescriptor; +use core::iter::StepBy; +use core::ops::Range; + register_bitfields! {u64, VADescriptor [ L0 OFFSET(39) NUMBITS(9) [], @@ -9,6 +14,35 @@ register_bitfields! {u64, ] } +#[derive(Copy, Clone)] +pub enum MMProt { + NormalReadOnly, + NormalExecOnly, + NormalReadWriteAll, + NormalReadWriteNoExec, + PrivilegedExecOnly, + PrivilegedReadOnly, + PrivilegedReadWrite, + SecureExecOnly, + SecureReadOnly, + SecureReadWrite, +} + +#[derive(Copy, Clone)] +pub enum MMType { + Device, + Normal, + NormalNoExec, + ReadOnly, + Instruction, + SystemReserved, + SystemReadOnly, + SystemInstruction, + SecureReadOnly, + SecureExecOnly, + SecureReadWrite, +} + pub struct VirtLayout { pub indexes: [u64; 4], pub offset: u64, @@ -38,19 +72,96 @@ impl MMRegion { } } -impl Iterator for MMRegion { - type Item = u64; - fn next(&mut self) -> Option { - let ret = self.mem.0; - if self.inbound(ret) { - self.mem.0 += self.granule; - Some(ret) - } else { - None +impl MMType { + pub fn default_prot(&self) -> MMProt { + match *self { + Self::Normal => MMProt::NormalReadWriteAll, + Self::NormalNoExec => MMProt::NormalReadWriteNoExec, + Self::ReadOnly => MMProt::NormalReadOnly, + Self::Instruction => MMProt::NormalExecOnly, + Self::Device => MMProt::PrivilegedReadWrite, + Self::SystemReserved => MMProt::PrivilegedReadWrite, + Self::SystemInstruction => MMProt::PrivilegedExecOnly, + Self::SystemReadOnly => MMProt::PrivilegedReadOnly, + _ => unimplemented!(), } } } +impl From for FieldValue { + fn from(value: MMProt) -> Self { + match value { + MMProt::NormalReadWriteAll => { + BlockDescriptor::UXN_XN::FALSE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RW_ELx_RW_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalReadWriteNoExec => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RW_ELx_RW_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalExecOnly => { + BlockDescriptor::UXN_XN::FALSE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RO_ELx_RO_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalReadOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RO_ELx_RO_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedReadOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RO_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedExecOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RO_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedReadWrite => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RW_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + _ => unimplemented!(), + } + } +} + +impl From for FieldValue { + fn from(value: MMType) -> Self { + let prot_fields: FieldValue = value.default_prot().into(); + let type_fields = match value { + MMType::Device => BlockDescriptor::SH::CLEAR, + _ => BlockDescriptor::SH::IS, + }; + prot_fields + + type_fields + + BlockDescriptor::NSE_NG::TRUE + + BlockDescriptor::VALID::TRUE + + BlockDescriptor::TYPE::BLOCK + + BlockDescriptor::AF::TRUE + } +} + +impl IntoIterator for MMRegion { + type Item = u64; + type IntoIter = StepBy>; + fn into_iter(self) -> Self::IntoIter { + (self.mem.0..self.mem.1).step_by(self.granule as usize) + } +} + impl From for VirtLayout { fn from(value: u64) -> Self { Self { diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 8cb466c..2e8cdd1 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -43,7 +43,9 @@ register_bitfields! {u64, TRUE = 0b1, FALSE = 0b0 ], - ATTR OFFSET(2) NUMBITS(2) [], + ATTR OFFSET(2) NUMBITS(2) [ + + ], TYPE OFFSET(1) NUMBITS(1) [ BLOCK = 0b0, PAGE = 0b1 From befb6ca0085c8350ac6032b5bd56b37b45f3ae53 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 22 Feb 2024 21:03:36 +0800 Subject: [PATCH 18/70] feat(registers): add TTBR traits for loading generics --- src/registers.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/registers.rs b/src/registers.rs index d09a0ea..18d6cb9 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -181,5 +181,12 @@ pub use vbar_el3::VBAR_EL3; pub use vtcr_el2::VTCR_EL2; pub use vttbr_el2::VTTBR_EL2; +pub trait TTBR {} + +impl TTBR for vttbr_el2::Reg{} +impl TTBR for ttbr0_el1::Reg{} +impl TTBR for ttbr1_el1::Reg{} +impl TTBR for ttbr0_el2::Reg{} + #[doc(inline)] pub use tock_registers::interfaces::{Readable, Writeable}; From 81fde03125d26a55cb331e944e8f19afcced87c6 Mon Sep 17 00:00:00 2001 From: varia Date: Mon, 4 Mar 2024 20:55:46 +0800 Subject: [PATCH 19/70] feat(reg): add field about data abort for esr_el2 --- src/registers/esr_el2.rs | 153 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/src/registers/esr_el2.rs b/src/registers/esr_el2.rs index 917b2ad..10e57f7 100644 --- a/src/registers/esr_el2.rs +++ b/src/registers/esr_el2.rs @@ -81,7 +81,158 @@ register_bitfields! {u64, /// Instruction Specific Syndrome. Architecturally, this field can be defined independently /// for each defined Exception class. However, in practice, some ISS encodings are used for /// more than one Exception class. - ISS OFFSET(0) NUMBITS(25) [] + ISS OFFSET(0) NUMBITS(25) [], + + // Data Abort Syndrome Register fields + // These fields are only valid if EC.DataAbort is set. + + // Is the syndrome valid? + ISV OFFSET(24) NUMBITS(1) [ + /// 0b0: The syndrome information is not valid. + NotValid = 0, + /// 0b1: The syndrome information is valid. + Valid = 1 + ], + + // Syndrome Access Size + SAS OFFSET(22) NUMBITS(2) [ + /// 0b00: Byte + Byte = 0b00, + /// 0b01: Half-word + HalfWord = 0b01, + /// 0b10: Word + Word = 0b10, + /// 0b11: Double-word + DoubleWord = 0b11 + ], + + // Syndrome Sign-Extend + SSE OFFSET(21) NUMBITS(1) [ + /// 0b0: Zero-extend + ZeroExtend = 0, + /// 0b1: Sign-extend + SignExtend = 1 + ], + + // Syndrome Register + SRT OFFSET(16) NUMBITS(5) [], + + // Syndrome Register Width + SF OFFSET(15) NUMBITS(1) [ + /// 0b0: 32-bit + Bit32 = 0, + /// 0b1: 64-bit + Bit64 = 1 + ], + + // Acquire-Release + AR OFFSET(14) NUMBITS(1) [ + /// 0b0: Normal memory access + Normal = 0, + /// 0b1: Acquire or release access + AcquireRelease = 1 + ], + + // Virtual Nested Abort + VNCR OFFSET(13) NUMBITS(1) [ + /// 0b0: Not a virtual nested abort + NotVirtualNested = 0, + /// 0b1: Virtual nested abort + VirtualNested = 1 + ], + + // Load-Store Type + LST OFFSET(11) NUMBITS(2) [ + /// 0b01: ST64BV + ST64BV = 0b01, + /// 0b10: LD64B or ST64B + LD64BorST64B = 0b10, + /// 0b11: ST64BV0 + ST64BV0 = 0b11 + ], + + // Is FAR not valid? + FnV OFFSET(10) NUMBITS(1) [ + /// 0b0: FAR is valid + Valid = 0, + /// 0b1: FAR is not valid + NotValid = 1 + ], + + // External Abort Type + EA OFFSET(9) NUMBITS(1) [ + /// 0b0 Not an external abort + NotExternal = 0, + /// 0b1: External + External = 1 + ], + + // Cache maintenance operation + CM OFFSET(8) NUMBITS(1) [ + /// 0b0: Not a cache maintenance operation + NotCacheMaintenance = 0, + /// 0b1: Cache maintenance operation + CacheMaintenance = 1 + ], + + // Which stage caused the stage 2 abort? + S1PTW OFFSET(7) NUMBITS(1) [ + /// 0b0: Stage 1 + Stage1 = 0, + /// 0b1: Stage 2 + Stage2 = 1 + ], + + // Write not Read + WnR OFFSET(6) NUMBITS(1) [ + /// 0b0: Read access + Read = 0, + /// 0b1: Write access + Write = 1 + ], + + // Data Fault Status Code + DFSC OFFSET(0) NUMBITS(6) [ + /// 0b000000: Address size fault, level 0 + AddressSizeFaultLevel0 = 0b000000, + /// 0b000001: Address size fault, level 1 + AddressSizeFaultLevel1 = 0b000001, + /// 0b000010: Address size fault, level 2 + AddressSizeFaultLevel2 = 0b000010, + /// 0b000011: Address size fault, level 3 + AddressSizeFaultLevel3 = 0b000011, + + /// 0b000100: Translation fault, level 0 + TranslationFaultLevel0 = 0b000100, + /// 0b000101: Translation fault, level 1 + TranslationFaultLevel1 = 0b000101, + /// 0b000110: Translation fault, level 2 + TranslationFaultLevel2 = 0b000110, + /// 0b000111: Translation fault, level 3 + TranslationFaultLevel3 = 0b000111, + + /// 0b001000: Access flag fault, level 0 + AccessFlagFaultLevel0 = 0b001000, + /// 0b001001: Access flag fault, level 1 + AccessFlagFaultLevel1 = 0b001001, + /// 0b001010: Access flag fault, level 2 + AccessFlagFaultLevel2 = 0b001010, + /// 0b001011: Access flag fault, level 3 + AccessFlagFaultLevel3 = 0b001011, + + /// 0b001101: Permission fault, level 1 + PermissionFaultLevel1 = 0b001101, + /// 0b001110: Permission fault, level 2 + PermissionFaultLevel2 = 0b001110, + /// 0b001111: Permission fault, level 3 + PermissionFaultLevel3 = 0b001111, + + /// 0b010000: Synchronous external abort, not on translation table walk or + /// hardware update of translation table + SynchronousExternalAbortNotOnTranslationTableWalk = 0b010000 + + // ... and many more + ] ] } From 99d4b6f70b6e71978fd8d3a9529befb67d38ec22 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 8 Mar 2024 03:18:54 +0800 Subject: [PATCH 20/70] feat(registers): add vmpidr_el2 Signed-off-by: Yiyang Wu --- src/registers.rs | 2 ++ src/registers/vmpidr_el2.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/registers/vmpidr_el2.rs diff --git a/src/registers.rs b/src/registers.rs index 18d6cb9..d51a188 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -92,6 +92,7 @@ mod vbar_el2; mod vbar_el3; mod vtcr_el2; mod vttbr_el2; +mod vmpidr_el2; pub use actlr_el1::ACTLR_EL1; pub use actlr_el2::ACTLR_EL2; @@ -180,6 +181,7 @@ pub use vbar_el2::VBAR_EL2; pub use vbar_el3::VBAR_EL3; pub use vtcr_el2::VTCR_EL2; pub use vttbr_el2::VTTBR_EL2; +pub use vmpidr_el2::VMPIDR_EL2; pub trait TTBR {} diff --git a/src/registers/vmpidr_el2.rs b/src/registers/vmpidr_el2.rs new file mode 100644 index 0000000..752c16b --- /dev/null +++ b/src/registers/vmpidr_el2.rs @@ -0,0 +1,31 @@ +use tock_registers::interfaces::{Readable, Writeable}; +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub VMPIDR_EL2 [ + U OFFSET(32) NUMBITS(8), + AFF3 OFFSET(25) NUMBITS(5), + MT OFFSET(24) NUMBITS(1), + AFF2 OFFSET(18) NUMBITS(5), + AFF1 OFFSET(8) NUMBITS(9), + AFF0 OFFSET(0) NUMBITS(8) + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = VMPIDR_EL2::Register; + + sys_coproc_read_raw!(u64, "VMPIDR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = VMPIDR_EL2::Register; + + sys_coproc_write_raw!(u64, "VMPIDR_EL2", "x"); +} + +pub const VMPIDR_EL2: Reg = Reg {}; From 8a52975b80723eee28aefcb20b76bbd95ce3c127 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:06 +0800 Subject: [PATCH 21/70] feat(asm): add tlbi support and rewrite barrier static methods --- src/asm.rs | 1 + src/asm/barrier.rs | 45 +++++++++++++-------------------------------- src/asm/tlb.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 32 deletions(-) create mode 100644 src/asm/tlb.rs diff --git a/src/asm.rs b/src/asm.rs index 8e0749d..87f3a13 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -10,6 +10,7 @@ pub mod barrier; pub mod random; +pub mod tlb; /// The classic no-op #[inline(always)] diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index c3e9373..c696455 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -9,15 +9,19 @@ mod sealed { pub trait Dmb { - fn __dmb(&self); + fn dmb(); } pub trait Dsb { - fn __dsb(&self); + fn dsb(); } pub trait Isb { - fn __isb(&self); + fn isb(); + } + + pub trait Tlbi { + fn __tlbi(); } } @@ -25,7 +29,7 @@ macro_rules! dmb_dsb { ($A:ident) => { impl sealed::Dmb for $A { #[inline(always)] - fn __dmb(&self) { + fn dmb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -39,7 +43,7 @@ macro_rules! dmb_dsb { } impl sealed::Dsb for $A { #[inline(always)] - fn __dsb(&self) { + fn dsb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -54,6 +58,9 @@ macro_rules! dmb_dsb { }; } + + + pub struct SY; pub struct ST; pub struct LD; @@ -82,7 +89,7 @@ dmb_dsb!(OSHLD); impl sealed::Isb for SY { #[inline(always)] - fn __isb(&self) { + fn isb() { match () { #[cfg(target_arch = "aarch64")] () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, @@ -93,29 +100,3 @@ impl sealed::Isb for SY { } } -/// Data Memory Barrier. -#[inline(always)] -pub fn dmb(arg: A) -where - A: sealed::Dmb, -{ - arg.__dmb() -} - -/// Data Synchronization Barrier. -#[inline(always)] -pub fn dsb(arg: A) -where - A: sealed::Dsb, -{ - arg.__dsb() -} - -/// Instruction Synchronization Barrier. -#[inline(always)] -pub fn isb(arg: A) -where - A: sealed::Isb, -{ - arg.__isb() -} diff --git a/src/asm/tlb.rs b/src/asm/tlb.rs new file mode 100644 index 0000000..62e311d --- /dev/null +++ b/src/asm/tlb.rs @@ -0,0 +1,30 @@ +mod sealed { + pub trait Tlbi { + fn invalidate(); + } +} + +macro_rules! tlbi{ + ($A: ident) => { + pub struct $A; + impl sealed::Tlbi for $A { + #[inline(always)] + fn invalidate(){ + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("tlbi ", stringify!($A)), options(nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + } +} + + +tlbi!(VMALLE1IS); +tlbi!(VMALLE2IS); +tlbi!(VMALLE3IS); From 0ad2db1a9a1978f823427de0ec127f3cbf90efda Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:32 +0800 Subject: [PATCH 22/70] feat: init mmu modules --- src/mmu.rs | 2 ++ src/mmu/entry.rs | 1 + src/mmu/table.rs | 0 3 files changed, 3 insertions(+) create mode 100644 src/mmu.rs create mode 100644 src/mmu/entry.rs create mode 100644 src/mmu/table.rs diff --git a/src/mmu.rs b/src/mmu.rs new file mode 100644 index 0000000..f5d6eb0 --- /dev/null +++ b/src/mmu.rs @@ -0,0 +1,2 @@ +pub mod entry; +pub mod table; diff --git a/src/mmu/entry.rs b/src/mmu/entry.rs new file mode 100644 index 0000000..834fca2 --- /dev/null +++ b/src/mmu/entry.rs @@ -0,0 +1 @@ +use tock_registers::{register_bitfields, interfaces::{Readable,Writeable}}; diff --git a/src/mmu/table.rs b/src/mmu/table.rs new file mode 100644 index 0000000..e69de29 From b43b4194951d52ba62bb460cf5be6179858e6e60 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:44 +0800 Subject: [PATCH 23/70] feat: add TTBR1_EL2 module --- src/registers/ttbr1_el2.rs | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/registers/ttbr1_el2.rs diff --git a/src/registers/ttbr1_el2.rs b/src/registers/ttbr1_el2.rs new file mode 100644 index 0000000..55e897d --- /dev/null +++ b/src/registers/ttbr1_el2.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2023 by the author(s) +// +// Author(s): +// - Yiyang Wu + +//! Translation Table Base Register 1 - EL2 +//! +//! Holds the base address of the translation table for the initial lookup for stage 1 of the +//! translation of an address from the higher VA range in the EL2&0 translation regime, and other +//! information for this translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TTBR1_EL2 [ + /// An ASID for the translation table base address. The TCR_EL2.A1 field selects either + /// TTBR0_EL2.ASID or TTBR1_EL1.ASID. + /// + /// If the implementation has only 8 bits of ASID, then the upper 8 bits of this field are + /// RES 0. + ASID OFFSET(48) NUMBITS(16) [], + + /// Translation table base address + BADDR OFFSET(1) NUMBITS(47) [], + + /// Common not Private + CnP OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = TTBR1_EL2::Register; + + sys_coproc_read_raw!(u64, "TTBR1_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TTBR1_EL2::Register; + + sys_coproc_write_raw!(u64, "TTBR1_EL2", "x"); +} + +impl Reg { + #[inline(always)] + pub fn get_baddr(&self) -> u64 { + self.read(TTBR1_EL2::BADDR) << 1 + } + + #[inline(always)] + pub fn set_baddr(&self, addr: u64) { + self.write(TTBR1_EL2::BADDR.val(addr >> 1)); + } +} + +pub const TTBR1_EL2: Reg = Reg {}; From fe0d945966dbb8384dbe56f44749dd3a6969a3fd Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Mon, 22 Jan 2024 02:09:54 +0800 Subject: [PATCH 24/70] deps: bmp Cargo deps --- rust-toolchain.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1a43ef9..b442dc7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] -targets = ["aarch64-unknown-none-softfloat"] +channel = "nightly" +targets = ["aarch64-unknown-none"] From 7c99a1193f23d605637223e93c50a7beeb4c5e1a Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 24 Jan 2024 23:28:58 +0800 Subject: [PATCH 25/70] fix(barrier): wrap barrier --- src/asm/barrier.rs | 80 +++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index c696455..8091e0f 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -9,27 +9,26 @@ mod sealed { pub trait Dmb { - fn dmb(); + fn dmb(&self); } pub trait Dsb { - fn dsb(); + fn dsb(&self); } pub trait Isb { - fn isb(); - } - - pub trait Tlbi { - fn __tlbi(); + fn isb(&self); } } macro_rules! dmb_dsb { - ($A:ident) => { - impl sealed::Dmb for $A { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::Dmb for $T { #[inline(always)] - fn dmb() { + fn dmb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -41,9 +40,9 @@ macro_rules! dmb_dsb { } } } - impl sealed::Dsb for $A { + impl sealed::Dsb for $T { #[inline(always)] - fn dsb() { + fn dsb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -58,38 +57,22 @@ macro_rules! dmb_dsb { }; } - - - -pub struct SY; -pub struct ST; -pub struct LD; -pub struct ISH; -pub struct ISHST; -pub struct ISHLD; -pub struct NSH; -pub struct NSHST; -pub struct NSHLD; -pub struct OSH; -pub struct OSHST; -pub struct OSHLD; - -dmb_dsb!(SY); -dmb_dsb!(ST); -dmb_dsb!(LD); -dmb_dsb!(ISH); -dmb_dsb!(ISHST); -dmb_dsb!(ISHLD); -dmb_dsb!(NSH); -dmb_dsb!(NSHST); -dmb_dsb!(NSHLD); -dmb_dsb!(OSH); -dmb_dsb!(OSHST); -dmb_dsb!(OSHLD); - -impl sealed::Isb for SY { +dmb_dsb!(SY, Sy); +dmb_dsb!(ST, St); +dmb_dsb!(LD, Ld); +dmb_dsb!(ISH, Ish); +dmb_dsb!(ISHST, Ishst); +dmb_dsb!(ISHLD, Ishld); +dmb_dsb!(NSH, Nsh); +dmb_dsb!(NSHST, Nshst); +dmb_dsb!(NSHLD, Nshld); +dmb_dsb!(OSH, Osh); +dmb_dsb!(OSHST, Oshst); +dmb_dsb!(OSHLD, Oshld); + +impl sealed::Isb for Sy { #[inline(always)] - fn isb() { + fn isb(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, @@ -100,3 +83,14 @@ impl sealed::Isb for SY { } } +pub fn isb(_arg: impl sealed::Isb) { + _arg.isb() +} + +pub fn dmb(_arg: impl sealed::Dmb) { + _arg.dmb() +} + +pub fn dsb(_arg: impl sealed::Dsb){ + _arg.dsb() +} From 21b8836b112fb894db84c828d6ecab28daef3dbb Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 24 Jan 2024 23:29:12 +0800 Subject: [PATCH 26/70] feat: impl mmu features --- src/lib.rs | 2 + src/mmu.rs | 4 +- src/mmu/address.rs | 49 ++++++++++++++++++ src/mmu/descriptor.rs | 118 ++++++++++++++++++++++++++++++++++++++++++ src/mmu/entry.rs | 1 - src/mmu/table.rs | 0 6 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/mmu/address.rs create mode 100644 src/mmu/descriptor.rs delete mode 100644 src/mmu/entry.rs delete mode 100644 src/mmu/table.rs diff --git a/src/lib.rs b/src/lib.rs index 52c7402..80be80d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,5 +55,7 @@ #![no_std] +#![feature(concat_idents)] pub mod asm; +pub mod mmu; pub mod registers; diff --git a/src/mmu.rs b/src/mmu.rs index f5d6eb0..5538bb6 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,2 +1,2 @@ -pub mod entry; -pub mod table; +pub mod descriptor; +pub mod address; diff --git a/src/mmu/address.rs b/src/mmu/address.rs new file mode 100644 index 0000000..bed24ab --- /dev/null +++ b/src/mmu/address.rs @@ -0,0 +1,49 @@ +use tock_registers::register_bitfields; +register_bitfields!{u64, + VADescriptor [ + L0 OFFSET(39) NUMBITS(9) [], + L1 OFFSET(30) NUMBITS(9) [], + L2 OFFSET(21) NUMBITS(9) [], + L3 OFFSET(12) NUMBITS(9) [], + OFFSET OFFSET(0) NUMBITS(12) [] + ] +} + +#[derive(Clone,Copy)] +#[repr(transparent)] +pub struct VirtAddress(pub u64); + +#[derive(Clone,Copy)] +#[repr(transparent)] +pub struct PhyAddress(pub u64); + +pub struct VirtLayout{ + pub indexes: [u64;4], + pub offset: u64 +} + +impl VirtAddress { + pub fn layout(&self) -> VirtLayout { + VirtLayout { + indexes: [ + VADescriptor::L0.read(self.0), + VADescriptor::L1.read(self.0), + VADescriptor::L2.read(self.0), + VADescriptor::L3.read(self.0) + ], + offset: VADescriptor::OFFSET.read(self.0) + } + } +} + +impl From for VirtAddress{ + fn from(value: u64) -> Self { + VirtAddress(value) + } +} + +impl From for PhyAddress { + fn from(value: u64) -> Self { + PhyAddress(value) + } +} diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs new file mode 100644 index 0000000..3c35349 --- /dev/null +++ b/src/mmu/descriptor.rs @@ -0,0 +1,118 @@ +use tock_registers::{ + register_bitfields, + fields::{FieldValue, Field}, + RegisterLongName, +}; + +register_bitfields! {u64, + pub BlockDescriptor [ + UXN_XN OFFSET(54) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + PXN OFFSET(53) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + CONTIGUOUS OFFSET(52) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + L1OUTPUT OFFSET(30) NUMBITS(18) [], + L2OUTPUT OFFSET(21) NUMBITS(27) [], + L3OUTPUT OFFSET(12) NUMBITS(36) [], + NSE_NG OFFSET(11) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + AF OFFSET(10) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + SH OFFSET(8) NUMBITS(2) [ + NS = 0b00, + RESERVED = 0b01, + OS = 0b10, + IS = 0b11 + ], + AP OFFSET(6) NUMBITS(2) [ + RW_ELx_None_EL0 = 0b00, + RW_ELx_RW_EL0 = 0b01, + RO_ELx_None_EL0 = 0b10, + RO_ELx_RO_EL0 = 0b11 + ], + NS OFFSET(5) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + ATTR OFFSET(2) NUMBITS(2) [], + TYPE OFFSET(1) NUMBITS(1) [ + BLOCK = 0b0, + PAGE = 0b1 + ], + VALID OFFSET(0) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ] + ] +} + +register_bitfields! {u64, + pub TableDescriptor [ + NS OFFSET(63) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + AP OFFSET(61) NUMBITS(2) [ + NO_EFFECT = 0b00, + UNPRIV_RESTRICTED = 0b01, + WR_RESTRICTED = 0b10, + WR_UNPRIV_RD_RESTRICTED = 0b11 + ], + UXN_XN OFFSET(60) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + PXN OFFSET(59) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ], + OUTPUT OFFSET(12) NUMBITS(36) [], + TYPE OFFSET(1) NUMBITS(1) [ + TABLE = 0b1, + BLOCK = 0b0 + ], + VALID OFFSET(0) NUMBITS(1) [ + TRUE = 0b1, + FALSE = 0b0 + ] + ] +} + +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct VADescriptor(pub u64); + +impl VADescriptor { + pub fn read(&self) -> u64 { + self.0 + } + + pub fn read_field(&self, field: Field) -> u64 + where + T: RegisterLongName, + { + field.read(self.0) + } + + pub fn write(&mut self, val: u64) { + self.0 = val; + } + + pub fn write_field(&mut self, field_value: FieldValue) + where + T: RegisterLongName, + { + self.0 = field_value.modify(self.0); + } +} diff --git a/src/mmu/entry.rs b/src/mmu/entry.rs deleted file mode 100644 index 834fca2..0000000 --- a/src/mmu/entry.rs +++ /dev/null @@ -1 +0,0 @@ -use tock_registers::{register_bitfields, interfaces::{Readable,Writeable}}; diff --git a/src/mmu/table.rs b/src/mmu/table.rs deleted file mode 100644 index e69de29..0000000 From a2dc639c572a375947ff26df843d5dd8423118f6 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:10:41 +0800 Subject: [PATCH 27/70] fix(tlb): fix missing vmalle2is --- src/asm/tlb.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/asm/tlb.rs b/src/asm/tlb.rs index 62e311d..91747fe 100644 --- a/src/asm/tlb.rs +++ b/src/asm/tlb.rs @@ -1,6 +1,6 @@ mod sealed { pub trait Tlbi { - fn invalidate(); + fn invalidate(&self); } } @@ -9,11 +9,11 @@ macro_rules! tlbi{ pub struct $A; impl sealed::Tlbi for $A { #[inline(always)] - fn invalidate(){ + fn invalidate(&self){ match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("tlbi ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("TLBI ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -26,5 +26,10 @@ macro_rules! tlbi{ tlbi!(VMALLE1IS); -tlbi!(VMALLE2IS); -tlbi!(VMALLE3IS); +tlbi!(ALLE2IS); +tlbi!(ALLE3IS); + +#[inline(always)] +pub fn tlb_inv(_arg: impl sealed::Tlbi){ + _arg.invalidate(); +} From 29bbeb73be037a312537aa0a3d6668de334d9d81 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:10:58 +0800 Subject: [PATCH 28/70] feat(barrier): add barrier with no option support --- src/asm/barrier.rs | 53 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs index 8091e0f..9691677 100644 --- a/src/asm/barrier.rs +++ b/src/asm/barrier.rs @@ -32,7 +32,7 @@ macro_rules! dmb_dsb { match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("DMB ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("dmb ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -46,7 +46,7 @@ macro_rules! dmb_dsb { match () { #[cfg(target_arch = "aarch64")] () => unsafe { - core::arch::asm!(concat!("DSB ", stringify!($A)), options(nostack)) + core::arch::asm!(concat!("dsb ", stringify!($A)), options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] @@ -75,7 +75,7 @@ impl sealed::Isb for Sy { fn isb(&self) { match () { #[cfg(target_arch = "aarch64")] - () => unsafe { core::arch::asm!("ISB SY", options(nostack)) }, + () => unsafe { core::arch::asm!("isb sy", options(nostack)) }, #[cfg(not(target_arch = "aarch64"))] () => unimplemented!(), @@ -83,14 +83,59 @@ impl sealed::Isb for Sy { } } +pub struct None; +pub const NONE: None = None {}; + +impl sealed::Dsb for None { + #[inline(always)] + fn dsb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("dsb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +impl sealed::Dmb for None { + #[inline(always)] + fn dmb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("dmb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +impl sealed::Isb for None { + #[inline(always)] + fn isb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { core::arch::asm!("isb", options(nostack)) }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +#[inline(always)] pub fn isb(_arg: impl sealed::Isb) { _arg.isb() } +#[inline(always)] pub fn dmb(_arg: impl sealed::Dmb) { _arg.dmb() } -pub fn dsb(_arg: impl sealed::Dsb){ +#[inline(always)] +pub fn dsb(_arg: impl sealed::Dsb) { _arg.dsb() } From 231affb7baf35c9d72d7f14db0b1d9273335f815 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Feb 2024 02:11:13 +0800 Subject: [PATCH 29/70] feat(cache): add cache invalidation support --- src/asm.rs | 1 + src/asm/cache.S | 62 +++++++++++++++++++++++++ src/asm/cache.rs | 75 +++++++++++++++++++++++++++++++ src/cache.rs | 97 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- src/mmu.rs | 1 + src/mmu/address.rs | 28 ++++++++---- src/registers/tcr_el2.rs | 4 ++ 8 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 src/asm/cache.S create mode 100644 src/asm/cache.rs create mode 100644 src/cache.rs diff --git a/src/asm.rs b/src/asm.rs index 87f3a13..f070b3b 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -10,6 +10,7 @@ pub mod barrier; pub mod random; +pub mod cache; pub mod tlb; /// The classic no-op diff --git a/src/asm/cache.S b/src/asm/cache.S new file mode 100644 index 0000000..499c738 --- /dev/null +++ b/src/asm/cache.S @@ -0,0 +1,62 @@ + +.macro dcache op + dsb sy + mrs x0, clidr_el1 + and x3, x0, #0x7000000 + lsr x3, x3, #23 + + cbz x3, finished_\op + mov x10, #0 + + loop1_\op: + add x2, x10, x10, lsr #1 + lsr x1, x0, x2 + and x1, x1, #7 + cmp x1, #2 + b.lt skip_\op + + msr csselr_el1, x10 + isb + + mrs x1, ccsidr_el1 + and x2, x1, #7 + add x2, x2, #4 + mov x4, #0x3ff + and x4, x4, x1, lsr #3 + clz w5, w4 + mov x7, #0x7fff + and x7, x7, x1, lsr #13 + + loop2_\op: + mov x9, x4 + + loop3_\op: + lsl x6, x9, x5 + orr x11, x10, x6 + lsl x6, x7, x2 + orr x11, x11, x6 + dc \op, x11 + subs x9, x9, #1 + b.ge loop3_\op + subs x7, x7, #1 + b.ge loop2_\op + + skip_\op: + add x10, x10, #2 + cmp x3, x10 + b.gt loop1_\op + + finished_\op: + mov x10, #0 + msr csselr_el1, x10 + dsb sy + isb +.endm + + +.global dcache_invall; +.type dcache_invall, %function; +dcache_invall: + dcache isw + ret +.size dcache_invall, .-dcache_invall diff --git a/src/asm/cache.rs b/src/asm/cache.rs new file mode 100644 index 0000000..9d751a7 --- /dev/null +++ b/src/asm/cache.rs @@ -0,0 +1,75 @@ +use crate::mmu::address::Segment; + +mod sealed { + + use crate::mmu::address::Segment; + + pub trait Ic { + fn ic(&self); + } + + pub trait Dc { + fn dc(&self, seg: Segment); + } +} + +macro_rules! ic { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::Ic for $T { + #[inline(always)] + fn ic(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("ic ", stringify!($A)), options(nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + }; +} + +macro_rules! dc { + ($A: ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T{}; + impl sealed::Dc for $T { + #[inline(always)] + fn dc(&self, mut seg: Segment){ + seg.round(64); + match() { + #[cfg(target_arch = "aarch64")] + () => unsafe { + for i in(seg.0 .. seg.1).step_by(64){ + core::arch::asm!(concat!("dc ",stringify!($A), ",{}"), in(reg) i, options(nostack)) + } + }, + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + } +} + +ic!(IALLU, Iallu); +ic!(IALLUIS, Ialluis); +dc!(CVAC, CVac); +dc!(IVAC, IVac); +dc!(CIVAC, CIVac); + +#[inline(always)] +pub fn ic(_arg: impl sealed::Ic) { + _arg.ic(); +} + +#[inline(always)] +pub fn dc(_arg: impl sealed::Dc, seg: Segment){ + _arg.dc(seg); +} diff --git a/src/cache.rs b/src/cache.rs new file mode 100644 index 0000000..4758302 --- /dev/null +++ b/src/cache.rs @@ -0,0 +1,97 @@ + +use core::arch::global_asm; +use super::asm::barrier::{NONE, isb, dsb, NSH}; +use super::asm::cache::{ic, IALLUIS}; +use crate::asm::cache::{dc, CVAC, IVAC, CIVAC}; +use crate::mmu::address::Segment; + +global_asm!(include_str!("./asm/cache.S")); + +mod sealed { + use crate::mmu::address::Segment; + pub trait Cache { + fn clean(&self, seg: Segment); + fn inv(&self, seg: Segment); + fn inv_all(&self); + fn inv_clean(&self, seg: Segment); + } +} + +extern "C" { + pub fn dcache_invall(); +} + +pub struct ICache {} +pub struct DCache {} + +pub const ICACHE: ICache = ICache {}; +pub const DCACHE: DCache = DCache {}; + +impl sealed::Cache for DCache { + + #[inline(always)] + fn clean(&self, seg: Segment) { + dc(IVAC, seg) + } + + #[inline(always)] + fn inv(&self, seg: Segment) { + dc(CVAC, seg) + } + + #[inline(always)] + fn inv_all(&self) { + unsafe { + dcache_invall(); + } + } + + #[inline(always)] + fn inv_clean(&self, seg: Segment) { + dc(CIVAC, seg); + } +} + +impl sealed::Cache for ICache{ + #[inline(always)] + fn clean(&self, seg: Segment){ + } + + #[inline(always)] + fn inv(&self, seg:Segment){ + + } + + #[inline(always)] + fn inv_all(&self){ + ic(IALLUIS); + } + + #[inline(always)] + fn inv_clean(&self, seg: Segment) { + + } + +} + +pub enum CacheFlush { + INV, + CLEAN, + INVCLEAN, +} + +pub fn flush_cache_area(_cache: impl sealed::Cache, seg: Segment, mode: CacheFlush) { + match mode { + CacheFlush::INV => _cache.inv(seg), + CacheFlush::INVCLEAN => _cache.inv_clean(seg), + CacheFlush::CLEAN => _cache.clean(seg), + } + dsb(NSH); + isb(NONE); +} + +pub fn flush_cache_all(_cache: impl sealed::Cache) { + _cache.inv_all(); + dsb(NSH); + isb(NONE); +} diff --git a/src/lib.rs b/src/lib.rs index 80be80d..f8f4240 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,8 +54,7 @@ //! profile](https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf?_ga=2.266626254.1122218691.1534883460-1326731866.1530967873). #![no_std] - -#![feature(concat_idents)] pub mod asm; pub mod mmu; pub mod registers; +pub mod cache; diff --git a/src/mmu.rs b/src/mmu.rs index 5538bb6..17b4adf 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,2 +1,3 @@ pub mod descriptor; pub mod address; + diff --git a/src/mmu/address.rs b/src/mmu/address.rs index bed24ab..9151199 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -1,5 +1,5 @@ use tock_registers::register_bitfields; -register_bitfields!{u64, +register_bitfields! {u64, VADescriptor [ L0 OFFSET(39) NUMBITS(9) [], L1 OFFSET(30) NUMBITS(9) [], @@ -9,19 +9,22 @@ register_bitfields!{u64, ] } -#[derive(Clone,Copy)] +#[derive(Clone, Copy)] #[repr(transparent)] pub struct VirtAddress(pub u64); -#[derive(Clone,Copy)] +#[derive(Clone, Copy)] #[repr(transparent)] pub struct PhyAddress(pub u64); -pub struct VirtLayout{ - pub indexes: [u64;4], - pub offset: u64 +pub struct VirtLayout { + pub indexes: [u64; 4], + pub offset: u64, } +#[derive(Clone, Copy)] +pub struct Segment(pub u64, pub u64); + impl VirtAddress { pub fn layout(&self) -> VirtLayout { VirtLayout { @@ -29,14 +32,21 @@ impl VirtAddress { VADescriptor::L0.read(self.0), VADescriptor::L1.read(self.0), VADescriptor::L2.read(self.0), - VADescriptor::L3.read(self.0) + VADescriptor::L3.read(self.0), ], - offset: VADescriptor::OFFSET.read(self.0) + offset: VADescriptor::OFFSET.read(self.0), } } } -impl From for VirtAddress{ +impl Segment { + pub fn round(&mut self, sz: u64) { + self.0 = self.0 & (!(sz - 1)); + self.1 = (self.1 + sz - 1) & (!(sz - 1)); + } +} + +impl From for VirtAddress { fn from(value: u64) -> Self { VirtAddress(value) } diff --git a/src/registers/tcr_el2.rs b/src/registers/tcr_el2.rs index d32dcea..92da8db 100644 --- a/src/registers/tcr_el2.rs +++ b/src/registers/tcr_el2.rs @@ -18,6 +18,10 @@ use tock_registers::{ register_bitfields! {u64, pub TCR_EL2 [ + AS OFFSET(36) NUMBITS(1) [ + Disable = 0, + Enable = 1, + ], /// When FEAT_HAFDBS is implemented hardware can update the dirty flags in the stage1 /// descriptors HD OFFSET(22) NUMBITS(1) [ From ab183277c2cedf72f1509a9a8f9b6ce70394b703 Mon Sep 17 00:00:00 2001 From: varia Date: Thu, 8 Feb 2024 20:12:11 +0800 Subject: [PATCH 30/70] feat: add at instruction --- src/asm.rs | 1 + src/asm/at.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/asm/at.rs diff --git a/src/asm.rs b/src/asm.rs index f070b3b..50224ab 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,6 +12,7 @@ pub mod barrier; pub mod random; pub mod cache; pub mod tlb; +pub mod at; /// The classic no-op #[inline(always)] diff --git a/src/asm/at.rs b/src/asm/at.rs new file mode 100644 index 0000000..d16ede3 --- /dev/null +++ b/src/asm/at.rs @@ -0,0 +1,34 @@ +mod sealed { + pub trait At { + fn at(&self, va: u64); + } +} + +macro_rules! at { + ($A:ident, $T: ident) => { + pub struct $T; + pub const $A: $T = $T {}; + + impl sealed::At for $T { + #[inline(always)] + fn at(&self, va: u64) { + match () { + #[cfg(target_arch = "aarch64")] + () => unsafe { + core::arch::asm!(concat!("at ", stringify!($A), ", {0}"), in(reg) va, options(nomem, nostack)) + }, + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + }; +} + +at!(S1E1R, S1e1r); + +#[inline(always)] +pub fn at(_arg:impl sealed::At , va:u64){ + _arg.at(va); +} From ad22e6984dbfe90b2ab3b1c6a95605ff64e2122f Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 00:58:03 +0200 Subject: [PATCH 31/70] feat(reg): add hpfar_el2 register --- src/registers/hpfar_el2.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/registers/hpfar_el2.rs b/src/registers/hpfar_el2.rs index beb9903..d75e9db 100644 --- a/src/registers/hpfar_el2.rs +++ b/src/registers/hpfar_el2.rs @@ -9,14 +9,21 @@ //! //! Holds the faulting IPA for some aborts on a stage 2 translation taken to EL2. -use tock_registers::{interfaces::Readable, register_bitfields}; +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; register_bitfields! {u64, pub HPFAR_EL2 [ - /// Faulting IPA address space. - NS OFFSET(63) NUMBITS(1) [], - - /// Faulting Intermediate Physical Address. + /// Faulting IPA address space + NS OFFSET(63) NUMBITS(1) [ + Secure = 0, + NonSecure = 1 + ], + /// Faulting Intermediate Physical Address + /// 40 bits, 40 = 52 - 12. 12 is the size of the page. + /// For implementations with fewer than 52 physical address bits, the corresponding upper bits in this field are RES0. FIPA OFFSET(4) NUMBITS(48) [] ] } @@ -30,4 +37,11 @@ impl Readable for Reg { sys_coproc_read_raw!(u64, "HPFAR_EL2", "x"); } +impl Writeable for Reg { + type T = u64; + type R = HPFAR_EL2::Register; + + sys_coproc_write_raw!(u64, "HPFAR_EL2", "x"); +} + pub const HPFAR_EL2: Reg = Reg {}; From 852bef6feb18f21e1b1543451dcfa8835023ec3f Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 14 Feb 2024 00:26:55 +0800 Subject: [PATCH 32/70] feat: update exception reason enum --- src/exception.rs | 14 ++++++++++++++ src/lib.rs | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/exception.rs diff --git a/src/exception.rs b/src/exception.rs new file mode 100644 index 0000000..2766b0a --- /dev/null +++ b/src/exception.rs @@ -0,0 +1,14 @@ +#[derive(Copy, Clone)] +pub enum ExceptionReason { + DataAbort = 0x24, + Unimplemented = 0xff, +} + +impl From for ExceptionReason{ + fn from(value: u64) -> Self { + match value { + x if x == Self::DataAbort as u64 => Self::DataAbort, + _ => Self::Unimplemented + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 525c047..4e35ed8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,4 +58,5 @@ pub mod asm; pub mod mmu; pub mod irq; pub mod cache; +pub mod exception; pub mod registers; From 7f1162b030517d5df53d81dc94e0d596386ad6b8 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 22 Feb 2024 16:56:13 +0800 Subject: [PATCH 33/70] feat(mmu): update mmtype/mmprot abstraction --- src/mmu/address.rs | 129 +++++++++++++++++++++++++++++++++++++++--- src/mmu/descriptor.rs | 4 +- 2 files changed, 123 insertions(+), 10 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 9f1ff8a..c393b15 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -1,4 +1,9 @@ use tock_registers::register_bitfields; +use tock_registers::fields::FieldValue; +use super::descriptor::BlockDescriptor; +use core::iter::StepBy; +use core::ops::Range; + register_bitfields! {u64, VADescriptor [ L0 OFFSET(39) NUMBITS(9) [], @@ -9,6 +14,35 @@ register_bitfields! {u64, ] } +#[derive(Copy, Clone)] +pub enum MMProt { + NormalReadOnly, + NormalExecOnly, + NormalReadWriteAll, + NormalReadWriteNoExec, + PrivilegedExecOnly, + PrivilegedReadOnly, + PrivilegedReadWrite, + SecureExecOnly, + SecureReadOnly, + SecureReadWrite, +} + +#[derive(Copy, Clone)] +pub enum MMType { + Device, + Normal, + NormalNoExec, + ReadOnly, + Instruction, + SystemReserved, + SystemReadOnly, + SystemInstruction, + SecureReadOnly, + SecureExecOnly, + SecureReadWrite, +} + pub struct VirtLayout { pub indexes: [u64; 4], pub offset: u64, @@ -38,19 +72,96 @@ impl MMRegion { } } -impl Iterator for MMRegion { - type Item = u64; - fn next(&mut self) -> Option { - let ret = self.mem.0; - if self.inbound(ret) { - self.mem.0 += self.granule; - Some(ret) - } else { - None +impl MMType { + pub fn default_prot(&self) -> MMProt { + match *self { + Self::Normal => MMProt::NormalReadWriteAll, + Self::NormalNoExec => MMProt::NormalReadWriteNoExec, + Self::ReadOnly => MMProt::NormalReadOnly, + Self::Instruction => MMProt::NormalExecOnly, + Self::Device => MMProt::PrivilegedReadWrite, + Self::SystemReserved => MMProt::PrivilegedReadWrite, + Self::SystemInstruction => MMProt::PrivilegedExecOnly, + Self::SystemReadOnly => MMProt::PrivilegedReadOnly, + _ => unimplemented!(), } } } +impl From for FieldValue { + fn from(value: MMProt) -> Self { + match value { + MMProt::NormalReadWriteAll => { + BlockDescriptor::UXN_XN::FALSE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RW_ELx_RW_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalReadWriteNoExec => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RW_ELx_RW_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalExecOnly => { + BlockDescriptor::UXN_XN::FALSE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RO_ELx_RO_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::NormalReadOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RO_ELx_RO_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedReadOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RO_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedExecOnly => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::AP::RO_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + MMProt::PrivilegedReadWrite => { + BlockDescriptor::UXN_XN::TRUE + + BlockDescriptor::PXN::TRUE + + BlockDescriptor::AP::RW_ELx_None_EL0 + + BlockDescriptor::NS::TRUE + } + _ => unimplemented!(), + } + } +} + +impl From for FieldValue { + fn from(value: MMType) -> Self { + let prot_fields: FieldValue = value.default_prot().into(); + let type_fields = match value { + MMType::Device => BlockDescriptor::SH::CLEAR, + _ => BlockDescriptor::SH::IS, + }; + prot_fields + + type_fields + + BlockDescriptor::NSE_NG::TRUE + + BlockDescriptor::VALID::TRUE + + BlockDescriptor::TYPE::BLOCK + + BlockDescriptor::AF::TRUE + } +} + +impl IntoIterator for MMRegion { + type Item = u64; + type IntoIter = StepBy>; + fn into_iter(self) -> Self::IntoIter { + (self.mem.0..self.mem.1).step_by(self.granule as usize) + } +} + impl From for VirtLayout { fn from(value: u64) -> Self { Self { diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 8cb466c..2e8cdd1 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -43,7 +43,9 @@ register_bitfields! {u64, TRUE = 0b1, FALSE = 0b0 ], - ATTR OFFSET(2) NUMBITS(2) [], + ATTR OFFSET(2) NUMBITS(2) [ + + ], TYPE OFFSET(1) NUMBITS(1) [ BLOCK = 0b0, PAGE = 0b1 From c6bf5d3eba3b920328011c374b17738b80358bf5 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 22 Feb 2024 21:03:36 +0800 Subject: [PATCH 34/70] feat(registers): add TTBR traits for loading generics --- src/registers.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/registers.rs b/src/registers.rs index c4cf57f..28fd751 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -261,5 +261,12 @@ pub use vbar_el3::VBAR_EL3; pub use vtcr_el2::VTCR_EL2; pub use vttbr_el2::VTTBR_EL2; +pub trait TTBR {} + +impl TTBR for vttbr_el2::Reg{} +impl TTBR for ttbr0_el1::Reg{} +impl TTBR for ttbr1_el1::Reg{} +impl TTBR for ttbr0_el2::Reg{} + #[doc(inline)] pub use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; From 54212dfef067de56c8588048936a4a5fade4ce62 Mon Sep 17 00:00:00 2001 From: varia Date: Mon, 4 Mar 2024 20:55:46 +0800 Subject: [PATCH 35/70] feat(reg): add field about data abort for esr_el2 --- src/registers/esr_el2.rs | 153 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/src/registers/esr_el2.rs b/src/registers/esr_el2.rs index 917b2ad..10e57f7 100644 --- a/src/registers/esr_el2.rs +++ b/src/registers/esr_el2.rs @@ -81,7 +81,158 @@ register_bitfields! {u64, /// Instruction Specific Syndrome. Architecturally, this field can be defined independently /// for each defined Exception class. However, in practice, some ISS encodings are used for /// more than one Exception class. - ISS OFFSET(0) NUMBITS(25) [] + ISS OFFSET(0) NUMBITS(25) [], + + // Data Abort Syndrome Register fields + // These fields are only valid if EC.DataAbort is set. + + // Is the syndrome valid? + ISV OFFSET(24) NUMBITS(1) [ + /// 0b0: The syndrome information is not valid. + NotValid = 0, + /// 0b1: The syndrome information is valid. + Valid = 1 + ], + + // Syndrome Access Size + SAS OFFSET(22) NUMBITS(2) [ + /// 0b00: Byte + Byte = 0b00, + /// 0b01: Half-word + HalfWord = 0b01, + /// 0b10: Word + Word = 0b10, + /// 0b11: Double-word + DoubleWord = 0b11 + ], + + // Syndrome Sign-Extend + SSE OFFSET(21) NUMBITS(1) [ + /// 0b0: Zero-extend + ZeroExtend = 0, + /// 0b1: Sign-extend + SignExtend = 1 + ], + + // Syndrome Register + SRT OFFSET(16) NUMBITS(5) [], + + // Syndrome Register Width + SF OFFSET(15) NUMBITS(1) [ + /// 0b0: 32-bit + Bit32 = 0, + /// 0b1: 64-bit + Bit64 = 1 + ], + + // Acquire-Release + AR OFFSET(14) NUMBITS(1) [ + /// 0b0: Normal memory access + Normal = 0, + /// 0b1: Acquire or release access + AcquireRelease = 1 + ], + + // Virtual Nested Abort + VNCR OFFSET(13) NUMBITS(1) [ + /// 0b0: Not a virtual nested abort + NotVirtualNested = 0, + /// 0b1: Virtual nested abort + VirtualNested = 1 + ], + + // Load-Store Type + LST OFFSET(11) NUMBITS(2) [ + /// 0b01: ST64BV + ST64BV = 0b01, + /// 0b10: LD64B or ST64B + LD64BorST64B = 0b10, + /// 0b11: ST64BV0 + ST64BV0 = 0b11 + ], + + // Is FAR not valid? + FnV OFFSET(10) NUMBITS(1) [ + /// 0b0: FAR is valid + Valid = 0, + /// 0b1: FAR is not valid + NotValid = 1 + ], + + // External Abort Type + EA OFFSET(9) NUMBITS(1) [ + /// 0b0 Not an external abort + NotExternal = 0, + /// 0b1: External + External = 1 + ], + + // Cache maintenance operation + CM OFFSET(8) NUMBITS(1) [ + /// 0b0: Not a cache maintenance operation + NotCacheMaintenance = 0, + /// 0b1: Cache maintenance operation + CacheMaintenance = 1 + ], + + // Which stage caused the stage 2 abort? + S1PTW OFFSET(7) NUMBITS(1) [ + /// 0b0: Stage 1 + Stage1 = 0, + /// 0b1: Stage 2 + Stage2 = 1 + ], + + // Write not Read + WnR OFFSET(6) NUMBITS(1) [ + /// 0b0: Read access + Read = 0, + /// 0b1: Write access + Write = 1 + ], + + // Data Fault Status Code + DFSC OFFSET(0) NUMBITS(6) [ + /// 0b000000: Address size fault, level 0 + AddressSizeFaultLevel0 = 0b000000, + /// 0b000001: Address size fault, level 1 + AddressSizeFaultLevel1 = 0b000001, + /// 0b000010: Address size fault, level 2 + AddressSizeFaultLevel2 = 0b000010, + /// 0b000011: Address size fault, level 3 + AddressSizeFaultLevel3 = 0b000011, + + /// 0b000100: Translation fault, level 0 + TranslationFaultLevel0 = 0b000100, + /// 0b000101: Translation fault, level 1 + TranslationFaultLevel1 = 0b000101, + /// 0b000110: Translation fault, level 2 + TranslationFaultLevel2 = 0b000110, + /// 0b000111: Translation fault, level 3 + TranslationFaultLevel3 = 0b000111, + + /// 0b001000: Access flag fault, level 0 + AccessFlagFaultLevel0 = 0b001000, + /// 0b001001: Access flag fault, level 1 + AccessFlagFaultLevel1 = 0b001001, + /// 0b001010: Access flag fault, level 2 + AccessFlagFaultLevel2 = 0b001010, + /// 0b001011: Access flag fault, level 3 + AccessFlagFaultLevel3 = 0b001011, + + /// 0b001101: Permission fault, level 1 + PermissionFaultLevel1 = 0b001101, + /// 0b001110: Permission fault, level 2 + PermissionFaultLevel2 = 0b001110, + /// 0b001111: Permission fault, level 3 + PermissionFaultLevel3 = 0b001111, + + /// 0b010000: Synchronous external abort, not on translation table walk or + /// hardware update of translation table + SynchronousExternalAbortNotOnTranslationTableWalk = 0b010000 + + // ... and many more + ] ] } From a50337663bcc83a07836ed75e692314f773f0f39 Mon Sep 17 00:00:00 2001 From: varia Date: Fri, 22 Mar 2024 15:07:22 +0800 Subject: [PATCH 36/70] feat(exception): add a new exception reason --- src/exception.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/exception.rs b/src/exception.rs index 2766b0a..5d8dd0f 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -1,13 +1,15 @@ #[derive(Copy, Clone)] pub enum ExceptionReason { - DataAbort = 0x24, + DataAbortLowerEl = 0b100100, + DataAbortCurrentEl = 0b100101, Unimplemented = 0xff, } impl From for ExceptionReason{ fn from(value: u64) -> Self { match value { - x if x == Self::DataAbort as u64 => Self::DataAbort, + x if x == Self::DataAbortLowerEl as u64 => Self::DataAbortLowerEl, + x if x == Self::DataAbortCurrentEl as u64 => Self::DataAbortCurrentEl, _ => Self::Unimplemented } } From de895d20c05f0f3942150db4aa47efafc132c714 Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:01:20 +0200 Subject: [PATCH 37/70] feat(mmu): refactor imports Signed-off-by: Yiyang Wu --- src/cache.rs | 2 +- src/mmu.rs | 3 ++- src/mmu/address.rs | 10 +++++----- src/mmu/descriptor.rs | 12 ++++++++++++ src/registers/hcr_el2.rs | 21 ++++++++++++++++++++- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/cache.rs b/src/cache.rs index f8f330d..53ad10c 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -2,7 +2,7 @@ use super::asm::barrier::{dsb, isb, NSH, SY}; use crate::{ asm::cache::{dc, ic, CISW, CIVAC, CSW, CVAC, IALLU, ISW, IVAC}, irq::IRQ, - mmu::address::{MMRegion, MMSegment}, + mmu::{MMRegion, MMSegment}, registers::{Readable, Writeable, CCSIDR_EL1, CLIDR_EL1, CSSELR_EL1}, }; diff --git a/src/mmu.rs b/src/mmu.rs index 17b4adf..e5cab22 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,3 +1,4 @@ pub mod descriptor; -pub mod address; +mod address; +pub use address::*; diff --git a/src/mmu/address.rs b/src/mmu/address.rs index c393b15..86ff946 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -44,7 +44,7 @@ pub enum MMType { } pub struct VirtLayout { - pub indexes: [u64; 4], + pub indexes: [usize; 4], pub offset: u64, } @@ -166,10 +166,10 @@ impl From for VirtLayout { fn from(value: u64) -> Self { Self { indexes: [ - VADescriptor::L0.read(value), - VADescriptor::L1.read(value), - VADescriptor::L2.read(value), - VADescriptor::L3.read(value), + VADescriptor::L0.read(value) as usize, + VADescriptor::L1.read(value) as usize, + VADescriptor::L2.read(value) as usize, + VADescriptor::L3.read(value) as usize, ], offset: VADescriptor::OFFSET.read(value), } diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 2e8cdd1..222b6d8 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -116,3 +116,15 @@ impl VADescriptor { self.0 = field_value.modify(self.0); } } + +impl From for VADescriptor { + fn from(value: u64) -> Self { + Self(value) + } +} + +impl From for u64 { + fn from(value: VADescriptor) -> Self { + value.0 + } +} diff --git a/src/registers/hcr_el2.rs b/src/registers/hcr_el2.rs index 61a14bf..b9d01b0 100644 --- a/src/registers/hcr_el2.rs +++ b/src/registers/hcr_el2.rs @@ -143,6 +143,12 @@ register_bitfields! {u64, EnableTrapGeneralExceptionsToEl2 = 1, ], + /// Trap Virtual Memory controls, from EL0. + TVM OFFSET(26) NUMBITS(1) [ + DisableTrapVMCtrlRegistersToEl2 = 0, + EnableTrapVMCtrlRegistersToEl2 = 1, + ], + /// Trap data or unified cache maintenance instructions that operate by Set/Way. /// Traps execution of those cache maintenance instructions at EL1 to EL2, when /// EL2 is enabled in the current Security state. @@ -216,6 +222,11 @@ register_bitfields! {u64, EnableTrapEl1SmcToEl2 = 1, ], + TWE OFFSET(15) NUMBITS(1) [ + DisableTrapEl1WfetoEl2 = 0, + EnableTrapEl1WfetoEl2 = 1 + ], + /// Default Cacheability. /// /// 0 This control has no effect on the Non-secure EL1&0 translation regime. @@ -329,6 +340,11 @@ register_bitfields! {u64, EnableVirtualFIQ = 1, ], + PTW OFFSET(2) NUMBITS(1) [ + DisablePTW = 0, + EnablePTW = 1 + ], + /// Set/Way Invalidation Override. Causes Non-secure EL1 execution of the data cache /// invalidate by set/way instructions to perform a data cache clean and invalidate by /// set/way: @@ -353,7 +369,10 @@ register_bitfields! {u64, /// /// When HCR_EL2.TGE is 1, the PE ignores the value of this field for all purposes other /// than a direct read of this field. - SWIO OFFSET(1) NUMBITS(1) [], + SWIO OFFSET(1) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], /// Virtualization enable. Enables stage 2 address translation for the EL1&0 translation regime, /// when EL2 is enabled in the current Security state. The possible values are: From 5a78e53f99d8f19789bfa9a901b734ed28b48e04 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Sun, 31 Mar 2024 16:48:21 +0800 Subject: [PATCH 38/70] feat(mmu): add virt page entry def Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 23 +++++++++++++++++++---- src/mmu/descriptor.rs | 6 ++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 86ff946..8c19756 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -23,6 +23,12 @@ pub enum MMProt { PrivilegedExecOnly, PrivilegedReadOnly, PrivilegedReadWrite, + VirtNone, + VirtWriteOnly, + VirtReadOnly, + VirtReadOnlyNoExec, + VirtReadWrite, + VirtReadWriteNoExec, SecureExecOnly, SecureReadOnly, SecureReadWrite, @@ -41,6 +47,12 @@ pub enum MMType { SecureReadOnly, SecureExecOnly, SecureReadWrite, + VirtNone, + VirtWriteOnly, + VirtReadOnly, + VirtReadOnlyNoExec, + VirtReadWrite, + VirtReadWriteNoExec, } pub struct VirtLayout { @@ -66,10 +78,6 @@ impl MMRegion { granule, } } - - pub fn inbound(&self, addr: u64) -> bool { - return self.mem.0 <= addr && addr < self.mem.1; - } } impl MMType { @@ -83,6 +91,7 @@ impl MMType { Self::SystemReserved => MMProt::PrivilegedReadWrite, Self::SystemInstruction => MMProt::PrivilegedExecOnly, Self::SystemReadOnly => MMProt::PrivilegedReadOnly, + Self::VirtReadWrite => MMProt::VirtReadWrite, _ => unimplemented!(), } } @@ -133,6 +142,12 @@ impl From for FieldValue { + BlockDescriptor::AP::RW_ELx_None_EL0 + BlockDescriptor::NS::TRUE } + MMProt::VirtReadWrite => { + BlockDescriptor::UXN_XN::FALSE + + BlockDescriptor::PXN::FALSE + + BlockDescriptor::S2AP::WR + + BlockDescriptor::NS::TRUE + } _ => unimplemented!(), } } diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 222b6d8..ca40e8f 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -39,6 +39,12 @@ register_bitfields! {u64, RO_ELx_None_EL0 = 0b10, RO_ELx_RO_EL0 = 0b11 ], + S2AP OFFSET(6) NUMBITS(2) [ + NONE = 0b00, + RO = 0b01, + WO = 0b10, + WR = 0b11, + ], NS OFFSET(5) NUMBITS(1) [ TRUE = 0b1, FALSE = 0b0 From a99c625657f57be913e023117c0008ad3b990080 Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:06:43 +0200 Subject: [PATCH 39/70] feat(registers): add icc_sre_elx registers Signed-off-by: toolmanp --- src/registers.rs | 3 ++ src/registers/icc_sre_el1.rs | 54 ++++++++++++++++++++++++++++++++++++ src/registers/icc_sre_el2.rs | 23 +++++++++++---- src/registers/icc_sre_el3.rs | 54 ++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 src/registers/icc_sre_el1.rs create mode 100644 src/registers/icc_sre_el3.rs diff --git a/src/registers.rs b/src/registers.rs index 96b058f..2fac938 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -133,6 +133,9 @@ mod vbar_el3; mod vtcr_el2; mod vttbr_el2; mod vmpidr_el2; +mod icc_sre_el1; +mod icc_sre_el2; +mod icc_sre_el3; pub use actlr_el1::ACTLR_EL1; pub use actlr_el2::ACTLR_EL2; diff --git a/src/registers/icc_sre_el1.rs b/src/registers/icc_sre_el1.rs new file mode 100644 index 0000000..c090432 --- /dev/null +++ b/src/registers/icc_sre_el1.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2023 by the author(s) +// +// Author(s): +// - Yiyang Wu + +//! Interrupt Mask Bits +//! +//! Allows access to the interrupt mask bits. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! { u64, + pub ICC_SRE_EL1 [ + EN OFFSET(3) NUMBITS(1) [ + ENABLED = 1, + DISABLED = 0, + ], + DIB OFFSET(2) NUMBITS(1) [ + ENABLED = 1, + DISABLED = 0, + ], + DFB OFFSET(1) NUMBITS(1)[ + ENABLED = 1, + DISABLED = 0 + ], + SRE OFFSET(1) NUMBITS(1) [ + MEMORY = 0, + SR = 1 + ] + ], +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_SRE_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_SRE_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICC_SRE_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_SRE_EL1", "x"); +} + +pub const ICC_SRE_EL1: Reg = Reg {}; diff --git a/src/registers/icc_sre_el2.rs b/src/registers/icc_sre_el2.rs index 2db4ed4..fcecc8a 100644 --- a/src/registers/icc_sre_el2.rs +++ b/src/registers/icc_sre_el2.rs @@ -1,9 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Copyright (c) 2024 by the author(s) +// Copyright (c) 2018-2024 by the author(s) // // Author(s): // - Sangwan Kwon +// - Yiyang Wu //! Interrupt Controller System Register Enable Register - EL2 //! @@ -23,21 +24,30 @@ register_bitfields! {u64, /// EL1 accesses to ICC_SRE_EL1 trap to EL2. /// /// 1 EL1 accesses to ICC_SRE_EL1 do not trap to EL2. - ENABLE OFFSET(3) NUMBITS(1) [], + ENABLE OFFSET(3) NUMBITS(1) [ + Enabled = 1, + Disabled = 0, + ], /// Disable IRQ bypass. /// /// 0 IRQ bypass enabled. /// /// 1 IRQ bypass disabled. - DIB OFFSET(2) NUMBITS(1) [], + DIB OFFSET(2) NUMBITS(1) [ + Enabled = 1, + Disabled = 0, + ], /// Disable FIQ bypass. /// /// 0 FIQ bypass enabled. /// /// 1 FIQ bypass disabled. - DFB OFFSET(1) NUMBITS(1) [], + DFB OFFSET(1) NUMBITS(1) [ + Enabled = 1, + Disabled = 0, + ], /// System Register Enable. /// @@ -46,7 +56,10 @@ register_bitfields! {u64, /// /// 1 The System register interface to the ICH_* registers and the EL1 and EL2 /// ICC_* registers is enabled for EL2. - SRE OFFSET(0) NUMBITS(1) [], + SRE OFFSET(0) NUMBITS(1) [ + SR = 1, + Memory = 0, + ] ] } diff --git a/src/registers/icc_sre_el3.rs b/src/registers/icc_sre_el3.rs new file mode 100644 index 0000000..72970be --- /dev/null +++ b/src/registers/icc_sre_el3.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2023 by the author(s) +// +// Author(s): +// - Yiyang Wu + +//! Interrupt Mask Bits +//! +//! Allows access to the interrupt mask bits. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! { u64, + pub ICC_SRE_EL3 [ + EN OFFSET(3) NUMBITS(1) [ + ENABLED = 1, + DISABLED = 0, + ], + DIB OFFSET(2) NUMBITS(1) [ + ENABLED = 1, + DISABLED = 0, + ], + DFB OFFSET(1) NUMBITS(1)[ + ENABLED = 1, + DISABLED = 0 + ], + SRE OFFSET(1) NUMBITS(1) [ + MEMORY = 0, + SR = 1 + ] + ], +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_SRE_EL3::Register; + + sys_coproc_read_raw!(u64, "ICC_SRE_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICC_SRE_EL3::Register; + + sys_coproc_write_raw!(u64, "ICC_SRE_EL3", "x"); +} + +pub const ICC_SRE_EL3: Reg = Reg {}; From 811a0a73f90285350af43b4547a555b5a33f8f50 Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:19:49 +0200 Subject: [PATCH 40/70] feat(registers): add gicv3 support Signed-off-by: Yiyang Wu --- src/registers.rs | 113 +++++++++++++++++++++++++++++-- src/registers/icc_ap0r_el1.rs | 34 ++++++++++ src/registers/icc_ap1r_el1.rs | 34 ++++++++++ src/registers/icc_asgi1r_el1.rs | 39 +++++++++++ src/registers/icc_bpr0_el1.rs | 25 +++++++ src/registers/icc_bpr1_el1.rs | 25 +++++++ src/registers/icc_ctlr_el1.rs | 41 ++++++++++- src/registers/icc_ctlr_el3.rs | 73 ++++++++++++++++++++ src/registers/icc_dir_el1.rs | 25 +++++++ src/registers/icc_eoir0_el1.rs | 19 ++++++ src/registers/icc_eoir1_el1.rs | 19 ++++++ src/registers/icc_hppir0_el1.rs | 19 ++++++ src/registers/icc_hppir1_el1.rs | 19 ++++++ src/registers/icc_iar0_el1.rs | 19 ++++++ src/registers/icc_iar1_el1.rs | 19 ++++++ src/registers/icc_igpren0_el1.rs | 21 ++++++ src/registers/icc_igpren1_el1.rs | 21 ++++++ src/registers/icc_igpren1_el3.rs | 25 +++++++ src/registers/icc_nmiar1_el1.rs | 18 +++++ src/registers/icc_pmr_el1.rs | 25 +++++++ src/registers/icc_rpr_el1.rs | 28 ++++++++ src/registers/icc_sgi0r_el1.rs | 31 +++++++++ src/registers/icc_sgi1r_el1.rs | 39 +++++++++++ src/registers/ich_eisr_el2.rs | 41 +++++++++++ src/registers/ich_elrsr_el2.rs | 41 +++++++++++ src/registers/ich_hcr_el2.rs | 72 +++++++++++++++++--- src/registers/ich_lr_el2.rs | 52 ++++++++++++++ src/registers/ich_misr_el2.rs | 17 ++++- src/registers/ich_vmcr_el2.rs | 35 +++++++++- src/registers/ich_vtr_el2.rs | 26 ++++++- src/registers/icv_ap0r_el1.rs | 34 ++++++++++ src/registers/icv_ap1r_el1.rs | 34 ++++++++++ src/registers/icv_asgi1r_el1.rs | 39 +++++++++++ src/registers/icv_bpr0_el1.rs | 25 +++++++ src/registers/icv_bpr1_el1.rs | 25 +++++++ src/registers/icv_ctlr_el1.rs | 58 ++++++++++++++++ src/registers/icv_ctlr_el3.rs | 73 ++++++++++++++++++++ src/registers/icv_dir_el1.rs | 25 +++++++ src/registers/icv_eoir0_el1.rs | 19 ++++++ src/registers/icv_eoir1_el1.rs | 19 ++++++ src/registers/icv_hppir0_el1.rs | 19 ++++++ src/registers/icv_hppir1_el1.rs | 19 ++++++ src/registers/icv_iar0_el1.rs | 19 ++++++ src/registers/icv_iar1_el1.rs | 19 ++++++ src/registers/icv_igpren0_el1.rs | 21 ++++++ src/registers/icv_igpren1_el1.rs | 21 ++++++ src/registers/icv_igpren1_el3.rs | 25 +++++++ src/registers/icv_nmiar1_el1.rs | 18 +++++ src/registers/icv_pmr_el1.rs | 25 +++++++ src/registers/icv_rpr_el1.rs | 28 ++++++++ 50 files changed, 1559 insertions(+), 21 deletions(-) create mode 100644 src/registers/icc_ap0r_el1.rs create mode 100644 src/registers/icc_ap1r_el1.rs create mode 100644 src/registers/icc_asgi1r_el1.rs create mode 100644 src/registers/icc_bpr0_el1.rs create mode 100644 src/registers/icc_bpr1_el1.rs create mode 100644 src/registers/icc_ctlr_el3.rs create mode 100644 src/registers/icc_dir_el1.rs create mode 100644 src/registers/icc_eoir0_el1.rs create mode 100644 src/registers/icc_eoir1_el1.rs create mode 100644 src/registers/icc_hppir0_el1.rs create mode 100644 src/registers/icc_hppir1_el1.rs create mode 100644 src/registers/icc_iar0_el1.rs create mode 100644 src/registers/icc_iar1_el1.rs create mode 100644 src/registers/icc_igpren0_el1.rs create mode 100644 src/registers/icc_igpren1_el1.rs create mode 100644 src/registers/icc_igpren1_el3.rs create mode 100644 src/registers/icc_nmiar1_el1.rs create mode 100644 src/registers/icc_pmr_el1.rs create mode 100644 src/registers/icc_rpr_el1.rs create mode 100644 src/registers/icc_sgi0r_el1.rs create mode 100644 src/registers/icc_sgi1r_el1.rs create mode 100644 src/registers/ich_eisr_el2.rs create mode 100644 src/registers/ich_elrsr_el2.rs create mode 100644 src/registers/ich_lr_el2.rs create mode 100644 src/registers/icv_ap0r_el1.rs create mode 100644 src/registers/icv_ap1r_el1.rs create mode 100644 src/registers/icv_asgi1r_el1.rs create mode 100644 src/registers/icv_bpr0_el1.rs create mode 100644 src/registers/icv_bpr1_el1.rs create mode 100644 src/registers/icv_ctlr_el1.rs create mode 100644 src/registers/icv_ctlr_el3.rs create mode 100644 src/registers/icv_dir_el1.rs create mode 100644 src/registers/icv_eoir0_el1.rs create mode 100644 src/registers/icv_eoir1_el1.rs create mode 100644 src/registers/icv_hppir0_el1.rs create mode 100644 src/registers/icv_hppir1_el1.rs create mode 100644 src/registers/icv_iar0_el1.rs create mode 100644 src/registers/icv_iar1_el1.rs create mode 100644 src/registers/icv_igpren0_el1.rs create mode 100644 src/registers/icv_igpren1_el1.rs create mode 100644 src/registers/icv_igpren1_el3.rs create mode 100644 src/registers/icv_nmiar1_el1.rs create mode 100644 src/registers/icv_pmr_el1.rs create mode 100644 src/registers/icv_rpr_el1.rs diff --git a/src/registers.rs b/src/registers.rs index 2fac938..c8dad6f 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -133,10 +133,62 @@ mod vbar_el3; mod vtcr_el2; mod vttbr_el2; mod vmpidr_el2; + +mod icc_ap0r_el1; +mod icc_ap1r_el1; +mod icc_asgi1r_el1; +mod icc_bpr0_el1; +mod icc_bpr1_el1; +mod icc_ctlr_el1; +mod icc_ctlr_el3; +mod icc_dir_el1; +mod icc_eoir0_el1; +mod icc_eoir1_el1; +mod icc_hppir0_el1; +mod icc_hppir1_el1; +mod icc_iar0_el1; +mod icc_iar1_el1; +mod icc_igpren0_el1; +mod icc_igpren1_el1; +mod icc_igpren1_el3; +mod icc_nmiar1_el1; +mod icc_pmr_el1; +mod icc_rpr_el1; +mod icc_sgi0r_el1; +mod icc_sgi1r_el1; mod icc_sre_el1; mod icc_sre_el2; mod icc_sre_el3; +mod ich_hcr_el2; +mod ich_lr_el2; +mod ich_vtr_el2; +mod ich_eisr_el2; +mod ich_misr_el2; +mod ich_vmcr_el2; +mod ich_elrsr_el2; + +mod icv_ap0r_el1; +mod icv_ap1r_el1; +mod icv_asgi1r_el1; +mod icv_bpr0_el1; +mod icv_bpr1_el1; +mod icv_ctlr_el1; +mod icv_ctlr_el3; +mod icv_dir_el1; +mod icv_eoir0_el1; +mod icv_eoir1_el1; +mod icv_hppir0_el1; +mod icv_hppir1_el1; +mod icv_iar0_el1; +mod icv_iar1_el1; +mod icv_igpren0_el1; +mod icv_igpren1_el1; +mod icv_igpren1_el3; +mod icv_nmiar1_el1; +mod icv_pmr_el1; +mod icv_rpr_el1; + pub use actlr_el1::ACTLR_EL1; pub use actlr_el2::ACTLR_EL2; pub use actlr_el3::ACTLR_EL3; @@ -266,12 +318,65 @@ pub use vtcr_el2::VTCR_EL2; pub use vttbr_el2::VTTBR_EL2; pub use vmpidr_el2::VMPIDR_EL2; +pub use icc_ap0r_el1::*; +pub use icc_ap1r_el1::*; +pub use icc_asgi1r_el1::ICC_ASGI1R_EL1; +pub use icc_bpr0_el1::ICC_BPR0_EL1; +pub use icc_bpr1_el1::ICC_BPR1_EL1; +pub use icc_ctlr_el1::ICC_CTLR_EL1; +pub use icc_ctlr_el3::ICC_CTLR_EL3; +pub use icc_eoir1_el1::ICC_EOIR1_EL1; +pub use icc_eoir0_el1::ICC_EOIR0_EL1; +pub use icc_hppir0_el1::ICC_HPPIR0_EL1; +pub use icc_hppir1_el1::ICC_HPPIR1_EL1; +pub use icc_iar0_el1::ICC_IAR0_EL1; +pub use icc_iar1_el1::ICC_IAR1_EL1; +pub use icc_igpren0_el1::ICC_IGPREN0_EL1; +pub use icc_igpren1_el1::ICC_IGPREN1_EL1; +pub use icc_igpren1_el3::ICC_IGPREN1_EL3; +pub use icc_sre_el1::ICC_SRE_EL1; +pub use icc_sre_el2::ICC_SRE_EL2; +pub use icc_sre_el3::ICC_SRE_EL3; +pub use icc_nmiar1_el1::ICC_NMIAR1_EL1; +pub use icc_pmr_el1::ICC_PMR_EL1; +pub use icc_rpr_el1::ICC_RPR_EL1; +pub use icc_sgi0r_el1::ICC_SGI0R_EL1; +pub use icc_sgi1r_el1::ICC_SGI1R_EL1; + +pub use ich_eisr_el2::ICH_EISR_EL2; +pub use ich_elrsr_el2::ICH_ELRSR_EL2; +pub use ich_hcr_el2::ICH_HCR_EL2; +pub use ich_lr_el2::*; +pub use ich_misr_el2::ICH_MISR_EL2; +pub use ich_vmcr_el2::ICH_VMCR_EL2; +pub use ich_vtr_el2::ICH_VTR_EL2; + +pub use icv_ap0r_el1::*; +pub use icv_ap1r_el1::*; +pub use icv_asgi1r_el1::ICV_ASGI1R_EL1; +pub use icv_bpr0_el1::ICV_BPR0_EL1; +pub use icv_bpr1_el1::ICV_BPR1_EL1; +pub use icv_ctlr_el1::ICV_CTLR_EL1; +pub use icv_ctlr_el3::ICV_CTLR_EL3; +pub use icv_eoir1_el1::ICV_EOIR1_EL1; +pub use icv_eoir0_el1::ICV_EOIR0_EL1; +pub use icv_hppir0_el1::ICV_HPPIR0_EL1; +pub use icv_hppir1_el1::ICV_HPPIR1_EL1; +pub use icv_iar0_el1::ICV_IAR0_EL1; +pub use icv_iar1_el1::ICV_IAR1_EL1; +pub use icv_igpren0_el1::ICV_IGPREN0_EL1; +pub use icv_igpren1_el1::ICV_IGPREN1_EL1; +pub use icv_igpren1_el3::ICV_IGPREN1_EL3; +pub use icv_nmiar1_el1::ICV_NMIAR1_EL1; +pub use icv_pmr_el1::ICV_PMR_EL1; +pub use icv_rpr_el1::ICV_RPR_EL1; + pub trait TTBR {} -impl TTBR for vttbr_el2::Reg{} -impl TTBR for ttbr0_el1::Reg{} -impl TTBR for ttbr1_el1::Reg{} -impl TTBR for ttbr0_el2::Reg{} +impl TTBR for vttbr_el2::Reg {} +impl TTBR for ttbr0_el1::Reg {} +impl TTBR for ttbr1_el1::Reg {} +impl TTBR for ttbr0_el2::Reg {} #[doc(inline)] pub use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; diff --git a/src/registers/icc_ap0r_el1.rs b/src/registers/icc_ap0r_el1.rs new file mode 100644 index 0000000..b185dda --- /dev/null +++ b/src/registers/icc_ap0r_el1.rs @@ -0,0 +1,34 @@ +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub ICC_AP0R_EL1 [ + FIELDS OFFSET(0) NUMBITS(32) [] + ] +} + +macro_rules! ap { + ($reg: ident, $name: tt) => { + #[allow(non_snake_case)] + mod $reg { + use tock_registers::interfaces::*; + use super::*; + pub struct Reg; + impl Writeable for Reg { + type T = u64; + type R = ICC_AP0R_EL1::Register; + sys_coproc_write_raw!(u64, $name, "x"); + } + impl Readable for Reg { + type T = u64; + type R = ICC_AP0R_EL1::Register; + sys_coproc_read_raw!(u64, $name, "x"); + } + } + pub const $reg: $reg::Reg = $reg::Reg {}; + }; +} + +ap!(ICC_AP0R0_EL1, "ICC_AP0R0_EL1"); +ap!(ICC_AP0R1_EL1, "ICC_AP0R1_EL1"); +ap!(ICC_AP0R2_EL1, "ICC_AP0R2_EL1"); +ap!(ICC_AP0R3_EL1, "ICC_AP0R3_EL1"); diff --git a/src/registers/icc_ap1r_el1.rs b/src/registers/icc_ap1r_el1.rs new file mode 100644 index 0000000..4520a3e --- /dev/null +++ b/src/registers/icc_ap1r_el1.rs @@ -0,0 +1,34 @@ +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub ICC_AP1R_EL1 [ + FIELDS OFFSET(0) NUMBITS(32) [] + ] +} + +macro_rules! ap { + ($reg: ident, $asm_name: tt) => { + #[allow(non_snake_case)] + mod $reg { + use tock_registers::interfaces::*; + use super::*; + pub struct Reg; + impl Writeable for Reg { + type T = u64; + type R = ICC_AP1R_EL1::Register; + sys_coproc_write_raw!(u64, $asm_name, "x"); + } + impl Readable for Reg { + type T = u64; + type R = ICC_AP1R_EL1::Register; + sys_coproc_read_raw!(u64, $asm_name, "x"); + } + } + pub const $reg: $reg::Reg = $reg::Reg {}; + }; +} + +ap!(ICC_AP1R0_EL1, "ICC_AP0R0_EL1"); +ap!(ICC_AP1R1_EL1, "ICC_AP0R1_EL1"); +ap!(ICC_AP1R2_EL1, "ICC_AP0R2_EL1"); +ap!(ICC_AP1R3_EL1, "ICC_AP0R3_EL1"); diff --git a/src/registers/icc_asgi1r_el1.rs b/src/registers/icc_asgi1r_el1.rs new file mode 100644 index 0000000..0e01b9c --- /dev/null +++ b/src/registers/icc_asgi1r_el1.rs @@ -0,0 +1,39 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_ASGI1R_EL1 [ + Aff3 OFFSET(48) NUMBITS(8) [], + RS OFFSET(44) NUMBITS(4) [], + IRM OFFSET(40) NUMBITS(1) [], + Aff2 OFFSET(32) NUMBITS(8) [ + + ], + INTID OFFSET(24) NUMBITS(4) [ + + ], + Aff1 OFFSET(16) NUMBITS(24) [ + + ], + TARGET OFFSET(0) NUMBITS(16) [ + + ] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_ASGI1R_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_ASGI1R_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_ASGI1R_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_ASGI1R_EL1", "x"); +} + +pub const ICC_ASGI1R_EL1: Reg = Reg {}; diff --git a/src/registers/icc_bpr0_el1.rs b/src/registers/icc_bpr0_el1.rs new file mode 100644 index 0000000..1715abb --- /dev/null +++ b/src/registers/icc_bpr0_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_BPR0_EL1 [ + BP OFFSET(0) NUMBITS(3) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_BPR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_BPR0_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_BPR0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_BPR0_EL1", "x"); +} + +pub const ICC_BPR0_EL1: Reg = Reg {}; diff --git a/src/registers/icc_bpr1_el1.rs b/src/registers/icc_bpr1_el1.rs new file mode 100644 index 0000000..153efb2 --- /dev/null +++ b/src/registers/icc_bpr1_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_BPR1_EL1 [ + BP OFFSET(0) NUMBITS(3) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_BPR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_BPR1_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_BPR1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_BPR1_EL1", "x"); +} + +pub const ICC_BPR1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_ctlr_el1.rs b/src/registers/icc_ctlr_el1.rs index 79bf22f..2e524ed 100644 --- a/src/registers/icc_ctlr_el1.rs +++ b/src/registers/icc_ctlr_el1.rs @@ -15,7 +15,39 @@ use tock_registers::{interfaces::Readable, register_bitfields}; register_bitfields! {u64, pub ICC_CTLR_EL1 [ /// Extended INTID range (read-only). - ExtRange OFFSET(19) NUMBITS(1) [], + ExtRange OFFSET(19) NUMBITS(1) [ + WideUnsupported = 0b0, // support int_id 1024 ... 8191 + WideSupported = 0b1, + ], + RSS OFFSET(18) NUMBITS(1) [ + Low = 0b0, + High = 0b1 + ], + A3V OFFSET(15) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1, + ], + SEIS OFFSET(14) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1 + ], + ID OFFSET(11) NUMBITS(3) [ + BIT_16 = 0b000, + BIT_24 = 0b001 + ], + PRI OFFSET(8) NUMBITS(3) [], + PMHE OFFSET(6) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], + EOI OFFSET(1) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + CBPR OFFSET(0) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ] ] } @@ -28,4 +60,11 @@ impl Readable for Reg { sys_coproc_read_raw!(u64, "ICC_CTLR_EL1", "x"); } +impl Writeable for Reg { + type T = u64; + type R = ICC_CTLR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_CTLR_EL1", "x"); +} + pub const ICC_CTLR_EL1: Reg = Reg {}; diff --git a/src/registers/icc_ctlr_el3.rs b/src/registers/icc_ctlr_el3.rs new file mode 100644 index 0000000..45790c3 --- /dev/null +++ b/src/registers/icc_ctlr_el3.rs @@ -0,0 +1,73 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_CTLR_EL3 [ + Ext OFFSET(19) NUMBITS(1) [ + WideUnsupported = 0b0, // support int_id 1024 ... 8191 + WideSupported = 0b1, + ], + RSS OFFSET(18) NUMBITS(1) [ + Low = 0b0, + High = 0b1 + ], + A3V OFFSET(15) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1, + ], + SEIS OFFSET(14) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1 + ], + ID OFFSET(11) NUMBITS(3) [ + BIT_16 = 0b000, + BIT_24 = 0b001 + ], + PRI OFFSET(8) NUMBITS(3) [], + PMHE OFFSET(6) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], + RM OFFSET(5) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + EOI_EL1S OFFSET(4) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + EOI_EL1NS OFFSET(3) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + EOI_EL3 OFFSET(2) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + CBPR_EL1NS OFFSET(1) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ], + CBPR_EL1S OFFSET(0) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_CTLR_EL3::Register; + + sys_coproc_read_raw!(u64, "ICC_CTLR_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICC_CTLR_EL3::Register; + + sys_coproc_write_raw!(u64, "ICC_CTLR_EL3", "x"); +} + +pub const ICC_CTLR_EL3: Reg = Reg {}; diff --git a/src/registers/icc_dir_el1.rs b/src/registers/icc_dir_el1.rs new file mode 100644 index 0000000..08fa5fc --- /dev/null +++ b/src/registers/icc_dir_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_DIR_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_DIR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_DIR_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_DIR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_DIR_EL1", "x"); +} + +pub const ICC_DIR_EL1: Reg = Reg {}; diff --git a/src/registers/icc_eoir0_el1.rs b/src/registers/icc_eoir0_el1.rs new file mode 100644 index 0000000..689a96a --- /dev/null +++ b/src/registers/icc_eoir0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_EOIR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_EOIR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_EOIR0_EL1", "x"); +} + +pub const ICC_EOIR0_EL1: Reg = Reg {}; diff --git a/src/registers/icc_eoir1_el1.rs b/src/registers/icc_eoir1_el1.rs new file mode 100644 index 0000000..8fd6549 --- /dev/null +++ b/src/registers/icc_eoir1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_EOIR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_EOIR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_EOIR1_EL1", "x"); +} + +pub const ICC_EOIR1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_hppir0_el1.rs b/src/registers/icc_hppir0_el1.rs new file mode 100644 index 0000000..6ee4f6e --- /dev/null +++ b/src/registers/icc_hppir0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_HPPIR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_HPPIR0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_HPPIR0_EL1", "x"); +} + +pub const ICC_HPPIR0_EL1: Reg = Reg {}; diff --git a/src/registers/icc_hppir1_el1.rs b/src/registers/icc_hppir1_el1.rs new file mode 100644 index 0000000..7a6a5d8 --- /dev/null +++ b/src/registers/icc_hppir1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_HPPIR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_HPPIR1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_HPPIR1_EL1", "x"); +} + +pub const ICC_HPPIR1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_iar0_el1.rs b/src/registers/icc_iar0_el1.rs new file mode 100644 index 0000000..699d908 --- /dev/null +++ b/src/registers/icc_iar0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_IAR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_IAR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_IAR0_EL1", "x"); +} + +pub const ICC_IAR0_EL1: Reg = Reg {}; diff --git a/src/registers/icc_iar1_el1.rs b/src/registers/icc_iar1_el1.rs new file mode 100644 index 0000000..68f6e9b --- /dev/null +++ b/src/registers/icc_iar1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_IAR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_IAR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_IAR1_EL1", "x"); +} + +pub const ICC_IAR1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_igpren0_el1.rs b/src/registers/icc_igpren0_el1.rs new file mode 100644 index 0000000..11a2a72 --- /dev/null +++ b/src/registers/icc_igpren0_el1.rs @@ -0,0 +1,21 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_IGPREN0_EL1 [ + EN OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_IGPREN0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_IGPREN0_EL1", "x"); +} + +pub const ICC_IGPREN0_EL1: Reg = Reg {}; diff --git a/src/registers/icc_igpren1_el1.rs b/src/registers/icc_igpren1_el1.rs new file mode 100644 index 0000000..cd107f1 --- /dev/null +++ b/src/registers/icc_igpren1_el1.rs @@ -0,0 +1,21 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_IGPREN1_EL1 [ + EN OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_IGPREN1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_IGPREN1_EL1", "x"); +} + +pub const ICC_IGPREN1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_igpren1_el3.rs b/src/registers/icc_igpren1_el3.rs new file mode 100644 index 0000000..569227b --- /dev/null +++ b/src/registers/icc_igpren1_el3.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_IGPREN1_EL3 [ + ENGRP1S OFFSET(1) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGRP1NS OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_IGPREN1_EL3::Register; + + sys_coproc_read_raw!(u64, "ICC_IGPREN1_EL3", "x"); +} + +pub const ICC_IGPREN1_EL3: Reg = Reg {}; diff --git a/src/registers/icc_nmiar1_el1.rs b/src/registers/icc_nmiar1_el1.rs new file mode 100644 index 0000000..6f14466 --- /dev/null +++ b/src/registers/icc_nmiar1_el1.rs @@ -0,0 +1,18 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_NMIAR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_NMIAR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_NMIAR1_EL1", "x"); +} + +pub const ICC_NMIAR1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_pmr_el1.rs b/src/registers/icc_pmr_el1.rs new file mode 100644 index 0000000..53a9109 --- /dev/null +++ b/src/registers/icc_pmr_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_PMR_EL1 [ + PRIORITY OFFSET(0) NUMBITS(8) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_PMR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_PMR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICC_PMR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_PMR_EL1", "x"); +} + +pub const ICC_PMR_EL1: Reg = Reg {}; diff --git a/src/registers/icc_rpr_el1.rs b/src/registers/icc_rpr_el1.rs new file mode 100644 index 0000000..6cfd888 --- /dev/null +++ b/src/registers/icc_rpr_el1.rs @@ -0,0 +1,28 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICC_RPR_EL1 [ + NMI OFFSET(63) NUMBITS(1) [], + NMI_NS OFFSET(62) NUMBITS(1) [], + PRIORITY OFFSET(0) NUMBITS(8) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICC_RPR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_RPR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICC_RPR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_RPR_EL1", "x"); +} + +pub const ICC_RPR_EL1: Reg = Reg {}; diff --git a/src/registers/icc_sgi0r_el1.rs b/src/registers/icc_sgi0r_el1.rs new file mode 100644 index 0000000..5bc3045 --- /dev/null +++ b/src/registers/icc_sgi0r_el1.rs @@ -0,0 +1,31 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_SGI0R_EL1 [ + Aff3 OFFSET(48) NUMBITS(8) [], + RS OFFSET(44) NUMBITS(4) [], + IRM OFFSET(40) NUMBITS(1) [], + Aff2 OFFSET(32) NUMBITS(8) [], + INTID OFFSET(24) NUMBITS(4) [], + Aff1 OFFSET(16) NUMBITS(24) [], + TARGET OFFSET(0) NUMBITS(16) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_SGI0R_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_SGI0R_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_SGI0R_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_SGI0R_EL1", "x"); +} + +pub const ICC_SGI0R_EL1: Reg = Reg {}; diff --git a/src/registers/icc_sgi1r_el1.rs b/src/registers/icc_sgi1r_el1.rs new file mode 100644 index 0000000..06be2da --- /dev/null +++ b/src/registers/icc_sgi1r_el1.rs @@ -0,0 +1,39 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICC_SGI1R_EL1 [ + Aff3 OFFSET(48) NUMBITS(8) [], + RS OFFSET(44) NUMBITS(4) [], + IRM OFFSET(40) NUMBITS(1) [], + Aff2 OFFSET(32) NUMBITS(8) [ + + ], + INTID OFFSET(24) NUMBITS(4) [ + + ], + Aff1 OFFSET(16) NUMBITS(24) [ + + ], + TARGET OFFSET(0) NUMBITS(16) [ + + ] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICC_SGI1R_EL1::Register; + + sys_coproc_write_raw!(u64, "ICC_SGI1R_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICC_SGI1R_EL1::Register; + + sys_coproc_read_raw!(u64, "ICC_SGI1R_EL1", "x"); +} + +pub const ICC_SGI1R_EL1: Reg = Reg {}; diff --git a/src/registers/ich_eisr_el2.rs b/src/registers/ich_eisr_el2.rs new file mode 100644 index 0000000..b1d6de1 --- /dev/null +++ b/src/registers/ich_eisr_el2.rs @@ -0,0 +1,41 @@ +use tock_registers::register_bitfields; +use tock_registers::interfaces::*; + +register_bitfields! {u64, + pub ICH_EISR_EL2 [ + STATUS15 OFFSET(15) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS14 OFFSET(14) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS13 OFFSET(13) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS12 OFFSET(12) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS11 OFFSET(11) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS10 OFFSET(10) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS9 OFFSET(9) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS8 OFFSET(8) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS7 OFFSET(7) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS6 OFFSET(6) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS5 OFFSET(5) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS4 OFFSET(4) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS3 OFFSET(3) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS2 OFFSET(2) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS1 OFFSET(1) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS0 OFFSET(0) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICH_EISR_EL2::Register; + + sys_coproc_read_raw!(u64, "ICH_EISR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICH_EISR_EL2::Register; + + sys_coproc_write_raw!(u64, "ICH_EISR_EL2", "x"); +} + +pub const ICH_EISR_EL2: Reg = Reg {}; diff --git a/src/registers/ich_elrsr_el2.rs b/src/registers/ich_elrsr_el2.rs new file mode 100644 index 0000000..79b77c1 --- /dev/null +++ b/src/registers/ich_elrsr_el2.rs @@ -0,0 +1,41 @@ +use tock_registers::register_bitfields; +use tock_registers::interfaces::*; + +register_bitfields! {u64, + pub ICH_ELRSR_EL2 [ + STATUS15 OFFSET(15) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS14 OFFSET(14) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS13 OFFSET(13) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS12 OFFSET(12) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS11 OFFSET(11) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS10 OFFSET(10) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS9 OFFSET(9) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS8 OFFSET(8) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS7 OFFSET(7) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS6 OFFSET(6) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS5 OFFSET(5) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS4 OFFSET(4) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS3 OFFSET(3) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS2 OFFSET(2) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS1 OFFSET(1) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + STATUS0 OFFSET(0) NUMBITS(1) [Enable = 0b1, Disable = 0b0], + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICH_ELRSR_EL2::Register; + + sys_coproc_read_raw!(u64, "ICH_ELRSR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICH_ELRSR_EL2::Register; + + sys_coproc_write_raw!(u64, "ICH_ELRSR_EL2", "x"); +} + +pub const ICH_ELRSR_EL2: Reg = Reg {}; diff --git a/src/registers/ich_hcr_el2.rs b/src/registers/ich_hcr_el2.rs index 451b686..0e1863e 100644 --- a/src/registers/ich_hcr_el2.rs +++ b/src/registers/ich_hcr_el2.rs @@ -22,51 +22,101 @@ register_bitfields! {u64, /// When ICH_VTR_EL2.DVIM == 1: /// Directly-injected Virtual Interrupt Mask. - DVIM OFFSET(15) NUMBITS(1) [], + DVIM OFFSET(15) NUMBITS(1) [ + Masked = 0b1, + Unmasked = 0b0 + ], /// When FEAT_GICv3_TDIR is implemented: /// Trap EL1 writes to ICC_DIR_EL1 and ICV_DIR_EL1. - TDIR OFFSET(14) NUMBITS(1) [], + TDIR OFFSET(14) NUMBITS(1) [ + Trapped = 0b1, + UnTrapped = 0b0 + ], + + TSEI OFFSET(13) NUMBITS(1) [ + Trapped = 0b1, + UnTrapped = 0b0 + ], + TALL1 OFFSET(12) NUMBITS(1) [ + Trapped = 0b1, + UnTrapped = 0b0 + ], + TALL0 OFFSET(11) NUMBITS(1) [ + Trapped = 0b1, + UnTrapped = 0b0 + ], + TC OFFSET(10) NUMBITS(1) [ + Trapped = 0b1, + UnTrapped = 0b0 + ], /// When FEAT_GICv4p1 is implemented: /// Controls whether deactivation of virtual SGIs can increment ICH_HCR_EL2.EOIcount. - vSGIEOICount OFFSET(8) NUMBITS(1) [], + vSGIEOICount OFFSET(8) NUMBITS(1) [ + Discard = 0b1, + Keep = 0b0 + ], /// VM Group 1 Disabled Interrupt Enable. Enables the signaling of a maintenance interrupt /// while signaling of Group 1 interrupts from the virtual CPU interface to the connected /// vPE is disabled. - VGrp1DIE OFFSET(7) NUMBITS(1) [], + VGrp1DIE OFFSET(7) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// VM Group 1 Enabled Interrupt Enable. Enables the signaling of a maintenance interrupt /// while signaling of Group 1 interrupts from the virtual CPU interface to the connected /// vPE is enabled - VGrp1EIE OFFSET(6) NUMBITS(1) [], + VGrp1EIE OFFSET(6) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// VM Group 0 Disabled Interrupt Enable. Enables the signaling of a maintenance interrupt /// while signaling of Group 0 interrupts from the virtual CPU interface to the connected /// vPE is disabled. - VGrp0DIE OFFSET(5) NUMBITS(1) [], + VGrp0DIE OFFSET(5) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// VM Group 0 Enabled Interrupt Enable. Enables the signaling of a maintenance interrupt /// while signaling of Group 0 interrupts from the virtual CPU interface to the connected /// vPE is enabled - VGrp0EIE OFFSET(4) NUMBITS(1) [], + VGrp0EIE OFFSET(4) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// No Pending Interrupt Enable. Enables the signaling of a maintenance interrupt when /// there are no List registers with the State field set to 0b01 (pending). - NPIE OFFSET(3) NUMBITS(1) [], + NPIE OFFSET(3) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// List Register Entry Not Present Interrupt Enable. Enables the signaling of a maintenance /// interrupt while the virtual CPU interface does not have a corresponding valid List /// register entry for an EOI request. - LRENPIE OFFSET(2) NUMBITS(1) [], + LRENPIE OFFSET(2) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], /// Underflow Interrupt Enable. Enables the signaling of a maintenance interrupt when the /// List registers are empty, or hold only one valid entry. - UIE OFFSET(1) NUMBITS(1) [], + UIE OFFSET(1) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], /// Enable. Global enable bit for the virtual CPU interface. - En OFFSET(0) NUMBITS(1) [], + En OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] ] } diff --git a/src/registers/ich_lr_el2.rs b/src/registers/ich_lr_el2.rs new file mode 100644 index 0000000..7c350bb --- /dev/null +++ b/src/registers/ich_lr_el2.rs @@ -0,0 +1,52 @@ +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub ICH_LR_EL2 [ + State OFFSET(62) NUMBITS(2) [], + HW OFFSET(61) NUMBITS(1) [], + Group OFFSET(60) NUMBITS(1) [], + NMI OFFSET(59) NUMBITS(1) [], + Priority OFFSET(48) NUMBITS(8) [], + PINTID OFFSET(32) NUMBITS(13) [], + VINTID OFFSET(0) NUMBITS(32) [] + ] +} + +macro_rules! lr { + ($reg: ident, $name: tt) => { + #[allow(non_snake_case)] + mod $reg { + use tock_registers::interfaces::*; + use super::*; + pub struct Reg; + impl Writeable for Reg { + type T = u64; + type R = ICH_LR_EL2::Register; + sys_coproc_write_raw!(u64, $name, "x"); + } + impl Readable for Reg { + type T = u64; + type R = ICH_LR_EL2::Register; + sys_coproc_read_raw!(u64, $name, "x"); + } + } + pub const $reg: $reg::Reg = $reg::Reg {}; + }; +} + +lr!(ICH_LR0_EL2, "ICH_LR1_EL2"); +lr!(ICH_LR1_EL2, "ICH_LR1_EL2"); +lr!(ICH_LR2_EL2, "ICH_LR2_EL2"); +lr!(ICH_LR3_EL2, "ICH_LR3_EL2"); +lr!(ICH_LR4_EL2, "ICH_LR4_EL2"); +lr!(ICH_LR5_EL2, "ICH_LR5_EL2"); +lr!(ICH_LR6_EL2, "ICH_LR6_EL2"); +lr!(ICH_LR7_EL2, "ICH_LR7_EL2"); +lr!(ICH_LR8_EL2, "ICH_LR8_EL2"); +lr!(ICH_LR9_EL2, "ICH_LR9_EL2"); +lr!(ICH_LR10_EL2, "ICH_LR10_EL2"); +lr!(ICH_LR11_EL2, "ICH_LR11_EL2"); +lr!(ICH_LR12_EL2, "ICH_LR12_EL2"); +lr!(ICH_LR13_EL2, "ICH_LR13_EL2"); +lr!(ICH_LR14_EL2, "ICH_LR14_EL2"); +lr!(ICH_LR15_EL2, "ICH_LR15_EL2"); diff --git a/src/registers/ich_misr_el2.rs b/src/registers/ich_misr_el2.rs index 99ba785..772d837 100644 --- a/src/registers/ich_misr_el2.rs +++ b/src/registers/ich_misr_el2.rs @@ -11,18 +11,31 @@ use tock_registers::interfaces::{Readable, Writeable}; +register_bitfields! {u64, + pub ICH_MISR_EL2 [ + VGrp1D OFFSET(7) NUMBITS(1) [Asserted = 0b1, None = 0b0], + VGrp1E OFFSET(6) NUMBITS(1) [Asserted = 0b1, None = 0b0], + VGrp0D OFFSET(5) NUMBITS(1) [Asserted = 0b1, None = 0b0], + VGrp0E OFFSET(4) NUMBITS(1) [Asserted = 0b1, None = 0b0], + NP OFFSET(3) NUMBITS(1) [Asserted = 0b1, None = 0b0], + LRENP OFFSET(2) NUMBITS(1) [Asserted = 0b1, None = 0b0], + U OFFSET(1) NUMBITS(1) [Asserted = 0b1, None = 0b0], + EOI OFFSET(0) NUMBITS(1) [Asserted = 0b1, None = 0b0], + ] +} + pub struct Reg; impl Readable for Reg { type T = u64; - type R = (); + type R = ICH_MISR_EL2::Register; sys_coproc_read_raw!(u64, "ICH_MISR_EL2", "x"); } impl Writeable for Reg { type T = u64; - type R = (); + type R = ICH_MISR_EL2::Register; sys_coproc_write_raw!(u64, "ICH_MISR_EL2", "x"); } diff --git a/src/registers/ich_vmcr_el2.rs b/src/registers/ich_vmcr_el2.rs index a7c848e..f956be6 100644 --- a/src/registers/ich_vmcr_el2.rs +++ b/src/registers/ich_vmcr_el2.rs @@ -11,18 +11,49 @@ use tock_registers::interfaces::{Readable, Writeable}; +register_bitfields! {u64, + pub ICH_VMCR_EL2 [ + VMPR OFFSET(24) NUMBITS(8) [], + VBPR0 OFFSET(21) NUMBITS(3) [], + VBPR1 OFFSET(18) NUMBITS(3) [], + VEOIM OFFSET(9) NUMBITS(1) [ + + ], + VCBPR OFFSET(4) NUMBITS(1) [ + Shared = 0b1, + Private = 0b0 + ], + VFIQEn OFFSET(3) NUMBITS(1) [ + IRQ = 0b0, + FIQ = 0b1 + ], + VAckCtl OFFSET(2) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + VENG1 OFFSET(1) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + VENG0 OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + pub struct Reg; impl Readable for Reg { type T = u64; - type R = (); + type R = ICH_VMCR_EL2::Register; sys_coproc_read_raw!(u64, "ICH_VMCR_EL2", "x"); } impl Writeable for Reg { type T = u64; - type R = (); + type R = ICH_VMCR_EL2::Register; sys_coproc_write_raw!(u64, "ICH_VMCR_EL2", "x"); } diff --git a/src/registers/ich_vtr_el2.rs b/src/registers/ich_vtr_el2.rs index 1f3a3a7..0a0b84a 100644 --- a/src/registers/ich_vtr_el2.rs +++ b/src/registers/ich_vtr_el2.rs @@ -20,7 +20,31 @@ register_bitfields! {u64, PREbits OFFSET(26) NUMBITS(3) [], /// The number of virtual interrupt identifier bits supported. - IDbits OFFSET(23) NUMBITS(3) [], + IDbits OFFSET(23) NUMBITS(3) [ + BITS_16 = 0b000, + BITS_24 = 0b001 + ], + + SEIS OFFSET(22) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + A3V OFFSET(21) NUMBITS(1) [ + Zero = 0b0, + NonZero = 0b1 + ], + NV4 OFFSET(20) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + TDS OFFSET(19) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], + DVIM OFFSET(18) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], /// List Registers. Indicates the number of List registers implemented, minus one. ListRegs OFFSET(0) NUMBITS(5) [], diff --git a/src/registers/icv_ap0r_el1.rs b/src/registers/icv_ap0r_el1.rs new file mode 100644 index 0000000..e6bdf22 --- /dev/null +++ b/src/registers/icv_ap0r_el1.rs @@ -0,0 +1,34 @@ +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub ICV_AP0R_EL1 [ + FIELDS OFFSET(0) NUMBITS(32) [] + ] +} + +macro_rules! ap { + ($reg: ident, $name: tt) => { + #[allow(non_snake_case)] + mod $reg { + use tock_registers::interfaces::*; + use super::*; + pub struct Reg; + impl Writeable for Reg { + type T = u64; + type R = ICV_AP0R_EL1::Register; + sys_coproc_write_raw!(u64, $name, "x"); + } + impl Readable for Reg { + type T = u64; + type R = ICV_AP0R_EL1::Register; + sys_coproc_read_raw!(u64, $name, "x"); + } + } + pub const $reg: $reg::Reg = $reg::Reg {}; + }; +} + +ap!(ICV_AP0R0_EL1, "ICV_AP0R0_EL1"); +ap!(ICV_AP0R1_EL1, "ICV_AP0R1_EL1"); +ap!(ICV_AP0R2_EL1, "ICV_AP0R2_EL1"); +ap!(ICV_AP0R3_EL1, "ICV_AP0R3_EL1"); diff --git a/src/registers/icv_ap1r_el1.rs b/src/registers/icv_ap1r_el1.rs new file mode 100644 index 0000000..b7e6300 --- /dev/null +++ b/src/registers/icv_ap1r_el1.rs @@ -0,0 +1,34 @@ +use tock_registers::register_bitfields; + +register_bitfields! {u64, + pub ICV_AP1R_EL1 [ + FIELDS OFFSET(0) NUMBITS(32) [] + ] +} + +macro_rules! ap { + ($reg: ident, $name: tt) => { + #[allow(non_snake_case)] + mod $reg { + use tock_registers::interfaces::*; + use super::*; + pub struct Reg; + impl Writeable for Reg { + type T = u64; + type R = ICV_AP1R_EL1::Register; + sys_coproc_write_raw!(u64, $name, "x"); + } + impl Readable for Reg { + type T = u64; + type R = ICV_AP1R_EL1::Register; + sys_coproc_read_raw!(u64, $name, "x"); + } + } + pub const $reg: $reg::Reg = $reg::Reg {}; + }; +} + +ap!(ICV_AP1R0_EL1, "ICV_AP0R0_EL1"); +ap!(ICV_AP1R1_EL1, "ICV_AP0R1_EL1"); +ap!(ICV_AP1R2_EL1, "ICV_AP0R2_EL1"); +ap!(ICV_AP1R3_EL1, "ICV_AP0R3_EL1"); diff --git a/src/registers/icv_asgi1r_el1.rs b/src/registers/icv_asgi1r_el1.rs new file mode 100644 index 0000000..155850a --- /dev/null +++ b/src/registers/icv_asgi1r_el1.rs @@ -0,0 +1,39 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_ASGI1R_EL1 [ + Aff3 OFFSET(48) NUMBITS(8) [], + RS OFFSET(44) NUMBITS(4) [], + IRM OFFSET(40) NUMBITS(1) [], + Aff2 OFFSET(32) NUMBITS(8) [ + + ], + INTID OFFSET(24) NUMBITS(4) [ + + ], + Aff1 OFFSET(16) NUMBITS(24) [ + + ], + TARGET OFFSET(0) NUMBITS(16) [ + + ] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_ASGI1R_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_ASGI1R_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICV_ASGI1R_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_ASGI1R_EL1", "x"); +} + +pub const ICV_ASGI1R_EL1: Reg = Reg {}; diff --git a/src/registers/icv_bpr0_el1.rs b/src/registers/icv_bpr0_el1.rs new file mode 100644 index 0000000..fcda017 --- /dev/null +++ b/src/registers/icv_bpr0_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_BPR0_EL1 [ + BP OFFSET(0) NUMBITS(3) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_BPR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_BPR0_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICV_BPR0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_BPR0_EL1", "x"); +} + +pub const ICV_BPR0_EL1: Reg = Reg {}; diff --git a/src/registers/icv_bpr1_el1.rs b/src/registers/icv_bpr1_el1.rs new file mode 100644 index 0000000..d605de1 --- /dev/null +++ b/src/registers/icv_bpr1_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_BPR1_EL1 [ + BP OFFSET(0) NUMBITS(3) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_BPR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_BPR1_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICV_BPR1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_BPR1_EL1", "x"); +} + +pub const ICV_BPR1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_ctlr_el1.rs b/src/registers/icv_ctlr_el1.rs new file mode 100644 index 0000000..b873ef4 --- /dev/null +++ b/src/registers/icv_ctlr_el1.rs @@ -0,0 +1,58 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_CTLR_EL1 [ + Ext OFFSET(19) NUMBITS(1) [ + WideUnsupported = 0b0, // support int_id 1024 ... 8191 + WideSupported = 0b1, + ], + RSS OFFSET(18) NUMBITS(1) [ + Low = 0b0, + High = 0b1 + ], + A3V OFFSET(15) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1, + ], + SEIS OFFSET(14) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1 + ], + ID OFFSET(11) NUMBITS(3) [ + BIT_16 = 0b000, + BIT_24 = 0b001 + ], + PRI OFFSET(8) NUMBITS(3) [], + PMHE OFFSET(6) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], + EOI OFFSET(1) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + CBPR OFFSET(0) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_CTLR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_CTLR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICV_CTLR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_CTLR_EL1", "x"); +} + +pub const ICV_CTLR_EL1: Reg = Reg {}; diff --git a/src/registers/icv_ctlr_el3.rs b/src/registers/icv_ctlr_el3.rs new file mode 100644 index 0000000..06688f1 --- /dev/null +++ b/src/registers/icv_ctlr_el3.rs @@ -0,0 +1,73 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_CTLR_EL3 [ + Ext OFFSET(19) NUMBITS(1) [ + WideUnsupported = 0b0, // support int_id 1024 ... 8191 + WideSupported = 0b1, + ], + RSS OFFSET(18) NUMBITS(1) [ + Low = 0b0, + High = 0b1 + ], + A3V OFFSET(15) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1, + ], + SEIS OFFSET(14) NUMBITS(1) [ + Disable = 0b0, + Enable = 0b1 + ], + ID OFFSET(11) NUMBITS(3) [ + BIT_16 = 0b000, + BIT_24 = 0b001 + ], + PRI OFFSET(8) NUMBITS(3) [], + PMHE OFFSET(6) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0, + ], + RM OFFSET(5) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + EOI_EL1S OFFSET(4) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + EOI_EL1NS OFFSET(3) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + EOI_EL3 OFFSET(2) NUMBITS(1) [ + EOIR_DropAndDeactivate = 0b0, + EOIR_Drop_Dir_Deactivate = 0b1 + ], + CBPR_EL1NS OFFSET(1) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ], + CBPR_EL1S OFFSET(0) NUMBITS(1) [ + Private = 0b0, + Shared = 0b1, + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_CTLR_EL3::Register; + + sys_coproc_read_raw!(u64, "ICV_CTLR_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICV_CTLR_EL3::Register; + + sys_coproc_write_raw!(u64, "ICV_CTLR_EL3", "x"); +} + +pub const ICV_CTLR_EL3: Reg = Reg {}; diff --git a/src/registers/icv_dir_el1.rs b/src/registers/icv_dir_el1.rs new file mode 100644 index 0000000..2f837ca --- /dev/null +++ b/src/registers/icv_dir_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_DIR_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_DIR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_DIR_EL1", "x"); +} + +impl Readable for Reg { + type T = u64; + type R = ICV_DIR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_DIR_EL1", "x"); +} + +pub const ICV_DIR_EL1: Reg = Reg {}; diff --git a/src/registers/icv_eoir0_el1.rs b/src/registers/icv_eoir0_el1.rs new file mode 100644 index 0000000..88d77f7 --- /dev/null +++ b/src/registers/icv_eoir0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_EOIR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_EOIR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_EOIR0_EL1", "x"); +} + +pub const ICV_EOIR0_EL1: Reg = Reg {}; diff --git a/src/registers/icv_eoir1_el1.rs b/src/registers/icv_eoir1_el1.rs new file mode 100644 index 0000000..a6af241 --- /dev/null +++ b/src/registers/icv_eoir1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_EOIR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_EOIR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_EOIR1_EL1", "x"); +} + +pub const ICV_EOIR1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_hppir0_el1.rs b/src/registers/icv_hppir0_el1.rs new file mode 100644 index 0000000..cd7c286 --- /dev/null +++ b/src/registers/icv_hppir0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_HPPIR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_HPPIR0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_HPPIR0_EL1", "x"); +} + +pub const ICV_HPPIR0_EL1: Reg = Reg {}; diff --git a/src/registers/icv_hppir1_el1.rs b/src/registers/icv_hppir1_el1.rs new file mode 100644 index 0000000..7d469bc --- /dev/null +++ b/src/registers/icv_hppir1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_HPPIR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_HPPIR1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_HPPIR1_EL1", "x"); +} + +pub const ICV_HPPIR1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_iar0_el1.rs b/src/registers/icv_iar0_el1.rs new file mode 100644 index 0000000..38c97bf --- /dev/null +++ b/src/registers/icv_iar0_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_IAR0_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_IAR0_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_IAR0_EL1", "x"); +} + +pub const ICV_IAR0_EL1: Reg = Reg {}; diff --git a/src/registers/icv_iar1_el1.rs b/src/registers/icv_iar1_el1.rs new file mode 100644 index 0000000..de3cef5 --- /dev/null +++ b/src/registers/icv_iar1_el1.rs @@ -0,0 +1,19 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_IAR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_IAR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_IAR1_EL1", "x"); +} + +pub const ICV_IAR1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_igpren0_el1.rs b/src/registers/icv_igpren0_el1.rs new file mode 100644 index 0000000..8a6aa3a --- /dev/null +++ b/src/registers/icv_igpren0_el1.rs @@ -0,0 +1,21 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_IGPREN0_EL1 [ + EN OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_IGPREN0_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_IGPREN0_EL1", "x"); +} + +pub const ICV_IGPREN0_EL1: Reg = Reg {}; diff --git a/src/registers/icv_igpren1_el1.rs b/src/registers/icv_igpren1_el1.rs new file mode 100644 index 0000000..61e48fb --- /dev/null +++ b/src/registers/icv_igpren1_el1.rs @@ -0,0 +1,21 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_IGPREN1_EL1 [ + EN OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_IGPREN1_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_IGPREN1_EL1", "x"); +} + +pub const ICV_IGPREN1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_igpren1_el3.rs b/src/registers/icv_igpren1_el3.rs new file mode 100644 index 0000000..a6d1779 --- /dev/null +++ b/src/registers/icv_igpren1_el3.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_IGPREN1_EL3 [ + ENGRP1S OFFSET(1) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGRP1NS OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_IGPREN1_EL3::Register; + + sys_coproc_read_raw!(u64, "ICV_IGPREN1_EL3", "x"); +} + +pub const ICV_IGPREN1_EL3: Reg = Reg {}; diff --git a/src/registers/icv_nmiar1_el1.rs b/src/registers/icv_nmiar1_el1.rs new file mode 100644 index 0000000..3efc248 --- /dev/null +++ b/src/registers/icv_nmiar1_el1.rs @@ -0,0 +1,18 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_NMIAR1_EL1 [ + INTID OFFSET(0) NUMBITS(24) [] + ] +} + +pub struct Reg; + +impl Writeable for Reg { + type T = u64; + type R = ICV_NMIAR1_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_NMIAR1_EL1", "x"); +} + +pub const ICV_NMIAR1_EL1: Reg = Reg {}; diff --git a/src/registers/icv_pmr_el1.rs b/src/registers/icv_pmr_el1.rs new file mode 100644 index 0000000..d9b4df7 --- /dev/null +++ b/src/registers/icv_pmr_el1.rs @@ -0,0 +1,25 @@ +use tock_registers::{interfaces::*, register_bitfields}; + +register_bitfields! {u64, + pub ICV_PMR_EL1 [ + PRIORITY OFFSET(0) NUMBITS(8) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_PMR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_PMR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICV_PMR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_PMR_EL1", "x"); +} + +pub const ICV_PMR_EL1: Reg = Reg {}; diff --git a/src/registers/icv_rpr_el1.rs b/src/registers/icv_rpr_el1.rs new file mode 100644 index 0000000..6fcd051 --- /dev/null +++ b/src/registers/icv_rpr_el1.rs @@ -0,0 +1,28 @@ +use tock_registers::{interfaces::*, register_bitfields}; + + +register_bitfields! {u64, + pub ICV_RPR_EL1 [ + NMI OFFSET(63) NUMBITS(1) [], + NMI_NS OFFSET(62) NUMBITS(1) [], + PRIORITY OFFSET(0) NUMBITS(8) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ICV_RPR_EL1::Register; + + sys_coproc_read_raw!(u64, "ICV_RPR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = ICV_RPR_EL1::Register; + + sys_coproc_write_raw!(u64, "ICV_RPR_EL1", "x"); +} + +pub const ICV_RPR_EL1: Reg = Reg {}; From ed28bd8ad8c551eeca6fa6c0b0d00fa5fa540ad8 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 18 Apr 2024 22:44:18 +0800 Subject: [PATCH 41/70] refactor: add lower field value for descriptor --- src/mmu/descriptor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index ca40e8f..04774c2 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -84,6 +84,7 @@ register_bitfields! {u64, FALSE = 0b0 ], OUTPUT OFFSET(0) NUMBITS(48) [], + LOWER OFFSET(0) NUMBITS(2) [], TYPE OFFSET(1) NUMBITS(1) [ TABLE = 0b1, BLOCK = 0b0 From 8180359020a23c56c40adb2b6b60416510ee2403 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 18 Apr 2024 22:45:08 +0800 Subject: [PATCH 42/70] feat(gic): add gic (re)distributer structure --- src/gic.rs | 22 +++++++ src/gic/v2.rs | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gic/v3.rs | 114 ++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 303 insertions(+) create mode 100644 src/gic.rs create mode 100644 src/gic/v2.rs create mode 100644 src/gic/v3.rs diff --git a/src/gic.rs b/src/gic.rs new file mode 100644 index 0000000..ab6607a --- /dev/null +++ b/src/gic.rs @@ -0,0 +1,22 @@ +pub mod v3; +pub mod v2; +pub mod registers; + +pub enum IRQState { + Inactive, + Pending, + Active, + PendingActive, +} + +impl From for IRQState { + fn from(value: u64) -> Self { + match value { + 0 => IRQState::Inactive, + 1 => IRQState::Pending, + 2 => IRQState::Active, + 3 => IRQState::PendingActive, + _ => panic!("illegal irq state input") + } + } +} diff --git a/src/gic/v2.rs b/src/gic/v2.rs new file mode 100644 index 0000000..9ccb22f --- /dev/null +++ b/src/gic/v2.rs @@ -0,0 +1,166 @@ +mod registers; +use tock_registers::{ + fields::FieldValue, + interfaces::{Readable, Writeable}, + registers::*, + *, +}; +use paste::paste; +pub use registers::*; + +pub const GICC_CTLR_EN_BIT: usize = 0x1; +pub const GICC_CTLR_EOIMODENS_BIT: usize = 1 << 9; +pub const GIC_SGIS_NUM: usize = 16; +pub const GIC_INTS_MAX: usize = 1024; +pub const GIC_PRIVINT_NUM: usize = GIC_SGIS_NUM + GIC_PPIS_NUM; +pub const GIC_SPI_MAX: usize = 1024 - GIC_PRIVINT_NUM; +pub const GIC_PRIO_BITS: usize = 8; +pub const GIC_TARGET_BITS: usize = 8; +pub const GIC_TARGETS_MAX: usize = GIC_TARGET_BITS; +pub const GIC_CONFIG_BITS: usize = 2; + +const GICD_CTLR_EN_BIT: usize = 0x1; +const GIC_PPIS_NUM: usize = 16; +const GICH_HCR_LRENPIE_BIT: usize = 1 << 2; +const GIC_INT_REGS_NUM: usize = GIC_INTS_MAX / 32; +const GIC_PRIO_REGS_NUM: usize = GIC_INTS_MAX * 8 / 32; +const GIC_TARGET_REGS_NUM: usize = GIC_INTS_MAX * 8 / 32; +const GIC_CONFIG_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; +const GIC_SEC_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; + +pub const GIC_SGI_REGS_NUM: usize = GIC_SGIS_NUM * 8 / 32; +pub const GIC_LIST_REGS_NUM: usize = 64; +pub const GICD_TYPER_CPUNUM_OFF: usize = 5; +pub const GICD_TYPER_CPUNUM_MSK: usize = 0b11111; + +register_structs! { + #[allow(non_snake_case)] + pub GicDistributorInner { + (0x0000 => pub CTLR: ReadWrite), + (0x0004 => pub TYPER: ReadOnly), + (0x0008 => pub IIDR: ReadOnly), + (0x000c => reserve0), + (0x0080 => pub IGROUPR: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0100 => pub ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0180 => pub ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0200 => pub ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0280 => pub ICPENDR: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0300 => pub ISACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0380 => pub ICACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), + (0x0400 => pub IPRIORITYR: [ReadWrite; GIC_PRIO_REGS_NUM]), + (0x0800 => pub ITARGETSR: [ReadWrite; GIC_TARGET_REGS_NUM]), + (0x0c00 => pub ICFGR: [ReadWrite; GIC_CONFIG_REGS_NUM]), + (0x0d00 => reserve1), + (0x0e00 => pub NSACR: [ReadWrite; GIC_SEC_REGS_NUM]), + (0x0f00 => pub SGIR: WriteOnly), + (0x0f04 => reserve2), + (0x0f10 => pub CPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), + (0x0f20 => pub SPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), + (0x0f30 => _reserved_3), + (0x1000 => @END), + } +} + +register_structs! { + #[allow(non_snake_case)] + pub GicCpuInterfaceInner { + (0x0000 => CTLR: ReadWrite), // CPU Interface Control Register + (0x0004 => PMR: ReadWrite), // Interrupt Priority Mask Register + (0x0008 => BPR: ReadWrite), // Binary Point Register + (0x000c => IAR: ReadOnly), // Interrupt Acknowledge Register + (0x0010 => EOIR: WriteOnly), // End of Interrupt Register + (0x0014 => RPR: ReadOnly), // Running Priority Register + (0x0018 => HPPIR: ReadOnly), // Highest Priority Pending Interrupt Register + (0x001c => ABPR: ReadWrite), // Aliased Binary Point Register + (0x0020 => AIAR: ReadOnly), // Aliased Interrupt Acknowledge Register + (0x0024 => AEOIR: WriteOnly), // Aliased End of Interrupt Register + (0x0028 => AHPPIR: ReadOnly), // Aliased Highest Priority Pending Interrupt Register + (0x002c => reserved_0), + (0x00d0 => APR: [ReadWrite; 4]), // Active Priorities Register + (0x00e0 => NSAPR: [ReadWrite; 4]), // Non-secure Active Priorities Register + (0x00f0 => reserved_1), + (0x00fc => IIDR: ReadOnly), // CPU Interface Identification Register + (0x0100 => reserved_2), + (0x1000 => DIR: WriteOnly), // Deactivate Interrupt Register + (0x1004 => reserved_3), + (0x2000 => @END), + } +} + +register_structs! { + #[allow(non_snake_case)] + pub GicHypervisorInterfaceInner { + (0x0000 => HCR: ReadWrite), + (0x0004 => VTR: ReadOnly), + (0x0008 => VMCR: ReadWrite), + (0x000c => reserve0), + (0x0010 => MISR: ReadOnly), + (0x0014 => reserve1), + (0x0020 => EISR: [ReadOnly; GIC_LIST_REGS_NUM / 32]), + (0x0028 => reserve2), + (0x0030 => ELRSR: [ReadOnly; GIC_LIST_REGS_NUM / 32]), + (0x0038 => reserve3), + (0x00f0 => APR: ReadWrite), + (0x00f4 => reserve4), + (0x0100 => LR: [ReadWrite; GIC_LIST_REGS_NUM]), + (0x0200 => reserve5), + (0x1000 => @END), + } +} + +unsafe impl Sync for GicDistributorInner {} +unsafe impl Sync for GicCpuInterfaceInner {} +unsafe impl Sync for GicHypervisorInterfaceInner {} + +type Field = ReadWrite; + +macro_rules! bit_imp { + ($method: ident, $field: ident, $width: expr) => { + pub fn $method(&mut self, id: u32, pos: u32) { + let field_num = 32 / $width; + let reg_id = id / field_num; + let field_id = id & (field_num - 1); + self.$field[reg_id as usize] + .set(self.$field[reg_id as usize].get() | (1 << pos) << field_id << $width); + } + paste! { + pub fn [](&mut self, gid: u32, value: u32){ + self.$field[gid as usize].set(value); + } + } + }; +} +macro_rules! field_imp { + ($method: ident, $field: ident, $width: expr, $interface: ident) => { + pub fn $method( + &mut self, + id: u32, + field: tock_registers::fields::FieldValue, + ) { + let field_num = 32 / $width; + let reg_id = id / field_num; + let field_id = id & (field_num - 1); + let mask = (1 << $width) - 1; + self.$field[reg_id as usize].set( + (self.$field[reg_id as usize].get() & (!(mask << field_id << $width))) + | (field.value << field_id << $width), + ); + } + }; +} + +impl GicDistributorInner { + bit_imp!(enable, ISENABLER, 1); + bit_imp!(disable, ICENABLER, 1); + bit_imp!(set_pending, ISPENDR, 1); + bit_imp!(clear_pending, ICPENDR, 1); + bit_imp!(activate, ISACTIVER, 1); + bit_imp!(deactivate, ICACTIVER, 1); + bit_imp!(set_priority, IPRIORITYR, 8); + field_imp!(set_nsacr, NSACR, 2, GICD_NSCAR); + field_imp!(set_icfgr, ICFGR, 2, GICD_ICFGR); + + pub fn forward(&mut self, id: u32, cpu: u32, interface: u32) { + self.ITARGETSR[id as usize].set(1 << (interface << (cpu << 3))); + } +} diff --git a/src/gic/v3.rs b/src/gic/v3.rs new file mode 100644 index 0000000..b0785f2 --- /dev/null +++ b/src/gic/v3.rs @@ -0,0 +1,114 @@ +use core::mem::size_of; +use tock_registers::{registers::*, *}; + +pub const GIC_SGIS_NUM: usize = 16; +pub const GIC_INTS_MAX: usize = 1024; +pub const GIC_PRIVINT_NUM: usize = GIC_SGIS_NUM + GIC_PPIS_NUM; +pub const GIC_SPI_MAX: usize = GIC_INTS_MAX - GIC_PRIVINT_NUM; +pub const GIC_PRIO_BITS: usize = 8; +pub const GIC_TARGET_BITS: usize = 8; +pub const GIC_TARGETS_MAX: usize = GIC_TARGET_BITS; +pub const GIC_CONFIG_BITS: usize = 2; +pub const GIC_SGI_REGS_NUM: usize = GIC_SGIS_NUM * 8 / 32; +pub const GIC_LIST_REGS_NUM: usize = 64; + +const GIC_PPIS_NUM: usize = 16; +const GIC_INT_RT_NUM: usize = 1019 - 32 + 1; +const GIC_INT_REGS_NUM: usize = GIC_INTS_MAX / 32; +const GIC_PRIO_REGS_NUM: usize = GIC_INTS_MAX * 8 / 32; +const GIC_TARGET_REGS_NUM: usize = GIC_INTS_MAX * 8 / 32; +const GIC_CONFIG_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; +const GIC_SEC_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; + +register_structs! { + #[allow(non_snake_case)] + pub GicDistributor { + (0x0000 => CTLR: ReadWrite), //Distributor Control Register + (0x0004 => TYPER: ReadOnly), //Interrupt Controller Type Register + (0x0008 => IIDR: ReadOnly), //Distributor Implementer Identification Register + (0x000c => TYPER2: ReadOnly), //Interrupt controller Type Register 2 + (0x0010 => STATUSR: ReadWrite), //Error Reporting Status Register, optional + (0x0014 => reserved0), + (0x0040 => SETSPI_NSR: WriteOnly), //Set SPI Register + (0x0044 => reserved1), + (0x0048 => CLRSPI_NSR: WriteOnly), //Clear SPI Register + (0x004c => reserved2), + (0x0050 => SETSPI_SR: WriteOnly), //Set SPI, Secure Register + (0x0054 => reserved3), + (0x0058 => CLRSPI_SR: WriteOnly), //Clear SPI, Secure Register + (0x005c => reserved4), + (0x0080 => IGROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers + (0x0100 => ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Enable Registers + (0x0180 => ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Enable Registers + (0x0200 => ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Pending Registers + (0x0280 => ICPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Pending Registers + (0x0300 => ISACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Active Registers + (0x0380 => ICACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Active Registers + (0x0400 => IPRIORITYR: [ReadWrite; GIC_PRIO_REGS_NUM]), //Interrupt Priority Registers + (0x0800 => ITARGETSR: [ReadWrite; GIC_TARGET_REGS_NUM]), //Interrupt Processor Targets Registers + (0x0c00 => ICFGR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Configuration Registers + (0x0d00 => IGRPMODR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Group Modifier Registers + (0x0e00 => NSACR: [ReadWrite; GIC_SEC_REGS_NUM]), //Non-secure Access Control Registers + (0x0f00 => SGIR: WriteOnly), //Software Generated Interrupt Register + (0x0f04 => reserved6), + (0x0f10 => CPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Clear-Pending Registers + (0x0f20 => SPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Set-Pending Registers + (0x0f30 => reserved7), + (0x6000 => IROUTER: [ReadWrite; (0x8000 - 0x6000) / size_of::()]), //Interrupt Routing Registers for extended SPI range + (0x8000 => reserved21), + (0xffd0 => ID: [ReadOnly; (0x10000 - 0xffd0) / size_of::()]), //Reserved for ID registers + (0x10000 => @END), + } +} + +register_structs! { + #[allow(non_snake_case)] + pub GICRedistributer { + (0x0000 => CTLR: ReadWrite), // Redistributor Control Register + (0x0004 => IIDR: ReadOnly), // Implementer Identification Register + (0x0008 => TYPER: ReadOnly), // Redistributor Type Register + (0x0010 => STATUSR: ReadWrite), // Error Reporting Status Register, optional + (0x0014 => WAKER: ReadWrite), // Redistributor Wake Register + (0x0018 => MPAMIDR: ReadOnly), // Report maximum PARTID and PMG Register + (0x001c => PARTIDR: ReadWrite), // Set PARTID and PMG Register + (0x0020 => reserved18), + (0x0040 => SETLPIR: WriteOnly), // Set LPI Pending Register + (0x0048 => CLRLPIR: WriteOnly), // Clear LPI Pending Register + (0x0050 => reserved17), + (0x0070 => PROPBASER: ReadWrite), //Redistributor Properties Base Address Register + (0x0078 => PEDNBASER: ReadWrite), //Redistributor LPI Pending Table Base Address Register + (0x0080 => reserved16), + (0x00a0 => INVLPIR: WriteOnly), // Redistributor Invalidate LPI Register + (0x00a8 => reserved15), + (0x00b0 => INVALLR: WriteOnly), // Redistributor Invalidate All Register + (0x00b8 => reserved14), + (0x00c0 => SYNCR: ReadOnly), // Redistributor Synchronize Register + (0x00c8 => reserved13), + (0xffd0 => ID: [ReadOnly; (0x10000 - 0xFFD0) / size_of::()]), + (0x10000 => reserved12), + (0x10080 => IGROUPR0: ReadWrite), //SGI_base frame, all below + (0x10084 => reserved11), + (0x10100 => ISENABLER0: ReadWrite), + (0x10104 => reserved10), + (0x10180 => ICENABLER0: ReadWrite), + (0x10184 => reserved9), + (0x10200 => ISPENDR0: ReadWrite), + (0x10204 => reserved8), + (0x10280 => ICPENDR0: ReadWrite), + (0x10284 => reserved7), + (0x10300 => ISACTIVER0: ReadWrite), + (0x10304 => reserved6), + (0x10380 => ICACTIVER0: ReadWrite), + (0x10384 => reserved5), + (0x10400 => IPRIORITYR: [ReadWrite;8]), + (0x10420 => reserved4), + (0x10c00 => ICFGR0: ReadWrite), + (0x10c04 => ICFGR1: ReadWrite), + (0x10c08 => reserved3), + (0x10d00 => IGRPMODR0: ReadWrite), + (0x10d04 => reserved2), + (0x10e00 => NSACR: ReadWrite), + (0x10e04 => reserved1), + (0x20000 => @END), + } +} diff --git a/src/lib.rs b/src/lib.rs index 4e35ed8..aea4b80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,3 +60,4 @@ pub mod irq; pub mod cache; pub mod exception; pub mod registers; +pub mod gic; From 73bb63b4bc7fb95c79203a19958e59522b38140a Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 18 Apr 2024 22:45:25 +0800 Subject: [PATCH 43/70] feat(gic): add gicv2 distributer register --- src/gic/v2/registers.rs | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/gic/v2/registers.rs diff --git a/src/gic/v2/registers.rs b/src/gic/v2/registers.rs new file mode 100644 index 0000000..7b764f8 --- /dev/null +++ b/src/gic/v2/registers.rs @@ -0,0 +1,45 @@ +use tock_registers::*; + +register_bitfields! {u32, + pub GICD_CTLR [ + ENGrp1 OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGrp0 OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ], + pub GICD_TYPER [ + LSPI OFFSET(11) NUMBITS(5) [], + SecurityExtn OFFSET(10) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + CPUNumber OFFSET(5) NUMBITS(3) [], + ITLines OFFSET(0) NUMBITS(5) [] + ], + pub GICD_IIDR [ + Variant OFFSET(16) NUMBITS(4) [], + Revision OFFSET(12) NUMBITS(4) [], + Implementer OFFSET(0) NUMBITS(12) [] + ], + pub GICD_ICFGR [ + IntConfig OFFSET(1) NUMBITS(1) [ + + ], + Trigger OFFSET(0) NUMBITS(1)[ + LevelSensative = 0b0, + EdgeTriggered = 0b1 + ] + ], + pub GICD_NSCAR [ + ACCESS OFFSET(0) NUMBITS(2) [ + None = 0b00, + RO = 0b01, + WO = 0b10, + WR = 0b11 + ] + ] +} From 74f2b92a86aef764612ea637671f54c957f6d0c2 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 18 Apr 2024 22:45:43 +0800 Subject: [PATCH 44/70] chore: bump Cargo.toml --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 5917e3c..95098f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ exclude = [ [dependencies] tock-registers = { version = "0.9.0", default-features = false } # Use it as interface-only library. +paste = { version = "1.0" } From 9517b6aaee00b611aed2ade0bbe8be68d7b9f4b2 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Sat, 27 Apr 2024 22:00:56 +0800 Subject: [PATCH 45/70] feat(gic): add gicv2 handlers Signed-off-by Yiyang Wu --- src/gic/v2.rs | 36 +++++++++++++++++++++++++++++++----- src/gic/v2/registers.rs | 26 +++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/gic/v2.rs b/src/gic/v2.rs index 9ccb22f..080631c 100644 --- a/src/gic/v2.rs +++ b/src/gic/v2.rs @@ -1,6 +1,5 @@ mod registers; use tock_registers::{ - fields::FieldValue, interfaces::{Readable, Writeable}, registers::*, *, @@ -35,6 +34,7 @@ pub const GICD_TYPER_CPUNUM_MSK: usize = 0b11111; register_structs! { #[allow(non_snake_case)] + #[repr(C)] pub GicDistributorInner { (0x0000 => pub CTLR: ReadWrite), (0x0004 => pub TYPER: ReadOnly), @@ -63,6 +63,7 @@ register_structs! { register_structs! { #[allow(non_snake_case)] + #[repr(C)] pub GicCpuInterfaceInner { (0x0000 => CTLR: ReadWrite), // CPU Interface Control Register (0x0004 => PMR: ReadWrite), // Interrupt Priority Mask Register @@ -89,6 +90,7 @@ register_structs! { register_structs! { #[allow(non_snake_case)] + #[repr(C)] pub GicHypervisorInterfaceInner { (0x0000 => HCR: ReadWrite), (0x0004 => VTR: ReadOnly), @@ -130,6 +132,7 @@ macro_rules! bit_imp { } }; } + macro_rules! field_imp { ($method: ident, $field: ident, $width: expr, $interface: ident) => { pub fn $method( @@ -150,17 +153,40 @@ macro_rules! field_imp { } impl GicDistributorInner { - bit_imp!(enable, ISENABLER, 1); - bit_imp!(disable, ICENABLER, 1); - bit_imp!(set_pending, ISPENDR, 1); - bit_imp!(clear_pending, ICPENDR, 1); + + bit_imp!(set_pend, ISPENDR, 1); + bit_imp!(clear_pend, ICPENDR, 1); bit_imp!(activate, ISACTIVER, 1); bit_imp!(deactivate, ICACTIVER, 1); bit_imp!(set_priority, IPRIORITYR, 8); + bit_imp!(enable_intr, ISENABLER, 1); + bit_imp!(disable_intr, ICENABLER, 1); + field_imp!(set_nsacr, NSACR, 2, GICD_NSCAR); field_imp!(set_icfgr, ICFGR, 2, GICD_ICFGR); pub fn forward(&mut self, id: u32, cpu: u32, interface: u32) { self.ITARGETSR[id as usize].set(1 << (interface << (cpu << 3))); } + + pub fn enable_gic(&mut self) { + self.CTLR + .set((GICD_CTLR::ENGrp0::Enable + GICD_CTLR::ENGrp1::Enable).into()) + } + + pub fn disable_gic(&mut self) { + self.CTLR + .set((GICD_CTLR::ENGrp0::Disable + GICD_CTLR::ENGrp1::Disable).into()) + } + +} + +impl GicCpuInterfaceInner { + pub fn enable(&mut self) { + self.CTLR.set(GICC_CTLR::EN::Enable.into()) + } + pub fn disable(&mut self) { + self.CTLR.set(GICC_CTLR::EN::Disable.into()) + } } + diff --git a/src/gic/v2/registers.rs b/src/gic/v2/registers.rs index 7b764f8..1597836 100644 --- a/src/gic/v2/registers.rs +++ b/src/gic/v2/registers.rs @@ -41,5 +41,29 @@ register_bitfields! {u32, WO = 0b10, WR = 0b11 ] - ] + ], + pub GICC_CTLR [ + EN OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ], + pub GICC_PMR [ + PRIORITY OFFSET(0) NUMBITS(7)[ + + ] + ], + pub GICC_BPR [ + BP OFFSET(0) NUMBITS(2) [ + + ] + ], + pub GICC_GENERIC [ + CPUID OFFSET(10) NUMBITS(2) [ + + ], + INTRID OFFSET(0) NUMBITS(10) [ + + ], + ], } From 78d07d69bc160399e91b5655260e2e076bf14404 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 2 May 2024 15:45:06 +0800 Subject: [PATCH 46/70] feat(mmu): refactor vadescriptor Signed-off-by Yiyang Wu --- src/mmu/address.rs | 1 - src/mmu/descriptor.rs | 12 +++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 8c19756..2b3acfb 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -164,7 +164,6 @@ impl From for FieldValue { + type_fields + BlockDescriptor::NSE_NG::TRUE + BlockDescriptor::VALID::TRUE - + BlockDescriptor::TYPE::BLOCK + BlockDescriptor::AF::TRUE } } diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 04774c2..b899128 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -19,6 +19,7 @@ register_bitfields! {u64, FALSE = 0b0 ], OUTPUT OFFSET(0) NUMBITS(48) [], + LOWER_ATTRS OFFSET(0) NUMBITS(12) [], NSE_NG OFFSET(11) NUMBITS(1) [ TRUE = 0b1, FALSE = 0b0 @@ -84,7 +85,7 @@ register_bitfields! {u64, FALSE = 0b0 ], OUTPUT OFFSET(0) NUMBITS(48) [], - LOWER OFFSET(0) NUMBITS(2) [], + LOWER_ATTRS OFFSET(0) NUMBITS(2) [], TYPE OFFSET(1) NUMBITS(1) [ TABLE = 0b1, BLOCK = 0b0 @@ -96,6 +97,11 @@ register_bitfields! {u64, ] } +pub trait Descriptor {} + +impl Descriptor for BlockDescriptor::Register {} +impl Descriptor for TableDescriptor::Register {} + #[derive(Clone, Copy)] #[repr(transparent)] pub struct VADescriptor(pub u64); @@ -122,6 +128,10 @@ impl VADescriptor { { self.0 = field_value.modify(self.0); } + + pub fn output(&self) -> u64 { + TableDescriptor::OUTPUT.read(self.0) & !TableDescriptor::LOWER_ATTRS.mask + } } impl From for VADescriptor { From 9f98f678f683d3a759423de9c510b9f4fe97c1ce Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 2 May 2024 15:45:26 +0800 Subject: [PATCH 47/70] fix(gic): remove unused mods Signed-off-by Yiyang Wu --- src/gic.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gic.rs b/src/gic.rs index ab6607a..a26d39e 100644 --- a/src/gic.rs +++ b/src/gic.rs @@ -1,6 +1,5 @@ pub mod v3; pub mod v2; -pub mod registers; pub enum IRQState { Inactive, From 754c180f62a73bbda294bb9fbab1a5eb41f5bc41 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 10 May 2024 01:46:33 +0800 Subject: [PATCH 48/70] refactor: move PageMode into aarch64-cpu Signed-off-by Yiyang Wu --- src/mmu/address.rs | 36 ++++++++++++++++++++++++++++++++++++ src/mmu/descriptor.rs | 12 ++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 2b3acfb..9f022f7 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -14,6 +14,42 @@ register_bitfields! {u64, ] } +#[derive(Clone, Copy)] +pub enum PageMode { + HugePage, + LargePage, + SmallPage, +} + +impl PageMode { + pub fn levels(&self) -> u8 { + match self { + PageMode::SmallPage => 3, + PageMode::LargePage => 2, + PageMode::HugePage => 1, + } + } +} + +impl Into for PageMode { + fn into(self) -> u64 { + match self { + Self::SmallPage => 0x1000, + Self::LargePage => 0x200000, + Self::HugePage => 0x40000000, + } + } +} + +impl From for FieldValue { + fn from(value: PageMode) -> Self { + match value { + PageMode::SmallPage => BlockDescriptor::TYPE::PAGE, + _ => BlockDescriptor::TYPE::BLOCK, + } + } +} + #[derive(Copy, Clone)] pub enum MMProt { NormalReadOnly, diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index b899128..b5e8de2 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -3,6 +3,7 @@ use tock_registers::{ fields::{FieldValue, Field}, RegisterLongName, }; +use super::{address::PageMode, MMType}; register_bitfields! {u64, pub BlockDescriptor [ @@ -132,6 +133,17 @@ impl VADescriptor { pub fn output(&self) -> u64 { TableDescriptor::OUTPUT.read(self.0) & !TableDescriptor::LOWER_ATTRS.mask } + + pub fn table(output: u64) -> u64 { + (TableDescriptor::OUTPUT.val(output) + + TableDescriptor::TYPE::TABLE + + TableDescriptor::VALID::TRUE) + .value + } + + pub fn block(output: u64, typ: MMType, mode: PageMode) -> u64 { + (BlockDescriptor::OUTPUT.val(output) + typ.into() + mode.into()).value + } } impl From for VADescriptor { From 88438de2cea95a0d508a24fc691287a456c1d54c Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:24:38 +0200 Subject: [PATCH 49/70] feat: add timer source for EL2 Signed-off-by: Yiyang Wu --- src/registers.rs | 24 ++++++++++++++---------- src/registers/cnthp_ctl_el2.rs | 11 +++++++++-- src/registers/cnthp_cval_el2.rs | 19 +++++++++++++++++++ src/registers/cnthp_tval_el2.rs | 31 +++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/registers/cnthp_cval_el2.rs create mode 100644 src/registers/cnthp_tval_el2.rs diff --git a/src/registers.rs b/src/registers.rs index c8dad6f..89682be 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -23,6 +23,8 @@ mod clidr_el1; mod cntfrq_el0; mod cnthctl_el2; mod cnthp_ctl_el2; +mod cnthp_cval_el2; +mod cnthp_tval_el2; mod cntkctl_el1; mod cntp_ctl_el0; mod cntp_cval_el0; @@ -130,9 +132,9 @@ mod ttbr1_el1; mod vbar_el1; mod vbar_el2; mod vbar_el3; +mod vmpidr_el2; mod vtcr_el2; mod vttbr_el2; -mod vmpidr_el2; mod icc_ap0r_el1; mod icc_ap1r_el1; @@ -160,13 +162,13 @@ mod icc_sre_el1; mod icc_sre_el2; mod icc_sre_el3; +mod ich_eisr_el2; +mod ich_elrsr_el2; mod ich_hcr_el2; mod ich_lr_el2; -mod ich_vtr_el2; -mod ich_eisr_el2; mod ich_misr_el2; mod ich_vmcr_el2; -mod ich_elrsr_el2; +mod ich_vtr_el2; mod icv_ap0r_el1; mod icv_ap1r_el1; @@ -207,6 +209,8 @@ pub use clidr_el1::CLIDR_EL1; pub use cntfrq_el0::CNTFRQ_EL0; pub use cnthctl_el2::CNTHCTL_EL2; pub use cnthp_ctl_el2::CNTHP_CTL_EL2; +pub use cnthp_cval_el2::CNTHP_CVAL_EL2; +pub use cnthp_tval_el2::CNTHP_TVAL_EL2; pub use cntkctl_el1::CNTKCTL_EL1; pub use cntp_ctl_el0::CNTP_CTL_EL0; pub use cntp_cval_el0::CNTP_CVAL_EL0; @@ -314,9 +318,9 @@ pub use ttbr1_el1::TTBR1_EL1; pub use vbar_el1::VBAR_EL1; pub use vbar_el2::VBAR_EL2; pub use vbar_el3::VBAR_EL3; +pub use vmpidr_el2::VMPIDR_EL2; pub use vtcr_el2::VTCR_EL2; pub use vttbr_el2::VTTBR_EL2; -pub use vmpidr_el2::VMPIDR_EL2; pub use icc_ap0r_el1::*; pub use icc_ap1r_el1::*; @@ -325,8 +329,8 @@ pub use icc_bpr0_el1::ICC_BPR0_EL1; pub use icc_bpr1_el1::ICC_BPR1_EL1; pub use icc_ctlr_el1::ICC_CTLR_EL1; pub use icc_ctlr_el3::ICC_CTLR_EL3; -pub use icc_eoir1_el1::ICC_EOIR1_EL1; pub use icc_eoir0_el1::ICC_EOIR0_EL1; +pub use icc_eoir1_el1::ICC_EOIR1_EL1; pub use icc_hppir0_el1::ICC_HPPIR0_EL1; pub use icc_hppir1_el1::ICC_HPPIR1_EL1; pub use icc_iar0_el1::ICC_IAR0_EL1; @@ -334,14 +338,14 @@ pub use icc_iar1_el1::ICC_IAR1_EL1; pub use icc_igpren0_el1::ICC_IGPREN0_EL1; pub use icc_igpren1_el1::ICC_IGPREN1_EL1; pub use icc_igpren1_el3::ICC_IGPREN1_EL3; -pub use icc_sre_el1::ICC_SRE_EL1; -pub use icc_sre_el2::ICC_SRE_EL2; -pub use icc_sre_el3::ICC_SRE_EL3; pub use icc_nmiar1_el1::ICC_NMIAR1_EL1; pub use icc_pmr_el1::ICC_PMR_EL1; pub use icc_rpr_el1::ICC_RPR_EL1; pub use icc_sgi0r_el1::ICC_SGI0R_EL1; pub use icc_sgi1r_el1::ICC_SGI1R_EL1; +pub use icc_sre_el1::ICC_SRE_EL1; +pub use icc_sre_el2::ICC_SRE_EL2; +pub use icc_sre_el3::ICC_SRE_EL3; pub use ich_eisr_el2::ICH_EISR_EL2; pub use ich_elrsr_el2::ICH_ELRSR_EL2; @@ -358,8 +362,8 @@ pub use icv_bpr0_el1::ICV_BPR0_EL1; pub use icv_bpr1_el1::ICV_BPR1_EL1; pub use icv_ctlr_el1::ICV_CTLR_EL1; pub use icv_ctlr_el3::ICV_CTLR_EL3; -pub use icv_eoir1_el1::ICV_EOIR1_EL1; pub use icv_eoir0_el1::ICV_EOIR0_EL1; +pub use icv_eoir1_el1::ICV_EOIR1_EL1; pub use icv_hppir0_el1::ICV_HPPIR0_EL1; pub use icv_hppir1_el1::ICV_HPPIR1_EL1; pub use icv_iar0_el1::ICV_IAR0_EL1; diff --git a/src/registers/cnthp_ctl_el2.rs b/src/registers/cnthp_ctl_el2.rs index be658f4..c953e47 100644 --- a/src/registers/cnthp_ctl_el2.rs +++ b/src/registers/cnthp_ctl_el2.rs @@ -4,6 +4,7 @@ // // Author(s): // - tsemo4917 +// - Yiyang Wu //! Counter-timer Hypervisor Physical Timer Control Register - EL2 //! @@ -34,13 +35,19 @@ register_bitfields! {u64, /// /// 0 Timer interrupt is not masked by the IMASK bit. /// 1 Timer interrupt is masked by the IMASK bit. - IMASK OFFSET(1) NUMBITS(1) [], + IMASK OFFSET(1) NUMBITS(1) [ + Masked = 1, + Unmasked = 0, + ], /// Enables the timer. Permitted values are: /// /// 0 Timer disabled. /// 1 Timer enabled. - ENABLE OFFSET(0) NUMBITS(1) [] + ENABLE OFFSET(0) NUMBITS(1) [ + Enabled = 1, + Disabled = 0 + ] ] } diff --git a/src/registers/cnthp_cval_el2.rs b/src/registers/cnthp_cval_el2.rs new file mode 100644 index 0000000..80cea87 --- /dev/null +++ b/src/registers/cnthp_cval_el2.rs @@ -0,0 +1,19 @@ +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTHP_CVAL_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTHP_CVAL_EL2", "x"); +} + +pub const CNTHP_CVAL_EL2: Reg = Reg {}; diff --git a/src/registers/cnthp_tval_el2.rs b/src/registers/cnthp_tval_el2.rs new file mode 100644 index 0000000..6a402b7 --- /dev/null +++ b/src/registers/cnthp_tval_el2.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2023 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Physical Timer TimerValue register - EL0 +//! +//! Holds the timer value for the EL1 physical timer. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTHP_TVAL_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTHP_TVAL_EL2", "x"); +} + +pub const CNTHP_TVAL_EL2: Reg = Reg {}; + From 8cb5b1fd19c829921a970d07b74f388e63195add Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Tue, 25 Jun 2024 11:07:08 +0800 Subject: [PATCH 50/70] feat: refine gicv2 methods Signed-off-by: Yiyang Wu --- src/gic/v2.rs | 35 ++++++++++++++++++++--------------- src/gic/v2/registers.rs | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/gic/v2.rs b/src/gic/v2.rs index 080631c..19b4f3c 100644 --- a/src/gic/v2.rs +++ b/src/gic/v2.rs @@ -1,11 +1,11 @@ mod registers; +use paste::paste; +pub use registers::*; use tock_registers::{ - interfaces::{Readable, Writeable}, + interfaces::{ReadWriteable, Readable, Writeable}, registers::*, *, }; -use paste::paste; -pub use registers::*; pub const GICC_CTLR_EN_BIT: usize = 0x1; pub const GICC_CTLR_EOIMODENS_BIT: usize = 1 << 9; @@ -114,8 +114,6 @@ unsafe impl Sync for GicDistributorInner {} unsafe impl Sync for GicCpuInterfaceInner {} unsafe impl Sync for GicHypervisorInterfaceInner {} -type Field = ReadWrite; - macro_rules! bit_imp { ($method: ident, $field: ident, $width: expr) => { pub fn $method(&mut self, id: u32, pos: u32) { @@ -123,7 +121,7 @@ macro_rules! bit_imp { let reg_id = id / field_num; let field_id = id & (field_num - 1); self.$field[reg_id as usize] - .set(self.$field[reg_id as usize].get() | (1 << pos) << field_id << $width); + .set(self.$field[reg_id as usize].get() | (1 << pos) << (field_id * $width)); } paste! { pub fn [](&mut self, gid: u32, value: u32){ @@ -145,15 +143,14 @@ macro_rules! field_imp { let field_id = id & (field_num - 1); let mask = (1 << $width) - 1; self.$field[reg_id as usize].set( - (self.$field[reg_id as usize].get() & (!(mask << field_id << $width))) - | (field.value << field_id << $width), + (self.$field[reg_id as usize].get() & (!(mask << (field_id * $width)))) + | (field.value << (field_id * $width)), ); } }; } impl GicDistributorInner { - bit_imp!(set_pend, ISPENDR, 1); bit_imp!(clear_pend, ICPENDR, 1); bit_imp!(activate, ISACTIVER, 1); @@ -165,10 +162,13 @@ impl GicDistributorInner { field_imp!(set_nsacr, NSACR, 2, GICD_NSCAR); field_imp!(set_icfgr, ICFGR, 2, GICD_ICFGR); - pub fn forward(&mut self, id: u32, cpu: u32, interface: u32) { - self.ITARGETSR[id as usize].set(1 << (interface << (cpu << 3))); + pub fn forward(&mut self, id: u32, cpu: u32) { + let i = (id / 4) as usize; + let j = id % 4; + let value = 1 << cpu; + let mask = (1 << 8) - 1; + self.ITARGETSR[i].set((self.ITARGETSR[i].get() & !(mask << (j << 3))) | value << (j << 3)) } - pub fn enable_gic(&mut self) { self.CTLR .set((GICD_CTLR::ENGrp0::Enable + GICD_CTLR::ENGrp1::Enable).into()) @@ -178,15 +178,20 @@ impl GicDistributorInner { self.CTLR .set((GICD_CTLR::ENGrp0::Disable + GICD_CTLR::ENGrp1::Disable).into()) } - } impl GicCpuInterfaceInner { pub fn enable(&mut self) { - self.CTLR.set(GICC_CTLR::EN::Enable.into()) + self.CTLR + .set((GICC_CTLR::EN::Enable + GICC_CTLR::EOI::EOIR_DIR).into()); } pub fn disable(&mut self) { self.CTLR.set(GICC_CTLR::EN::Disable.into()) } + pub fn set_priority_mask(&mut self, mask: u8) { + self.PMR.set(GICC_PMR::PRIORITY.val(mask as u32).into()) + } + pub fn set_bpr(&mut self, bpr: u8) { + self.BPR.set(GICC_BPR::BP.val(bpr as u32).into()) + } } - diff --git a/src/gic/v2/registers.rs b/src/gic/v2/registers.rs index 1597836..cc57088 100644 --- a/src/gic/v2/registers.rs +++ b/src/gic/v2/registers.rs @@ -43,6 +43,20 @@ register_bitfields! {u32, ] ], pub GICC_CTLR [ + EOI OFFSET(9) NUMBITS(1) [ + EOIR_DIR = 1, + EOIR_ONLY = 0 + ], + FIQBYPDISGRP1 OFFSET(6) NUMBITS(1) [ + Signal = 1, + NoSignal = 0 + ], + IRQBYPDISGRP1 OFFSET(5) NUMBITS(1) [ + // Bypass FIQ signal whether or not still affects CPU + // execution even if the gic is turned off + Signal = 1, + NoSignal = 0, + ], EN OFFSET(0) NUMBITS(1) [ Enable = 0b1, Disable = 0b0 From f20b70e798868fee750df6ca8bc51e86c6691760 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 28 Jun 2024 15:43:37 +0800 Subject: [PATCH 51/70] feat: add AMO annoation Signed-off-by: Yiyang Wu --- src/registers/hcr_el2.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/registers/hcr_el2.rs b/src/registers/hcr_el2.rs index b9d01b0..c6c6c13 100644 --- a/src/registers/hcr_el2.rs +++ b/src/registers/hcr_el2.rs @@ -279,7 +279,10 @@ register_bitfields! {u64, /// Security state: /// - Physical SError interrupts are taken to EL2, unless they are routed to EL3. /// - When the value of HCR_EL2.TGE is 0, then virtual SError interrupts are enabled. - AMO OFFSET(5) NUMBITS(1) [], + AMO OFFSET(5) NUMBITS(1) [ + EnableSError = 1, + DisableSError= 0, + ], /// Physical IRQ Routing. /// From 812e8af7be4724a9bdc0084a7e9fc55a51f93265 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 28 Jun 2024 15:44:06 +0800 Subject: [PATCH 52/70] feat: add raw set method Signed-off-by: Yiyang Wu --- src/gic/v2.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gic/v2.rs b/src/gic/v2.rs index 19b4f3c..35f6e9a 100644 --- a/src/gic/v2.rs +++ b/src/gic/v2.rs @@ -123,6 +123,15 @@ macro_rules! bit_imp { self.$field[reg_id as usize] .set(self.$field[reg_id as usize].get() | (1 << pos) << (field_id * $width)); } + paste! { + pub fn [<$method _val>](&mut self, id: u32, val: u32){ + let field_num = 32 / $width; + let reg_id = id / field_num; + let field_id = id & (field_num - 1); + self.$field[reg_id as usize] + .set(self.$field[reg_id as usize].get() | (val << (field_id * $width))); + } + } paste! { pub fn [](&mut self, gid: u32, value: u32){ self.$field[gid as usize].set(value); From 046277a6bd5e57421ccf916431533f99d28cbf89 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 28 Jun 2024 15:44:39 +0800 Subject: [PATCH 53/70] refactor: change into impl for PageMode Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 9f022f7..cced60e 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -1,8 +1,6 @@ -use tock_registers::register_bitfields; -use tock_registers::fields::FieldValue; use super::descriptor::BlockDescriptor; -use core::iter::StepBy; -use core::ops::Range; +use core::{iter::StepBy, ops::Range}; +use tock_registers::{fields::FieldValue, register_bitfields}; register_bitfields! {u64, VADescriptor [ @@ -31,12 +29,12 @@ impl PageMode { } } -impl Into for PageMode { - fn into(self) -> u64 { - match self { - Self::SmallPage => 0x1000, - Self::LargePage => 0x200000, - Self::HugePage => 0x40000000, +impl From for u64 { + fn from(value: PageMode) -> Self { + match value { + PageMode::SmallPage => 0x1000, + PageMode::LargePage => 0x200000, + PageMode::HugePage => 0x40000000, } } } From d5480f51946be3a33dc3aa5afe9756c148e802d8 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 5 Jul 2024 16:51:14 +0800 Subject: [PATCH 54/70] feat: add Derive Debug in MM Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index cced60e..937a5e1 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -12,7 +12,7 @@ register_bitfields! {u64, ] } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub enum PageMode { HugePage, LargePage, @@ -96,12 +96,13 @@ pub struct VirtLayout { pub type MMSegment = (u64, u64); -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MMRegion { pub mem: MMSegment, pub granule: u64, } + impl MMRegion { pub fn new(segment: MMSegment, granule: u64) -> Self { MMRegion { From 14673acf9658e63898625b6e3ef6445d979bf8cc Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:25:18 +0200 Subject: [PATCH 55/70] refactor: export ReadWritable Signed-off-by: Yiyang Wu From 20a86dcec093da817f895ee7909a1c3e0f1dd409 Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Thu, 18 Jul 2024 14:06:03 +0800 Subject: [PATCH 56/70] feat: add translation command Signed-off-by: Yiyang Wu --- src/asm/at.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/asm/at.rs b/src/asm/at.rs index d16ede3..d6a6433 100644 --- a/src/asm/at.rs +++ b/src/asm/at.rs @@ -1,3 +1,5 @@ +use crate::registers::*; + mod sealed { pub trait At { fn at(&self, va: u64); @@ -27,8 +29,20 @@ macro_rules! at { } at!(S1E1R, S1e1r); +at!(S1E2R, S1e2r); + +#[inline(always)] +pub fn at(_arg: impl sealed::At, va: u64) { + _arg.at(va); +} #[inline(always)] -pub fn at(_arg:impl sealed::At , va:u64){ +pub fn translate(_arg: impl sealed::At, va: u64) -> Option { _arg.at(va); + let par = PAR_EL1.get(); + if PAR_EL1::F.read(par) == PAR_EL1::F::TranslationAborted.value { + None + } else { + Some(PAR_EL1::PA.read(par) << 12) + } } From b628461dfb6146f05727a7d34ac16e72708a8d81 Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:27:30 +0200 Subject: [PATCH 57/70] fix(sctlr): add missing fields Signed-off-by: Yiyang Wu --- src/registers/sctlr_el2.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/registers/sctlr_el2.rs b/src/registers/sctlr_el2.rs index 64ab713..a7b6434 100644 --- a/src/registers/sctlr_el2.rs +++ b/src/registers/sctlr_el2.rs @@ -83,6 +83,24 @@ register_bitfields! {u64, IsSynch = 1 ], + /// Non-aligned access. This bit controls generation of Alignment faults under certain + /// conditions at EL2, and, when EL2 is enabled in the current Security state and + /// HCR_EL2.{E2H, TGE} == {1, 1}, EL0. + NAA OFFSET(6) NUMBITS(1) [ + Allowed = 1, + NotAllowed = 0 + ], + + /// SP Alignment check enable for EL0. + /// + /// When set to 1, if a load or store instruction executed at EL0 uses the SP + /// as the base address and the SP is not aligned to a 16-byte boundary, + /// then a SP alignment fault exception is generated. + SA0 OFFSET(4) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + /// SP Alignment check enable. /// /// When set to 1, if a load or store instruction executed at EL2 uses the SP From d866874decd8a109f1e81c8c4047839f5843a7da Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 24 Jul 2024 15:21:06 +0800 Subject: [PATCH 58/70] feat: add MMAttrIdx support Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 23 ++++++++++++++++++++--- src/mmu/descriptor.rs | 13 ++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 937a5e1..7e6d809 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -102,7 +102,6 @@ pub struct MMRegion { pub granule: u64, } - impl MMRegion { pub fn new(segment: MMSegment, granule: u64) -> Self { MMRegion { @@ -192,8 +191,8 @@ impl From for FieldValue { fn from(value: MMType) -> Self { let prot_fields: FieldValue = value.default_prot().into(); let type_fields = match value { - MMType::Device => BlockDescriptor::SH::CLEAR, - _ => BlockDescriptor::SH::IS, + MMType::Device => BlockDescriptor::SH::CLEAR + BlockDescriptor::ATTR.val(0), + _ => BlockDescriptor::SH::IS + BlockDescriptor::ATTR.val(4), }; prot_fields + type_fields @@ -203,6 +202,24 @@ impl From for FieldValue { } } +#[derive(Copy, Clone)] +pub enum MMAttrIdx { + Attr0 = 0, + Attr1 = 1, + Attr2 = 2, + Attr3 = 3, + Attr4 = 4, + Attr5 = 5, + Attr6 = 6, + Attr7 = 7, +} + +impl From for FieldValue { + fn from(value: MMAttrIdx) -> Self { + BlockDescriptor::ATTR.val(value as u64) + } +} + impl IntoIterator for MMRegion { type Item = u64; type IntoIter = StepBy>; diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index b5e8de2..95b3767 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -1,9 +1,8 @@ +use super::{address::PageMode, MMAttrIdx, MMType}; use tock_registers::{ - register_bitfields, - fields::{FieldValue, Field}, - RegisterLongName, + fields::{Field, FieldValue}, + register_bitfields, RegisterLongName, }; -use super::{address::PageMode, MMType}; register_bitfields! {u64, pub BlockDescriptor [ @@ -51,7 +50,7 @@ register_bitfields! {u64, TRUE = 0b1, FALSE = 0b0 ], - ATTR OFFSET(2) NUMBITS(2) [ + ATTR OFFSET(2) NUMBITS(3) [ ], TYPE OFFSET(1) NUMBITS(1) [ @@ -141,8 +140,8 @@ impl VADescriptor { .value } - pub fn block(output: u64, typ: MMType, mode: PageMode) -> u64 { - (BlockDescriptor::OUTPUT.val(output) + typ.into() + mode.into()).value + pub fn block(output: u64, typ: MMType, mode: PageMode, idx: MMAttrIdx) -> u64 { + (BlockDescriptor::OUTPUT.val(output) + typ.into() + mode.into() + idx.into()).value } } From ccdd5d75284b107d0c549605aa0c06e744381bbc Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Thu, 25 Jul 2024 12:51:57 +0800 Subject: [PATCH 59/70] add gicv3 support Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 148 +++++++++++++++++++++++++------ src/gic/v3/registers.rs | 43 +++++++++ src/registers/icc_ap0r_el1.rs | 8 +- src/registers/icc_ap1r_el1.rs | 8 +- src/registers/icc_igpren1_el1.rs | 11 ++- 5 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 src/gic/v3/registers.rs diff --git a/src/gic/v3.rs b/src/gic/v3.rs index b0785f2..80f8b96 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -1,5 +1,18 @@ +mod registers; +pub use registers::*; +use paste::paste; use core::mem::size_of; -use tock_registers::{registers::*, *}; +use tock_registers::{ + interfaces::{Readable, Writeable}, + registers::*, + *, +}; + +use crate::{ + registers::*, + asm::barrier::*, +}; + pub const GIC_SGIS_NUM: usize = 16; pub const GIC_INTS_MAX: usize = 1024; @@ -20,12 +33,38 @@ const GIC_TARGET_REGS_NUM: usize = GIC_INTS_MAX * 8 / 32; const GIC_CONFIG_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; const GIC_SEC_REGS_NUM: usize = GIC_INTS_MAX * 2 / 32; +macro_rules! bit_imp { + ($method: ident, $field: ident, $width: expr) => { + pub fn $method(&mut self, id: u32, pos: u32) { + let field_num = 32 / $width; + let reg_id = id / field_num; + let field_id = id & (field_num - 1); + self.$field[reg_id as usize] + .set(self.$field[reg_id as usize].get() | (1 << pos) << (field_id * $width)); + } + paste! { + pub fn [<$method _val>](&mut self, id: u32, val: u32){ + let field_num = 32 / $width; + let reg_id = id / field_num; + let field_id = id & (field_num - 1); + self.$field[reg_id as usize] + .set(self.$field[reg_id as usize].get() | (val << (field_id * $width))); + } + } + paste! { + pub fn [](&mut self, gid: u32, value: u32){ + self.$field[gid as usize].set(value); + } + } + }; +} + register_structs! { #[allow(non_snake_case)] - pub GicDistributor { + pub GicDistributorInner { (0x0000 => CTLR: ReadWrite), //Distributor Control Register (0x0004 => TYPER: ReadOnly), //Interrupt Controller Type Register - (0x0008 => IIDR: ReadOnly), //Distributor Implementer Identification Register + (0x0008 => pub IIDR: ReadOnly), //Distributor Implementer Identification Register (0x000c => TYPER2: ReadOnly), //Interrupt controller Type Register 2 (0x0010 => STATUSR: ReadWrite), //Error Reporting Status Register, optional (0x0014 => reserved0), @@ -38,18 +77,18 @@ register_structs! { (0x0058 => CLRSPI_SR: WriteOnly), //Clear SPI, Secure Register (0x005c => reserved4), (0x0080 => IGROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers - (0x0100 => ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Enable Registers - (0x0180 => ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Enable Registers - (0x0200 => ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Pending Registers - (0x0280 => ICPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Pending Registers - (0x0300 => ISACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Active Registers - (0x0380 => ICACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Active Registers - (0x0400 => IPRIORITYR: [ReadWrite; GIC_PRIO_REGS_NUM]), //Interrupt Priority Registers - (0x0800 => ITARGETSR: [ReadWrite; GIC_TARGET_REGS_NUM]), //Interrupt Processor Targets Registers - (0x0c00 => ICFGR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Configuration Registers - (0x0d00 => IGRPMODR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Group Modifier Registers - (0x0e00 => NSACR: [ReadWrite; GIC_SEC_REGS_NUM]), //Non-secure Access Control Registers - (0x0f00 => SGIR: WriteOnly), //Software Generated Interrupt Register + (0x0100 => pub ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Enable Registers + (0x0180 => pub ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Enable Registers + (0x0200 => pub ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Pending Registers + (0x0280 => pub ICPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Pending Registers + (0x0300 => pub ISACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Active Registers + (0x0380 => pub ICACTIVER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Active Registers + (0x0400 => pub IPRIORITYR: [ReadWrite; GIC_PRIO_REGS_NUM]), //Interrupt Priority Registers + (0x0800 => pub ITARGETSR: [ReadWrite; GIC_TARGET_REGS_NUM]), //Interrupt Processor Targets Registers + (0x0c00 => pub ICFGR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Configuration Registers + (0x0d00 => pub IGRPMODR: [ReadWrite; GIC_CONFIG_REGS_NUM]), //Interrupt Group Modifier Registers + (0x0e00 => pub NSACR: [ReadWrite; GIC_SEC_REGS_NUM]), //Non-secure Access Control Registers + (0x0f00 => pub SGIR: WriteOnly), //Software Generated Interrupt Register (0x0f04 => reserved6), (0x0f10 => CPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Clear-Pending Registers (0x0f20 => SPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Set-Pending Registers @@ -63,12 +102,12 @@ register_structs! { register_structs! { #[allow(non_snake_case)] - pub GICRedistributer { + pub GicRedistributorInner { (0x0000 => CTLR: ReadWrite), // Redistributor Control Register (0x0004 => IIDR: ReadOnly), // Implementer Identification Register (0x0008 => TYPER: ReadOnly), // Redistributor Type Register (0x0010 => STATUSR: ReadWrite), // Error Reporting Status Register, optional - (0x0014 => WAKER: ReadWrite), // Redistributor Wake Register + (0x0014 => pub WAKER: ReadWrite), // Redistributor Wake Register (0x0018 => MPAMIDR: ReadOnly), // Report maximum PARTID and PMG Register (0x001c => PARTIDR: ReadWrite), // Set PARTID and PMG Register (0x0020 => reserved18), @@ -86,24 +125,24 @@ register_structs! { (0x00c8 => reserved13), (0xffd0 => ID: [ReadOnly; (0x10000 - 0xFFD0) / size_of::()]), (0x10000 => reserved12), - (0x10080 => IGROUPR0: ReadWrite), //SGI_base frame, all below + (0x10080 => pub IGROUPR0: ReadWrite), //SGI_base frame, all below (0x10084 => reserved11), - (0x10100 => ISENABLER0: ReadWrite), + (0x10100 => pub ISENABLER0: ReadWrite), (0x10104 => reserved10), - (0x10180 => ICENABLER0: ReadWrite), + (0x10180 => pub ICENABLER0: ReadWrite), (0x10184 => reserved9), - (0x10200 => ISPENDR0: ReadWrite), + (0x10200 => pub ISPENDR0: ReadWrite), (0x10204 => reserved8), - (0x10280 => ICPENDR0: ReadWrite), + (0x10280 => pub ICPENDR0: ReadWrite), (0x10284 => reserved7), - (0x10300 => ISACTIVER0: ReadWrite), + (0x10300 => pub ISACTIVER0: ReadWrite), (0x10304 => reserved6), - (0x10380 => ICACTIVER0: ReadWrite), + (0x10380 => pub ICACTIVER0: ReadWrite), (0x10384 => reserved5), (0x10400 => IPRIORITYR: [ReadWrite;8]), (0x10420 => reserved4), - (0x10c00 => ICFGR0: ReadWrite), - (0x10c04 => ICFGR1: ReadWrite), + (0x10c00 => pub ICFGR0: ReadWrite), + (0x10c04 => pub ICFGR1: ReadWrite), (0x10c08 => reserved3), (0x10d00 => IGRPMODR0: ReadWrite), (0x10d04 => reserved2), @@ -112,3 +151,60 @@ register_structs! { (0x20000 => @END), } } + +#[repr(C)] +pub struct GICCpuInterface; + + +unsafe impl Sync for GicDistributorInner {} +unsafe impl Sync for GicRedistributorInner {} +unsafe impl Sync for GICCpuInterface {} + +impl GicDistributorInner { + bit_imp!(set_priority, IPRIORITYR, 8); + bit_imp!(deactivate, ICACTIVER, 1); + bit_imp!(enable_intr, ISENABLER, 1); + bit_imp!(disable_intr, ICENABLER, 1); + bit_imp!(clear_pend, ICPENDR, 1); + bit_imp!(set_group, IGROUPR, 1); + bit_imp!(set_group_mod, IGRPMODR, 1); + bit_imp!(configure_intr, ICFGR, 2); + + pub fn forward(&mut self, id: u32, cpu: u32) { + // remove this hardcode + let cpumask = (cpu & 0x1) + ((cpu >> 1) << 7); + self.IROUTER[id as usize].set(cpumask as u64); + } + pub fn enable_gic(&mut self) { + self.CTLR + .set((GICD_CTLR::ENGrp1NS::Enable + GICD_CTLR::ARE_NS::Enable).into()) + } + + pub fn disable_gic(&mut self) { + self.CTLR + .set((GICD_CTLR::ENGrp1NS::Disable + GICD_CTLR::ARE_NS::Disable).into()) + } + + pub fn get_nr_lines(&self) -> u32{ + 32 * (1 + GICD_TYPER::ITLines.read(self.TYPER.get())) + } +} + +impl GicRedistributorInner { + bit_imp!(set_priority, IPRIORITYR, 8); + + pub fn wake_up_redis(&mut self) { + self.WAKER.set(GICR_WAKER::ProcessorSleep::NotinLowState.modify(self.WAKER.get())); + while GICR_WAKER::ChildrenAsleep.is_set(self.WAKER.get()) {}; + } +} + +impl GICCpuInterface { + pub fn enable_sre_bit(&self) { + if !ICC_SRE_EL1.is_set(ICC_SRE_EL1::SRE) { + ICC_SRE_EL1.modify(ICC_SRE_EL1::SRE::SR); + isb(NONE); + assert!(ICC_SRE_EL1.is_set(ICC_SRE_EL1::SRE)); + } + } +} \ No newline at end of file diff --git a/src/gic/v3/registers.rs b/src/gic/v3/registers.rs new file mode 100644 index 0000000..6fe7461 --- /dev/null +++ b/src/gic/v3/registers.rs @@ -0,0 +1,43 @@ +use tock_registers::*; + +register_bitfields! {u32, + pub GICD_CTLR [ + ARE_NS OFFSET(5) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ARE_S OFFSET(4) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGrp1S OFFSET(2) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGrp1NS OFFSET(1) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + ENGrp0 OFFSET(0) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ] + ], + pub GICD_TYPER [ + LSPI OFFSET(17) NUMBITS(5) [], + SecurityExtn OFFSET(10) NUMBITS(1) [ + Enable = 0b1, + Disable = 0b0 + ], + CPUNumber OFFSET(5) NUMBITS(3) [], + ITLines OFFSET(0) NUMBITS(5) [] + ], + pub GICR_WAKER [ + ChildrenAsleep OFFSET(2) NUMBITS(1) [], + ProcessorSleep OFFSET(1) NUMBITS(1) [ + NotinLowState = 0b0, + LowState = 0b1 + ], + IMPDEF OFFSET(0) NUMBITS(1) [], + ], +} diff --git a/src/registers/icc_ap0r_el1.rs b/src/registers/icc_ap0r_el1.rs index b185dda..d100c53 100644 --- a/src/registers/icc_ap0r_el1.rs +++ b/src/registers/icc_ap0r_el1.rs @@ -28,7 +28,7 @@ macro_rules! ap { }; } -ap!(ICC_AP0R0_EL1, "ICC_AP0R0_EL1"); -ap!(ICC_AP0R1_EL1, "ICC_AP0R1_EL1"); -ap!(ICC_AP0R2_EL1, "ICC_AP0R2_EL1"); -ap!(ICC_AP0R3_EL1, "ICC_AP0R3_EL1"); +ap!(ICC_AP0R0_EL1, "S3_0_C12_C9_4"); +ap!(ICC_AP0R1_EL1, "S3_0_C12_C9_5"); +ap!(ICC_AP0R2_EL1, "S3_0_C12_C9_6"); +ap!(ICC_AP0R3_EL1, "S3_0_C12_C9_7"); diff --git a/src/registers/icc_ap1r_el1.rs b/src/registers/icc_ap1r_el1.rs index 4520a3e..e8fb2a4 100644 --- a/src/registers/icc_ap1r_el1.rs +++ b/src/registers/icc_ap1r_el1.rs @@ -28,7 +28,7 @@ macro_rules! ap { }; } -ap!(ICC_AP1R0_EL1, "ICC_AP0R0_EL1"); -ap!(ICC_AP1R1_EL1, "ICC_AP0R1_EL1"); -ap!(ICC_AP1R2_EL1, "ICC_AP0R2_EL1"); -ap!(ICC_AP1R3_EL1, "ICC_AP0R3_EL1"); +ap!(ICC_AP1R0_EL1, "S3_0_C12_C9_0"); +ap!(ICC_AP1R1_EL1, "S3_0_C12_C9_1"); +ap!(ICC_AP1R2_EL1, "S3_0_C12_C9_2"); +ap!(ICC_AP1R3_EL1, "S3_0_C12_C9_3"); diff --git a/src/registers/icc_igpren1_el1.rs b/src/registers/icc_igpren1_el1.rs index cd107f1..1ec3c14 100644 --- a/src/registers/icc_igpren1_el1.rs +++ b/src/registers/icc_igpren1_el1.rs @@ -15,7 +15,16 @@ impl Readable for Reg { type T = u64; type R = ICC_IGPREN1_EL1::Register; - sys_coproc_read_raw!(u64, "ICC_IGPREN1_EL1", "x"); + sys_coproc_read_raw!(u64, "S3_0_C12_C12_7", "x"); } + +impl Writeable for Reg { + type T = u64; + type R = ICC_IGPREN1_EL1::Register; + + sys_coproc_write_raw!(u64, "S3_0_C12_C12_7", "x"); +} + + pub const ICC_IGPREN1_EL1: Reg = Reg {}; From 997914711e32c143b722e44e15f165e930c5b0e0 Mon Sep 17 00:00:00 2001 From: zhr1502 Date: Thu, 25 Jul 2024 13:14:06 +0800 Subject: [PATCH 60/70] fix: fix DCACHE flush_all --- src/cache.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cache.rs b/src/cache.rs index 53ad10c..8e91d8c 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -54,9 +54,10 @@ impl DCache { isb(SY); } + #[inline(always)] pub fn flush_all(&self, mode: FlushMode) { dsb(SY); - let loc = CLIDR_EL1.read(CLIDR_EL1::LoC); + let loc = CLIDR_EL1.read(CLIDR_EL1::LoC) * 2; let clidr = CLIDR_EL1.get(); let _flush = self.get_flush_func(mode, AddressMode::WAYSET); let mut irq = IRQ::new(); @@ -79,7 +80,7 @@ impl DCache { irq.restore_and_enable(); (0..m + 1) - .flat_map(move |i| (0..n + 1).map(move |j| (i << k) | (j << ls))) + .flat_map(move |i| (0..n + 1).map(move |j| (i << k) | level | (j << ls))) .for_each(&_flush); } } From 7221ffad1541bfad310f7fb87495af0a9a94d59a Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 2 Aug 2024 14:34:14 +0800 Subject: [PATCH 61/70] fix: fix sl2 page descriptors bug Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 43 ++++++++++++++++++++++++++++++++++++------- src/mmu/descriptor.rs | 11 +++++++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index 7e6d809..a2f0c9a 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -190,15 +190,14 @@ impl From for FieldValue { impl From for FieldValue { fn from(value: MMType) -> Self { let prot_fields: FieldValue = value.default_prot().into(); + let type_fields = match value { - MMType::Device => BlockDescriptor::SH::CLEAR + BlockDescriptor::ATTR.val(0), - _ => BlockDescriptor::SH::IS + BlockDescriptor::ATTR.val(4), + MMType::Device => BlockDescriptor::SH::CLEAR, + MMType::VirtReadWrite => BlockDescriptor::SH::OS, + _ => BlockDescriptor::SH::IS + BlockDescriptor::NSE_NG::TRUE, }; - prot_fields - + type_fields - + BlockDescriptor::NSE_NG::TRUE - + BlockDescriptor::VALID::TRUE - + BlockDescriptor::AF::TRUE + + prot_fields + type_fields + BlockDescriptor::VALID::TRUE + BlockDescriptor::AF::TRUE } } @@ -220,6 +219,36 @@ impl From for FieldValue { } } +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +pub enum S2MemAttrNoFWB { + Device_nGnRnE = 0b0000, + Device_nGnRE = 0b0001, + Device_nGRE = 0b0010, + Device_GRE = 0b0011, + // this is only for platform supported MTE_PERM, + // if not, setting this will cause UNDEFINED BEHAVIOR. + Normal_NTA_Outer_WBC_Inner_WBC_FEAT_MTE_PERM = 0b0100, + + Normal_Outer_NC_Inner_NC = 0b0101, + Normal_Outer_NC_Inner_WTC = 0b0110, + Normal_Outer_NC_Inner_WBC = 0b0111, + + Normal_Outer_WTC_Inner_NC = 0b1001, + Normal_Outer_WTC_Inner_WTC = 0b1010, + Normal_Outer_WTC_Inner_WBC = 0b1011, + + Normal_OuterWBC_Inner_NC = 0b1101, + Normal_OuterWBC_Inner_WTC = 0b1110, + Normal_OuterWBC_Inner_WBC = 0b1111, +} + +impl From for FieldValue { + fn from(value: S2MemAttrNoFWB) -> Self { + BlockDescriptor::S2ATTR.val(value as u64) + } +} + impl IntoIterator for MMRegion { type Item = u64; type IntoIter = StepBy>; diff --git a/src/mmu/descriptor.rs b/src/mmu/descriptor.rs index 95b3767..1115e59 100644 --- a/src/mmu/descriptor.rs +++ b/src/mmu/descriptor.rs @@ -1,4 +1,4 @@ -use super::{address::PageMode, MMAttrIdx, MMType}; +use super::{address::PageMode, MMAttrIdx, MMType, S2MemAttrNoFWB}; use tock_registers::{ fields::{Field, FieldValue}, register_bitfields, RegisterLongName, @@ -52,6 +52,10 @@ register_bitfields! {u64, ], ATTR OFFSET(2) NUMBITS(3) [ + ], + + S2ATTR OFFSET(2) NUMBITS(4) [ + ], TYPE OFFSET(1) NUMBITS(1) [ BLOCK = 0b0, @@ -140,7 +144,10 @@ impl VADescriptor { .value } - pub fn block(output: u64, typ: MMType, mode: PageMode, idx: MMAttrIdx) -> u64 { + pub fn s1_block(output: u64, typ: MMType, mode: PageMode, idx: MMAttrIdx) -> u64 { + (BlockDescriptor::OUTPUT.val(output) + typ.into() + mode.into() + idx.into()).value + } + pub fn s2_block(output: u64, typ: MMType, mode: PageMode, idx: S2MemAttrNoFWB) -> u64 { (BlockDescriptor::OUTPUT.val(output) + typ.into() + mode.into() + idx.into()).value } } From 17236c3e12b7aeb6b2666864be48204f9a50847b Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Wed, 7 Aug 2024 17:19:25 +0800 Subject: [PATCH 62/70] refactor: rename variable Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index a2f0c9a..ae68517 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -238,9 +238,9 @@ pub enum S2MemAttrNoFWB { Normal_Outer_WTC_Inner_WTC = 0b1010, Normal_Outer_WTC_Inner_WBC = 0b1011, - Normal_OuterWBC_Inner_NC = 0b1101, - Normal_OuterWBC_Inner_WTC = 0b1110, - Normal_OuterWBC_Inner_WBC = 0b1111, + Normal_Outer_WBC_Inner_NC = 0b1101, + Normal_Outer_WBC_Inner_WTC = 0b1110, + Normal_Outer_WBC_Inner_WBC = 0b1111, } impl From for FieldValue { From 21681f5d2a0e1d0045c6d7dd602f7468c0e7040c Mon Sep 17 00:00:00 2001 From: Yiyang Wu Date: Fri, 16 Aug 2024 14:19:30 +0800 Subject: [PATCH 63/70] mm: add size method Signed-off-by: Yiyang Wu --- src/mmu/address.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mmu/address.rs b/src/mmu/address.rs index ae68517..bec5dec 100644 --- a/src/mmu/address.rs +++ b/src/mmu/address.rs @@ -112,6 +112,9 @@ impl MMRegion { granule, } } + pub fn size(&self) -> u64 { + self.mem.1 - self.mem.0 + } } impl MMType { From 2b1d2b6848d2f7ae9d4adafe56b467185698419b Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Sat, 9 Nov 2024 01:32:23 +0200 Subject: [PATCH 64/70] chore: rustfmt Signed-off-by: Yiyang Wu --- src/asm.rs | 4 ++-- src/asm/tlb.rs | 9 ++++----- src/exception.rs | 4 ++-- src/gic.rs | 4 ++-- src/gic/v3.rs | 20 ++++++++------------ src/lib.rs | 6 +++--- src/mmu.rs | 3 +-- src/registers/cnthp_tval_el2.rs | 1 - src/registers/esr_el2.rs | 2 +- src/registers/icc_ap0r_el1.rs | 2 +- src/registers/icc_ap1r_el1.rs | 2 +- src/registers/icc_eoir0_el1.rs | 1 - src/registers/icc_eoir1_el1.rs | 1 - src/registers/icc_hppir0_el1.rs | 1 - src/registers/icc_hppir1_el1.rs | 1 - src/registers/icc_iar0_el1.rs | 1 - src/registers/icc_iar1_el1.rs | 1 - src/registers/icc_igpren1_el1.rs | 2 -- src/registers/icc_rpr_el1.rs | 1 - src/registers/ich_eisr_el2.rs | 3 +-- src/registers/ich_elrsr_el2.rs | 3 +-- src/registers/ich_lr_el2.rs | 2 +- src/registers/ich_vmcr_el2.rs | 5 ++++- src/registers/icv_ap0r_el1.rs | 2 +- src/registers/icv_ap1r_el1.rs | 2 +- src/registers/icv_ctlr_el1.rs | 1 - src/registers/icv_eoir0_el1.rs | 1 - src/registers/icv_eoir1_el1.rs | 1 - src/registers/icv_hppir0_el1.rs | 1 - src/registers/icv_hppir1_el1.rs | 1 - src/registers/icv_iar0_el1.rs | 1 - src/registers/icv_iar1_el1.rs | 1 - src/registers/icv_rpr_el1.rs | 1 - src/registers/vmpidr_el2.rs | 6 ++++-- 34 files changed, 38 insertions(+), 59 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 50224ab..bfa9ef8 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -8,11 +8,11 @@ //! Wrappers around ARMv8-A instructions. +pub mod at; pub mod barrier; -pub mod random; pub mod cache; +pub mod random; pub mod tlb; -pub mod at; /// The classic no-op #[inline(always)] diff --git a/src/asm/tlb.rs b/src/asm/tlb.rs index 91747fe..8e19cb0 100644 --- a/src/asm/tlb.rs +++ b/src/asm/tlb.rs @@ -4,12 +4,12 @@ mod sealed { } } -macro_rules! tlbi{ +macro_rules! tlbi { ($A: ident) => { pub struct $A; impl sealed::Tlbi for $A { #[inline(always)] - fn invalidate(&self){ + fn invalidate(&self) { match () { #[cfg(target_arch = "aarch64")] () => unsafe { @@ -21,15 +21,14 @@ macro_rules! tlbi{ } } } - } + }; } - tlbi!(VMALLE1IS); tlbi!(ALLE2IS); tlbi!(ALLE3IS); #[inline(always)] -pub fn tlb_inv(_arg: impl sealed::Tlbi){ +pub fn tlb_inv(_arg: impl sealed::Tlbi) { _arg.invalidate(); } diff --git a/src/exception.rs b/src/exception.rs index 5d8dd0f..a981ae1 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -5,12 +5,12 @@ pub enum ExceptionReason { Unimplemented = 0xff, } -impl From for ExceptionReason{ +impl From for ExceptionReason { fn from(value: u64) -> Self { match value { x if x == Self::DataAbortLowerEl as u64 => Self::DataAbortLowerEl, x if x == Self::DataAbortCurrentEl as u64 => Self::DataAbortCurrentEl, - _ => Self::Unimplemented + _ => Self::Unimplemented, } } } diff --git a/src/gic.rs b/src/gic.rs index a26d39e..f01cccf 100644 --- a/src/gic.rs +++ b/src/gic.rs @@ -1,5 +1,5 @@ -pub mod v3; pub mod v2; +pub mod v3; pub enum IRQState { Inactive, @@ -15,7 +15,7 @@ impl From for IRQState { 1 => IRQState::Pending, 2 => IRQState::Active, 3 => IRQState::PendingActive, - _ => panic!("illegal irq state input") + _ => panic!("illegal irq state input"), } } } diff --git a/src/gic/v3.rs b/src/gic/v3.rs index 80f8b96..a2fa62a 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -1,18 +1,14 @@ mod registers; -pub use registers::*; -use paste::paste; use core::mem::size_of; +use paste::paste; +pub use registers::*; use tock_registers::{ interfaces::{Readable, Writeable}, registers::*, *, }; -use crate::{ - registers::*, - asm::barrier::*, -}; - +use crate::{asm::barrier::*, registers::*}; pub const GIC_SGIS_NUM: usize = 16; pub const GIC_INTS_MAX: usize = 1024; @@ -155,7 +151,6 @@ register_structs! { #[repr(C)] pub struct GICCpuInterface; - unsafe impl Sync for GicDistributorInner {} unsafe impl Sync for GicRedistributorInner {} unsafe impl Sync for GICCpuInterface {} @@ -185,7 +180,7 @@ impl GicDistributorInner { .set((GICD_CTLR::ENGrp1NS::Disable + GICD_CTLR::ARE_NS::Disable).into()) } - pub fn get_nr_lines(&self) -> u32{ + pub fn get_nr_lines(&self) -> u32 { 32 * (1 + GICD_TYPER::ITLines.read(self.TYPER.get())) } } @@ -194,8 +189,9 @@ impl GicRedistributorInner { bit_imp!(set_priority, IPRIORITYR, 8); pub fn wake_up_redis(&mut self) { - self.WAKER.set(GICR_WAKER::ProcessorSleep::NotinLowState.modify(self.WAKER.get())); - while GICR_WAKER::ChildrenAsleep.is_set(self.WAKER.get()) {}; + self.WAKER + .set(GICR_WAKER::ProcessorSleep::NotinLowState.modify(self.WAKER.get())); + while GICR_WAKER::ChildrenAsleep.is_set(self.WAKER.get()) {} } } @@ -207,4 +203,4 @@ impl GICCpuInterface { assert!(ICC_SRE_EL1.is_set(ICC_SRE_EL1::SRE)); } } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index aea4b80..0f310af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,9 +55,9 @@ #![no_std] pub mod asm; -pub mod mmu; -pub mod irq; pub mod cache; pub mod exception; -pub mod registers; pub mod gic; +pub mod irq; +pub mod mmu; +pub mod registers; diff --git a/src/mmu.rs b/src/mmu.rs index e5cab22..04d0d7f 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,4 +1,3 @@ -pub mod descriptor; mod address; +pub mod descriptor; pub use address::*; - diff --git a/src/registers/cnthp_tval_el2.rs b/src/registers/cnthp_tval_el2.rs index 6a402b7..57e3e07 100644 --- a/src/registers/cnthp_tval_el2.rs +++ b/src/registers/cnthp_tval_el2.rs @@ -28,4 +28,3 @@ impl Writeable for Reg { } pub const CNTHP_TVAL_EL2: Reg = Reg {}; - diff --git a/src/registers/esr_el2.rs b/src/registers/esr_el2.rs index 10e57f7..ca64ddd 100644 --- a/src/registers/esr_el2.rs +++ b/src/registers/esr_el2.rs @@ -227,7 +227,7 @@ register_bitfields! {u64, /// 0b001111: Permission fault, level 3 PermissionFaultLevel3 = 0b001111, - /// 0b010000: Synchronous external abort, not on translation table walk or + /// 0b010000: Synchronous external abort, not on translation table walk or /// hardware update of translation table SynchronousExternalAbortNotOnTranslationTableWalk = 0b010000 diff --git a/src/registers/icc_ap0r_el1.rs b/src/registers/icc_ap0r_el1.rs index d100c53..f6b92ca 100644 --- a/src/registers/icc_ap0r_el1.rs +++ b/src/registers/icc_ap0r_el1.rs @@ -10,8 +10,8 @@ macro_rules! ap { ($reg: ident, $name: tt) => { #[allow(non_snake_case)] mod $reg { - use tock_registers::interfaces::*; use super::*; + use tock_registers::interfaces::*; pub struct Reg; impl Writeable for Reg { type T = u64; diff --git a/src/registers/icc_ap1r_el1.rs b/src/registers/icc_ap1r_el1.rs index e8fb2a4..c708d02 100644 --- a/src/registers/icc_ap1r_el1.rs +++ b/src/registers/icc_ap1r_el1.rs @@ -10,8 +10,8 @@ macro_rules! ap { ($reg: ident, $asm_name: tt) => { #[allow(non_snake_case)] mod $reg { - use tock_registers::interfaces::*; use super::*; + use tock_registers::interfaces::*; pub struct Reg; impl Writeable for Reg { type T = u64; diff --git a/src/registers/icc_eoir0_el1.rs b/src/registers/icc_eoir0_el1.rs index 689a96a..5bd0fcc 100644 --- a/src/registers/icc_eoir0_el1.rs +++ b/src/registers/icc_eoir0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_EOIR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_eoir1_el1.rs b/src/registers/icc_eoir1_el1.rs index 8fd6549..df9ab87 100644 --- a/src/registers/icc_eoir1_el1.rs +++ b/src/registers/icc_eoir1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_EOIR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_hppir0_el1.rs b/src/registers/icc_hppir0_el1.rs index 6ee4f6e..cf88344 100644 --- a/src/registers/icc_hppir0_el1.rs +++ b/src/registers/icc_hppir0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_HPPIR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_hppir1_el1.rs b/src/registers/icc_hppir1_el1.rs index 7a6a5d8..9ae6402 100644 --- a/src/registers/icc_hppir1_el1.rs +++ b/src/registers/icc_hppir1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_HPPIR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_iar0_el1.rs b/src/registers/icc_iar0_el1.rs index 699d908..a2b78d4 100644 --- a/src/registers/icc_iar0_el1.rs +++ b/src/registers/icc_iar0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_IAR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_iar1_el1.rs b/src/registers/icc_iar1_el1.rs index 68f6e9b..867393f 100644 --- a/src/registers/icc_iar1_el1.rs +++ b/src/registers/icc_iar1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_IAR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icc_igpren1_el1.rs b/src/registers/icc_igpren1_el1.rs index 1ec3c14..09d04dc 100644 --- a/src/registers/icc_igpren1_el1.rs +++ b/src/registers/icc_igpren1_el1.rs @@ -18,7 +18,6 @@ impl Readable for Reg { sys_coproc_read_raw!(u64, "S3_0_C12_C12_7", "x"); } - impl Writeable for Reg { type T = u64; type R = ICC_IGPREN1_EL1::Register; @@ -26,5 +25,4 @@ impl Writeable for Reg { sys_coproc_write_raw!(u64, "S3_0_C12_C12_7", "x"); } - pub const ICC_IGPREN1_EL1: Reg = Reg {}; diff --git a/src/registers/icc_rpr_el1.rs b/src/registers/icc_rpr_el1.rs index 6cfd888..7a29f99 100644 --- a/src/registers/icc_rpr_el1.rs +++ b/src/registers/icc_rpr_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICC_RPR_EL1 [ NMI OFFSET(63) NUMBITS(1) [], diff --git a/src/registers/ich_eisr_el2.rs b/src/registers/ich_eisr_el2.rs index b1d6de1..77b3d92 100644 --- a/src/registers/ich_eisr_el2.rs +++ b/src/registers/ich_eisr_el2.rs @@ -1,5 +1,4 @@ -use tock_registers::register_bitfields; -use tock_registers::interfaces::*; +use tock_registers::{interfaces::*, register_bitfields}; register_bitfields! {u64, pub ICH_EISR_EL2 [ diff --git a/src/registers/ich_elrsr_el2.rs b/src/registers/ich_elrsr_el2.rs index 79b77c1..c11aac3 100644 --- a/src/registers/ich_elrsr_el2.rs +++ b/src/registers/ich_elrsr_el2.rs @@ -1,5 +1,4 @@ -use tock_registers::register_bitfields; -use tock_registers::interfaces::*; +use tock_registers::{interfaces::*, register_bitfields}; register_bitfields! {u64, pub ICH_ELRSR_EL2 [ diff --git a/src/registers/ich_lr_el2.rs b/src/registers/ich_lr_el2.rs index 7c350bb..e586243 100644 --- a/src/registers/ich_lr_el2.rs +++ b/src/registers/ich_lr_el2.rs @@ -16,8 +16,8 @@ macro_rules! lr { ($reg: ident, $name: tt) => { #[allow(non_snake_case)] mod $reg { - use tock_registers::interfaces::*; use super::*; + use tock_registers::interfaces::*; pub struct Reg; impl Writeable for Reg { type T = u64; diff --git a/src/registers/ich_vmcr_el2.rs b/src/registers/ich_vmcr_el2.rs index f956be6..2d15f41 100644 --- a/src/registers/ich_vmcr_el2.rs +++ b/src/registers/ich_vmcr_el2.rs @@ -9,7 +9,10 @@ //! //! Enables the hypervisor to save and restore the virtual machine view of the GIC state. -use tock_registers::interfaces::{Readable, Writeable}; +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; register_bitfields! {u64, pub ICH_VMCR_EL2 [ diff --git a/src/registers/icv_ap0r_el1.rs b/src/registers/icv_ap0r_el1.rs index e6bdf22..4f99803 100644 --- a/src/registers/icv_ap0r_el1.rs +++ b/src/registers/icv_ap0r_el1.rs @@ -10,8 +10,8 @@ macro_rules! ap { ($reg: ident, $name: tt) => { #[allow(non_snake_case)] mod $reg { - use tock_registers::interfaces::*; use super::*; + use tock_registers::interfaces::*; pub struct Reg; impl Writeable for Reg { type T = u64; diff --git a/src/registers/icv_ap1r_el1.rs b/src/registers/icv_ap1r_el1.rs index b7e6300..d6e5270 100644 --- a/src/registers/icv_ap1r_el1.rs +++ b/src/registers/icv_ap1r_el1.rs @@ -10,8 +10,8 @@ macro_rules! ap { ($reg: ident, $name: tt) => { #[allow(non_snake_case)] mod $reg { - use tock_registers::interfaces::*; use super::*; + use tock_registers::interfaces::*; pub struct Reg; impl Writeable for Reg { type T = u64; diff --git a/src/registers/icv_ctlr_el1.rs b/src/registers/icv_ctlr_el1.rs index b873ef4..e8baa0c 100644 --- a/src/registers/icv_ctlr_el1.rs +++ b/src/registers/icv_ctlr_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_CTLR_EL1 [ Ext OFFSET(19) NUMBITS(1) [ diff --git a/src/registers/icv_eoir0_el1.rs b/src/registers/icv_eoir0_el1.rs index 88d77f7..b411055 100644 --- a/src/registers/icv_eoir0_el1.rs +++ b/src/registers/icv_eoir0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_EOIR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_eoir1_el1.rs b/src/registers/icv_eoir1_el1.rs index a6af241..f0ea1f9 100644 --- a/src/registers/icv_eoir1_el1.rs +++ b/src/registers/icv_eoir1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_EOIR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_hppir0_el1.rs b/src/registers/icv_hppir0_el1.rs index cd7c286..86dcbc3 100644 --- a/src/registers/icv_hppir0_el1.rs +++ b/src/registers/icv_hppir0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_HPPIR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_hppir1_el1.rs b/src/registers/icv_hppir1_el1.rs index 7d469bc..e6d9b35 100644 --- a/src/registers/icv_hppir1_el1.rs +++ b/src/registers/icv_hppir1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_HPPIR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_iar0_el1.rs b/src/registers/icv_iar0_el1.rs index 38c97bf..ffe8098 100644 --- a/src/registers/icv_iar0_el1.rs +++ b/src/registers/icv_iar0_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_IAR0_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_iar1_el1.rs b/src/registers/icv_iar1_el1.rs index de3cef5..51801a7 100644 --- a/src/registers/icv_iar1_el1.rs +++ b/src/registers/icv_iar1_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_IAR1_EL1 [ INTID OFFSET(0) NUMBITS(24) [] diff --git a/src/registers/icv_rpr_el1.rs b/src/registers/icv_rpr_el1.rs index 6fcd051..65c675b 100644 --- a/src/registers/icv_rpr_el1.rs +++ b/src/registers/icv_rpr_el1.rs @@ -1,6 +1,5 @@ use tock_registers::{interfaces::*, register_bitfields}; - register_bitfields! {u64, pub ICV_RPR_EL1 [ NMI OFFSET(63) NUMBITS(1) [], diff --git a/src/registers/vmpidr_el2.rs b/src/registers/vmpidr_el2.rs index 752c16b..3adede3 100644 --- a/src/registers/vmpidr_el2.rs +++ b/src/registers/vmpidr_el2.rs @@ -1,5 +1,7 @@ -use tock_registers::interfaces::{Readable, Writeable}; -use tock_registers::register_bitfields; +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; register_bitfields! {u64, pub VMPIDR_EL2 [ From 74356c72e4d599e7ef595d0d3a3729c533e22ebd Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Mon, 19 Aug 2024 15:04:06 +0800 Subject: [PATCH 65/70] add GICD_PIDR2 for gicv3 Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gic/v3.rs b/src/gic/v3.rs index a2fa62a..632ee34 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -91,7 +91,9 @@ register_structs! { (0x0f30 => reserved7), (0x6000 => IROUTER: [ReadWrite; (0x8000 - 0x6000) / size_of::()]), //Interrupt Routing Registers for extended SPI range (0x8000 => reserved21), - (0xffd0 => ID: [ReadOnly; (0x10000 - 0xffd0) / size_of::()]), //Reserved for ID registers + (0xffd0 => ID_res1: [ReadOnly; (0xffe8 - 0xffd0) / size_of::()]), //Reserved for IMPLEMENTATION registers + (0xffe8 => pub PIDR2: ReadOnly), //Distributor Peripheral ID2 Register + (0xffec => ID_res2: [ReadOnly; (0x10000 - 0xffec) / size_of::()]), //Reserved for IMPLEMENTATION registers (0x10000 => @END), } } From 1540463a073424b1ea00f32049eadf2161d23d48 Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Tue, 20 Aug 2024 16:00:42 +0800 Subject: [PATCH 66/70] add GICR_PIDR2 and GICR_TYPER field Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 12 +++++++----- src/gic/v3/registers.rs | 8 ++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/gic/v3.rs b/src/gic/v3.rs index 632ee34..aaafde1 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -59,7 +59,7 @@ register_structs! { #[allow(non_snake_case)] pub GicDistributorInner { (0x0000 => CTLR: ReadWrite), //Distributor Control Register - (0x0004 => TYPER: ReadOnly), //Interrupt Controller Type Register + (0x0004 => pub TYPER: ReadOnly), //Interrupt Controller Type Register (0x0008 => pub IIDR: ReadOnly), //Distributor Implementer Identification Register (0x000c => TYPER2: ReadOnly), //Interrupt controller Type Register 2 (0x0010 => STATUSR: ReadWrite), //Error Reporting Status Register, optional @@ -101,9 +101,9 @@ register_structs! { register_structs! { #[allow(non_snake_case)] pub GicRedistributorInner { - (0x0000 => CTLR: ReadWrite), // Redistributor Control Register - (0x0004 => IIDR: ReadOnly), // Implementer Identification Register - (0x0008 => TYPER: ReadOnly), // Redistributor Type Register + (0x0000 => pub CTLR: ReadWrite), // Redistributor Control Register + (0x0004 => pub IIDR: ReadOnly), // Implementer Identification Register + (0x0008 => pub TYPER: ReadOnly), // Redistributor Type Register (0x0010 => STATUSR: ReadWrite), // Error Reporting Status Register, optional (0x0014 => pub WAKER: ReadWrite), // Redistributor Wake Register (0x0018 => MPAMIDR: ReadOnly), // Report maximum PARTID and PMG Register @@ -121,7 +121,9 @@ register_structs! { (0x00b8 => reserved14), (0x00c0 => SYNCR: ReadOnly), // Redistributor Synchronize Register (0x00c8 => reserved13), - (0xffd0 => ID: [ReadOnly; (0x10000 - 0xFFD0) / size_of::()]), + (0xffd0 => ID_res1: [ReadOnly; (0xffe8 - 0xffd0) / size_of::()]), //Reserved for IMPLEMENTATION registers + (0xffe8 => pub PIDR2: ReadOnly), //Distributor Peripheral ID2 Register + (0xffec => ID_res2: [ReadOnly; (0x10000 - 0xffec) / size_of::()]), //Reserved for IMPLEMENTATION registers (0x10000 => reserved12), (0x10080 => pub IGROUPR0: ReadWrite), //SGI_base frame, all below (0x10084 => reserved11), diff --git a/src/gic/v3/registers.rs b/src/gic/v3/registers.rs index 6fe7461..0a16c5a 100644 --- a/src/gic/v3/registers.rs +++ b/src/gic/v3/registers.rs @@ -41,3 +41,11 @@ register_bitfields! {u32, IMPDEF OFFSET(0) NUMBITS(1) [], ], } +register_bitfields! {u64, + pub GICR_TYPER [ + Last OFFSET(4) NUMBITS(1) [ + NotLast = 0b0, + Last = 0b1, + ] + ] +} From 3a97cc4c7a63e1fb38063ffe7c1ecb9b6eb3eb60 Mon Sep 17 00:00:00 2001 From: zhr1502 Date: Mon, 26 Aug 2024 16:02:49 +0800 Subject: [PATCH 67/70] feat(exception): add HVC64 exception reason field --- src/exception.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/exception.rs b/src/exception.rs index a981ae1..5384e3e 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -1,5 +1,6 @@ #[derive(Copy, Clone)] pub enum ExceptionReason { + HVC64 = 0b010110, DataAbortLowerEl = 0b100100, DataAbortCurrentEl = 0b100101, Unimplemented = 0xff, From ea1d62c9f49f42395e34c74035564da459164a11 Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Mon, 26 Aug 2024 21:30:52 +0800 Subject: [PATCH 68/70] change all visibility of GICD registers to pub Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/gic/v3.rs b/src/gic/v3.rs index aaafde1..de99a34 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -58,21 +58,21 @@ macro_rules! bit_imp { register_structs! { #[allow(non_snake_case)] pub GicDistributorInner { - (0x0000 => CTLR: ReadWrite), //Distributor Control Register + (0x0000 => pub CTLR: ReadWrite), //Distributor Control Register (0x0004 => pub TYPER: ReadOnly), //Interrupt Controller Type Register (0x0008 => pub IIDR: ReadOnly), //Distributor Implementer Identification Register - (0x000c => TYPER2: ReadOnly), //Interrupt controller Type Register 2 - (0x0010 => STATUSR: ReadWrite), //Error Reporting Status Register, optional + (0x000c => pub TYPER2: ReadOnly), //Interrupt controller Type Register 2 + (0x0010 => pub STATUSR: ReadWrite), //Error Reporting Status Register, optional (0x0014 => reserved0), - (0x0040 => SETSPI_NSR: WriteOnly), //Set SPI Register + (0x0040 => pub SETSPI_NSR: WriteOnly), //Set SPI Register (0x0044 => reserved1), - (0x0048 => CLRSPI_NSR: WriteOnly), //Clear SPI Register + (0x0048 => pub CLRSPI_NSR: WriteOnly), //Clear SPI Register (0x004c => reserved2), - (0x0050 => SETSPI_SR: WriteOnly), //Set SPI, Secure Register + (0x0050 => pub SETSPI_SR: WriteOnly), //Set SPI, Secure Register (0x0054 => reserved3), - (0x0058 => CLRSPI_SR: WriteOnly), //Clear SPI, Secure Register + (0x0058 => pub CLRSPI_SR: WriteOnly), //Clear SPI, Secure Register (0x005c => reserved4), - (0x0080 => IGROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers + (0x0080 => pub GROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers (0x0100 => pub ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Enable Registers (0x0180 => pub ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Enable Registers (0x0200 => pub ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Pending Registers @@ -86,10 +86,10 @@ register_structs! { (0x0e00 => pub NSACR: [ReadWrite; GIC_SEC_REGS_NUM]), //Non-secure Access Control Registers (0x0f00 => pub SGIR: WriteOnly), //Software Generated Interrupt Register (0x0f04 => reserved6), - (0x0f10 => CPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Clear-Pending Registers - (0x0f20 => SPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Set-Pending Registers + (0x0f10 => pub CPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Clear-Pending Registers + (0x0f20 => pub SPENDSGIR: [ReadWrite; GIC_SGI_REGS_NUM]), //SGI Set-Pending Registers (0x0f30 => reserved7), - (0x6000 => IROUTER: [ReadWrite; (0x8000 - 0x6000) / size_of::()]), //Interrupt Routing Registers for extended SPI range + (0x6000 => pub IROUTER: [ReadWrite; (0x8000 - 0x6000) / size_of::()]), //Interrupt Routing Registers for extended SPI range (0x8000 => reserved21), (0xffd0 => ID_res1: [ReadOnly; (0xffe8 - 0xffd0) / size_of::()]), //Reserved for IMPLEMENTATION registers (0xffe8 => pub PIDR2: ReadOnly), //Distributor Peripheral ID2 Register From 0fa3c67b0f6dbf451c5bef0b3d86471d62036005 Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Mon, 26 Aug 2024 21:45:27 +0800 Subject: [PATCH 69/70] fix typo Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gic/v3.rs b/src/gic/v3.rs index de99a34..3a5753a 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -72,7 +72,7 @@ register_structs! { (0x0054 => reserved3), (0x0058 => pub CLRSPI_SR: WriteOnly), //Clear SPI, Secure Register (0x005c => reserved4), - (0x0080 => pub GROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers + (0x0080 => pub IGROUPR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Group Registers (0x0100 => pub ISENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Enable Registers (0x0180 => pub ICENABLER: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Clear-Enable Registers (0x0200 => pub ISPENDR: [ReadWrite; GIC_INT_REGS_NUM]), //Interrupt Set-Pending Registers From 4bbfb6aaa76c4bc1b100376643a9cfda69cd6444 Mon Sep 17 00:00:00 2001 From: Yan Xingyu Date: Thu, 29 Aug 2024 14:34:12 +0800 Subject: [PATCH 70/70] make gicr members public Signed-off-by: Yan Xingyu --- src/gic/v3.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/gic/v3.rs b/src/gic/v3.rs index 3a5753a..b7ba65d 100644 --- a/src/gic/v3.rs +++ b/src/gic/v3.rs @@ -104,22 +104,22 @@ register_structs! { (0x0000 => pub CTLR: ReadWrite), // Redistributor Control Register (0x0004 => pub IIDR: ReadOnly), // Implementer Identification Register (0x0008 => pub TYPER: ReadOnly), // Redistributor Type Register - (0x0010 => STATUSR: ReadWrite), // Error Reporting Status Register, optional + (0x0010 => pub STATUSR: ReadWrite), // Error Reporting Status Register, optional (0x0014 => pub WAKER: ReadWrite), // Redistributor Wake Register - (0x0018 => MPAMIDR: ReadOnly), // Report maximum PARTID and PMG Register - (0x001c => PARTIDR: ReadWrite), // Set PARTID and PMG Register + (0x0018 => pub MPAMIDR: ReadOnly), // Report maximum PARTID and PMG Register + (0x001c => pub PARTIDR: ReadWrite), // Set PARTID and PMG Register (0x0020 => reserved18), - (0x0040 => SETLPIR: WriteOnly), // Set LPI Pending Register - (0x0048 => CLRLPIR: WriteOnly), // Clear LPI Pending Register + (0x0040 => pub SETLPIR: WriteOnly), // Set LPI Pending Register + (0x0048 => pub CLRLPIR: WriteOnly), // Clear LPI Pending Register (0x0050 => reserved17), - (0x0070 => PROPBASER: ReadWrite), //Redistributor Properties Base Address Register - (0x0078 => PEDNBASER: ReadWrite), //Redistributor LPI Pending Table Base Address Register + (0x0070 => pub PROPBASER: ReadWrite), //Redistributor Properties Base Address Register + (0x0078 => pub PEDNBASER: ReadWrite), //Redistributor LPI Pending Table Base Address Register (0x0080 => reserved16), - (0x00a0 => INVLPIR: WriteOnly), // Redistributor Invalidate LPI Register + (0x00a0 => pub INVLPIR: WriteOnly), // Redistributor Invalidate LPI Register (0x00a8 => reserved15), - (0x00b0 => INVALLR: WriteOnly), // Redistributor Invalidate All Register + (0x00b0 => pub INVALLR: WriteOnly), // Redistributor Invalidate All Register (0x00b8 => reserved14), - (0x00c0 => SYNCR: ReadOnly), // Redistributor Synchronize Register + (0x00c0 => pub SYNCR: ReadOnly), // Redistributor Synchronize Register (0x00c8 => reserved13), (0xffd0 => ID_res1: [ReadOnly; (0xffe8 - 0xffd0) / size_of::()]), //Reserved for IMPLEMENTATION registers (0xffe8 => pub PIDR2: ReadOnly), //Distributor Peripheral ID2 Register @@ -139,14 +139,14 @@ register_structs! { (0x10304 => reserved6), (0x10380 => pub ICACTIVER0: ReadWrite), (0x10384 => reserved5), - (0x10400 => IPRIORITYR: [ReadWrite;8]), + (0x10400 => pub IPRIORITYR: [ReadWrite;8]), (0x10420 => reserved4), (0x10c00 => pub ICFGR0: ReadWrite), (0x10c04 => pub ICFGR1: ReadWrite), (0x10c08 => reserved3), - (0x10d00 => IGRPMODR0: ReadWrite), + (0x10d00 => pub IGRPMODR0: ReadWrite), (0x10d04 => reserved2), - (0x10e00 => NSACR: ReadWrite), + (0x10e00 => pub NSACR: ReadWrite), (0x10e04 => reserved1), (0x20000 => @END), } @@ -175,8 +175,10 @@ impl GicDistributorInner { self.IROUTER[id as usize].set(cpumask as u64); } pub fn enable_gic(&mut self) { - self.CTLR - .set((GICD_CTLR::ENGrp1NS::Enable + GICD_CTLR::ARE_NS::Enable).into()) + self.CTLR.set( + (GICD_CTLR::ENGrp1NS::Enable + GICD_CTLR::ARE_NS::Enable + GICD_CTLR::ENGrp0::Enable) + .into(), + ) } pub fn disable_gic(&mut self) {