From 4cb517a02631b05917ac900cdf3632918ba1e292 Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Tue, 22 Mar 2022 16:15:17 +0000 Subject: Initial import. Bug: 223166344 Change-Id: I0b181158a5316e6122627d4a51301b908581656a --- .cargo_vcs_info.json | 6 + Cargo.toml | 27 +++ Cargo.toml.orig | 23 ++ LICENSE | 1 + LICENSE-APACHE | 201 +++++++++++++++++ LICENSE-MIT | 21 ++ METADATA | 20 ++ MODULE_LICENSE_APACHE2 | 0 OWNERS | 1 + README.md | 93 ++++++++ rust-toolchain.toml | 3 + src/asm.rs | 113 ++++++++++ src/asm/barrier.rs | 111 ++++++++++ src/lib.rs | 87 ++++++++ src/registers.rs | 107 +++++++++ src/registers/cntfrq_el0.rs | 25 +++ src/registers/cnthctl_el2.rs | 73 +++++++ src/registers/cntp_ctl_el0.rs | 63 ++++++ src/registers/cntp_tval_el0.rs | 30 +++ src/registers/cntpct_el0.rs | 23 ++ src/registers/cntv_ctl_el0.rs | 69 ++++++ src/registers/cntv_cval_el0.rs | 49 +++++ src/registers/cntv_tval_el0.rs | 31 +++ src/registers/cntvct_el0.rs | 25 +++ src/registers/cntvoff_el2.rs | 31 +++ src/registers/currentel.rs | 46 ++++ src/registers/daif.rs | 87 ++++++++ src/registers/elr_el1.rs | 30 +++ src/registers/elr_el2.rs | 30 +++ src/registers/elr_el3.rs | 31 +++ src/registers/esr_el1.rs | 82 +++++++ src/registers/esr_el2.rs | 94 ++++++++ src/registers/far_el1.rs | 31 +++ src/registers/far_el2.rs | 31 +++ src/registers/fp.rs | 28 +++ src/registers/hcr_el2.rs | 281 ++++++++++++++++++++++++ src/registers/id_aa64mmfr0_el1.rs | 96 ++++++++ src/registers/lr.rs | 29 +++ src/registers/macros.rs | 76 +++++++ src/registers/mair_el1.rs | 447 +++++++++++++++++++++++++++++++++++++ src/registers/mair_el2.rs | 448 ++++++++++++++++++++++++++++++++++++++ src/registers/midr_el1.rs | 96 ++++++++ src/registers/mpidr_el1.rs | 24 ++ src/registers/oslar_el1.rs | 48 ++++ src/registers/par_el1.rs | 63 ++++++ src/registers/scr_el3.rs | 95 ++++++++ src/registers/sctlr_el1.rs | 320 +++++++++++++++++++++++++++ src/registers/sctlr_el2.rs | 148 +++++++++++++ src/registers/sp.rs | 28 +++ src/registers/sp_el0.rs | 31 +++ src/registers/sp_el1.rs | 36 +++ src/registers/spsel.rs | 49 +++++ src/registers/spsr_el1.rs | 145 ++++++++++++ src/registers/spsr_el2.rs | 149 +++++++++++++ src/registers/spsr_el3.rs | 150 +++++++++++++ src/registers/tcr_el1.rs | 347 +++++++++++++++++++++++++++++ src/registers/tcr_el2.rs | 176 +++++++++++++++ src/registers/tpidr_el0.rs | 31 +++ src/registers/tpidr_el1.rs | 31 +++ src/registers/tpidrro_el0.rs | 31 +++ src/registers/ttbr0_el1.rs | 64 ++++++ src/registers/ttbr0_el2.rs | 60 +++++ src/registers/ttbr1_el1.rs | 64 ++++++ src/registers/vbar_el1.rs | 30 +++ src/registers/vbar_el2.rs | 31 +++ 65 files changed, 5347 insertions(+) create mode 100644 .cargo_vcs_info.json create mode 100644 Cargo.toml create mode 100644 Cargo.toml.orig create mode 120000 LICENSE create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 METADATA create mode 100644 MODULE_LICENSE_APACHE2 create mode 100644 OWNERS create mode 100644 README.md create mode 100644 rust-toolchain.toml create mode 100644 src/asm.rs create mode 100644 src/asm/barrier.rs create mode 100644 src/lib.rs create mode 100644 src/registers.rs create mode 100644 src/registers/cntfrq_el0.rs create mode 100644 src/registers/cnthctl_el2.rs create mode 100644 src/registers/cntp_ctl_el0.rs create mode 100644 src/registers/cntp_tval_el0.rs create mode 100644 src/registers/cntpct_el0.rs create mode 100644 src/registers/cntv_ctl_el0.rs create mode 100644 src/registers/cntv_cval_el0.rs create mode 100644 src/registers/cntv_tval_el0.rs create mode 100644 src/registers/cntvct_el0.rs create mode 100644 src/registers/cntvoff_el2.rs create mode 100644 src/registers/currentel.rs create mode 100644 src/registers/daif.rs create mode 100644 src/registers/elr_el1.rs create mode 100644 src/registers/elr_el2.rs create mode 100644 src/registers/elr_el3.rs create mode 100644 src/registers/esr_el1.rs create mode 100644 src/registers/esr_el2.rs create mode 100644 src/registers/far_el1.rs create mode 100644 src/registers/far_el2.rs create mode 100644 src/registers/fp.rs create mode 100644 src/registers/hcr_el2.rs create mode 100644 src/registers/id_aa64mmfr0_el1.rs create mode 100644 src/registers/lr.rs create mode 100644 src/registers/macros.rs create mode 100644 src/registers/mair_el1.rs create mode 100644 src/registers/mair_el2.rs create mode 100644 src/registers/midr_el1.rs create mode 100644 src/registers/mpidr_el1.rs create mode 100644 src/registers/oslar_el1.rs create mode 100644 src/registers/par_el1.rs create mode 100644 src/registers/scr_el3.rs create mode 100644 src/registers/sctlr_el1.rs create mode 100644 src/registers/sctlr_el2.rs create mode 100644 src/registers/sp.rs create mode 100644 src/registers/sp_el0.rs create mode 100644 src/registers/sp_el1.rs create mode 100644 src/registers/spsel.rs create mode 100644 src/registers/spsr_el1.rs create mode 100644 src/registers/spsr_el2.rs create mode 100644 src/registers/spsr_el3.rs create mode 100644 src/registers/tcr_el1.rs create mode 100644 src/registers/tcr_el2.rs create mode 100644 src/registers/tpidr_el0.rs create mode 100644 src/registers/tpidr_el1.rs create mode 100644 src/registers/tpidrro_el0.rs create mode 100644 src/registers/ttbr0_el1.rs create mode 100644 src/registers/ttbr0_el2.rs create mode 100644 src/registers/ttbr1_el1.rs create mode 100644 src/registers/vbar_el1.rs create mode 100644 src/registers/vbar_el2.rs diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json new file mode 100644 index 0000000..36ee32b --- /dev/null +++ b/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5c942a99d9e534f3d0973c23d408384c7aefce05" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d6d0295 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cortex-a" +version = "7.2.0" +authors = ["Andre Richter "] +exclude = [".github", ".gitignore", ".rustfmt.toml", ".vscode", ".editorconfig", "Makefile"] +description = "Low level access to Cortex-A processors" +homepage = "https://github.com/rust-embedded/cortex-a" +readme = "README.md" +keywords = ["arm", "aarch64", "cortex-a", "register"] +categories = ["embedded", "hardware-support", "no-std"] +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-embedded/cortex-a" +[dependencies.tock-registers] +version = "0.7.x" +default-features = false diff --git a/Cargo.toml.orig b/Cargo.toml.orig new file mode 100644 index 0000000..22d5fac --- /dev/null +++ b/Cargo.toml.orig @@ -0,0 +1,23 @@ +[package] +name = "cortex-a" +version = "7.2.0" +authors = ["Andre Richter "] +description = "Low level access to Cortex-A processors" +homepage = "https://github.com/rust-embedded/cortex-a" +repository = "https://github.com/rust-embedded/cortex-a" +readme = "README.md" +keywords = ["arm", "aarch64", "cortex-a", "register"] +categories = ["embedded", "hardware-support", "no-std"] +license = "MIT/Apache-2.0" +edition = "2018" +exclude = [ + ".github", + ".gitignore", + ".rustfmt.toml", + ".vscode", + ".editorconfig", + "Makefile" +] + +[dependencies] +tock-registers = { version = "0.7.x", default-features = false } # Use it as interface-only library. diff --git a/LICENSE b/LICENSE new file mode 120000 index 0000000..6b579aa --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +LICENSE-APACHE \ No newline at end of file diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..d36a7e1 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2018-2022 by the respective authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..b1970eb --- /dev/null +++ b/METADATA @@ -0,0 +1,20 @@ +name: "cortex-a" +description: "Low level access to Cortex-A processors" +third_party { + url { + type: HOMEPAGE + value: "https://crates.io/crates/cortex-a" + } + url { + type: ARCHIVE + value: "https://static.crates.io/crates/cortex-a/cortex-a-7.2.0.crate" + } + version: "7.2.0" + # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + license_type: NOTICE + last_upgrade_date { + year: 2022 + month: 3 + day: 22 + } +} diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000..45dc4dd --- /dev/null +++ b/OWNERS @@ -0,0 +1 @@ +include platform/prebuilts/rust:master:/OWNERS diff --git a/README.md b/README.md new file mode 100644 index 0000000..a7b547c --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +[![crates.io](https://img.shields.io/crates/d/cortex-a.svg)](https://crates.io/crates/cortex-a) +[![crates.io](https://img.shields.io/crates/v/cortex-a.svg)](https://crates.io/crates/cortex-a) + +# cortex-a + +Low level access to Cortex-A processors. + +## Currently Supported Execution States + +- [x] AArch64 +- [ ] AArch32 + +## Minimum Supported Rust Version + +Requires a recent nightly of Rust. + +## Usage + +Please note that for using this crate's [register definitions](src/registers) (as provided by +`cortex_a::registers::*`), you need to also include +[`tock-registers`](https://crates.io/crates/tock-registers) in your project. This is because the +`interface` traits provided by `tock-registers` are implemented by this crate. You should include +the same version of `tock-registers` as is being used by this crate to ensure sane +interoperatbility. + +For example, in the following snippet, `X.Y.Z` should be the same version of `tock-registers` that +is mentioned in `cortex-a`'s [`Cargo.toml`](Cargo.toml). + +```toml +[package] +name = "Your embedded project" + +# Some parts omitted for brevity. + +[dependencies] +tock-registers = "X.Y.Z" +cortex-a = "A.B.C" # <-- Includes tock-registers itself. +``` + +### Example + +Check out https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials for usage examples. Listed +below is a snippet of `rust-raspberrypi-OS-tutorials`'s early boot code. + +```rust +use cortex_a::{asm, registers::*}; +use tock_registers::interfaces::Writeable; // <-- Trait needed to use `write()` and `set()`. + +// Some parts omitted for brevity. + +unsafe fn prepare_el2_to_el1_transition( + virt_boot_core_stack_end_exclusive_addr: u64, + virt_kernel_init_addr: u64, +) { + // Enable timer counter registers for EL1. + CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET); + + // No offset for reading the counters. + CNTVOFF_EL2.set(0); + + // Set EL1 execution state to AArch64. + HCR_EL2.write(HCR_EL2::RW::EL1IsAarch64); + + // Set up a simulated exception return. + SPSR_EL2.write( + SPSR_EL2::D::Masked + + SPSR_EL2::A::Masked + + SPSR_EL2::I::Masked + + SPSR_EL2::F::Masked + + SPSR_EL2::M::EL1h, + ); +``` + +## Disclaimer + +Descriptive comments in the source files are taken from the +[ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile](https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf?_ga=2.266626254.1122218691.1534883460-1326731866.1530967873). + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the +work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..a500664 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +targets = ["aarch64-unknown-none-softfloat"] diff --git a/src/asm.rs b/src/asm.rs new file mode 100644 index 0000000..0e4a942 --- /dev/null +++ b/src/asm.rs @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Jorge Aparicio +// - Andre Richter + +//! Wrappers around ARMv8-A instructions. + +pub mod barrier; + +/// The classic no-op +#[inline(always)] +pub fn nop() { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("nop", options(nomem, nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Wait For Interrupt +/// +/// For more details on wfi, refer to [here](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CIHEGBBF.html). +#[inline(always)] +pub fn wfi() { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("wfi", options(nomem, nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Wait For Event +/// +/// For more details of wfe - sev pair, refer to [here](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CIHEGBBF.html). +#[inline(always)] +pub fn wfe() { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("wfe", options(nomem, nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Send EVent.Locally +/// +/// SEV causes an event to be signaled to the local core within a multiprocessor system. +/// +/// For more details of wfe - sev/sevl pair, refer to [here](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CIHEGBBF.html). +#[inline(always)] +pub fn sevl() { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("sevl", options(nomem, nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Send EVent. +/// +/// SEV causes an event to be signaled to all cores within a multiprocessor system. +/// +/// For more details of wfe - sev pair, refer to [here](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CIHEGBBF.html). +#[inline(always)] +pub fn sev() { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("sev", options(nomem, nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Exception return +/// +/// Will jump to wherever the corresponding link register points to, and therefore never return. +#[inline(always)] +pub fn eret() -> ! { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("eret", options(nomem, nostack)); + core::intrinsics::unreachable() + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} + +/// Function return +/// +/// Will jump to wherever the corresponding link register points to, and therefore never return. +#[inline(always)] +pub fn ret() -> ! { + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("ret", options(nomem, nostack)); + core::intrinsics::unreachable() + } + + #[cfg(not(target_arch = "aarch64"))] + unimplemented!() +} diff --git a/src/asm/barrier.rs b/src/asm/barrier.rs new file mode 100644 index 0000000..690c32f --- /dev/null +++ b/src/asm/barrier.rs @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Barrier functions. + +mod sealed { + pub trait Dmb { + unsafe fn __dmb(&self); + } + + pub trait Dsb { + unsafe fn __dsb(&self); + } + + pub trait Isb { + unsafe fn __isb(&self); + } +} + +macro_rules! dmb_dsb { + ($A:ident) => { + impl sealed::Dmb for $A { + #[inline(always)] + unsafe fn __dmb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => { + core::arch::asm!(concat!("DMB ", stringify!($A)), options(nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + impl sealed::Dsb for $A { + #[inline(always)] + unsafe fn __dsb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => { + core::arch::asm!(concat!("DSB ", stringify!($A)), options(nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + } + }; +} + +pub struct SY; +pub struct ISH; +pub struct ISHST; + +dmb_dsb!(ISH); +dmb_dsb!(ISHST); +dmb_dsb!(SY); + +impl sealed::Isb for SY { + #[inline(always)] + unsafe fn __isb(&self) { + match () { + #[cfg(target_arch = "aarch64")] + () => { + core::arch::asm!("ISB SY", options(nostack)) + } + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } +} + +/// # Safety +/// +/// In your own hands, this is hardware land! +#[inline(always)] +pub unsafe fn dmb(arg: A) +where + A: sealed::Dmb, +{ + arg.__dmb() +} + +/// # Safety +/// +/// In your own hands, this is hardware land! +#[inline(always)] +pub unsafe fn dsb(arg: A) +where + A: sealed::Dsb, +{ + arg.__dsb() +} + +/// # Safety +/// +/// In your own hands, this is hardware land! +#[inline(always)] +pub unsafe fn isb(arg: A) +where + A: sealed::Isb, +{ + arg.__isb() +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..36e13fd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Low level access to Cortex-A processors. +//! +//! ## Currently Supported Execution States +//! +//! - [x] AArch64 +//! - [ ] AArch32 +//! +//! ## Minimum Supported Rust Version +//! +//! Requires a recent nightly of Rust. +//! +//! ## Usage +//! +//! Please note that for using this crate's [register definitions](src/registers) (as provided by +//! `cortex_a::registers::*`), you need to also include +//! [`tock-registers`](https://crates.io/crates/tock-registers) in your project. This is because the +//! `interface` traits provided by `tock-registers` are implemented by this crate. You should +//! include the same version of `tock-registers` as is being used by this crate to ensure sane +//! interoperatbility. +//! +//! For example, in the following snippet, `X.Y.Z` should be the same version of `tock-registers` +//! that is mentioned in `cortex-a`'s [`Cargo.toml`](Cargo.toml). +//! +//! ```toml +//! [package] +//! name = "Your embedded project" +//! +//! # Some parts omitted for brevity. +//! +//! [dependencies] +//! tock-registers = "X.Y.Z" +//! cortex-a = "A.B.C" # <-- Includes tock-registers itself. +//! ``` +//! +//! ### Example +//! +//! Check out https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials for usage examples. +//! Listed below is a snippet of `rust-raspberrypi-OS-tutorials`'s early boot code. +//! +//! ```rust +//! use cortex_a::{asm, registers::*}; +//! use tock_registers::interfaces::Writeable; // <-- Trait needed to use `write()` and `set()`. +//! +//! // Some parts omitted for brevity. +//! +//! unsafe fn prepare_el2_to_el1_transition( +//! virt_boot_core_stack_end_exclusive_addr: u64, +//! virt_kernel_init_addr: u64, +//! ) { +//! // Enable timer counter registers for EL1. +//! CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET); +//! +//! // No offset for reading the counters. +//! CNTVOFF_EL2.set(0); +//! +//! // Set EL1 execution state to AArch64. +//! HCR_EL2.write(HCR_EL2::RW::EL1IsAarch64); +//! +//! // Set up a simulated exception return. +//! SPSR_EL2.write( +//! SPSR_EL2::D::Masked +//! + SPSR_EL2::A::Masked +//! + SPSR_EL2::I::Masked +//! + SPSR_EL2::F::Masked +//! + SPSR_EL2::M::EL1h, +//! ); +//! ``` +//! +//! ## Disclaimer +//! +//! Descriptive comments in the source files are taken from the [ARM Architecture Reference Manual +//! ARMv8, for ARMv8-A architecture +//! profile](https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf?_ga=2.266626254.1122218691.1534883460-1326731866.1530967873). + +#![feature(core_intrinsics)] +#![feature(custom_inner_attributes)] +#![no_std] + +pub mod asm; +pub mod registers; diff --git a/src/registers.rs b/src/registers.rs new file mode 100644 index 0000000..b805942 --- /dev/null +++ b/src/registers.rs @@ -0,0 +1,107 @@ +//! Processor core registers + +#![allow(unused_attributes)] +#![rustfmt::skip] + +#[macro_use] +mod macros; + +mod cntfrq_el0; +mod cnthctl_el2; +mod cntp_ctl_el0; +mod cntp_tval_el0; +mod cntpct_el0; +mod cntv_ctl_el0; +mod cntv_cval_el0; +mod cntv_tval_el0; +mod cntvct_el0; +mod cntvoff_el2; +mod currentel; +mod daif; +mod elr_el1; +mod elr_el2; +mod elr_el3; +mod esr_el1; +mod esr_el2; +mod far_el1; +mod far_el2; +mod fp; +mod hcr_el2; +mod id_aa64mmfr0_el1; +mod lr; +mod mair_el1; +mod mair_el2; +mod midr_el1; +mod mpidr_el1; +mod oslar_el1; +mod par_el1; +mod scr_el3; +mod sctlr_el1; +mod sctlr_el2; +mod sp; +mod sp_el0; +mod sp_el1; +mod spsel; +mod spsr_el1; +mod spsr_el2; +mod spsr_el3; +mod tcr_el1; +mod tcr_el2; +mod tpidr_el0; +mod tpidr_el1; +mod tpidrro_el0; +mod ttbr0_el1; +mod ttbr0_el2; +mod ttbr1_el1; +mod vbar_el1; +mod vbar_el2; + +pub use cntfrq_el0::CNTFRQ_EL0; +pub use cnthctl_el2::CNTHCTL_EL2; +pub use cntp_ctl_el0::CNTP_CTL_EL0; +pub use cntp_tval_el0::CNTP_TVAL_EL0; +pub use cntpct_el0::CNTPCT_EL0; +pub use cntv_ctl_el0::CNTV_CTL_EL0; +pub use cntv_cval_el0::CNTV_CVAL_EL0; +pub use cntv_tval_el0::CNTV_TVAL_EL0; +pub use cntvct_el0::CNTVCT_EL0; +pub use cntvoff_el2::CNTVOFF_EL2; +pub use currentel::CurrentEL; +pub use daif::DAIF; +pub use elr_el1::ELR_EL1; +pub use elr_el2::ELR_EL2; +pub use elr_el3::ELR_EL3; +pub use esr_el1::ESR_EL1; +pub use esr_el2::ESR_EL2; +pub use far_el1::FAR_EL1; +pub use far_el2::FAR_EL2; +pub use fp::FP; +pub use hcr_el2::HCR_EL2; +pub use id_aa64mmfr0_el1::ID_AA64MMFR0_EL1; +pub use lr::LR; +pub use mair_el1::MAIR_EL1; +pub use mair_el2::MAIR_EL2; +pub use midr_el1::MIDR_EL1; +pub use mpidr_el1::MPIDR_EL1; +pub use oslar_el1::OSLAR_EL1; +pub use par_el1::PAR_EL1; +pub use scr_el3::SCR_EL3; +pub use sctlr_el1::SCTLR_EL1; +pub use sctlr_el2::SCTLR_EL2; +pub use sp::SP; +pub use sp_el0::SP_EL0; +pub use sp_el1::SP_EL1; +pub use spsel::SPSel; +pub use spsr_el1::SPSR_EL1; +pub use spsr_el2::SPSR_EL2; +pub use spsr_el3::SPSR_EL3; +pub use tcr_el1::TCR_EL1; +pub use tcr_el2::TCR_EL2; +pub use tpidr_el0::TPIDR_EL0; +pub use tpidr_el1::TPIDR_EL1; +pub use tpidrro_el0::TPIDRRO_EL0; +pub use ttbr0_el1::TTBR0_EL1; +pub use ttbr0_el2::TTBR0_EL2; +pub use ttbr1_el1::TTBR1_EL1; +pub use vbar_el1::VBAR_EL1; +pub use vbar_el2::VBAR_EL2; diff --git a/src/registers/cntfrq_el0.rs b/src/registers/cntfrq_el0.rs new file mode 100644 index 0000000..24c658d --- /dev/null +++ b/src/registers/cntfrq_el0.rs @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Frequency register - EL0 +//! +//! This register is provided so that software can discover the frequency of the system counter. It +//! must be programmed with this value as part of system initialization. The value of the register +//! is not interpreted by hardware. + +use tock_registers::interfaces::Readable; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTFRQ_EL0", "x"); +} + +pub const CNTFRQ_EL0: Reg = Reg {}; diff --git a/src/registers/cnthctl_el2.rs b/src/registers/cnthctl_el2.rs new file mode 100644 index 0000000..c591e3e --- /dev/null +++ b/src/registers/cnthctl_el2.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Hypervisor Control register - EL2 +//! +//! Controls the generation of an event stream from the physical counter, and +//! access from Non-secure EL1 to the physical counter and the Non-secure EL1 +//! physical timer. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +// When HCR_EL2.E2H == 0: +// TODO: Figure out how we can differentiate depending on HCR_EL2.E2H state +// +// For now, implement the HCR_EL2.E2H == 0 version +register_bitfields! {u64, + pub CNTHCTL_EL2 [ + /// Traps Non-secure EL0 and EL1 accesses to the physical timer registers to EL2. + /// + /// 0 From AArch64 state: Non-secure EL0 and EL1 accesses to the CNTP_CTL_EL0, + /// CNTP_CVAL_EL0, and CNTP_TVAL_EL0 are trapped to EL2, unless it is trapped by + /// CNTKCTL_EL1.EL0PTEN. + /// + /// From AArch32 state: Non-secure EL0 and EL1 accesses to the CNTP_CTL, CNTP_CVAL, and + /// CNTP_TVAL are trapped to EL2, unless it is trapped by CNTKCTL_EL1.EL0PTEN or + /// CNTKCTL.PL0PTEN. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// If EL3 is implemented and EL2 is not implemented, behavior is as if this bit is 1 other + /// than for the purpose of a direct read. + EL1PCEN OFFSET(1) NUMBITS(1) [], + + /// Traps Non-secure EL0 and EL1 accesses to the physical counter register to EL2. + /// + /// 0 From AArch64 state: Non-secure EL0 and EL1 accesses to the CNTPCT_EL0 are trapped to + /// EL2, unless it is trapped by CNTKCTL_EL1.EL0PCTEN. + /// + /// From AArch32 state: Non-secure EL0 and EL1 accesses to the CNTPCT are trapped to EL2, + /// unless it is trapped by CNTKCTL_EL1.EL0PCTEN or CNTKCTL.PL0PCTEN. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// If EL3 is implemented and EL2 is not implemented, behavior is as if this bit is 1 other + /// than for the purpose of a direct read. + EL1PCTEN OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = CNTHCTL_EL2::Register; + + sys_coproc_read_raw!(u64, "CNTHCTL_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = CNTHCTL_EL2::Register; + + sys_coproc_write_raw!(u64, "CNTHCTL_EL2", "x"); +} + +pub const CNTHCTL_EL2: Reg = Reg {}; diff --git a/src/registers/cntp_ctl_el0.rs b/src/registers/cntp_ctl_el0.rs new file mode 100644 index 0000000..50ee701 --- /dev/null +++ b/src/registers/cntp_ctl_el0.rs @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Physical Timer Control register - EL0 +//! +//! Control register for the EL1 physical timer. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub CNTP_CTL_EL0 [ + /// The status of the timer. This bit indicates whether the timer condition is met: + /// + /// 0 Timer condition is not met. + /// 1 Timer condition is met. + /// + /// When the value of the ENABLE bit is 1, ISTATUS indicates whether the timer condition is + /// met. ISTATUS takes no account of the value of the IMASK bit. If the value of ISTATUS is + /// 1 and the value of IMASK is 0 then the timer interrupt is asserted. + /// + /// When the value of the ENABLE bit is 0, the ISTATUS field is UNKNOWN. + /// + /// This bit is read-only. + ISTATUS OFFSET(2) NUMBITS(1) [], + + /// Timer interrupt mask bit. Permitted values are: + /// + /// 0 Timer interrupt is not masked by the IMASK bit. + /// 1 Timer interrupt is masked by the IMASK bit. + IMASK OFFSET(1) NUMBITS(1) [], + + /// Enables the timer. Permitted values are: + /// + /// 0 Timer disabled. + /// 1 Timer enabled. + ENABLE OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = CNTP_CTL_EL0::Register; + + sys_coproc_read_raw!(u64, "CNTP_CTL_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = CNTP_CTL_EL0::Register; + + sys_coproc_write_raw!(u64, "CNTP_CTL_EL0", "x"); +} + +pub const CNTP_CTL_EL0: Reg = Reg {}; diff --git a/src/registers/cntp_tval_el0.rs b/src/registers/cntp_tval_el0.rs new file mode 100644 index 0000000..e28a4a0 --- /dev/null +++ b/src/registers/cntp_tval_el0.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 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, "CNTP_TVAL_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTP_TVAL_EL0", "x"); +} + +pub const CNTP_TVAL_EL0: Reg = Reg {}; diff --git a/src/registers/cntpct_el0.rs b/src/registers/cntpct_el0.rs new file mode 100644 index 0000000..95e917b --- /dev/null +++ b/src/registers/cntpct_el0.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Physical Count register - EL0 +//! +//! Holds the 64-bit physical count value. + +use tock_registers::interfaces::Readable; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTPCT_EL0", "x"); +} + +pub const CNTPCT_EL0: Reg = Reg {}; diff --git a/src/registers/cntv_ctl_el0.rs b/src/registers/cntv_ctl_el0.rs new file mode 100644 index 0000000..75f7c3e --- /dev/null +++ b/src/registers/cntv_ctl_el0.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Gregor Reitzenstein + +//! Counter-timer Virtual Timer Control register - EL0 +//! +//! Control register for the virtual timer + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub CNTV_CTL_EL0 [ + /// The status of the timer. This bit indicates whether the timer condition is met: + /// + /// 0 Timer condition is not met. + /// 1 Timer condition is met. + /// + /// When the value of the ENABLE bit is 1, ISTATUS indicates whether the timer condition is + /// met. ISTATUS takes no account of the value of the IMASK bit. If the value of ISTATUS is + /// 1 and the value of IMASK is 0 then the timer interrupt is asserted. + /// + /// When the value of the ENABLE bit is 0, the ISTATUS field is UNKNOWN. + /// + /// This bit is read-only. + ISTATUS OFFSET(2) NUMBITS(1) [], + + /// Timer interrupt mask bit. Permitted values are: + /// + /// 0 Timer interrupt is not masked by the IMASK bit. + /// 1 Timer interrupt is masked by the IMASK bit. + IMASK OFFSET(1) NUMBITS(1) [], + + /// Enables the timer. Permitted values are: + /// + /// 0 Timer disabled. + /// 1 Timer enabled. + /// + /// Setting this bit to 0 disables the timer output signal but the timer value accessible + /// from `CNTV_TVAL_EL0` continues to count down. + /// + /// Disabling the output signal might be a power-saving option + ENABLE OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = CNTV_CTL_EL0::Register; + + sys_coproc_read_raw!(u64, "CNTV_CTL_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = CNTV_CTL_EL0::Register; + + sys_coproc_write_raw!(u64, "CNTV_CTL_EL0", "x"); +} + +pub const CNTV_CTL_EL0: Reg = Reg {}; diff --git a/src/registers/cntv_cval_el0.rs b/src/registers/cntv_cval_el0.rs new file mode 100644 index 0000000..cb46074 --- /dev/null +++ b/src/registers/cntv_cval_el0.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Javier Alvarez + +//! Counter-timer Virtual Timer CompareValue register - EL0 +//! +//! Holds the compare value for the virtual timer. +//! +//! When CNTV_CTL_EL0.ENABLE is 1, the timer condition is met when (CNTVCT_EL0 - CompareValue) is +//! greater than or equal to zero. This means that CompareValue acts like a 64-bit upcounter timer. +//! +//! When the timer condition is met: +//! - CNTV_CTL_EL0.ISTATUS is set to 1. +//! - If CNTV_CTL_EL0.IMASK is 0, an interrupt is generated. +//! +//! When CNTV_CTL_EL0.ENABLE is 0, the timer condition is not met, but CNTVCT_EL0 continues to +//! count. +//! +//! If the Generic counter is implemented at a size less than 64 bits, then this field is permitted +//! to be implemented at the same width as the counter, and the upper bits are RES0. +//! +//! The value of this field is treated as zero-extended in all counter calculations. +//! +//! The reset behaviour of this field is: +//! - On a Warm reset, this field resets to an architecturally UNKNOWN value. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTV_CVAL_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTV_CVAL_EL0", "x"); +} + +pub const CNTV_CVAL_EL0: Reg = Reg {}; diff --git a/src/registers/cntv_tval_el0.rs b/src/registers/cntv_tval_el0.rs new file mode 100644 index 0000000..e90e70b --- /dev/null +++ b/src/registers/cntv_tval_el0.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Gregor Reitzenstein + +//! Counter-timer Virtual Timer TimerValue register - EL0 +//! +//! Holds the timer value for the EL1 virtual timer. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTV_TVAL_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTV_TVAL_EL0", "x"); +} + +pub const CNTV_TVAL_EL0: Reg = Reg {}; diff --git a/src/registers/cntvct_el0.rs b/src/registers/cntvct_el0.rs new file mode 100644 index 0000000..c541aac --- /dev/null +++ b/src/registers/cntvct_el0.rs @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Gregor Reitzenstein + +//! Counter-timer Virtual Count register - EL0 +//! +//! Holds the 64-bit virtual count value. The virtual count value is equal to the physical count +//! value in `CNTPCT_EL0` minus the virtual offset visible in `CNTVOFF_EL2` + +use tock_registers::interfaces::Readable; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTVCT_EL0", "x"); +} + +pub const CNTVCT_EL0: Reg = Reg {}; diff --git a/src/registers/cntvoff_el2.rs b/src/registers/cntvoff_el2.rs new file mode 100644 index 0000000..d944055 --- /dev/null +++ b/src/registers/cntvoff_el2.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Counter-timer Virtual Offset register - EL2 +//! +//! Holds the 64-bit virtual offset. This is the offset between the physical count value visible in +//! CNTPCT_EL0 and the virtual count value visible in CNTVCT_EL0. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "CNTVOFF_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "CNTVOFF_EL2", "x"); +} + +pub const CNTVOFF_EL2: Reg = Reg {}; diff --git a/src/registers/currentel.rs b/src/registers/currentel.rs new file mode 100644 index 0000000..cafee3e --- /dev/null +++ b/src/registers/currentel.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Current Exception Level +//! +//! Holds the current Exception level. + +use tock_registers::{interfaces::Readable, register_bitfields}; + +register_bitfields! {u64, + pub CurrentEL [ + /// Current Exception level. Possible values of this field are: + /// + /// 00 EL0 + /// 01 EL1 + /// 10 EL2 + /// 11 EL3 + /// + /// When the HCR_EL2.NV bit is 1, Non-secure EL1 read accesses to the CurrentEL register + /// return the value of 0x2 in this field. + /// + /// This field resets to a value that is architecturally UNKNOWN. + EL OFFSET(2) NUMBITS(2) [ + EL0 = 0, + EL1 = 1, + EL2 = 2, + EL3 = 3 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = CurrentEL::Register; + + sys_coproc_read_raw!(u64, "CurrentEL", "x"); +} + +#[allow(non_upper_case_globals)] +pub const CurrentEL: Reg = Reg {}; diff --git a/src/registers/daif.rs b/src/registers/daif.rs new file mode 100644 index 0000000..2cabdaa --- /dev/null +++ b/src/registers/daif.rs @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Interrupt Mask Bits +//! +//! Allows access to the interrupt mask bits. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub DAIF [ + /// Process state D mask. The possible values of this bit are: + /// + /// 0 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are not masked. + /// + /// 1 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are masked. + /// + /// When the target Exception level of the debug exception is higher than the current + /// Exception level, the exception is not masked by this bit. + /// + /// When this register has an architecturally-defined reset value, this field resets to 1. + D OFFSET(9) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// SError interrupt mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + /// + /// When this register has an architecturally-defined reset value, this field resets to 1. + A OFFSET(8) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// IRQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + /// + /// When this register has an architecturally-defined reset value, this field resets to 1. + I OFFSET(7) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// FIQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + /// + /// When this register has an architecturally-defined reset value, this field resets to 1. + F OFFSET(6) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = DAIF::Register; + + sys_coproc_read_raw!(u64, "DAIF", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = DAIF::Register; + + sys_coproc_write_raw!(u64, "DAIF", "x"); +} + +pub const DAIF: Reg = Reg {}; diff --git a/src/registers/elr_el1.rs b/src/registers/elr_el1.rs new file mode 100644 index 0000000..9d094cb --- /dev/null +++ b/src/registers/elr_el1.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Exception Link Register - EL1 +//! +//! When taking an exception to EL1, holds the address to return to. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "ELR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "ELR_EL1", "x"); +} + +pub const ELR_EL1: Reg = Reg {}; diff --git a/src/registers/elr_el2.rs b/src/registers/elr_el2.rs new file mode 100644 index 0000000..062a513 --- /dev/null +++ b/src/registers/elr_el2.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Exception Link Register - EL2 +//! +//! When taking an exception to EL2, holds the address to return to. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "ELR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "ELR_EL2", "x"); +} + +pub const ELR_EL2: Reg = Reg {}; diff --git a/src/registers/elr_el3.rs b/src/registers/elr_el3.rs new file mode 100644 index 0000000..911e9b2 --- /dev/null +++ b/src/registers/elr_el3.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Berkus Decker + +//! Exception Link Register - EL3 +//! +//! When taking an exception to EL3, holds the address to return to. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "ELR_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "ELR_EL3", "x"); +} + +pub const ELR_EL3: Reg = Reg {}; diff --git a/src/registers/esr_el1.rs b/src/registers/esr_el1.rs new file mode 100644 index 0000000..0cad468 --- /dev/null +++ b/src/registers/esr_el1.rs @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Berkus Decker + +//! Exception Syndrome Register - EL1 +//! +//! Holds syndrome information for an exception taken to EL1. + +use tock_registers::{interfaces::Readable, register_bitfields}; + +register_bitfields! {u64, + pub ESR_EL1 [ + /// Exception Class. Indicates the reason for the exception that this register holds + /// information about. + /// + /// For each EC value, the table references a subsection that gives information about: + /// - The cause of the exception, for example the configuration required to enable the + /// trap. + /// - The encoding of the associated ISS. + /// + /// Incomplete listing - to be done. + EC OFFSET(26) NUMBITS(6) [ + Unknown = 0b00_0000, + TrappedWFIorWFE = 0b00_0001, + TrappedMCRorMRC = 0b00_0011, // A32 + TrappedMCRRorMRRC = 0b00_0100, // A32 + TrappedMCRorMRC2 = 0b00_0101, // A32 + TrappedLDCorSTC = 0b00_0110, // A32 + TrappedFP = 0b00_0111, + TrappedMRRC = 0b00_1100, // A32 + BranchTarget = 0b00_1101, + IllegalExecutionState = 0b00_1110, + SVC32 = 0b01_0001, // A32 + SVC64 = 0b01_0101, + HVC64 = 0b01_0110, + SMC64 = 0b01_0111, + TrappedMsrMrs = 0b01_1000, + TrappedSve = 0b01_1001, + PointerAuth = 0b01_1100, + InstrAbortLowerEL = 0b10_0000, + InstrAbortCurrentEL = 0b10_0001, + PCAlignmentFault = 0b10_0010, + DataAbortLowerEL = 0b10_0100, + DataAbortCurrentEL = 0b10_0101, + SPAlignmentFault = 0b10_0110, + TrappedFP32 = 0b10_1000, // A32 + TrappedFP64 = 0b10_1100, + SError = 0b10_1111, + BreakpointLowerEL = 0b11_0000, + BreakpointCurrentEL = 0b11_0001, + SoftwareStepLowerEL = 0b11_0010, + SoftwareStepCurrentEL = 0b11_0011, + WatchpointLowerEL = 0b11_0100, + WatchpointCurrentEL = 0b11_0101, + Bkpt32 = 0b11_1000, // A32 BKTP instruction + Brk64 = 0b11_1100 // A64 BRK instruction + ], + + /// Instruction Length for synchronous exceptions. + IL OFFSET(25) NUMBITS(1) [], + + /// 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) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ESR_EL1::Register; + + sys_coproc_read_raw!(u64, "ESR_EL1", "x"); +} + +pub const ESR_EL1: Reg = Reg {}; diff --git a/src/registers/esr_el2.rs b/src/registers/esr_el2.rs new file mode 100644 index 0000000..af9f27e --- /dev/null +++ b/src/registers/esr_el2.rs @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Berkus Decker +// - Bradley Landherr + +//! Exception Syndrome Register - EL2 +//! +//! Holds syndrome information for an exception taken to EL2. + +use tock_registers::{interfaces::Readable, register_bitfields}; + +register_bitfields! {u64, + pub ESR_EL2 [ + + /// Reserved + RES0 OFFSET(37) NUMBITS(27) [], + + /// Instruction Specific Syndrome 2. If a memory access generated by an ST64BV or ST64BV0 + /// instruction generates a Data Abort for a Translation fault, Access flag fault, or + /// Permission fault, then this field holds register specifier, Xs. + /// + /// For any other Data Abort, this field is RES0. + ISS2 OFFSET(32) NUMBITS(5) [], + + /// Exception Class. Indicates the reason for the exception that this register holds + /// information about. + /// + /// For each EC value, the table references a subsection that gives information about: + /// - The cause of the exception, for example the configuration required to enable the + /// trap. + /// - The encoding of the associated ISS. + /// + /// Incomplete listing - to be done. + EC OFFSET(26) NUMBITS(6) [ + Unknown = 0b00_0000, + TrappedWFIorWFE = 0b00_0001, + TrappedMCRorMRC = 0b00_0011, // A32 + TrappedMCRRorMRRC = 0b00_0100, // A32 + TrappedMCRorMRC2 = 0b00_0101, // A32 + TrappedLDCorSTC = 0b00_0110, // A32 + TrappedFP = 0b00_0111, + TrappedMRRC = 0b00_1100, // A32 + BranchTarget = 0b00_1101, + IllegalExecutionState = 0b00_1110, + SVC32 = 0b01_0001, // A32 + SVC64 = 0b01_0101, + HVC64 = 0b01_0110, + SMC64 = 0b01_0111, + TrappedMsrMrs = 0b01_1000, + TrappedSve = 0b01_1001, + PointerAuth = 0b01_1100, + InstrAbortLowerEL = 0b10_0000, + InstrAbortCurrentEL = 0b10_0001, + PCAlignmentFault = 0b10_0010, + DataAbortLowerEL = 0b10_0100, + DataAbortCurrentEL = 0b10_0101, + SPAlignmentFault = 0b10_0110, + TrappedFP32 = 0b10_1000, // A32 + TrappedFP64 = 0b10_1100, + SError = 0b10_1111, + BreakpointLowerEL = 0b11_0000, + BreakpointCurrentEL = 0b11_0001, + SoftwareStepLowerEL = 0b11_0010, + SoftwareStepCurrentEL = 0b11_0011, + WatchpointLowerEL = 0b11_0100, + WatchpointCurrentEL = 0b11_0101, + Bkpt32 = 0b11_1000, // A32 BKTP instruction + Brk64 = 0b11_1100 // A64 BRK instruction + ], + + /// Instruction Length for synchronous exceptions. + IL OFFSET(25) NUMBITS(1) [], + + /// 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) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ESR_EL2::Register; + + sys_coproc_read_raw!(u64, "ESR_EL2", "x"); +} + +pub const ESR_EL2: Reg = Reg {}; diff --git a/src/registers/far_el1.rs b/src/registers/far_el1.rs new file mode 100644 index 0000000..2bd77d1 --- /dev/null +++ b/src/registers/far_el1.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Fault Address Register - EL1 +//! +//! Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment +//! fault and Watchpoint exceptions that are taken to EL1. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "FAR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "FAR_EL1", "x"); +} + +pub const FAR_EL1: Reg = Reg {}; diff --git a/src/registers/far_el2.rs b/src/registers/far_el2.rs new file mode 100644 index 0000000..0dcfa8a --- /dev/null +++ b/src/registers/far_el2.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Fault Address Register - EL2 +//! +//! Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment +//! fault and Watchpoint exceptions that are taken to EL2. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "FAR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "FAR_EL2", "x"); +} + +pub const FAR_EL2: Reg = Reg {}; diff --git a/src/registers/fp.rs b/src/registers/fp.rs new file mode 100644 index 0000000..76169ea --- /dev/null +++ b/src/registers/fp.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! The frame pointer register + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + read_raw!(u64, "x29", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + write_raw!(u64, "x29", "x"); +} + +pub const FP: Reg = Reg {}; diff --git a/src/registers/hcr_el2.rs b/src/registers/hcr_el2.rs new file mode 100644 index 0000000..877ee30 --- /dev/null +++ b/src/registers/hcr_el2.rs @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Bradley Landherr +// - Javier Alvarez + +//! Hypervisor Configuration Register - EL2 +//! +//! Provides configuration controls for virtualization, including defining +//! whether various Non-secure operations are trapped to EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub HCR_EL2 [ + /// Controls the use of instructions related to Pointer Authentication: + /// + /// - In EL0, when HCR_EL2.TGE==0 or HCR_EL2.E2H==0, and the associated SCTLR_EL1.En==1. + /// - In EL1, the associated SCTLR_EL1.En==1. + /// + /// Traps are reported using EC syndrome value 0x09. The Pointer Authentication instructions + /// trapped are: + /// + /// AUTDA, AUTDB, AUTDZA, AUTDZB, AUTIA, AUTIA1716, AUTIASP, AUTIAZ, AUTIB, AUTIB1716, + /// AUTIBSP, AUTIBZ, AUTIZA, AUTIZB, PACGA, PACDA, PACDB, PACDZA, PACDZB, PACIA, + /// PACIA1716, PACIASP, PACIAZ, PACIB, PACIB1716, PACIBSP, PACIBZ, PACIZA, PACIZB. + /// RETAA, RETAB, BRAA, BRAB, BLRAA, BLRAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ. + /// ERETAA, ERETAB, LDRAA, and LDRAB. + API OFFSET(41) NUMBITS(1) [ + EnableTrapPointerAuthInstToEl2 = 0, + DisableTrapPointerAuthInstToEl2 = 1 + ], + + /// Trap registers holding "key" values for Pointer Authentication. Traps accesses to the + /// following registers from EL1 to EL2, when EL2 is enabled in the current Security state, + /// reported using EC syndrome value 0x18: + /// + /// APIAKeyLo_EL1, APIAKeyHi_EL1, APIBKeyLo_EL1, APIBKeyHi_EL1, APDAKeyLo_EL1, + /// APDAKeyHi_EL1, APDBKeyLo_EL1, APDBKeyHi_EL1, APGAKeyLo_EL1, and APGAKeyHi_EL1. + APK OFFSET(40) NUMBITS(1) [ + EnableTrapPointerAuthKeyRegsToEl2 = 0, + DisableTrapPointerAuthKeyRegsToEl2 = 1, + ], + + /// Route synchronous External abort exceptions to EL2. + /// if 0: This control does not cause exceptions to be routed from EL0 and EL1 to EL2. + /// if 1: Route synchronous External abort exceptions from EL0 and EL1 to EL2, when EL2 is + /// enabled in the current Security state, if not routed to EL3. + TEA OFFSET(37) NUMBITS(1) [ + DisableTrapSyncExtAbortsToEl2 = 0, + EnableTrapSyncExtAbortsToEl2 = 1, + ], + + /// EL2 Host. Enables a configuration where a Host Operating System is running in EL2, and + /// the Host Operating System's applications are running in EL0. + E2H OFFSET(34) NUMBITS(1) [ + DisableOsAtEl2 = 0, + EnableOsAtEl2 = 1 + ], + + /// Execution state control for lower Exception levels: + /// + /// 0 Lower levels are all AArch32. + /// 1 The Execution state for EL1 is AArch64. The Execution state for EL0 is determined by + /// the current value of PSTATE.nRW when executing at EL0. + /// + /// If all lower Exception levels cannot use AArch32 then this bit is RAO/WI. + /// + /// In an implementation that includes EL3, when SCR_EL3.NS==0, the PE behaves as if this + /// bit has the same value as the SCR_EL3.RW bit for all purposes other than a direct read + /// or write access of HCR_EL2. + /// + /// The RW bit is permitted to be cached in a TLB. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this + /// field behaves as 1 for all purposes other than a direct read of the value of this bit. + RW OFFSET(31) NUMBITS(1) [ + AllLowerELsAreAarch32 = 0, + EL1IsAarch64 = 1 + ], + + /// Trap General Exceptions, from EL0. + /// + /// If enabled: + /// - When EL2 is not enabled in the current Security state, this control has no effect on + /// execution at EL0. + /// + /// - When EL2 is enabled in the current Security state, in all cases: + /// + /// - All exceptions that would be routed to EL1 are routed to EL2. + /// - If EL1 is using AArch64, the SCTLR_EL1.M field is treated as being 0 for all + /// purposes other than returning the result of a direct read of SCTLR_EL1. + /// - If EL1 is using AArch32, the SCTLR.M field is treated as being 0 for all + /// purposes other than returning the result of a direct read of SCTLR. + /// - All virtual interrupts are disabled. + /// - Any IMPLEMENTATION DEFINED mechanisms for signaling virtual interrupts are + /// disabled. + /// - An exception return to EL1 is treated as an illegal exception return. + /// - The MDCR_EL2.{TDRA, TDOSA, TDA, TDE} fields are treated as being 1 for all + /// purposes other than returning the result of a direct read of MDCR_EL2. + /// + /// - In addition, when EL2 is enabled in the current Security state, if: + /// + /// - HCR_EL2.E2H is 0, the Effective values of the HCR_EL2.{FMO, IMO, AMO} fields + /// are 1. + /// - HCR_EL2.E2H is 1, the Effective values of the HCR_EL2.{FMO, IMO, AMO} fields + /// are 0. + /// + /// - For further information on the behavior of this bit when E2H is 1, see 'Behavior of + /// HCR_EL2.E2H'. + TGE OFFSET(27) NUMBITS(1) [ + DisableTrapGeneralExceptionsToEl2 = 0, + EnableTrapGeneralExceptionsToEl2 = 1, + ], + + /// Default Cacheability. + /// + /// 0 This control has no effect on the Non-secure EL1&0 translation regime. + /// + /// 1 In Non-secure state: + /// - When EL1 is using AArch64, the PE behaves as if the value of the SCTLR_EL1.M field + /// is 0 for all purposes other than returning the value of a direct read of SCTLR_EL1. + /// + /// - When EL1 is using AArch32, the PE behaves as if the value of the SCTLR.M field is 0 + /// for all purposes other than returning the value of a direct read of SCTLR. + /// + /// - The PE behaves as if the value of the HCR_EL2.VM field is 1 for all purposes other + /// than returning the value of a direct read of HCR_EL2. + /// + /// - The memory type produced by stage 1 of the EL1&0 translation regime is Normal + /// Non-Shareable, Inner Write-Back Read-Allocate Write-Allocate, Outer Write-Back + /// Read-Allocate Write-Allocate. + /// + /// This field has no effect on the EL2, EL2&0, and EL3 translation regimes. + /// + /// This field is permitted to be cached in a TLB. + /// + /// In an implementation that includes EL3, when the value of SCR_EL3.NS is 0 the PE behaves + /// as if this field is 0 for all purposes other than a direct read or write access of + /// HCR_EL2. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this + /// field behaves as 0 for all purposes other than a direct read of the value of this field. + DC OFFSET(12) NUMBITS(1) [], + + /// Physical SError interrupt routing. + /// - If bit is 1 when executing at any Exception level, and EL2 is enabled in the current + /// 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) [], + + /// Physical IRQ Routing. + /// + /// If this bit is 0: + /// - When executing at Exception levels below EL2, and EL2 is enabled in the current + /// Security state: + /// - When the value of HCR_EL2.TGE is 0, Physical IRQ interrupts are not taken to EL2. + /// - When the value of HCR_EL2.TGE is 1, Physical IRQ interrupts are taken to EL2 + /// unless they are routed to EL3. + /// - Virtual IRQ interrupts are disabled. + /// + /// If this bit is 1: + /// - When executing at any Exception level, and EL2 is enabled in the current Security + /// state: + /// - Physical IRQ interrupts are taken to EL2, unless they are routed to EL3. + /// - When the value of HCR_EL2.TGE is 0, then Virtual IRQ interrupts are enabled. + /// + /// If EL2 is enabled in the current Security state, and the value of HCR_EL2.TGE is 1: + /// - Regardless of the value of the IMO bit, physical IRQ Interrupts target EL2 unless + /// they are routed to EL3. + /// - When FEAT_VHE is not implemented, or if HCR_EL2.E2H is 0, this field behaves as 1 + /// for all purposes other than a direct read of the value of this bit. + /// - When FEAT_VHE is implemented and HCR_EL2.E2H is 1, this field behaves as 0 for all + /// purposes other than a direct read of the value of this bit. + /// + /// For more information, see 'Asynchronous exception routing'. + IMO OFFSET(4) NUMBITS(1) [ + DisableVirtualIRQ = 0, + EnableVirtualIRQ = 1, + ], + + /// Physical FIQ Routing. + /// If this bit is 0: + /// - When executing at Exception levels below EL2, and EL2 is enabled in the current + /// Security state: + /// - When the value of HCR_EL2.TGE is 0, Physical FIQ interrupts are not taken to EL2. + /// - When the value of HCR_EL2.TGE is 1, Physical FIQ interrupts are taken to EL2 + /// unless they are routed to EL3. + /// - Virtual FIQ interrupts are disabled. + /// + /// If this bit is 1: + /// - When executing at any Exception level, and EL2 is enabled in the current Security + /// state: + /// - Physical FIQ interrupts are taken to EL2, unless they are routed to EL3. + /// - When HCR_EL2.TGE is 0, then Virtual FIQ interrupts are enabled. + /// + /// If EL2 is enabled in the current Security state and the value of HCR_EL2.TGE is 1: + /// - Regardless of the value of the FMO bit, physical FIQ Interrupts target EL2 unless + /// they are routed to EL3. + /// - When FEAT_VHE is not implemented, or if HCR_EL2.E2H is 0, this field behaves as 1 + /// for all purposes other than a direct read of the value of this bit. + /// - When FEAT_VHE is implemented and HCR_EL2.E2H is 1, this field behaves as 0 for all + /// purposes other than a direct read of the value of this bit. + /// + /// For more information, see 'Asynchronous exception routing'. + FMO OFFSET(3) NUMBITS(1) [ + DisableVirtualFIQ = 0, + EnableVirtualFIQ = 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: + /// + /// 0 This control has no effect on the operation of data cache invalidate by set/way + /// instructions. + /// + /// 1 Data cache invalidate by set/way instructions perform a data cache clean and + /// invalidate by set/way. + /// + /// When the value of this bit is 1: + /// + /// AArch32: DCISW performs the same invalidation as a DCCISW instruction. + /// + /// AArch64: DC ISW performs the same invalidation as a DC CISW instruction. + /// + /// This bit can be implemented as RES 1. + /// + /// In an implementation that includes EL3, when the value of SCR_EL3.NS is 0 the PE behaves + /// as if this field is 0 for all purposes other than a direct read or write access of + /// HCR_EL2. + /// + /// 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) [], + + /// 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: + /// + /// 0 EL1&0 stage 2 address translation disabled. + /// 1 EL1&0 stage 2 address translation enabled. + /// + /// When the value of this bit is 1, data cache invalidate instructions executed at EL1 perform + /// a data cache clean and invalidate. For the invalidate by set/way instruction this behavior + /// applies regardless of the value of the HCR_EL2.SWIO bit. + /// + /// This bit is permitted to be cached in a TLB. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this + /// field behaves as 0 for all purposes other than a direct read of the value of this field. + VM OFFSET(0) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = HCR_EL2::Register; + + sys_coproc_read_raw!(u64, "HCR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = HCR_EL2::Register; + + sys_coproc_write_raw!(u64, "HCR_EL2", "x"); +} + +pub const HCR_EL2: Reg = Reg {}; diff --git a/src/registers/id_aa64mmfr0_el1.rs b/src/registers/id_aa64mmfr0_el1.rs new file mode 100644 index 0000000..933a6ec --- /dev/null +++ b/src/registers/id_aa64mmfr0_el1.rs @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! AArch64 Memory Model Feature Register 0 - EL1 +//! +//! Provides information about the implemented memory model and memory +//! management support in AArch64 state. + +use tock_registers::{interfaces::Readable, register_bitfields}; + +register_bitfields! {u64, + pub ID_AA64MMFR0_EL1 [ + /// Support for 4KiB memory translation granule size. Defined values are: + /// + /// 0000 4KiB granule supported. + /// 1111 4KiB granule not supported. + /// + /// All other values are reserved. + TGran4 OFFSET(28) NUMBITS(4) [ + Supported = 0b0000, + NotSupported = 0b1111 + ], + + /// Support for 64KiB memory translation granule size. Defined values are: + /// + /// 0000 64KiB granule supported. + /// 1111 64KiB granule not supported. + /// + /// All other values are reserved. + TGran64 OFFSET(24) NUMBITS(4) [ + Supported = 0b0000, + NotSupported = 0b1111 + ], + + /// Support for 16KiB memory translation granule size. Defined values are: + /// + /// 0001 16KiB granule supported. + /// 0000 16KiB granule not supported. + /// + /// All other values are reserved. + TGran16 OFFSET(20) NUMBITS(4) [ + Supported = 0b0001, + NotSupported = 0b0000 + ], + + /// Number of bits supported in the ASID: + /// + /// 0000 ASIDs are 8 bits. + /// 0010 ASIDs are 16 bits. + /// + /// All other values are reserved. + ASIDBits OFFSET(4) NUMBITS(4) [ + Bits_8 = 0b0000, + Bits_16 = 0b0010 + ], + + /// Physical Address range supported. Defined values are: + /// + /// 0000 32 bits, 4GiB. + /// 0001 36 bits, 64GiB. + /// 0010 40 bits, 1TiB. + /// 0011 42 bits, 4TiB. + /// 0100 44 bits, 16TiB. + /// 0101 48 bits, 256TiB. + /// 0110 52 bits, 4PiB. + /// + /// All other values are reserved. + /// + /// The value 0110 is permitted only if the implementation includes ARMv8.2-LPA, otherwise + /// it is reserved. + PARange OFFSET(0) NUMBITS(4) [ + Bits_32 = 0b0000, + Bits_36 = 0b0001, + Bits_40 = 0b0010, + Bits_42 = 0b0011, + Bits_44 = 0b0100, + Bits_48 = 0b0101, + Bits_52 = 0b0110 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = ID_AA64MMFR0_EL1::Register; + + sys_coproc_read_raw!(u64, "ID_AA64MMFR0_EL1", "x"); +} + +pub const ID_AA64MMFR0_EL1: Reg = Reg {}; diff --git a/src/registers/lr.rs b/src/registers/lr.rs new file mode 100644 index 0000000..78b8795 --- /dev/null +++ b/src/registers/lr.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Alban Seurat + +//! The link register + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + read_raw!(u64, "lr", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + write_raw!(u64, "lr", "x"); +} + +pub const LR: Reg = Reg {}; diff --git a/src/registers/macros.rs b/src/registers/macros.rs new file mode 100644 index 0000000..536670d --- /dev/null +++ b/src/registers/macros.rs @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +macro_rules! __read_raw { + ($width:ty, $asm_instr:tt, $asm_reg_name:tt, $asm_width:tt) => { + /// Reads the raw bits of the CPU register. + #[inline] + fn get(&self) -> $width { + match () { + #[cfg(target_arch = "aarch64")] + () => { + let reg; + unsafe { + core::arch::asm!(concat!($asm_instr, " {reg:", $asm_width, "}, ", $asm_reg_name), reg = out(reg) reg, options(nomem, nostack)); + } + reg + } + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + }; +} + +macro_rules! __write_raw { + ($width:ty, $asm_instr:tt, $asm_reg_name:tt, $asm_width:tt) => { + /// Writes raw bits to the CPU register. + #[cfg_attr(not(target_arch = "aarch64"), allow(unused_variables))] + #[inline] + fn set(&self, value: $width) { + match () { + #[cfg(target_arch = "aarch64")] + () => { + unsafe { + core::arch::asm!(concat!($asm_instr, " ", $asm_reg_name, ", {reg:", $asm_width, "}"), reg = in(reg) value, options(nomem, nostack)) + } + } + + #[cfg(not(target_arch = "aarch64"))] + () => unimplemented!(), + } + } + }; +} + +/// Raw read from system coprocessor registers. +macro_rules! sys_coproc_read_raw { + ($width:ty, $asm_reg_name:tt, $asm_width:tt) => { + __read_raw!($width, "mrs", $asm_reg_name, $asm_width); + }; +} + +/// Raw write to system coprocessor registers. +macro_rules! sys_coproc_write_raw { + ($width:ty, $asm_reg_name:tt, $asm_width:tt) => { + __write_raw!($width, "msr", $asm_reg_name, $asm_width); + }; +} + +/// Raw read from (ordinary) registers. +macro_rules! read_raw { + ($width:ty, $asm_reg_name:tt, $asm_width:tt) => { + __read_raw!($width, "mov", $asm_reg_name, $asm_width); + }; +} +/// Raw write to (ordinary) registers. +macro_rules! write_raw { + ($width:ty, $asm_reg_name:tt, $asm_width:tt) => { + __write_raw!($width, "mov", $asm_reg_name, $asm_width); + }; +} diff --git a/src/registers/mair_el1.rs b/src/registers/mair_el1.rs new file mode 100644 index 0000000..478a7c7 --- /dev/null +++ b/src/registers/mair_el1.rs @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Erik Verbruggen + +//! Memory Attribute Indirection Register - EL1 +//! +//! Provides the memory attribute encodings corresponding to the possible AttrIndx values in a +//! Long-descriptor format translation table entry for stage 1 translations at EL1. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub MAIR_EL1 [ + /// Attribute 7 + Attr7_Normal_Outer OFFSET(60) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr7_Device OFFSET(56) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr7_Normal_Inner OFFSET(56) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 6 + Attr6_Normal_Outer OFFSET(52) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr6_Device OFFSET(48) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr6_Normal_Inner OFFSET(48) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 5 + Attr5_Normal_Outer OFFSET(44) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr5_Device OFFSET(40) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr5_Normal_Inner OFFSET(40) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 4 + Attr4_Normal_Outer OFFSET(36) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr4_Device OFFSET(32) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr4_Normal_Inner OFFSET(32) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 3 + Attr3_Normal_Outer OFFSET(28) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr3_Device OFFSET(24) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr3_Normal_Inner OFFSET(24) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 2 + Attr2_Normal_Outer OFFSET(20) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr2_Device OFFSET(16) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr2_Normal_Inner OFFSET(16) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 1 + Attr1_Normal_Outer OFFSET(12) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr1_Device OFFSET(8) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr1_Normal_Inner OFFSET(8) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 0 + Attr0_Normal_Outer OFFSET(4) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr0_Device OFFSET(0) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr0_Normal_Inner OFFSET(0) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = MAIR_EL1::Register; + + sys_coproc_read_raw!(u64, "MAIR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = MAIR_EL1::Register; + + sys_coproc_write_raw!(u64, "MAIR_EL1", "x"); +} + +pub const MAIR_EL1: Reg = Reg {}; diff --git a/src/registers/mair_el2.rs b/src/registers/mair_el2.rs new file mode 100644 index 0000000..859cada --- /dev/null +++ b/src/registers/mair_el2.rs @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Erik Verbruggen +// - Bradley Landherr + +//! Memory Attribute Indirection Register - EL2 +//! +//! Provides the memory attribute encodings corresponding to the possible AttrIndx values in a +//! Long-descriptor format translation table entry for stage 1 translations at EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub MAIR_EL2 [ + /// Attribute 7 + Attr7_Normal_Outer OFFSET(60) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr7_Device OFFSET(56) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr7_Normal_Inner OFFSET(56) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 6 + Attr6_Normal_Outer OFFSET(52) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr6_Device OFFSET(48) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr6_Normal_Inner OFFSET(48) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 5 + Attr5_Normal_Outer OFFSET(44) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr5_Device OFFSET(40) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr5_Normal_Inner OFFSET(40) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 4 + Attr4_Normal_Outer OFFSET(36) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr4_Device OFFSET(32) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr4_Normal_Inner OFFSET(32) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 3 + Attr3_Normal_Outer OFFSET(28) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr3_Device OFFSET(24) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr3_Normal_Inner OFFSET(24) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 2 + Attr2_Normal_Outer OFFSET(20) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr2_Device OFFSET(16) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr2_Normal_Inner OFFSET(16) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 1 + Attr1_Normal_Outer OFFSET(12) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr1_Device OFFSET(8) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr1_Normal_Inner OFFSET(8) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + + /// Attribute 0 + Attr0_Normal_Outer OFFSET(4) NUMBITS(4) [ + Device = 0b0000, + + WriteThrough_Transient_WriteAlloc = 0b0001, + WriteThrough_Transient_ReadAlloc = 0b0010, + WriteThrough_Transient_ReadWriteAlloc = 0b0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ], + Attr0_Device OFFSET(0) NUMBITS(8) [ + nonGathering_nonReordering_noEarlyWriteAck = 0b0000_0000, + nonGathering_nonReordering_EarlyWriteAck = 0b0000_0100, + nonGathering_Reordering_EarlyWriteAck = 0b0000_1000, + Gathering_Reordering_EarlyWriteAck = 0b0000_1100 + ], + Attr0_Normal_Inner OFFSET(0) NUMBITS(4) [ + WriteThrough_Transient = 0x0000, + WriteThrough_Transient_WriteAlloc = 0x0001, + WriteThrough_Transient_ReadAlloc = 0x0010, + WriteThrough_Transient_ReadWriteAlloc = 0x0011, + + NonCacheable = 0b0100, + WriteBack_Transient_WriteAlloc = 0b0101, + WriteBack_Transient_ReadAlloc = 0b0110, + WriteBack_Transient_ReadWriteAlloc = 0b0111, + + WriteThrough_NonTransient = 0b1000, + WriteThrough_NonTransient_WriteAlloc = 0b1001, + WriteThrough_NonTransient_ReadAlloc = 0b1010, + WriteThrough_NonTransient_ReadWriteAlloc = 0b1011, + + WriteBack_NonTransient = 0b1100, + WriteBack_NonTransient_WriteAlloc = 0b1101, + WriteBack_NonTransient_ReadAlloc = 0b1110, + WriteBack_NonTransient_ReadWriteAlloc = 0b1111 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = MAIR_EL2::Register; + + sys_coproc_read_raw!(u64, "MAIR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = MAIR_EL2::Register; + + sys_coproc_write_raw!(u64, "MAIR_EL2", "x"); +} + +pub const MAIR_EL2: Reg = Reg {}; diff --git a/src/registers/midr_el1.rs b/src/registers/midr_el1.rs new file mode 100644 index 0000000..10082e1 --- /dev/null +++ b/src/registers/midr_el1.rs @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Main ID Register - EL1 +//! +//! Provides identification information for the processor, including an implementer code for the +//! device and a device ID number. + +use tock_registers::{interfaces::Readable, register_bitfields}; + +register_bitfields! {u64, + pub MIDR_EL1 [ + /// The Implementer code. This field must hold an implementer code that has been assigned by + /// Arm. Assigned codes include the following: + /// + /// Hex representation Implementer + /// 0x00 Reserved for software use + /// 0xC0 Ampere Computing + /// 0x41 Arm Limited + /// 0x42 Broadcom Corporation + /// 0x43 Cavium Inc. + /// 0x44 Digital Equipment Corporation + /// 0x46 Fujitsu Ltd. + /// 0x49 Infineon Technologies AG + /// 0x4D Motorola or Freescale Semiconductor Inc. + /// 0x4E NVIDIA Corporation + /// 0x50 Applied Micro Circuits Corporation + /// 0x51 Qualcomm Inc. + /// 0x56 Marvell International Ltd. + /// 0x69 Intel Corporation + /// + /// Arm can assign codes that are not published in this manual. All values not assigned by + /// Arm are reserved and must not be used. + Implementer OFFSET(24) NUMBITS(8) [ + Reserved = 0x00, + Ampere = 0xC0, + Arm = 0x41, + Broadcom = 0x42, + Cavium = 0x43, + DigitalEquipment = 0x44, + Fujitsu = 0x46, + Infineon = 0x49, + MotorolaOrFreescale = 0x4D, + NVIDIA = 0x4E, + AppliedMicroCircuits = 0x50, + Qualcomm = 0x51, + Marvell = 0x56, + Intel = 0x69 + ], + + /// An IMPLEMENTATION DEFINED variant number. Typically, this field is used to distinguish + /// between different product variants, or major revisions of a product. + Variant OFFSET(20) NUMBITS(4) [], + + /// The permitted values of this field are: + /// + /// 0001 Armv4. + /// 0010 Armv4T. + /// 0011 Armv5 (obsolete). + /// 0100 Armv5T. + /// 0101 Armv5TE. + /// 0110 Armv5TEJ. + /// 0111 Armv6. + /// 1111 Architectural features are individually identified in the ID_* registers, see ID + /// registers on page K14-8060. + /// + /// All other values are reserved. + Architecture OFFSET(16) NUMBITS(4) [ + Individual = 0b1111 + ], + + /// An IMPLEMENTATION DEFINED primary part number for the device. + /// + /// On processors implemented by Arm, if the top four bits of the primary part number are + /// 0x0 or 0x7, the variant and architecture are encoded differently. + PartNum OFFSET(4) NUMBITS(12) [], + + /// An IMPLEMENTATION DEFINED revision number for the device. + Revision OFFSET(0) NUMBITS(4) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = MIDR_EL1::Register; + + sys_coproc_read_raw!(u64, "MIDR_EL1", "x"); +} + +pub const MIDR_EL1: Reg = Reg {}; diff --git a/src/registers/mpidr_el1.rs b/src/registers/mpidr_el1.rs new file mode 100644 index 0000000..7db1eba --- /dev/null +++ b/src/registers/mpidr_el1.rs @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Multiprocessor Affinity Register - EL1 +//! +//! In a multiprocessor system, provides an additional PE identification mechanism for scheduling +//! purposes. + +use tock_registers::interfaces::Readable; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "MPIDR_EL1", "x"); +} + +pub const MPIDR_EL1: Reg = Reg {}; diff --git a/src/registers/oslar_el1.rs b/src/registers/oslar_el1.rs new file mode 100644 index 0000000..0acd317 --- /dev/null +++ b/src/registers/oslar_el1.rs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Javier Alvarez + +//! OS Lock Access Register - EL1 +//! +//! Used to lock or unlock the OS Lock. +//! +//! AArch64 System register OSLAR_EL1 bits [31:0] are architecturally mapped to External register +//! OSLAR_EL1[31:0]. The OS Lock can also be locked or unlocked using DBGOSLAR. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub OSLAR_EL1 [ + /// On writes to OSLAR_EL1, bit[0] is copied to the OS Lock. + /// Use OSLSR_EL1.OSLK to check the current status of the lock. + OSLK OFFSET(0) NUMBITS(1) [ + Unlocked = 0, + Locked = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = OSLAR_EL1::Register; + + sys_coproc_read_raw!(u64, "OSLAR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = OSLAR_EL1::Register; + + sys_coproc_write_raw!(u64, "OSLAR_EL1", "x"); +} + +pub const OSLAR_EL1: Reg = Reg {}; diff --git a/src/registers/par_el1.rs b/src/registers/par_el1.rs new file mode 100644 index 0000000..e0c76a3 --- /dev/null +++ b/src/registers/par_el1.rs @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2021-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Physical Address Register - EL1 +//! +//! Returns the output address (OA) from an Address translation instruction that executed +//! successfully, or fault information if the instruction did not execute successfully. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub PAR_EL1 [ + /// Output address. The output address (OA) corresponding to the supplied input address. + /// This field returns address bits[47:12]. + /// + /// When ARMv8.2-LPA is implemented, and 52-bit addresses and a 64KB translation granule are + /// in use, the PA[51:48] bits form the upper part of the address value. Otherwise the + /// PA[51:48] bits are RES0. + /// + /// For implementations with fewer than 48 physical address bits, the corresponding upper + /// bits in this field are RES0. + /// + /// This field resets to an architecturally UNKNOWN value. + PA OFFSET(12) NUMBITS(36) [], + + /// Indicates whether the instruction performed a successful address translation. + /// + /// 0 Address translation completed successfully. + /// + /// 1 Address translation aborted. + /// + /// This field resets to an architecturally UNKNOWN value. + F OFFSET(0) NUMBITS(1) [ + TranslationSuccessfull = 0, + TranslationAborted = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = PAR_EL1::Register; + + sys_coproc_read_raw!(u64, "PAR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = PAR_EL1::Register; + + sys_coproc_write_raw!(u64, "PAR_EL1", "x"); +} + +pub const PAR_EL1: Reg = Reg {}; diff --git a/src/registers/scr_el3.rs b/src/registers/scr_el3.rs new file mode 100644 index 0000000..537ff9d --- /dev/null +++ b/src/registers/scr_el3.rs @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2019-2022 by the author(s) +// +// Author(s): +// - Berkus Decker + +//! Secure Configuration Register - EL3, page D12.2.99 of armv8arm. +//! Defines the configuration of the current Security state. It specifies: +//! • The Security state of EL0, EL1, and EL2. The Security state is either Secure or Non-secure. +//! • The Execution state at lower Exception levels. +//! • Whether IRQ, FIQ, SError interrupts, and External abort exceptions are taken to EL3. +//! • Whether various operations are trapped to EL3. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SCR_EL3 [ + /// Execution state control for lower Exception levels: + /// + /// 0 Lower levels are all AArch32. + /// 1 The next lower level is AArch64. + /// If EL2 is present: + /// The Execution state for EL2 is AArch64. + /// EL2 controls EL1 and EL0 behaviors. + /// If EL2 is not present: + /// The Execution state for EL1 is AArch64. + /// The Execution state for EL0 is determined by the current value of PSTATE.nRW when + /// executing at EL0. + /// + /// If all lower Exception levels cannot use AArch32 then this bit is RAO/WI. + /// + /// When SCR_EL3.{EEL2,NS}=={1,0}, this bit is treated as 1 for all purposes other than + /// reading or writing the register. + /// + /// The RW bit is permitted to be cached in a TLB. + RW OFFSET(10) NUMBITS(1) [ + AllLowerELsAreAarch32 = 0, + NextELIsAarch64 = 1 + ], + + /// Hypervisor Call Enable + /// + /// 0 The HVC instruction is undefined at all exception levels. + /// 1 The HVC instruction is enabled at EL1, EL2, or EL3. + HCE OFFSET(8) NUMBITS(1) [ + HvcDisabled = 0, + HvcEnabled = 1 + ], + + /// Secure Monitor call Disable + /// + /// 0 The SMC instruction is enabled at EL1, EL2, and EL3. + /// + /// 1 The SMC instruction is undefined at all exception levels. At EL1, in the Non-secure + /// state, the HCR_EL2.TSC bit has priority over this control. + SMD OFFSET(7) NUMBITS(1) [ + SmcEnabled = 0, + SmcDisabled = 1 + ], + + /// Non-secure bit. + /// 0 Indicates that EL0 and EL1 are in Secure state. + /// + /// 1 Indicates that Exception levels lower than EL3 are in Non-secure state, and so memory + /// accesses from those Exception levels cannot access Secure memory. + /// + /// When SCR_EL3.{EEL2, NS} == {1, 0}, then EL2 is using AArch64 and in Secure state. + NS OFFSET(0) NUMBITS(1) [ + Secure = 0, + NonSecure = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SCR_EL3::Register; + + sys_coproc_read_raw!(u64, "SCR_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SCR_EL3::Register; + + sys_coproc_write_raw!(u64, "SCR_EL3", "x"); +} + +pub const SCR_EL3: Reg = Reg {}; diff --git a/src/registers/sctlr_el1.rs b/src/registers/sctlr_el1.rs new file mode 100644 index 0000000..8ba4025 --- /dev/null +++ b/src/registers/sctlr_el1.rs @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! System Control Register - EL1 +//! +//! Provides top level control of the system, including its memory system, at EL1 and EL0. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SCTLR_EL1 [ + /// Traps EL0 execution of cache maintenance instructions to EL1, from AArch64 state only. + /// + /// 0 Any attempt to execute a DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU + /// instruction at EL0 using AArch64 is trapped to EL1. + /// 1 This control does not cause any instructions to be trapped. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + /// + /// If the Point of Coherency is before any level of data cache, it is IMPLEMENTATION DEFINED whether + /// the execution of any data or unified cache clean, or clean and invalidate instruction that operates by + /// VA to the point of coherency can be trapped when the value of this control is 1. + /// + /// If the Point of Unification is before any level of data cache, it is IMPLEMENTATION DEFINED whether + /// the execution of any data or unified cache clean by VA to the point of unification instruction can be + /// trapped when the value of this control is 1. + /// + /// If the Point of Unification is before any level of instruction cache, it is IMPLEMENTATION DEFINED + /// whether the execution of any instruction cache invalidate by VA to the point of unification + /// instruction can be trapped when the value of this control is 1. + UCI OFFSET(26) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Endianness of data accesses at EL1, and stage 1 translation table walks in the EL1&0 translation regime. + /// + /// 0 Explicit data accesses at EL1, and stage 1 translation table walks in the EL1&0 + /// translation regime are little-endian. + /// 1 Explicit data accesses at EL1, and stage 1 translation table walks in the EL1&0 + /// translation regime are big-endian. + /// + /// If an implementation does not provide Big-endian support at Exception Levels higher than EL0, this + /// bit is RES 0. + /// + /// If an implementation does not provide Little-endian support at Exception Levels higher than EL0, + /// this bit is RES 1. + /// + /// The EE bit is permitted to be cached in a TLB. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on the PE. + EE OFFSET(25) NUMBITS(1) [ + LittleEndian = 0, + BigEndian = 1, + ], + + /// Endianness of data accesses at EL0. + /// + /// 0 Explicit data accesses at EL0 are little-endian. + /// + /// 1 Explicit data accesses at EL0 are big-endian. + /// + /// If an implementation only supports Little-endian accesses at EL0 then this bit is RES 0. This option + /// is not permitted when SCTLR_EL1.EE is RES 1. + /// + /// If an implementation only supports Big-endian accesses at EL0 then this bit is RES 1. This option is + /// not permitted when SCTLR_EL1.EE is RES 0. + /// + /// This bit has no effect on the endianness of LDTR , LDTRH , LDTRSH , LDTRSW , STTR , and STTRH instructions + /// executed at EL1. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + E0E OFFSET(24) NUMBITS(1) [ + LittleEndian = 0, + BigEndian = 1, + ], + + /// Write permission implies XN (Execute-never). For the EL1&0 translation regime, this bit can force + /// all memory regions that are writable to be treated as XN. + /// + /// 0 This control has no effect on memory access permissions. + /// + /// 1 Any region that is writable in the EL1&0 translation regime is forced to XN for accesses + /// from software executing at EL1 or EL0. + /// + /// The WXN bit is permitted to be cached in a TLB. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on the PE. + WXN OFFSET(19) NUMBITS(1) [ + Disable = 0, + Enable = 1, + ], + + /// Traps EL0 execution of WFE instructions to EL1, from both Execution states. + /// + /// 0 Any attempt to execute a WFE instruction at EL0 is trapped to EL1, if the instruction + /// would otherwise have caused the PE to enter a low-power state. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// In AArch32 state, the attempted execution of a conditional WFE instruction is only trapped if the + /// instruction passes its condition code check. + /// + /// **Note:** + /// + /// Since a WFE or WFI can complete at any time, even without a Wakeup event, the traps on WFE of + /// WFI are not guaranteed to be taken, even if the WFE or WFI is executed when there is no Wakeup + /// event. The only guarantee is that if the instruction does not complete in finite time in the + /// absence of a Wakeup event, the trap will be taken. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + NTWE OFFSET(18) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Traps EL0 executions of WFI instructions to EL1, from both execution states: + /// + /// 0 Any attempt to execute a WFI instruction at EL0 is trapped EL1, if the instruction would + /// otherwise have caused the PE to enter a low-power state. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// In AArch32 state, the attempted execution of a conditional WFI instruction is only trapped if the + /// instruction passes its condition code check. + /// + /// **Note:** + /// + /// Since a WFE or WFI can complete at any time, even without a Wakeup event, the traps on WFE of + /// WFI are not guaranteed to be taken, even if the WFE or WFI is executed when there is no Wakeup + /// event. The only guarantee is that if the instruction does not complete in finite time in the + /// absence of a Wakeup event, the trap will be taken. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + NTWI OFFSET(16) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Traps EL0 accesses to the CTR_EL0 to EL1, from AArch64 state only. + /// + /// 0 Accesses to the CTR_EL0 from EL0 using AArch64 are trapped to EL1. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + UCT OFFSET(15) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Traps EL0 execution of DC ZVA instructions to EL1, from AArch64 state only. + /// + /// 0 Any attempt to execute a DC ZVA instruction at EL0 using AArch64 is trapped to EL1. + /// Reading DCZID_EL0.DZP from EL0 returns 1, indicating that DC ZVA instructions + /// are not supported. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + DZE OFFSET(14) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Instruction access Cacheability control, for accesses at EL0 and + /// EL1: + /// + /// 0 All instruction access to Normal memory from EL0 and EL1 are Non-cacheable for all + /// levels of instruction and unified cache. + /// + /// If the value of SCTLR_EL1.M is 0, instruction accesses from stage 1 of the EL1&0 + /// translation regime are to Normal, Outer Shareable, Inner Non-cacheable, Outer + /// Non-cacheable memory. + /// + /// 1 This control has no effect on the Cacheability of instruction access to Normal memory + /// from EL0 and EL1. + /// + /// If the value of SCTLR_EL1.M is 0, instruction accesses from stage 1 of the EL1&0 + /// translation regime are to Normal, Outer Shareable, Inner Write-Through, Outer + /// Write-Through memory. + /// + /// When the value of the HCR_EL2.DC bit is 1, then instruction access to Normal memory from + /// EL0 and EL1 are Cacheable regardless of the value of the SCTLR_EL1.I bit. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on the PE. + /// + /// When this register has an architecturally-defined reset value, this field resets to 0. + I OFFSET(12) NUMBITS(1) [ + NonCacheable = 0, + Cacheable = 1 + ], + + /// User Mask Access. Traps EL0 execution of MSR and MRS instructions that access the + /// PSTATE.{D, A, I, F} masks to EL1, from AArch64 state only. + /// + /// 0 Any attempt at EL0 using AArch64 to execute an MRS , MSR(register) , or MSR(immediate) + /// instruction that accesses the [`DAIF`](module@super::super::DAIF) is trapped to EL1. + /// + /// 1 This control does not cause any instructions to be trapped. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on execution at EL0. + UMA OFFSET(9) NUMBITS(1) [ + Trap = 0, + DontTrap = 1, + ], + + /// Non-aligned access. This bit controls generation of Alignment faults at EL1 and EL0 under certain conditions. + /// + /// LDAPR, LDAPRH, LDAPUR, LDAPURH, LDAPURSH, LDAPURSW, LDAR, LDARH, LDLAR, LDLARH, + /// STLLR, STLLRH, STLR, STLRH, STLUR, and STLURH will or will not generate an Alignment + /// fault if all bytes being accessed are not within a single 16-byte quantity, + /// aligned to 16 bytes for accesses. + NAA OFFSET(6) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// 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 EL1 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. + SA OFFSET(3) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// Cacheability control, for data accesses. + /// + /// 0 All data access to Normal memory from EL0 and EL1, and all Normal memory accesses to + /// the EL1&0 stage 1 translation tables, are Non-cacheable for all levels of data and + /// unified cache. + /// + /// 1 This control has no effect on the Cacheability of: + /// - Data access to Normal memory from EL0 and EL1. + /// - Normal memory accesses to the EL1&0 stage 1 translation tables. + /// + /// When the value of the HCR_EL2.DC bit is 1, the PE ignores SCLTR.C. This means that + /// Non-secure EL0 and Non-secure EL1 data accesses to Normal memory are Cacheable. + /// + /// When ARMv8.1-VHE is implemented, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on the PE. + /// + /// When this register has an architecturally-defined reset value, this field resets to 0. + C OFFSET(2) NUMBITS(1) [ + NonCacheable = 0, + Cacheable = 1 + ], + + /// Alignment check enable. This is the enable bit for Alignment fault checking at EL1 and EL0. + /// + /// Instructions that load or store one or more registers, other than load/store exclusive + /// and load-acquire/store-release, will or will not check that the address being accessed + /// is aligned to the size of the data element(s) being accessed depending on this flag. + /// + /// Load/store exclusive and load-acquire/store-release instructions have an alignment check + /// regardless of the value of the A bit. + A OFFSET(1) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// MMU enable for EL1 and EL0 stage 1 address translation. Possible values of this bit are: + /// + /// 0 EL1 and EL0 stage 1 address translation disabled. + /// - See the SCTLR_EL1.I field for the behavior of instruction accesses to Normal memory. + /// + /// 1 EL1 and EL0 stage 1 address translation enabled. + M OFFSET(0) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SCTLR_EL1::Register; + + sys_coproc_read_raw!(u64, "SCTLR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SCTLR_EL1::Register; + + sys_coproc_write_raw!(u64, "SCTLR_EL1", "x"); +} + +pub const SCTLR_EL1: Reg = Reg {}; diff --git a/src/registers/sctlr_el2.rs b/src/registers/sctlr_el2.rs new file mode 100644 index 0000000..3e4a760 --- /dev/null +++ b/src/registers/sctlr_el2.rs @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Bradley Landherr + +//! System Control Register - EL2 +//! +//! Provides top level control of the system, including its memory system, at EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SCTLR_EL2 [ + + /// Exception endianness. The possible values are: + /// + /// 0 Little endian. + /// 1 Big endian. + EE OFFSET(25) NUMBITS(1) [ + Little = 0, + Big = 1 + ], + + /// Force treatment of all memory regions with write permissions as XN. + /// The possible values are: + /// + /// 0 Regions with write permissions are not forced XN. This is the reset value. + /// 1 Regions with write permissions are forced XN. + WXN OFFSET(19) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// Instruction Cache Control, two possible values: + /// + /// 0 All instruction access to Normal memory from EL2 are Non-cacheable for all + /// levels of instruction and unified cache. + /// + /// If the value of SCTLR_EL2.M is 0, instruction accesses from stage 1 of the EL2 or EL2&0 + /// translation regime are to Normal, Outer Shareable, Inner Non-cacheable, Outer + /// Non-cacheable memory. + /// + /// 1 This control has no effect on the Cacheability of instruction access to Normal memory + /// from EL2 and, when EL2 is enabled in the current Security state and + /// HCR_EL2.{E2H, TGE} == {1, 1}, instruction access to Normal memory from EL0. + /// + /// If the value of SCTLR_EL2.M is 0, instruction accesses from stage 1 of the EL2&0 + /// translation regime are to Normal, Outer Shareable, Inner Write-Through, Outer + /// Write-Through memory. + /// + /// When EL2 is disabled, and the value of HCR_EL2.{E2H, TGE} is {1, 1}, this bit + /// has no effect on the PE. + /// + /// On a Warm reset, in a system where the PE resets into EL2, this field resets to 0. + I OFFSET(12) NUMBITS(1) [ + NonCacheable = 0, + Cacheable = 1 + ], + + /// SP Alignment check enable. + /// + /// When set to 1, if a load or store instruction executed at EL2 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. + SA OFFSET(3) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// Cacheability control, for data accesses. + /// + /// 0 The following are Non-cacheable for all levels of data and unified cache: + /// - Data accesses to Normal memory from EL2. + /// - When HCR_EL2.{E2H, TGE} != {1, 1}, Normal memory accesses to the EL2 translation tables. + /// - When EL2 is enabled in the current Security state and HCR_EL2.{E2H, TGE} == {1, 1}: + /// - Data accesses to Normal memory from EL0. + /// - Normal memory accesses to the EL2&0 translation tables. + /// + /// 1 This control has no effect on the Cacheability of: + /// - Data access to Normal memory from EL2. + /// - When HCR_EL2.{E2H, TGE} != {1, 1}, Normal memory accesses to the EL2 translation tables. + /// - When EL2 is enabled in the current Security state and HCR_EL2.{E2H, TGE} == {1, 1}: + /// - Data accesses to Normal memory from EL0. + /// - Normal memory accesses to the EL2&0 translation tables. + /// + /// When EL2 is disabled in the current Security state or HCR_EL2.{E2H, TGE} != {1, 1}, + /// this bit has no effect on the EL1&0 translation regime. + /// + /// On a Warm reset, in a system where the PE resets into EL2, this field resets to 0. + C OFFSET(2) NUMBITS(1) [ + NonCacheable = 0, + Cacheable = 1 + ], + + /// Alignment check enable. This is the enable bit for Alignment fault checking at EL2 and, + /// when EL2 is enabled in the current Security state and HCR_EL2.{E2H, TGE} == {1, 1}, EL0. + /// + /// Instructions that load or store one or more registers, other than load/store exclusive + /// and load-acquire/store-release, will or will not check that the address being accessed + /// is aligned to the size of the data element(s) being accessed depending on this flag. + /// + /// Load/store exclusive and load-acquire/store-release instructions have an alignment check + /// regardless of the value of the A bit. + A OFFSET(1) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ], + + /// MMU enable for EL2 or EL2&0 stage 1 address translation. Possible values of this bit are: + /// + /// 0 - When HCR_EL2.{E2H, TGE} != {1, 1}, EL2 stage 1 address translation disabled. + /// - When HCR_EL2.{E2H, TGE} == {1, 1}, EL2&0 stage 1 address translation disabled. + /// - See the SCTLR_EL2.I field for the behavior of instruction accesses to Normal memory. + /// + /// 1 - When HCR_EL2.{E2H, TGE} != {1, 1}, EL2 stage 1 address translation enabled. + /// - When HCR_EL2.{E2H, TGE} == {1, 1}, EL2&0 stage 1 address translation enabled. + /// + /// On a Warm reset, in a system where the PE resets into EL2, this field resets to 0. + M OFFSET(0) NUMBITS(1) [ + Disable = 0, + Enable = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SCTLR_EL2::Register; + + sys_coproc_read_raw!(u64, "SCTLR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SCTLR_EL2::Register; + + sys_coproc_write_raw!(u64, "SCTLR_EL2", "x"); +} + +pub const SCTLR_EL2: Reg = Reg {}; diff --git a/src/registers/sp.rs b/src/registers/sp.rs new file mode 100644 index 0000000..5065320 --- /dev/null +++ b/src/registers/sp.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! The stack pointer + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + read_raw!(u64, "sp", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + write_raw!(u64, "sp", "x"); +} + +pub const SP: Reg = Reg {}; diff --git a/src/registers/sp_el0.rs b/src/registers/sp_el0.rs new file mode 100644 index 0000000..074120a --- /dev/null +++ b/src/registers/sp_el0.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! The stack pointer - EL0 +//! +//! Holds the stack pointer associated with EL0. At higher Exception levels, this is used as the +//! current stack pointer when the value of SPSel.SP is 0. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "SP_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "SP_EL0", "x"); +} + +pub const SP_EL0: Reg = Reg {}; diff --git a/src/registers/sp_el1.rs b/src/registers/sp_el1.rs new file mode 100644 index 0000000..640b3aa --- /dev/null +++ b/src/registers/sp_el1.rs @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! The stack pointer - EL1 +//! +//! Holds the stack pointer associated with EL1. When executing at EL1, the value of SPSel.SP +//! determines the current stack pointer: +//! +//! SPSel.SP | current stack pointer +//! -------------------------------- +//! 0 | SP_EL0 +//! 1 | SP_EL1 + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "SP_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "SP_EL1", "x"); +} + +pub const SP_EL1: Reg = Reg {}; diff --git a/src/registers/spsel.rs b/src/registers/spsel.rs new file mode 100644 index 0000000..f90b1f5 --- /dev/null +++ b/src/registers/spsel.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Stack Pointer Select +//! +//! Allows the Stack Pointer to be selected between SP_EL0 and SP_ELx. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SPSel [ + /// Stack pointer to use. Possible values of this bit are: + /// + /// 0 Use SP_EL0 at all Exception levels. + /// 1 Use SP_ELx for Exception level ELx. + /// + /// When this register has an architecturally-defined reset value, this field resets to 1. + SP OFFSET(0) NUMBITS(1) [ + EL0 = 0, + ELx = 1 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SPSel::Register; + + sys_coproc_read_raw!(u64, "SPSEL", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SPSel::Register; + + sys_coproc_write_raw!(u64, "SPSEL", "x"); +} + +#[allow(non_upper_case_globals)] +pub const SPSel: Reg = Reg {}; diff --git a/src/registers/spsr_el1.rs b/src/registers/spsr_el1.rs new file mode 100644 index 0000000..958f19f --- /dev/null +++ b/src/registers/spsr_el1.rs @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Saved Program Status Register - EL1 +//! +//! Holds the saved process state when an exception is taken to EL1. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SPSR_EL1 [ + /// Negative condition flag. + /// + /// Set to the value of the N condition flag on taking an exception to EL1, and copied to + /// the N condition flag on executing an exception return operation in EL1. + /// + /// Set to 1 if the result of the last flag-setting instruction was negative. + N OFFSET(31) NUMBITS(1) [], + + /// Zero condition flag. + /// + /// Set to the value of the Z condition flag on taking an exception to EL1, and copied to + /// the Z condition flag on executing an exception return operation in EL1. + /// + /// Set to 1 if the result of the last flag-setting instruction was zero, and to 0 + /// otherwise. A result of zero often indicates an equal result from a comparison. + Z OFFSET(30) NUMBITS(1) [], + + /// Carry condition flag. + /// + /// Set to the value of the C condition flag on taking an exception to EL1, and copied to + /// the C condition flag on executing an exception return operation in EL1. + /// + /// Set to 1 if the last flag-setting instruction resulted in a carry condition, for example + /// an unsigned overflow on an addition. + C OFFSET(29) NUMBITS(1) [], + + /// Overflow condition flag. + /// + /// Set to the value of the V condition flag on taking an exception to EL1, and copied to + /// the V condition flag on executing an exception return operation in EL1. + /// + /// Set to 1 if the last flag-setting instruction resulted in an overflow condition, for + /// example a signed overflow on an addition. + V OFFSET(28) NUMBITS(1) [], + + /// Software step. Shows the value of PSTATE.SS immediately before the exception was taken. + SS OFFSET(21) NUMBITS(1) [], + + /// Illegal Execution state bit. Shows the value of PSTATE.IL immediately before the + /// exception was taken. + IL OFFSET(20) NUMBITS(1) [], + + /// Process state D mask. The possible values of this bit are: + /// + /// 0 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are not masked. + /// + /// 1 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are masked. + /// + /// When the target Exception level of the debug exception is higher than the current + /// Exception level, the exception is not masked by this bit. + D OFFSET(9) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// SError interrupt mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + A OFFSET(8) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// IRQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + I OFFSET(7) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// FIQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + F OFFSET(6) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// AArch64 state (Exception level and selected SP) that an exception was taken from. The + /// possible values are: + /// + /// M[3:0] | State + /// -------------- + /// 0b0000 | EL0t + /// 0b0100 | EL1t + /// 0b0101 | EL1h + /// + /// Other values are reserved, and returning to an Exception level that is using AArch64 + /// with a reserved value in this field is treated as an illegal exception return. + /// + /// The bits in this field are interpreted as follows: + /// - M[3:2] holds the Exception Level. + /// - M[1] is unused and is RES 0 for all non-reserved values. + /// - M[0] is used to select the SP: + /// - 0 means the SP is always SP0. + /// - 1 means the exception SP is determined by the EL. + M OFFSET(0) NUMBITS(4) [ + EL0t = 0b0000, + EL1t = 0b0100, + EL1h = 0b0101 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SPSR_EL1::Register; + + sys_coproc_read_raw!(u64, "SPSR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SPSR_EL1::Register; + + sys_coproc_write_raw!(u64, "SPSR_EL1", "x"); +} + +pub const SPSR_EL1: Reg = Reg {}; diff --git a/src/registers/spsr_el2.rs b/src/registers/spsr_el2.rs new file mode 100644 index 0000000..9493c3e --- /dev/null +++ b/src/registers/spsr_el2.rs @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Saved Program Status Register - EL2 +//! +//! Holds the saved process state when an exception is taken to EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SPSR_EL2 [ + /// Negative condition flag. + /// + /// Set to the value of the N condition flag on taking an exception to EL2, and copied to + /// the N condition flag on executing an exception return operation in EL2. + /// + /// Set to 1 if the result of the last flag-setting instruction was negative. + N OFFSET(31) NUMBITS(1) [], + + /// Zero condition flag. + /// + /// Set to the value of the Z condition flag on taking an exception to EL2, and copied to + /// the Z condition flag on executing an exception return operation in EL2. + /// + /// Set to 1 if the result of the last flag-setting instruction was zero, and to 0 + /// otherwise. A result of zero often indicates an equal result from a comparison. + Z OFFSET(30) NUMBITS(1) [], + + /// Carry condition flag. + /// + /// Set to the value of the C condition flag on taking an exception to EL2, and copied to + /// the C condition flag on executing an exception return operation in EL2. + /// + /// Set to 1 if the last flag-setting instruction resulted in a carry condition, for example + /// an unsigned overflow on an addition. + C OFFSET(29) NUMBITS(1) [], + + /// Overflow condition flag. + /// + /// Set to the value of the V condition flag on taking an exception to EL2, and copied to + /// the V condition flag on executing an exception return operation in EL2. + /// + /// Set to 1 if the last flag-setting instruction resulted in an overflow condition, for + /// example a signed overflow on an addition. + V OFFSET(28) NUMBITS(1) [], + + /// Software step. Shows the value of PSTATE.SS immediately before the exception was taken. + SS OFFSET(21) NUMBITS(1) [], + + /// Illegal Execution state bit. Shows the value of PSTATE.IL immediately before the + /// exception was taken. + IL OFFSET(20) NUMBITS(1) [], + + /// Process state D mask. The possible values of this bit are: + /// + /// 0 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are not masked. + /// + /// 1 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are masked. + /// + /// When the target Exception level of the debug exception is higher than the current + /// Exception level, the exception is not masked by this bit. + D OFFSET(9) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// SError interrupt mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + A OFFSET(8) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// IRQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + I OFFSET(7) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// FIQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + F OFFSET(6) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// AArch64 state (Exception level and selected SP) that an exception was taken from. The + /// possible values are: + /// + /// M[3:0] | State + /// -------------- + /// 0b0000 | EL0t + /// 0b0100 | EL1t + /// 0b0101 | EL1h + /// 0b1000 | EL2t + /// 0b1001 | EL2h + /// + /// Other values are reserved, and returning to an Exception level that is using AArch64 + /// with a reserved value in this field is treated as an illegal exception return. + /// + /// The bits in this field are interpreted as follows: + /// - M[3:2] holds the Exception Level. + /// - M[1] is unused and is RES 0 for all non-reserved values. + /// - M[0] is used to select the SP: + /// - 0 means the SP is always SP0. + /// - 1 means the exception SP is determined by the EL. + M OFFSET(0) NUMBITS(4) [ + EL0t = 0b0000, + EL1t = 0b0100, + EL1h = 0b0101, + EL2t = 0b1000, + EL2h = 0b1001 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SPSR_EL2::Register; + + sys_coproc_read_raw!(u64, "SPSR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SPSR_EL2::Register; + + sys_coproc_write_raw!(u64, "SPSR_EL2", "x"); +} + +pub const SPSR_EL2: Reg = Reg {}; diff --git a/src/registers/spsr_el3.rs b/src/registers/spsr_el3.rs new file mode 100644 index 0000000..857d9c0 --- /dev/null +++ b/src/registers/spsr_el3.rs @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Berkus Decker + +//! Saved Program Status Register - EL3 +//! +//! Holds the saved process state when an exception is taken to EL3. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub SPSR_EL3 [ + /// Negative condition flag. + /// + /// Set to the value of the N condition flag on taking an exception to EL3, and copied to + /// the N condition flag on executing an exception return operation in EL3. + /// + /// Set to 1 if the result of the last flag-setting instruction was negative. + N OFFSET(31) NUMBITS(1) [], + + /// Zero condition flag. + /// + /// Set to the value of the Z condition flag on taking an exception to EL3, and copied to + /// the Z condition flag on executing an exception return operation in EL3. + /// + /// Set to 1 if the result of the last flag-setting instruction was zero, and to 0 + /// otherwise. A result of zero often indicates an equal result from a comparison. + Z OFFSET(30) NUMBITS(1) [], + + /// Carry condition flag. + /// + /// Set to the value of the C condition flag on taking an exception to EL3, and copied to + /// the C condition flag on executing an exception return operation in EL3. + /// + /// Set to 1 if the last flag-setting instruction resulted in a carry condition, for example + /// an unsigned overflow on an addition. + C OFFSET(29) NUMBITS(1) [], + + /// Overflow condition flag. + /// + /// Set to the value of the V condition flag on taking an exception to EL3, and copied to + /// the V condition flag on executing an exception return operation in EL3. + /// + /// Set to 1 if the last flag-setting instruction resulted in an overflow condition, for + /// example a signed overflow on an addition. + V OFFSET(28) NUMBITS(1) [], + + /// Software step. Shows the value of PSTATE.SS immediately before the exception was taken. + SS OFFSET(21) NUMBITS(1) [], + + /// Illegal Execution state bit. Shows the value of PSTATE.IL immediately before the + /// exception was taken. + IL OFFSET(20) NUMBITS(1) [], + + /// Process state D mask. The possible values of this bit are: + /// + /// 0 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are not masked. + /// + /// 1 Watchpoint, Breakpoint, and Software Step exceptions targeted at the current Exception + /// level are masked. + /// + /// When the target Exception level of the debug exception is higher than the current + /// Exception level, the exception is not masked by this bit. + D OFFSET(9) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// SError interrupt mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + A OFFSET(8) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// IRQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + I OFFSET(7) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// FIQ mask bit. The possible values of this bit are: + /// + /// 0 Exception not masked. + /// 1 Exception masked. + F OFFSET(6) NUMBITS(1) [ + Unmasked = 0, + Masked = 1 + ], + + /// AArch64 state (Exception level and selected SP) that an exception was taken from. The + /// possible values are: + /// + /// M[3:0] | State + /// -------------- + /// 0b0000 | EL0t + /// 0b0100 | EL1t + /// 0b0101 | EL1h + /// 0b1000 | EL2t + /// 0b1001 | EL2h + /// + /// Other values are reserved, and returning to an Exception level that is using AArch64 + /// with a reserved value in this field is treated as an illegal exception return. + /// + /// The bits in this field are interpreted as follows: + /// - M[3:2] holds the Exception Level. + /// - M[1] is unused and is RES 0 for all non-reserved values. + /// - M[0] is used to select the SP: + /// - 0 means the SP is always SP0. + /// - 1 means the exception SP is determined by the EL. + M OFFSET(0) NUMBITS(4) [ + EL0t = 0b0000, + EL1t = 0b0100, + EL1h = 0b0101, + EL2t = 0b1000, + EL2h = 0b1001 + ] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = SPSR_EL3::Register; + + sys_coproc_read_raw!(u64, "SPSR_EL3", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = SPSR_EL3::Register; + + sys_coproc_write_raw!(u64, "SPSR_EL3", "x"); +} + +pub const SPSR_EL3: Reg = Reg {}; diff --git a/src/registers/tcr_el1.rs b/src/registers/tcr_el1.rs new file mode 100644 index 0000000..8ab1308 --- /dev/null +++ b/src/registers/tcr_el1.rs @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Translation Control Register - EL1 +//! +//! The control register for stage 1 of the EL1&0 translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TCR_EL1 [ + /// When ARMv8.3-PAuth is implemented: + /// Controls the use of the top byte of instruction addresses for address matching. + /// 0 TCR_EL1.TBI1 applies to Instruction and Data accesses. + /// 1 TCR_EL1.TBI1 applies to Data accesses only. + /// This affects addresses where the address would be translated by tables pointed + /// to by TTBR1_EL1. This field resets to an architecturally UNKNOWN value. + /// Otherwise: + /// Reserved, RES0. + TBID1 OFFSET(52) NUMBITS(1) [], + + /// When ARMv8.3-PAuth is implemented: + /// Controls the use of the top byte of instruction addresses for address matching. + /// 0 TCR_EL1.TBI0 applies to Instruction and Data accesses. + /// 1 TCR_EL1.TBI0 applies to Data accesses only. + /// This affects addresses where the address would be translated by tables pointed + /// to by TTBR0_EL1. This field resets to an architecturally UNKNOWN value. + /// Otherwise: + /// Reserved, RES0. + TBID0 OFFSET(51) NUMBITS(1) [], + + /// Top Byte ignored - indicates whether the top byte of an address is used for address + /// match for the TTBR1_EL1 region, or ignored and used for tagged addresses. Defined values + /// are: + /// + /// 0 Top Byte used in the address calculation. + /// + /// 1 Top Byte ignored in the address calculation. + /// + /// This affects addresses generated in EL0 and EL1 using AArch64 where the address would be + /// translated by tables pointed to by TTBR1_EL1. It has an effect whether the EL1&0 + /// translation regime is enabled or not. + /// + /// If ARMv8.3-PAuth is implemented and TCR_EL1.TBID1 is 1, then this field only applies to + /// Data accesses. + /// Otherwise, if the value of TBI1 is 1 and bit [55] of the target address to be stored to + /// the PC is 0, then bits[63:56] of that target address are also set to 0 before the + /// address is stored in the PC, in the following cases: + /// + /// • A branch or procedure return within EL0 or EL1. + /// • An exception taken to EL1. + /// • An exception return to EL0 or EL1. + TBI1 OFFSET(38) NUMBITS(1) [ + Used = 0, + Ignored = 1 + ], + + /// Top Byte ignored - indicates whether the top byte of an address is used for address + /// match for the TTBR0_EL1 region, or ignored and used for tagged addresses. Defined values + /// are: + /// + /// 0 Top Byte used in the address calculation. + /// + /// 1 Top Byte ignored in the address calculation. + /// + /// This affects addresses generated in EL0 and EL1 using AArch64 where the address would be + /// translated by tables pointed to by TTBR0_EL1. It has an effect whether the EL1&0 + /// translation regime is enabled or not. + /// + /// If ARMv8.3-PAuth is implemented and TCR_EL1.TBID0 is 1, then this field only applies to + /// Data accesses. + /// Otherwise, if the value of TBI0 is 1 and bit [55] of the target address to be stored to + /// the PC is 0, then bits[63:56] of that target address are also set to 0 before the + /// address is stored in the PC, in the following cases: + /// + /// • A branch or procedure return within EL0 or EL1. + /// • An exception taken to EL1. + /// • An exception return to EL0 or EL1. + TBI0 OFFSET(37) NUMBITS(1) [ + Used = 0, + Ignored = 1 + ], + + /// ASID Size. Defined values are: + /// + /// 0 8 bit - the upper 8 bits of TTBR0_EL1 and TTBR1_EL1 are ignored by hardware for every + /// purpose except reading back the register, and are treated as if they are all + /// zeros for when used for allocation and matching entries in the TLB. + /// + /// 1 16 bit - the upper 16 bits of TTBR0_EL1 and TTBR1_EL1 are used for allocation and + /// matching in the TLB. + /// + /// If the implementation has only 8 bits of ASID, this field is RES0. + AS OFFSET(36) NUMBITS(1) [ + ASID8Bits = 0, + ASID16Bits = 1 + ], + + /// Intermediate Physical Address Size. + /// + /// 000 32 bits, 4GiB. + /// 001 36 bits, 64GiB. + /// 010 40 bits, 1TiB. + /// 011 42 bits, 4TiB. + /// 100 44 bits, 16TiB. + /// 101 48 bits, 256TiB. + /// 110 52 bits, 4PiB + /// + /// Other values are reserved. + /// + /// The reserved values behave in the same way as the 101 or 110 encoding, but software must + /// not rely on this property as the behavior of the reserved values might change in a + /// future revision of the architecture. + /// + /// The value 110 is permitted only if ARMv8.2-LPA is implemented and the translation + /// granule size is 64KiB. + /// + /// In an implementation that supports 52-bit PAs, if the value of this field is not 110 , + /// then bits[51:48] of every translation table base address for the stage of translation + /// controlled by TCR_EL1 are 0000. + IPS OFFSET(32) NUMBITS(3) [ + Bits_32 = 0b000, + Bits_36 = 0b001, + Bits_40 = 0b010, + Bits_42 = 0b011, + Bits_44 = 0b100, + Bits_48 = 0b101, + Bits_52 = 0b110 + ], + + /// Granule size for the TTBR1_EL1. + /// + /// 10 4KiB + /// 01 16KiB + /// 11 64KiB + /// + /// Other values are reserved. + /// + /// If the value is programmed to either a reserved value, or a size that has not been + /// implemented, then the hardware will treat the field as if it has been programmed to an + /// IMPLEMENTATION DEFINED choice of the sizes that has been implemented for all purposes + /// other than the value read back from this register. + /// + /// It is IMPLEMENTATION DEFINED whether the value read back is the value programmed or the + /// value that corresponds to the size chosen. + TG1 OFFSET(30) NUMBITS(2) [ + KiB_4 = 0b10, + KiB_16 = 0b01, + KiB_64 = 0b11 + ], + + /// Shareability attribute for memory associated with translation table walks using + /// TTBR1_EL1. + /// + /// 00 Non-shareable + /// 10 Outer Shareable + /// 11 Inner Shareable + /// + /// Other values are reserved. + SH1 OFFSET(28) NUMBITS(2) [ + None = 0b00, + Outer = 0b10, + Inner = 0b11 + ], + + /// Outer cacheability attribute for memory associated with translation table walks using + /// TTBR1_EL1. + /// + /// 00 Normal memory, Outer Non-cacheable + /// + /// 01 Normal memory, Outer Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Outer Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Outer Write-Back Read-Allocate No Write-Allocate Cacheable + ORGN1 OFFSET(26) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + /// Inner cacheability attribute for memory associated with translation + /// table walks using TTBR1_EL1. + /// + /// 00 Normal memory, Inner Non-cacheable + /// + /// 01 Normal memory, Inner Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Inner Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Inner Write-Back Read-Allocate No Write-Allocate Cacheable + IRGN1 OFFSET(24) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + /// Translation table walk disable for translations using TTBR1_EL1. This bit controls + /// whether a translation table walk is performed on a TLB miss, for an address that is + /// translated using TTBR1_EL1. The encoding of this bit is: + /// + /// 0 Perform translation table walks using TTBR1_EL1. + /// + /// 1 A TLB miss on an address that is translated using TTBR1_EL1 generates a Translation + /// fault. No translation table walk is performed. + EPD1 OFFSET(23) NUMBITS(1) [ + EnableTTBR1Walks = 0, + DisableTTBR1Walks = 1 + ], + + /// Selects whether TTBR0_EL1 or TTBR1_EL1 defines the ASID. The encoding of this bit is: + /// + /// 0 TTBR0_EL1.ASID defines the ASID. + /// 1 TTBR1_EL1.ASID defines the ASID. + A1 OFFSET(22) NUMBITS(1) [ + TTBR0 = 0, + TTBR1 = 1 + ], + + /// The size offset of the memory region addressed by TTBR1_EL1. The region size is + /// 2^(64-T1SZ) bytes. + /// + /// The maximum and minimum possible values for T1SZ depend on the level of translation + /// table and the memory translation granule size, as described in the AArch64 Virtual + /// Memory System Architecture chapter. + /// + /// This field resets to an architecturally UNKNOWN value. + T1SZ OFFSET(16) NUMBITS(6) [], + + /// Granule size for the TTBR0_EL1. + /// + /// 00 4KiB + /// 01 64KiB + /// 10 16KiB + /// + /// Other values are reserved. + /// + /// If the value is programmed to either a reserved value, or a size that has not been + /// implemented, then the hardware will treat the field as if it has been programmed to an + /// IMPLEMENTATION DEFINED choice of the sizes that has been implemented for all purposes + /// other than the value read back from this register. + /// + /// It is IMPLEMENTATION DEFINED whether the value read back is the value programmed or the + /// value that corresponds to the size chosen. + TG0 OFFSET(14) NUMBITS(2) [ + KiB_4 = 0b00, + KiB_16 = 0b10, + KiB_64 = 0b01 + ], + + /// Shareability attribute for memory associated with translation table walks using + /// TTBR0_EL1. + /// + /// 00 Non-shareable + /// 10 Outer Shareable + /// 11 Inner Shareable + /// + /// Other values are reserved. + SH0 OFFSET(12) NUMBITS(2) [ + None = 0b00, + Outer = 0b10, + Inner = 0b11 + ], + + /// Outer cacheability attribute for memory associated with translation table walks using + /// TTBR0_EL1. + /// + /// 00 Normal memory, Outer Non-cacheable + /// + /// 01 Normal memory, Outer Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Outer Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Outer Write-Back Read-Allocate No Write-Allocate Cacheable + ORGN0 OFFSET(10) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + /// Inner cacheability attribute for memory associated with translation table walks using + /// TTBR0_EL1. + /// + /// 00 Normal memory, Inner Non-cacheable + /// + /// 01 Normal memory, Inner Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Inner Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Inner Write-Back Read-Allocate No Write-Allocate Cacheable + IRGN0 OFFSET(8) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + /// Translation table walk disable for translations using TTBR0_EL1. This bit controls + /// whether a translation table walk is performed on a TLB miss, for an address that is + /// translated using TTBR0_EL1. The encoding of this bit is: + /// + /// 0 Perform translation table walks using TTBR0_EL1. + /// + /// 1 A TLB miss on an address that is translated using TTBR0_EL1 generates a Translation + /// fault. No translation table walk is performed. + EPD0 OFFSET(7) NUMBITS(1) [ + EnableTTBR0Walks = 0, + DisableTTBR0Walks = 1 + ], + + /// The size offset of the memory region addressed by TTBR0_EL1. The region size is + /// 2^(64-T0SZ) bytes. + /// + /// The maximum and minimum possible values for T0SZ depend on the level of translation + /// table and the memory translation granule size, as described in the AArch64 Virtual + /// Memory System Architecture chapter. + T0SZ OFFSET(0) NUMBITS(6) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = TCR_EL1::Register; + + sys_coproc_read_raw!(u64, "TCR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TCR_EL1::Register; + + sys_coproc_write_raw!(u64, "TCR_EL1", "x"); +} + +pub const TCR_EL1: Reg = Reg {}; diff --git a/src/registers/tcr_el2.rs b/src/registers/tcr_el2.rs new file mode 100644 index 0000000..386ded0 --- /dev/null +++ b/src/registers/tcr_el2.rs @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Bradley Landherr + +//! Translation Control Register - EL2 +//! +//! The control register for stage 1 of the EL2, or EL2&0 translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TCR_EL2 [ + + /// Top Byte ignored - indicates whether the top byte of an address is used for address + /// match for the TTBR0_EL2 region, or ignored and used for tagged addresses. Defined values + /// are: + /// + /// 0 Top Byte used in the address calculation. + /// + /// 1 Top Byte ignored in the address calculation. + /// + /// This affects addresses generated in EL2 using AArch64 where the address would be + /// translated by tables pointed to by TTBR0_EL2. It has an effect whether the EL2, + /// or EL2&0, translation regime is enabled or not. + /// + /// If ARMv8.3-PAuth is implemented and TCR_EL2.TBID1 is 1, then this field only applies to + /// Data accesses. + /// + /// If the value of TBI is 1, then bits[63:56] of that target address are also set to 0 + /// before the address is stored in the PC, in the following cases: + /// + /// • A branch or procedure return within EL2. + /// • An exception taken to EL2. + /// • An exception return to EL2. + TBI OFFSET(20) NUMBITS(1) [ + Used = 0, + Ignored = 1 + ], + + /// Physical Address Size. + /// + /// 000 32 bits, 4GiB. + /// 001 36 bits, 64GiB. + /// 010 40 bits, 1TiB. + /// 011 42 bits, 4TiB. + /// 100 44 bits, 16TiB. + /// 101 48 bits, 256TiB. + /// 110 52 bits, 4PB + /// + /// Other values are reserved. + /// + /// The reserved values behave in the same way as the 101 or 110 encoding, but software must + /// not rely on this property as the behavior of the reserved values might change in a + /// future revision of the architecture. + /// + /// The value 110 is permitted only if ARMv8.2-LPA is implemented and the translation + /// granule size is 64KiB. + /// + /// In an implementation that supports 52-bit PAs, if the value of this field is not 110 , + /// then bits[51:48] of every translation table base address for the stage of translation + /// controlled by TCR_EL2 are 0000. + PS OFFSET(16) NUMBITS(3) [ + Bits_32 = 0b000, + Bits_36 = 0b001, + Bits_40 = 0b010, + Bits_42 = 0b011, + Bits_44 = 0b100, + Bits_48 = 0b101, + Bits_52 = 0b110 + ], + + /// Granule size for the TTBR0_EL2. + /// + /// 0b00 4KiB + /// 0b01 64KiB + /// 0b10 16KiB + /// + /// Other values are reserved. + /// + /// If the value is programmed to either a reserved value, or a size that has not been + /// implemented, then the hardware will treat the field as if it has been programmed to an + /// IMPLEMENTATION DEFINED choice of the sizes that has been implemented for all purposes + /// other than the value read back from this register. + /// + /// It is IMPLEMENTATION DEFINED whether the value read back is the value programmed or the + /// value that corresponds to the size chosen. + TG0 OFFSET(14) NUMBITS(2) [ + KiB_4 = 0b00, + KiB_64 = 0b01, + KiB_16 = 0b10 + ], + + /// Shareability attribute for memory associated with translation table walks using + /// TTBR0_EL2. + /// + /// 00 Non-shareable + /// 01 Reserved + /// 10 Outer Shareable + /// 11 Inner Shareable + /// + /// Other values are reserved. + SH0 OFFSET(12) NUMBITS(2) [ + None = 0b00, + Outer = 0b10, + Inner = 0b11 + ], + + /// Outer cacheability attribute for memory associated with translation table walks using + /// TTBR0_EL2. + /// + /// 00 Normal memory, Outer Non-cacheable + /// + /// 01 Normal memory, Outer Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Outer Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Outer Write-Back Read-Allocate No Write-Allocate Cacheable + ORGN0 OFFSET(10) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + /// Inner cacheability attribute for memory associated with translation table walks using + /// TTBR0_EL2. + /// + /// 00 Normal memory, Inner Non-cacheable + /// + /// 01 Normal memory, Inner Write-Back Read-Allocate Write-Allocate Cacheable + /// + /// 10 Normal memory, Inner Write-Through Read-Allocate No Write-Allocate Cacheable + /// + /// 11 Normal memory, Inner Write-Back Read-Allocate No Write-Allocate Cacheable + IRGN0 OFFSET(8) NUMBITS(2) [ + NonCacheable = 0b00, + WriteBack_ReadAlloc_WriteAlloc_Cacheable = 0b01, + WriteThrough_ReadAlloc_NoWriteAlloc_Cacheable = 0b10, + WriteBack_ReadAlloc_NoWriteAlloc_Cacheable = 0b11 + ], + + + /// The size offset of the memory region addressed by TTBR0_EL2. The region size is + /// 2^(64-T0SZ) bytes. + /// + /// The maximum and minimum possible values for T0SZ depend on the level of translation + /// table and the memory translation granule size, as described in the AArch64 Virtual + /// Memory System Architecture chapter. + T0SZ OFFSET(0) NUMBITS(6) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = TCR_EL2::Register; + + sys_coproc_read_raw!(u64, "TCR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TCR_EL2::Register; + + sys_coproc_write_raw!(u64, "TCR_EL2", "x"); +} + +pub const TCR_EL2: Reg = Reg {}; diff --git a/src/registers/tpidr_el0.rs b/src/registers/tpidr_el0.rs new file mode 100644 index 0000000..458aaa5 --- /dev/null +++ b/src/registers/tpidr_el0.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2020-2022 by the author(s) +// +// Author(s): +// - Erik Verbruggen + +//! Read/Write Software Thread ID Register - EL0. +//! +//! Provides a location where software executing at EL0 can store thread identifying information, +//! for OS management purposes. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "TPIDR_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "TPIDR_EL0", "x"); +} + +pub const TPIDR_EL0: Reg = Reg {}; diff --git a/src/registers/tpidr_el1.rs b/src/registers/tpidr_el1.rs new file mode 100644 index 0000000..7819a4e --- /dev/null +++ b/src/registers/tpidr_el1.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2020-2022 by the author(s) +// +// Author(s): +// - Erik Verbruggen + +//! Software Thread ID Register - EL1. +//! +//! Provides a location where software executing at EL1 can store thread identifying information, +//! for OS management purposes. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "TPIDR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "TPIDR_EL1", "x"); +} + +pub const TPIDR_EL1: Reg = Reg {}; diff --git a/src/registers/tpidrro_el0.rs b/src/registers/tpidrro_el0.rs new file mode 100644 index 0000000..612e898 --- /dev/null +++ b/src/registers/tpidrro_el0.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2020-2022 by the author(s) +// +// Author(s): +// - Erik Verbruggen + +//! Read-Only Software Thread ID Register - EL0. +//! +//! Provides a location where software executing at EL1 or higher can store thread identifying +//! information that is visible to software executing at EL0, for OS management purposes. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "TPIDRRO_EL0", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "TPIDRRO_EL0", "x"); +} + +pub const TPIDRRO_EL0: Reg = Reg {}; diff --git a/src/registers/ttbr0_el1.rs b/src/registers/ttbr0_el1.rs new file mode 100644 index 0000000..1307ab2 --- /dev/null +++ b/src/registers/ttbr0_el1.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Translation Table Base Register 0 - EL1 +//! +//! Holds the base address of the translation table for the initial lookup for stage 1 of the +//! translation of an address from the lower VA range in the EL1&0 translation regime, and other +//! information for this translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TTBR0_EL1 [ + /// An ASID for the translation table base address. The TCR_EL1.A1 field selects either + /// TTBR0_EL1.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 = TTBR0_EL1::Register; + + sys_coproc_read_raw!(u64, "TTBR0_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TTBR0_EL1::Register; + + sys_coproc_write_raw!(u64, "TTBR0_EL1", "x"); +} + +impl Reg { + #[inline(always)] + pub fn get_baddr(&self) -> u64 { + self.read(TTBR0_EL1::BADDR) << 1 + } + + #[inline(always)] + pub fn set_baddr(&self, addr: u64) { + self.write(TTBR0_EL1::BADDR.val(addr >> 1)); + } +} + +pub const TTBR0_EL1: Reg = Reg {}; diff --git a/src/registers/ttbr0_el2.rs b/src/registers/ttbr0_el2.rs new file mode 100644 index 0000000..737e470 --- /dev/null +++ b/src/registers/ttbr0_el2.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Bradley Landherr + +//! Translation Table Base Register 0 - EL2 +//! +//! Holds the base address of the translation table for the initial lookup for stage 1 of the +//! translation of an address from the lower VA range for accesses from EL2. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TTBR0_EL2 [ + /// Reserved + RES0 OFFSET(48) NUMBITS(16) [], + + /// Translation table base address + BADDR OFFSET(1) NUMBITS(48) [], + + /// Common not Private + CnP OFFSET(0) NUMBITS(1) [] + ] +} + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = TTBR0_EL2::Register; + + sys_coproc_read_raw!(u64, "TTBR0_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TTBR0_EL2::Register; + + sys_coproc_write_raw!(u64, "TTBR0_EL2", "x"); +} + +impl Reg { + #[inline(always)] + pub fn get_baddr(&self) -> u64 { + self.read(TTBR0_EL2::BADDR) << 1 + } + + #[inline(always)] + pub fn set_baddr(&self, addr: u64) { + self.write(TTBR0_EL2::BADDR.val(addr >> 1)); + } +} + +pub const TTBR0_EL2: Reg = Reg {}; diff --git a/src/registers/ttbr1_el1.rs b/src/registers/ttbr1_el1.rs new file mode 100644 index 0000000..0626189 --- /dev/null +++ b/src/registers/ttbr1_el1.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Translation Table Base Register 1 - EL1 +//! +//! 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 EL1&0 translation regime, and other +//! information for this translation regime. + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, +}; + +register_bitfields! {u64, + pub TTBR1_EL1 [ + /// An ASID for the translation table base address. The TCR_EL1.A1 field selects either + /// TTBR0_EL1.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_EL1::Register; + + sys_coproc_read_raw!(u64, "TTBR1_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = TTBR1_EL1::Register; + + sys_coproc_write_raw!(u64, "TTBR1_EL1", "x"); +} + +impl Reg { + #[inline(always)] + pub fn get_baddr(&self) -> u64 { + self.read(TTBR1_EL1::BADDR) << 1 + } + + #[inline(always)] + pub fn set_baddr(&self, addr: u64) { + self.write(TTBR1_EL1::BADDR.val(addr >> 1)); + } +} + +pub const TTBR1_EL1: Reg = Reg {}; diff --git a/src/registers/vbar_el1.rs b/src/registers/vbar_el1.rs new file mode 100644 index 0000000..cef722f --- /dev/null +++ b/src/registers/vbar_el1.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter + +//! Vector Base Address Register - EL1 +//! +//! Holds the vector base address for any exception that is taken to EL1. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "VBAR_EL1", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "VBAR_EL1", "x"); +} + +pub const VBAR_EL1: Reg = Reg {}; diff --git a/src/registers/vbar_el2.rs b/src/registers/vbar_el2.rs new file mode 100644 index 0000000..f624e97 --- /dev/null +++ b/src/registers/vbar_el2.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Copyright (c) 2018-2022 by the author(s) +// +// Author(s): +// - Andre Richter +// - Javier Alvarez + +//! Vector Base Address Register - EL2 +//! +//! Holds the vector base address for any exception that is taken to EL2. + +use tock_registers::interfaces::{Readable, Writeable}; + +pub struct Reg; + +impl Readable for Reg { + type T = u64; + type R = (); + + sys_coproc_read_raw!(u64, "VBAR_EL2", "x"); +} + +impl Writeable for Reg { + type T = u64; + type R = (); + + sys_coproc_write_raw!(u64, "VBAR_EL2", "x"); +} + +pub const VBAR_EL2: Reg = Reg {}; -- cgit v1.2.3