├── .cargo └── config.toml ├── .github ├── dependabot.yml └── workflows │ ├── package.yml │ ├── rust.yml │ └── web.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── aarch64-esr-web ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── js │ └── index.js ├── package-lock.json ├── package.json ├── src │ └── lib.rs ├── static │ ├── google2d2782625f584348.html │ ├── index.html │ ├── midr.html │ ├── smccc.html │ └── style.css └── webpack.config.js └── src ├── esr ├── abort.rs ├── breakpoint.rs ├── bti.rs ├── common.rs ├── fp.rs ├── hvc.rs ├── ld64b.rs ├── ldc.rs ├── mcr.rs ├── mod.rs ├── msr.rs ├── pauth.rs ├── serror.rs ├── sve.rs ├── tests.rs └── wf.rs ├── lib.rs ├── main.rs ├── midr.rs ├── smccc.rs └── smccc ├── arm.rs ├── common.rs ├── ffa.rs ├── hyp.rs ├── secure.rs └── tapp.rs /.cargo/config.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/aarch64-esr-decoder/ec0d67338d44d8432386f4658b09121a3c3fc93a/.cargo/config.toml -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | - package-ecosystem: "cargo" 8 | directory: "/aarch64-esr-web" 9 | schedule: 10 | interval: "weekly" 11 | - package-ecosystem: "npm" 12 | directory: "/aarch64-esr-web" 13 | schedule: 14 | interval: "weekly" 15 | - package-ecosystem: "github-actions" 16 | directory: "/" 17 | schedule: 18 | interval: "weekly" 19 | -------------------------------------------------------------------------------- /.github/workflows/package.yml: -------------------------------------------------------------------------------- 1 | name: Package 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | tags: ["*"] 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | cargo-deb-version: 2.0.2 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | target: 18 | - arm-unknown-linux-gnueabi 19 | - armv7-unknown-linux-gnueabihf 20 | - aarch64-unknown-linux-gnu 21 | - x86_64-unknown-linux-gnu 22 | include: 23 | - target: arm-unknown-linux-gnueabi 24 | binutils: binutils-arm-linux-gnueabi 25 | - target: armv7-unknown-linux-gnueabihf 26 | binutils: binutils-arm-linux-gnueabihf 27 | - target: aarch64-unknown-linux-gnu 28 | binutils: binutils-aarch64-linux-gnu 29 | 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Install dependencies 33 | run: sudo apt-get update && sudo apt-get install ${{ matrix.binutils }} 34 | - name: Toolchain 35 | uses: actions-rs/toolchain@v1 36 | with: 37 | toolchain: stable 38 | target: ${{ matrix.target }} 39 | override: true 40 | 41 | - name: Cache .cargo and target 42 | uses: actions/cache@v4 43 | with: 44 | path: | 45 | ~/.cargo/git 46 | ~/.cargo/registry 47 | target 48 | key: ${{ runner.os }}-${{ matrix.target }}-package-cargo-${{ hashFiles('**/Cargo.lock') }} 49 | - name: Cache cargo-deb and cross 50 | uses: actions/cache@v4 51 | with: 52 | path: | 53 | ~/.cargo/bin/cargo-deb 54 | ~/.cargo/bin/cross 55 | ~/.cargo/.crates.toml 56 | ~/.cargo/.crates2.json 57 | key: ${{ runner.os }}-cargo-bin-${{ env.cargo-deb-version }} 58 | 59 | - name: Install cargo-deb 60 | run: cargo install cargo-deb --version ${{ env.cargo-deb-version }} 61 | 62 | - name: Cross build 63 | uses: actions-rs/cargo@v1 64 | with: 65 | use-cross: true 66 | command: build 67 | args: --release --target ${{ matrix.target }} 68 | - name: Package 69 | run: cargo deb --target ${{ matrix.target }} --no-build 70 | 71 | - name: Upload package 72 | uses: actions/upload-artifact@v4 73 | with: 74 | name: debian-package-${{ matrix.target }} 75 | path: target/${{ matrix.target }}/debian/ 76 | 77 | release: 78 | name: Draft release 79 | runs-on: ubuntu-latest 80 | needs: build 81 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') 82 | steps: 83 | - name: Download packages 84 | uses: actions/download-artifact@v4 85 | - name: Parse tag for version 86 | id: parse_tag 87 | uses: actions-ecosystem/action-regex-match@v2 88 | with: 89 | text: ${{ github.ref }} 90 | regex: "^refs/tags/(.+)$" 91 | - name: Create draft release 92 | id: create_release 93 | uses: actions/create-release@v1 94 | env: 95 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions. 96 | with: 97 | tag_name: ${{ github.ref }} 98 | release_name: ${{ steps.parse_tag.outputs.group1 }} 99 | draft: true 100 | prerelease: false 101 | - name: Upload packages to release 102 | uses: shogo82148/actions-upload-release-asset@v1 103 | with: 104 | upload_url: ${{ steps.create_release.outputs.upload_url }} 105 | asset_path: "debian-package-*/aarch64-esr-decoder_*.deb" 106 | asset_content_type: application/vnd.debian.binary-package 107 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | 11 | jobs: 12 | build: 13 | permissions: 14 | checks: write 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Build 19 | run: cargo build 20 | - name: Run tests 21 | run: cargo test 22 | - name: Run clippy 23 | uses: actions-rs/clippy-check@v1 24 | with: 25 | token: ${{ secrets.GITHUB_TOKEN }} 26 | args: --all-features 27 | 28 | format: 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Format Rust code 33 | run: cargo fmt --all -- --check 34 | 35 | coverage: 36 | runs-on: ubuntu-latest 37 | env: 38 | RUSTC_BOOTSTRAP: 1 39 | steps: 40 | - uses: actions/checkout@v4 41 | - name: Install cargo-llvm-cov 42 | uses: taiki-e/install-action@v2 43 | with: 44 | tool: cargo-llvm-cov 45 | - name: Run tests with coverage 46 | run: cargo llvm-cov test --all-features --codecov --output-path codecov-report.json 47 | - name: Upload coverage to codecov.io 48 | uses: codecov/codecov-action@v5 49 | with: 50 | fail_ci_if_error: true 51 | files: codecov-report.json 52 | token: ${{ secrets.CODECOV_TOKEN }} 53 | -------------------------------------------------------------------------------- /.github/workflows/web.yml: -------------------------------------------------------------------------------- 1 | name: Web 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | 11 | jobs: 12 | build: 13 | permissions: 14 | contents: write 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Install wasm-pack 19 | uses: jetli/wasm-pack-action@v0.4.0 20 | - name: Build with wasm-pack 21 | working-directory: aarch64-esr-web 22 | run: wasm-pack build 23 | - name: NPM install and build 24 | working-directory: aarch64-esr-web 25 | run: | 26 | npm install 27 | npm run build 28 | - name: Deploy to GitHub Pages 29 | if: ${{ github.event_name == 'push' }} 30 | uses: JamesIves/github-pages-deploy-action@v4.7.3 31 | with: 32 | branch: gh-pages 33 | folder: aarch64-esr-web/dist 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.2.3 4 | 5 | ### New features 6 | 7 | - Added support for ISS decoding with RME extension. 8 | 9 | ## 0.2.2 10 | 11 | ### New features 12 | 13 | - Added support for decoding SMCCC function IDs. 14 | - Added support for MIDR and SMCCC to command-line tool. 15 | 16 | ## 0.2.1 17 | 18 | ### Bugfixes 19 | 20 | - Print long name for multi-bit fields in command-line app (they were only being printed for single 21 | bit fields). 22 | 23 | ### New features 24 | 25 | - Added support for decoding MIDR values too. 26 | - Added HVC and SMC ECs for `ESR_EL2`. 27 | 28 | ## 0.2.0 29 | 30 | ### Breaking changes 31 | 32 | - Removed `Decoded` struct, inlined its fields into `FieldInfo`. 33 | - `DecodeError` variants changed. 34 | - Added `long_name` to `FieldInfo` struct. 35 | 36 | ### Bugfixes 37 | 38 | - Added CRn field which was missing from MCR or MRC accesses. 39 | 40 | ### New features 41 | 42 | - Added ISS decoding for SVE exceptions. 43 | - Added ISS decoding for LD64B/ST64B\* exceptions. 44 | - Added ISS decoding for Branch Target Exception. 45 | - Added ISS decoding for HVC and SVC exceptions. 46 | - Added ISS decoding for MRS and MSR exceptions, including system register names. 47 | - Added ISS decoding for Pointer Authentication failures. 48 | - Added ISS decoding for floating-point exceptions. 49 | - Added ISS decoding for SError interrupts. 50 | - Added ISS decoding for Breakpoint, Watchpoint, Software Step and Vector Catch exceptions. 51 | 52 | ## 0.1.0 53 | 54 | Initial release. 55 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Community Guidelines 27 | 28 | This project follows 29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 30 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aarch64-esr-decoder" 7 | version = "0.2.3" 8 | dependencies = [ 9 | "bit_field", 10 | "thiserror", 11 | ] 12 | 13 | [[package]] 14 | name = "bit_field" 15 | version = "0.10.2" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" 18 | 19 | [[package]] 20 | name = "proc-macro2" 21 | version = "1.0.89" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" 24 | dependencies = [ 25 | "unicode-ident", 26 | ] 27 | 28 | [[package]] 29 | name = "quote" 30 | version = "1.0.35" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 33 | dependencies = [ 34 | "proc-macro2", 35 | ] 36 | 37 | [[package]] 38 | name = "syn" 39 | version = "2.0.87" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" 42 | dependencies = [ 43 | "proc-macro2", 44 | "quote", 45 | "unicode-ident", 46 | ] 47 | 48 | [[package]] 49 | name = "thiserror" 50 | version = "2.0.12" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 53 | dependencies = [ 54 | "thiserror-impl", 55 | ] 56 | 57 | [[package]] 58 | name = "thiserror-impl" 59 | version = "2.0.12" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 62 | dependencies = [ 63 | "proc-macro2", 64 | "quote", 65 | "syn", 66 | ] 67 | 68 | [[package]] 69 | name = "unicode-ident" 70 | version = "1.0.10" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" 73 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aarch64-esr-decoder" 3 | version = "0.2.3" 4 | authors = ["Andrew Walbran "] 5 | edition = "2018" 6 | license = "Apache-2.0" 7 | description = "A library and command-line utility for decoding aarch64 Exception Syndrome Register values." 8 | repository = "https://github.com/google/aarch64-esr-decoder/" 9 | keywords = ["aarch64", "esr"] 10 | categories = ["development-tools"] 11 | exclude = [".github/"] 12 | readme = "README.md" 13 | 14 | [dependencies] 15 | bit_field = "0.10.1" 16 | thiserror = "2.0.12" 17 | 18 | [package.metadata.deb] 19 | section = "devel" 20 | copyright = "Google LLC" 21 | extended-description = "" 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aarch64-esr-decoder 2 | 3 | [![crates.io page](https://img.shields.io/crates/v/aarch64-esr-decoder.svg)](https://crates.io/crates/aarch64-esr-decoder) 4 | [![docs.rs page](https://docs.rs/aarch64-esr-decoder/badge.svg)](https://docs.rs/aarch64-esr-decoder) 5 | 6 | A small utility for decoding aarch64 ESR register values. 7 | 8 | This is not an officially supported Google product. 9 | 10 | ## Usage 11 | 12 | Install a Debian package from the 13 | [latest release](https://github.com/google/aarch64-esr-decoder/releases/tag/0.2.0), install with 14 | `cargo install aarch64-esr-decoder`, or 15 | [try the web version](https://google.github.io/aarch64-esr-decoder/). 16 | 17 | For the command-line version, just pass the ESR value you're interested in as a parameter, in 18 | decimal or hexadecimal: 19 | 20 | ``` 21 | $ aarch64-esr-decoder 0x96000050 22 | ESR 0x00000000000000000000000096000050: 23 | # Data Abort taken without a change in Exception level 24 | 37..63 RES0: 0x0000000 0b000000000000000000000000000 25 | 32..36 ISS2: 0x00 0b00000 26 | 26..31 EC: 0x25 0b100101 27 | # Data Abort taken without a change in Exception level 28 | 25 IL: true 29 | # 32-bit instruction trapped 30 | 00..24 ISS: 0x0000050 0b0000000000000000001010000 31 | 24 ISV: false 32 | # No valid instruction syndrome 33 | 14..23 RES0: 0x000 0b0000000000 34 | 13 VNCR: false 35 | 11..12 SET: 0x0 0b00 36 | # Recoverable state (UER) 37 | 10 FnV: false 38 | # FAR is valid 39 | 09 EA: false 40 | 08 CM: false 41 | 07 S1PTW: false 42 | 06 WnR: true 43 | # Abort caused by writing to memory 44 | 00..05 DFSC: 0x10 0b010000 45 | # Synchronous External abort, not on translation table walk or hardware update of translation table. 46 | ``` 47 | 48 | For long field names, add `-v`. 49 | 50 | ## License 51 | 52 | Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 53 | 54 | ## Contributing 55 | 56 | If you want to contribute to the project, see details of 57 | [how we accept contributions](CONTRIBUTING.md). 58 | -------------------------------------------------------------------------------- /aarch64-esr-web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | /target 4 | /pkg 5 | /wasm-pack.log 6 | -------------------------------------------------------------------------------- /aarch64-esr-web/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aarch64-esr-decoder" 7 | version = "0.2.3" 8 | dependencies = [ 9 | "bit_field", 10 | "thiserror", 11 | ] 12 | 13 | [[package]] 14 | name = "aarch64-esr-web" 15 | version = "0.1.0" 16 | dependencies = [ 17 | "aarch64-esr-decoder", 18 | "console_error_panic_hook", 19 | "wasm-bindgen", 20 | "wasm-bindgen-test", 21 | "web-sys", 22 | ] 23 | 24 | [[package]] 25 | name = "bit_field" 26 | version = "0.10.2" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" 29 | 30 | [[package]] 31 | name = "bumpalo" 32 | version = "3.13.0" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 35 | 36 | [[package]] 37 | name = "cc" 38 | version = "1.1.15" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" 41 | dependencies = [ 42 | "shlex", 43 | ] 44 | 45 | [[package]] 46 | name = "cfg-if" 47 | version = "1.0.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 50 | 51 | [[package]] 52 | name = "console_error_panic_hook" 53 | version = "0.1.7" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 56 | dependencies = [ 57 | "cfg-if", 58 | "wasm-bindgen", 59 | ] 60 | 61 | [[package]] 62 | name = "js-sys" 63 | version = "0.3.77" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 66 | dependencies = [ 67 | "once_cell", 68 | "wasm-bindgen", 69 | ] 70 | 71 | [[package]] 72 | name = "log" 73 | version = "0.4.19" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 76 | 77 | [[package]] 78 | name = "minicov" 79 | version = "0.3.5" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" 82 | dependencies = [ 83 | "cc", 84 | "walkdir", 85 | ] 86 | 87 | [[package]] 88 | name = "once_cell" 89 | version = "1.18.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 92 | 93 | [[package]] 94 | name = "proc-macro2" 95 | version = "1.0.92" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 98 | dependencies = [ 99 | "unicode-ident", 100 | ] 101 | 102 | [[package]] 103 | name = "quote" 104 | version = "1.0.36" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 107 | dependencies = [ 108 | "proc-macro2", 109 | ] 110 | 111 | [[package]] 112 | name = "rustversion" 113 | version = "1.0.19" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 116 | 117 | [[package]] 118 | name = "same-file" 119 | version = "1.0.6" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 122 | dependencies = [ 123 | "winapi-util", 124 | ] 125 | 126 | [[package]] 127 | name = "shlex" 128 | version = "1.3.0" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 131 | 132 | [[package]] 133 | name = "syn" 134 | version = "2.0.90" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" 137 | dependencies = [ 138 | "proc-macro2", 139 | "quote", 140 | "unicode-ident", 141 | ] 142 | 143 | [[package]] 144 | name = "thiserror" 145 | version = "2.0.11" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 148 | dependencies = [ 149 | "thiserror-impl", 150 | ] 151 | 152 | [[package]] 153 | name = "thiserror-impl" 154 | version = "2.0.11" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 157 | dependencies = [ 158 | "proc-macro2", 159 | "quote", 160 | "syn", 161 | ] 162 | 163 | [[package]] 164 | name = "unicode-ident" 165 | version = "1.0.10" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" 168 | 169 | [[package]] 170 | name = "walkdir" 171 | version = "2.5.0" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 174 | dependencies = [ 175 | "same-file", 176 | "winapi-util", 177 | ] 178 | 179 | [[package]] 180 | name = "wasm-bindgen" 181 | version = "0.2.100" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 184 | dependencies = [ 185 | "cfg-if", 186 | "once_cell", 187 | "rustversion", 188 | "wasm-bindgen-macro", 189 | ] 190 | 191 | [[package]] 192 | name = "wasm-bindgen-backend" 193 | version = "0.2.100" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 196 | dependencies = [ 197 | "bumpalo", 198 | "log", 199 | "proc-macro2", 200 | "quote", 201 | "syn", 202 | "wasm-bindgen-shared", 203 | ] 204 | 205 | [[package]] 206 | name = "wasm-bindgen-futures" 207 | version = "0.4.50" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 210 | dependencies = [ 211 | "cfg-if", 212 | "js-sys", 213 | "once_cell", 214 | "wasm-bindgen", 215 | "web-sys", 216 | ] 217 | 218 | [[package]] 219 | name = "wasm-bindgen-macro" 220 | version = "0.2.100" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 223 | dependencies = [ 224 | "quote", 225 | "wasm-bindgen-macro-support", 226 | ] 227 | 228 | [[package]] 229 | name = "wasm-bindgen-macro-support" 230 | version = "0.2.100" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 233 | dependencies = [ 234 | "proc-macro2", 235 | "quote", 236 | "syn", 237 | "wasm-bindgen-backend", 238 | "wasm-bindgen-shared", 239 | ] 240 | 241 | [[package]] 242 | name = "wasm-bindgen-shared" 243 | version = "0.2.100" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 246 | dependencies = [ 247 | "unicode-ident", 248 | ] 249 | 250 | [[package]] 251 | name = "wasm-bindgen-test" 252 | version = "0.3.50" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" 255 | dependencies = [ 256 | "js-sys", 257 | "minicov", 258 | "wasm-bindgen", 259 | "wasm-bindgen-futures", 260 | "wasm-bindgen-test-macro", 261 | ] 262 | 263 | [[package]] 264 | name = "wasm-bindgen-test-macro" 265 | version = "0.3.50" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" 268 | dependencies = [ 269 | "proc-macro2", 270 | "quote", 271 | "syn", 272 | ] 273 | 274 | [[package]] 275 | name = "web-sys" 276 | version = "0.3.77" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 279 | dependencies = [ 280 | "js-sys", 281 | "wasm-bindgen", 282 | ] 283 | 284 | [[package]] 285 | name = "winapi-util" 286 | version = "0.1.9" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 289 | dependencies = [ 290 | "windows-sys", 291 | ] 292 | 293 | [[package]] 294 | name = "windows-sys" 295 | version = "0.59.0" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 298 | dependencies = [ 299 | "windows-targets", 300 | ] 301 | 302 | [[package]] 303 | name = "windows-targets" 304 | version = "0.52.6" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 307 | dependencies = [ 308 | "windows_aarch64_gnullvm", 309 | "windows_aarch64_msvc", 310 | "windows_i686_gnu", 311 | "windows_i686_gnullvm", 312 | "windows_i686_msvc", 313 | "windows_x86_64_gnu", 314 | "windows_x86_64_gnullvm", 315 | "windows_x86_64_msvc", 316 | ] 317 | 318 | [[package]] 319 | name = "windows_aarch64_gnullvm" 320 | version = "0.52.6" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 323 | 324 | [[package]] 325 | name = "windows_aarch64_msvc" 326 | version = "0.52.6" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 329 | 330 | [[package]] 331 | name = "windows_i686_gnu" 332 | version = "0.52.6" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 335 | 336 | [[package]] 337 | name = "windows_i686_gnullvm" 338 | version = "0.52.6" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 341 | 342 | [[package]] 343 | name = "windows_i686_msvc" 344 | version = "0.52.6" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 347 | 348 | [[package]] 349 | name = "windows_x86_64_gnu" 350 | version = "0.52.6" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 353 | 354 | [[package]] 355 | name = "windows_x86_64_gnullvm" 356 | version = "0.52.6" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 359 | 360 | [[package]] 361 | name = "windows_x86_64_msvc" 362 | version = "0.52.6" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 365 | -------------------------------------------------------------------------------- /aarch64-esr-web/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aarch64-esr-web" 3 | version = "0.1.0" 4 | authors = ["Andrew Walbran "] 5 | edition = "2018" 6 | license = "Apache-2.0" 7 | description = "A webapp for decoding aarch64 Exception Syndrome Register values." 8 | repository = "https://github.com/google/aarch64-esr-decoder/" 9 | keywords = ["aarch64", "esr", "wasm"] 10 | categories = ["development-tools"] 11 | 12 | [lib] 13 | crate-type = ["cdylib"] 14 | 15 | [features] 16 | default = ["console_error_panic_hook"] 17 | 18 | [profile.release] 19 | lto = true 20 | # Optimize for small code size. 21 | opt-level = "s" 22 | 23 | [dependencies] 24 | wasm-bindgen = "0.2.100" 25 | aarch64-esr-decoder = { path = ".." } 26 | web-sys = { version = "0.3.76", features = [ "Document", "Element", "HtmlElement", "Node", "Window" ] } 27 | 28 | # The `console_error_panic_hook` crate provides better debugging of panics by 29 | # logging them with `console.error`. This is great for development, but requires 30 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 31 | # code size when deploying. 32 | console_error_panic_hook = { version = "0.1.7", optional = true } 33 | 34 | [dev-dependencies] 35 | wasm-bindgen-test = "0.3.49" 36 | -------------------------------------------------------------------------------- /aarch64-esr-web/README.md: -------------------------------------------------------------------------------- 1 | # aarch64-esr-web 2 | 3 | A small webapp for decoding aarch64 ESR register values. 4 | 5 | [See it in action](https://google.github.io/aarch64-esr-decoder/). 6 | 7 | This is not an officially supported Google product. 8 | 9 | ## Usage 10 | 11 | Build with `wasm-pack build`. 12 | 13 | ## License 14 | 15 | Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 16 | 17 | ## Contributing 18 | 19 | If you want to contribute to the project, see details of 20 | [how we accept contributions](../CONTRIBUTING.md). 21 | -------------------------------------------------------------------------------- /aarch64-esr-web/js/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import("../pkg").then((wasm) => { 16 | wasm.init(); 17 | 18 | const esr = document.getElementById("esr"); 19 | if (esr != null) { 20 | esr.oninput = () => { 21 | if (esr.value.length > 0) { 22 | wasm.decode_esr(esr.value); 23 | } 24 | window.location.hash = esr.value; 25 | }; 26 | 27 | if (window.location.hash) { 28 | esr.value = window.location.hash.substring(1); 29 | wasm.decode_esr(esr.value); 30 | } 31 | } 32 | 33 | const midr = document.getElementById("midr"); 34 | if (midr != null) { 35 | midr.oninput = () => { 36 | if (midr.value.length > 0) { 37 | wasm.decode_midr(midr.value); 38 | } 39 | window.location.hash = midr.value; 40 | }; 41 | 42 | if (window.location.hash) { 43 | midr.value = window.location.hash.substring(1); 44 | wasm.decode_midr(midr.value); 45 | } 46 | } 47 | 48 | const smccc = document.getElementById("smccc"); 49 | if (smccc != null) { 50 | smccc.oninput = () => { 51 | if (smccc.value.length > 0) { 52 | wasm.decode_smccc(smccc.value); 53 | } 54 | window.location.hash = smccc.value; 55 | }; 56 | 57 | if (window.location.hash) { 58 | smccc.value = window.location.hash.substring(1); 59 | wasm.decode_smccc(smccc.value); 60 | } 61 | } 62 | }); 63 | -------------------------------------------------------------------------------- /aarch64-esr-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Andrew Walbran ", 3 | "name": "aarch64-esr-web-www", 4 | "version": "0.1.0", 5 | "description": "Webapp to decode aarch64 ESR values", 6 | "scripts": { 7 | "build": "rimraf dist pkg && webpack", 8 | "start": "rimraf dist pkg && webpack-dev-server --open", 9 | "test": "cargo test && wasm-pack test --node" 10 | }, 11 | "devDependencies": { 12 | "@wasm-tool/wasm-pack-plugin": "^1.7.0", 13 | "@webassemblyjs/ast": "^1.14.1", 14 | "@webassemblyjs/wasm-edit": "^1.14.1", 15 | "@webassemblyjs/wasm-parser": "^1.14.1", 16 | "copy-webpack-plugin": "^13.0.0", 17 | "rimraf": "^6.0.1", 18 | "webpack": "^5.99.9", 19 | "webpack-cli": "^6.0.1", 20 | "webpack-dev-server": "^5.2.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /aarch64-esr-web/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use aarch64_esr_decoder::{decode, parse_number, DecodeError, FieldInfo}; 16 | use std::convert::TryFrom; 17 | use std::ops::Deref; 18 | use wasm_bindgen::prelude::*; 19 | use web_sys::{Document, Element}; 20 | 21 | #[wasm_bindgen] 22 | pub fn init() { 23 | #[cfg(feature = "console_error_panic_hook")] 24 | console_error_panic_hook::set_once(); 25 | } 26 | 27 | #[wasm_bindgen] 28 | pub fn decode_esr(esr: &str) -> Result<(), JsValue> { 29 | match parse_number(esr) { 30 | Ok(esr) => { 31 | let decoded = decode(esr); 32 | show_decoded(esr, decoded, u64::BITS)?; 33 | } 34 | Err(_) => show_error("ESR not valid hex or decimal number"), 35 | } 36 | Ok(()) 37 | } 38 | 39 | #[wasm_bindgen] 40 | pub fn decode_midr(midr: &str) -> Result<(), JsValue> { 41 | match parse_number(midr) { 42 | Ok(midr) => { 43 | let decoded = aarch64_esr_decoder::decode_midr(midr); 44 | show_decoded(midr, decoded, u64::BITS)?; 45 | } 46 | Err(_) => show_error("MIDR not valid hex or decimal number"), 47 | } 48 | Ok(()) 49 | } 50 | 51 | #[wasm_bindgen] 52 | pub fn decode_smccc(fn_id: &str) -> Result<(), JsValue> { 53 | match parse_number(fn_id) { 54 | Ok(fn_id) => { 55 | let decoded = aarch64_esr_decoder::decode_smccc(fn_id); 56 | show_decoded(fn_id, decoded, u32::BITS)?; 57 | } 58 | Err(_) => show_error("SMCCC Function ID not valid hex or decimal number"), 59 | } 60 | Ok(()) 61 | } 62 | 63 | fn show_error(error: &str) { 64 | let document = web_sys::window() 65 | .expect("Couldn't find window") 66 | .document() 67 | .expect("Couldn't find document"); 68 | let error_element = document 69 | .get_element_by_id("error") 70 | .expect("Couldn't find error element"); 71 | let table = document 72 | .get_element_by_id("result_table") 73 | .expect("Couldn't find result table"); 74 | // Clear output table. 75 | table.set_inner_html(""); 76 | error_element.set_text_content(Some(error)); 77 | } 78 | 79 | fn show_decoded( 80 | esr: u64, 81 | decoded: Result, DecodeError>, 82 | nr_bit: u32, 83 | ) -> Result<(), JsValue> { 84 | assert!(nr_bit <= u64::BITS); 85 | let nr_bit = usize::try_from(nr_bit).unwrap(); 86 | let document = web_sys::window() 87 | .expect("Couldn't find window") 88 | .document() 89 | .expect("Couldn't find document"); 90 | let error_element = document 91 | .get_element_by_id("error") 92 | .expect("Couldn't find error element"); 93 | let table = document 94 | .get_element_by_id("result_table") 95 | .expect("Couldn't find result table"); 96 | // Remove existing contents. 97 | error_element.set_inner_html(""); 98 | table.set_inner_html(""); 99 | 100 | // ESR in hexadecimal 101 | let row = document.create_element("tr")?; 102 | row.set_attribute("class", "value")?; 103 | let esr_hex = format!("{:016x}", esr); 104 | // Loop over number of chars of interest only 105 | let nr_nib = (nr_bit + 3) / 4; 106 | for digit in esr_hex.chars().skip(16 - nr_nib) { 107 | let cell = make_cell(&document, Some(&digit.to_string()), None, 4)?; 108 | row.append_child(&cell)?; 109 | } 110 | table.append_child(&row)?; 111 | 112 | // ESR in binary 113 | let row = document.create_element("tr")?; 114 | row.set_attribute("class", "value")?; 115 | for i in (0..nr_bit).rev() { 116 | let bit = esr & (1 << i) != 0; 117 | let cell = make_cell(&document, Some(if bit { "1" } else { "0" }), None, 1)?; 118 | row.append_child(&cell)?; 119 | } 120 | table.append_child(&row)?; 121 | 122 | match decoded { 123 | Ok(fields) => { 124 | // Top-level field names and values 125 | let row = document.create_element("tr")?; 126 | row.set_attribute("class", "name")?; 127 | let mut last = nr_bit; 128 | add_field_cells( 129 | &document, 130 | &row, 131 | &fields, 132 | &mut last, 133 | |field| Some(field.to_string()), 134 | |field| field.long_name, 135 | )?; 136 | table.append_child(&row)?; 137 | 138 | // Top-level field descriptions 139 | let row = document.create_element("tr")?; 140 | row.set_attribute("class", "description")?; 141 | let mut last = nr_bit; 142 | add_field_cells( 143 | &document, 144 | &row, 145 | &fields, 146 | &mut last, 147 | |field| field.description.clone(), 148 | |_| None, 149 | )?; 150 | table.append_child(&row)?; 151 | 152 | // Second level field names and values 153 | let row = document.create_element("tr")?; 154 | row.set_attribute("class", "name")?; 155 | let mut last = nr_bit; 156 | for field in &fields { 157 | add_field_cells( 158 | &document, 159 | &row, 160 | &field.subfields, 161 | &mut last, 162 | |field| Some(field.to_string()), 163 | |field| field.long_name, 164 | )?; 165 | } 166 | table.append_child(&row)?; 167 | 168 | // Second level field descriptions 169 | let row = document.create_element("tr")?; 170 | row.set_attribute("class", "description")?; 171 | let mut last = nr_bit; 172 | for field in &fields { 173 | add_field_cells( 174 | &document, 175 | &row, 176 | &field.subfields, 177 | &mut last, 178 | |field| field.description.clone(), 179 | |_| None, 180 | )?; 181 | } 182 | table.append_child(&row)?; 183 | } 184 | Err(e) => error_element.set_text_content(Some(&e.to_string())), 185 | } 186 | 187 | Ok(()) 188 | } 189 | 190 | fn make_cell( 191 | document: &Document, 192 | contents: Option<&str>, 193 | hover_title: Option<&str>, 194 | colspan: usize, 195 | ) -> Result { 196 | let cell = document.create_element("td")?; 197 | cell.set_attribute("colspan", &colspan.to_string())?; 198 | if let Some(title) = hover_title { 199 | let abbr = document.create_element("abbr")?; 200 | abbr.set_attribute("title", title)?; 201 | abbr.set_text_content(contents); 202 | cell.append_child(&abbr)?; 203 | } else { 204 | cell.set_text_content(contents); 205 | } 206 | Ok(cell) 207 | } 208 | 209 | fn add_field_cells( 210 | document: &Document, 211 | row: &Element, 212 | fields: &[FieldInfo], 213 | last: &mut usize, 214 | get_contents: F, 215 | get_hover_title: G, 216 | ) -> Result<(), JsValue> 217 | where 218 | F: Fn(&FieldInfo) -> Option, 219 | G: Fn(&FieldInfo) -> Option<&str>, 220 | S: Deref, 221 | { 222 | for field in fields { 223 | if field.start + field.width != *last { 224 | // Add a filler 225 | let cell = make_cell(document, None, None, *last - field.start - field.width)?; 226 | row.append_child(&cell)?; 227 | } 228 | let cell = make_cell( 229 | document, 230 | get_contents(field).as_deref(), 231 | get_hover_title(field).as_deref(), 232 | field.width, 233 | )?; 234 | row.append_child(&cell)?; 235 | *last = field.start; 236 | } 237 | Ok(()) 238 | } 239 | -------------------------------------------------------------------------------- /aarch64-esr-web/static/google2d2782625f584348.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google2d2782625f584348.html -------------------------------------------------------------------------------- /aarch64-esr-web/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AArch64 ESR decoder 6 | 7 | 8 | 9 | 10 | 11 |

AArch64 register decoder

12 | 17 |
18 |

Decimal or hexadecimal input supported. Use 0x for hexadecimal.

19 |

20 | 21 | 22 |

23 |
24 |
25 |

26 |

Source and command-line version

27 | 28 | 29 | -------------------------------------------------------------------------------- /aarch64-esr-web/static/midr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AArch64 MIDR decoder 6 | 7 | 8 | 9 | 10 | 11 |

AArch64 register decoder

12 | 17 |
18 |

Decimal or hexadecimal input supported. Use 0x for hexadecimal.

19 |

20 | 21 | 22 |

23 |
24 |
25 |

26 |

Source and command-line version

27 | 28 | 29 | -------------------------------------------------------------------------------- /aarch64-esr-web/static/smccc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Arm SMCCC decoder 6 | 7 | 8 | 9 | 10 | 11 |

AArch64 register decoder

12 |
    13 |
  • ESR
  • 14 |
  • MIDR
  • 15 |
  • SMCCC
  • 16 |
17 |
18 |

Decimal or hexadecimal input supported. Use 0x for hexadecimal.

19 |

20 | 21 | 22 |

23 |
24 |
25 |

26 |

Source and command-line version

27 | 28 | 29 | -------------------------------------------------------------------------------- /aarch64-esr-web/static/style.css: -------------------------------------------------------------------------------- 1 | table { 2 | border-collapse: collapse; 3 | } 4 | td { 5 | border: 1px solid black; 6 | } 7 | tr.value td { 8 | font-family: monospace; 9 | } 10 | tr.description td:not(:empty) { 11 | background-color: #ffffdd; 12 | } 13 | tr.name td:not(:empty) { 14 | background-color: #ddffdd; 15 | font-family: monospace; 16 | } 17 | p#error { 18 | color: red; 19 | } 20 | ul.tabbar { 21 | margin: 0; 22 | padding-top: 5px; 23 | padding-bottom: 0; 24 | padding-left: 5px; 25 | padding-right: 5px; 26 | width: 100%; 27 | list-style: none; 28 | border-bottom: 1px solid #ddffdd; 29 | } 30 | .tabbar li { 31 | display: inline-block; 32 | } 33 | .tabbar li.current { 34 | background-color: #ddffdd; 35 | padding: 10px; 36 | } 37 | .tabbar li a { 38 | background-color: #ffffdd; 39 | display: block; 40 | padding: 10px; 41 | } 42 | .tabbar li a:hover { 43 | background-color: #cceecc; 44 | } 45 | -------------------------------------------------------------------------------- /aarch64-esr-web/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const CopyPlugin = require("copy-webpack-plugin"); 3 | const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); 4 | 5 | const dist = path.resolve(__dirname, "dist"); 6 | 7 | module.exports = { 8 | mode: "production", 9 | entry: { 10 | index: "./js/index.js", 11 | }, 12 | output: { 13 | path: dist, 14 | filename: "[name].js", 15 | }, 16 | devtool: "source-map", 17 | optimization: { 18 | minimize: true, 19 | usedExports: true, 20 | }, 21 | experiments: { 22 | asyncWebAssembly: true, 23 | }, 24 | plugins: [ 25 | new CopyPlugin({ patterns: [path.resolve(__dirname, "static")] }), 26 | 27 | new WasmPackPlugin({ 28 | crateDirectory: __dirname, 29 | }), 30 | ], 31 | }; 32 | -------------------------------------------------------------------------------- /src/esr/abort.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | use std::fmt::{self, Debug, Display, Formatter}; 17 | 18 | /// Decodes the ISS value for an Instruction Abort. 19 | pub fn decode_iss_instruction_abort(iss: u64) -> Result, DecodeError> { 20 | let res0a = FieldInfo::get(iss, "RES0", Some("Reserved"), 13, 25).check_res0()?; 21 | let fnv = FieldInfo::get_bit(iss, "FnV", Some("FAR not Valid"), 10).describe_bit(describe_fnv); 22 | let ea = FieldInfo::get_bit(iss, "EA", Some("External abort type"), 9); 23 | let res0b = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 8).check_res0()?; 24 | let s1ptw = FieldInfo::get_bit(iss, "S1PTW", Some("Stage-1 translation table walk"), 7); 25 | let res0c = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 6).check_res0()?; 26 | let ifsc = FieldInfo::get(iss, "IFSC", Some("Instruction Fault Status Code"), 0, 6) 27 | .describe(describe_fsc)?; 28 | 29 | let set = if ifsc.value == 0b010000 { 30 | FieldInfo::get(iss, "SET", Some("Synchronous Error Type"), 11, 13).describe(describe_set)? 31 | } else { 32 | FieldInfo::get(iss, "RES0", Some("Reserved"), 11, 13) 33 | }; 34 | 35 | Ok(vec![res0a, set, fnv, ea, res0b, s1ptw, res0c, ifsc]) 36 | } 37 | 38 | /// Decodes the ISS value for a Data Abort. 39 | pub fn decode_iss_data_abort(iss: u64) -> Result, DecodeError> { 40 | let isv = FieldInfo::get_bit(iss, "ISV", Some("Instruction Syndrome Valid"), 24) 41 | .describe_bit(describe_isv); 42 | 43 | let intruction_syndrome_fields = if isv.as_bit() { 44 | // These fields are part of the instruction syndrome, and are only valid if ISV is true. 45 | let sas = FieldInfo::get(iss, "SAS", Some("Syndrome Access Size"), 22, 24); 46 | let sas_value = match sas.value { 47 | 0b00 => SyndromeAccessSize::Byte, 48 | 0b01 => SyndromeAccessSize::Halfword, 49 | 0b10 => SyndromeAccessSize::Word, 50 | 0b11 => SyndromeAccessSize::Doubleword, 51 | _ => unreachable!(), 52 | }; 53 | let sas = sas.with_description(sas_value.to_string()); 54 | let sse = FieldInfo::get_bit(iss, "SSE", Some("Syndrome Sign Extend"), 21); 55 | let srt = FieldInfo::get(iss, "SRT", Some("Syndrome Register Transfer"), 16, 21); 56 | let sf = FieldInfo::get_bit(iss, "SF", Some("Sixty-Four"), 15).describe_bit(describe_sf); 57 | let ar = 58 | FieldInfo::get_bit(iss, "AR", Some("Acquire/Release"), 14).describe_bit(describe_ar); 59 | vec![sas, sse, srt, sf, ar] 60 | } else { 61 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 14, 24).check_res0()?; 62 | vec![res0] 63 | }; 64 | 65 | let vncr = FieldInfo::get_bit(iss, "VNCR", None, 13); 66 | let fnv = FieldInfo::get_bit(iss, "FnV", Some("FAR not Valid"), 10).describe_bit(describe_fnv); 67 | let ea = FieldInfo::get_bit(iss, "EA", Some("External abort type"), 9); 68 | let cm = FieldInfo::get_bit(iss, "CM", Some("Cache Maintenance"), 8); 69 | let s1ptw = FieldInfo::get_bit(iss, "S1PTW", Some("Stage-1 translation table walk"), 7); 70 | let wnr = FieldInfo::get_bit(iss, "WnR", Some("Write not Read"), 6).describe_bit(describe_wnr); 71 | let dfsc = 72 | FieldInfo::get(iss, "DFSC", Some("Data Fault Status Code"), 0, 6).describe(describe_fsc)?; 73 | let set = if dfsc.value == 0b010000 { 74 | FieldInfo::get(iss, "SET", Some("Synchronous Error Type"), 11, 13).describe(describe_set)? 75 | } else { 76 | FieldInfo::get(iss, "RES0", Some("Reserved"), 11, 13) 77 | }; 78 | 79 | let mut fields = vec![isv]; 80 | fields.extend(intruction_syndrome_fields); 81 | fields.extend(vec![vncr, set, fnv, ea, cm, s1ptw, wnr, dfsc]); 82 | Ok(fields) 83 | } 84 | 85 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 86 | enum SyndromeAccessSize { 87 | Byte = 0b00, 88 | Halfword = 0b01, 89 | Word = 0b10, 90 | Doubleword = 0b11, 91 | } 92 | 93 | impl Display for SyndromeAccessSize { 94 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 95 | let s = match self { 96 | Self::Byte => "byte", 97 | Self::Halfword => "halfword", 98 | Self::Word => "word", 99 | Self::Doubleword => "doubleword", 100 | }; 101 | write!(f, "{}", s) 102 | } 103 | } 104 | 105 | fn describe_isv(isv: bool) -> &'static str { 106 | if isv { 107 | "Valid instruction syndrome" 108 | } else { 109 | "No valid instruction syndrome" 110 | } 111 | } 112 | 113 | fn describe_sf(sf: bool) -> &'static str { 114 | if sf { 115 | "64-bit wide register" 116 | } else { 117 | "32-bit wide register" 118 | } 119 | } 120 | 121 | fn describe_ar(ar: bool) -> &'static str { 122 | if ar { 123 | "Acquire/release semantics" 124 | } else { 125 | "No acquire/release semantics" 126 | } 127 | } 128 | 129 | fn describe_fnv(fnv: bool) -> &'static str { 130 | if fnv { 131 | "FAR is not valid, it holds an unknown value" 132 | } else { 133 | "FAR is valid" 134 | } 135 | } 136 | 137 | fn describe_wnr(wnr: bool) -> &'static str { 138 | if wnr { 139 | "Abort caused by writing to memory" 140 | } else { 141 | "Abort caused by reading from memory" 142 | } 143 | } 144 | 145 | fn describe_fsc(fsc: u64) -> Result<&'static str, DecodeError> { 146 | let description = match fsc { 147 | 0b000000 => { 148 | "Address size fault, level 0 of translation or translation table base register." 149 | } 150 | 0b000001 => "Address size fault, level 1.", 151 | 0b000010 => "Address size fault, level 2.", 152 | 0b000011 => "Address size fault, level 3.", 153 | 0b000100 => "Translation fault, level 0.", 154 | 0b000101 => "Translation fault, level 1.", 155 | 0b000110 => "Translation fault, level 2.", 156 | 0b000111 => "Translation fault, level 3.", 157 | 0b001001 => "Access flag fault, level 1.", 158 | 0b001010 => "Access flag fault, level 2.", 159 | 0b001011 => "Access flag fault, level 3.", 160 | 0b001000 => "Access flag fault, level 0.", 161 | 0b001100 => "Permission fault, level 0.", 162 | 0b001101 => "Permission fault, level 1.", 163 | 0b001110 => "Permission fault, level 2.", 164 | 0b001111 => "Permission fault, level 3.", 165 | 0b010000 => { 166 | "Synchronous External abort, not on translation table walk or hardware update of \ 167 | translation table." 168 | } 169 | 0b010001 => "Synchronous Tag Check Fault.", 170 | 0b010011 => { 171 | "Synchronous External abort on translation table walk or hardware update of \ 172 | translation table, level -1." 173 | } 174 | 0b010100 => { 175 | "Synchronous External abort on translation table walk or hardware update of \ 176 | translation table, level 0." 177 | } 178 | 0b010101 => { 179 | "Synchronous External abort on translation table walk or hardware update of \ 180 | translation table, level 1." 181 | } 182 | 0b010110 => { 183 | "Synchronous External abort on translation table walk or hardware update of \ 184 | translation table, level 2." 185 | } 186 | 0b010111 => { 187 | "Synchronous External abort on translation table walk or hardware update of \ 188 | translation table, level 3." 189 | } 190 | 0b011000 => { 191 | "Synchronous parity or ECC error on memory access, not on translation table walk." 192 | } 193 | 0b011011 => { 194 | "Synchronous parity or ECC error on memory access on translation table walk or \ 195 | hardware update of translation table, level -1." 196 | } 197 | 0b011100 => { 198 | "Synchronous parity or ECC error on memory access on translation table walk or \ 199 | hardware update of translation table, level 0." 200 | } 201 | 0b011101 => { 202 | "Synchronous parity or ECC error on memory access on translation table walk or \ 203 | hardware update of translation table, level 1." 204 | } 205 | 0b011110 => { 206 | "Synchronous parity or ECC error on memory access on translation table walk or \ 207 | hardware update of translation table, level 2." 208 | } 209 | 0b011111 => { 210 | "Synchronous parity or ECC error on memory access on translation table walk or \ 211 | hardware update of translation table, level 3." 212 | } 213 | 0b100001 => "Alignment fault.", 214 | 0b100011 => { 215 | "Granule Protection Fault on translation table walk or hardware update of \ 216 | translation table, level -1." 217 | } 218 | 0b100100 => { 219 | "Granule Protection Fault on translation table walk or hardware update of \ 220 | translation table, level 0." 221 | } 222 | 0b100101 => { 223 | "Granule Protection Fault on translation table walk or hardware update of \ 224 | translation table, level 1." 225 | } 226 | 0b100110 => { 227 | "Granule Protection Fault on translation table walk or hardware update of \ 228 | translation table, level 2." 229 | } 230 | 0b100111 => { 231 | "Granule Protection Fault on translation table walk or hardware update of \ 232 | translation table, level 3." 233 | } 234 | 0b101000 => { 235 | "Granule Protection Fault, not on translation table walk or hardware update of \ 236 | translation table." 237 | } 238 | 0b101001 => "Address size fault, level -1.", 239 | 0b101011 => "Translation fault, level -1.", 240 | 0b110000 => "TLB conflict abort.", 241 | 0b110001 => "Unsupported atomic hardware update fault.", 242 | 0b110100 => "IMPLEMENTATION DEFINED fault (Lockdown).", 243 | 0b110101 => "IMPLEMENTATION DEFINED fault (Unsupported Exclusive or Atomic access).", 244 | _ => return Err(DecodeError::InvalidFsc { fsc }), 245 | }; 246 | Ok(description) 247 | } 248 | 249 | fn describe_set(set: u64) -> Result<&'static str, DecodeError> { 250 | Ok(match set { 251 | 0b00 => "Recoverable state (UER)", 252 | 0b10 => "Uncontainable (UC)", 253 | 0b11 => "Restartable state (UEO)", 254 | _ => return Err(DecodeError::InvalidSet { set }), 255 | }) 256 | } 257 | -------------------------------------------------------------------------------- /src/esr/breakpoint.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for a Breakpoint or Vector Catch debug exception. 18 | pub fn decode_iss_breakpoint_vector_catch(iss: u64) -> Result, DecodeError> { 19 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 6, 25).check_res0()?; 20 | let ifsc = FieldInfo::get(iss, "IFSC", Some("Instruction Fault Status Code"), 0, 6) 21 | .describe(describe_fsc)?; 22 | 23 | Ok(vec![res0, ifsc]) 24 | } 25 | 26 | /// Decodes the ISS value for a Software Step exception. 27 | pub fn decode_iss_software_step(iss: u64) -> Result, DecodeError> { 28 | let isv = FieldInfo::get_bit(iss, "ISV", Some("Instruction Syndrome Valid"), 24) 29 | .describe_bit(describe_isv); 30 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 7, 24).check_res0()?; 31 | let ex = if isv.as_bit() { 32 | FieldInfo::get_bit(iss, "EX", Some("Exclusive operation"), 6).describe_bit(describe_ex) 33 | } else { 34 | FieldInfo::get_bit(iss, "RES0", Some("Reserved because ISV is false"), 6).check_res0()? 35 | }; 36 | let ifsc = FieldInfo::get(iss, "IFSC", Some("Instruction Fault Status Code"), 0, 6) 37 | .describe(describe_fsc)?; 38 | 39 | Ok(vec![isv, res0, ex, ifsc]) 40 | } 41 | 42 | /// Decodes the ISS value for a Watchpoint exception. 43 | pub fn decode_iss_watchpoint(iss: u64) -> Result, DecodeError> { 44 | let res0a = FieldInfo::get(iss, "RES0", Some("Reserved"), 15, 25).check_res0()?; 45 | let res0b = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 14).check_res0()?; 46 | let vncr = FieldInfo::get_bit(iss, "VNCR", None, 13); 47 | let res0c = FieldInfo::get(iss, "RES0", Some("Reserved"), 9, 13).check_res0()?; 48 | let cm = FieldInfo::get_bit(iss, "CM", Some("Cache Maintenance"), 8); 49 | let res0d = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 7).check_res0()?; 50 | let wnr = FieldInfo::get_bit(iss, "WnR", Some("Write not Read"), 6).describe_bit(describe_wnr); 51 | let dfsc = 52 | FieldInfo::get(iss, "DFSC", Some("Data Fault Status Code"), 0, 6).describe(describe_fsc)?; 53 | 54 | Ok(vec![res0a, res0b, vncr, res0c, cm, res0d, wnr, dfsc]) 55 | } 56 | 57 | /// Decodes the ISS value for a Breakpoint instruction. 58 | pub fn decode_iss_breakpoint(iss: u64) -> Result, DecodeError> { 59 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 16, 25).check_res0()?; 60 | let comment = FieldInfo::get( 61 | iss, 62 | "Comment", 63 | Some("Instruction comment field or immediate field"), 64 | 0, 65 | 16, 66 | ); 67 | 68 | Ok(vec![res0, comment]) 69 | } 70 | 71 | fn describe_fsc(fsc: u64) -> Result<&'static str, DecodeError> { 72 | match fsc { 73 | 0b100010 => Ok("Debug exception"), 74 | _ => Err(DecodeError::InvalidFsc { fsc }), 75 | } 76 | } 77 | 78 | fn describe_isv(isv: bool) -> &'static str { 79 | if isv { 80 | "EX bit is valid" 81 | } else { 82 | "EX bit is RES0" 83 | } 84 | } 85 | 86 | fn describe_ex(ex: bool) -> &'static str { 87 | if ex { 88 | "A Load-Exclusive instruction was stepped" 89 | } else { 90 | "Some instruction other than a Load-Exclusive was stepped" 91 | } 92 | } 93 | 94 | fn describe_wnr(wnr: bool) -> &'static str { 95 | if wnr { 96 | "Watchpoint caused by writing to memory" 97 | } else { 98 | "Watchpoint caused by reading from memory" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/esr/bti.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for a Branch Target Exception. 18 | pub fn decode_iss_bti(iss: u64) -> Result, DecodeError> { 19 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 2, 25).check_res0()?; 20 | let btype = FieldInfo::get(iss, "BTYPE", Some("PSTATE.BTYPE value"), 0, 2); 21 | 22 | Ok(vec![res0, btype]) 23 | } 24 | -------------------------------------------------------------------------------- /src/esr/common.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Description functions shared between multiple modules. 16 | 17 | pub fn describe_cv(cv: bool) -> &'static str { 18 | if cv { 19 | "COND is valid" 20 | } else { 21 | "COND is not valid" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/esr/fp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for a floating-point exception. 18 | pub fn decode_iss_fp(iss: u64) -> Result, DecodeError> { 19 | let res0a = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 24).check_res0()?; 20 | let tfv = 21 | FieldInfo::get_bit(iss, "TFV", Some("Trapped Fault Valid"), 23).describe_bit(describe_tfv); 22 | let res0b = FieldInfo::get(iss, "RES0", Some("Reserved"), 11, 23).check_res0()?; 23 | let vecitr = FieldInfo::get(iss, "VECITR", Some("RES1 or UNKNOWN"), 8, 11); 24 | let idf = FieldInfo::get_bit(iss, "IDF", Some("Input Denormal"), 7).describe_bit(describe_idf); 25 | let res0c = FieldInfo::get(iss, "RES0", Some("Reserved"), 5, 7).check_res0()?; 26 | let ixf = FieldInfo::get_bit(iss, "IXF", Some("Inexact"), 4).describe_bit(describe_ixf); 27 | let uff = FieldInfo::get_bit(iss, "UFF", Some("Underflow"), 3).describe_bit(describe_uff); 28 | let off = FieldInfo::get_bit(iss, "OFF", Some("Overflow"), 2).describe_bit(describe_off); 29 | let dzf = FieldInfo::get_bit(iss, "DZF", Some("Divide by Zero"), 1).describe_bit(describe_dzf); 30 | let iof = 31 | FieldInfo::get_bit(iss, "IOF", Some("Invalid Operation"), 0).describe_bit(describe_iof); 32 | 33 | Ok(vec![ 34 | res0a, tfv, res0b, vecitr, idf, res0c, ixf, uff, off, dzf, iof, 35 | ]) 36 | } 37 | 38 | fn describe_tfv(tfv: bool) -> &'static str { 39 | if tfv { 40 | "One or more floating-point exceptions occurred; IDF, IXF, UFF, OFF, DZF and IOF hold information about what." 41 | } else { 42 | "IDF, IXF, UFF, OFF, DZF and IOF do not hold valid information." 43 | } 44 | } 45 | 46 | fn describe_idf(idf: bool) -> &'static str { 47 | if idf { 48 | "Input denormal floating-point exception occurred." 49 | } else { 50 | "Input denormal floating-point exception did not occur." 51 | } 52 | } 53 | 54 | fn describe_ixf(ixf: bool) -> &'static str { 55 | if ixf { 56 | "Inexact floating-point exception occurred." 57 | } else { 58 | "Inexact floating-point exception did not occur." 59 | } 60 | } 61 | 62 | fn describe_uff(uff: bool) -> &'static str { 63 | if uff { 64 | "Underflow floating-point exception occurred." 65 | } else { 66 | "Underflow floating-point exception did not occur." 67 | } 68 | } 69 | 70 | fn describe_off(off: bool) -> &'static str { 71 | if off { 72 | "Overflow floating-point exception occurred." 73 | } else { 74 | "Overflow floating-point exception did not occur." 75 | } 76 | } 77 | 78 | fn describe_dzf(dzf: bool) -> &'static str { 79 | if dzf { 80 | "Divide by Zero floating-point exception occurred." 81 | } else { 82 | "Divide by Zero floating-point exception did not occur." 83 | } 84 | } 85 | 86 | fn describe_iof(iof: bool) -> &'static str { 87 | if iof { 88 | "Invalid Operation floating-point exception occurred." 89 | } else { 90 | "Invalid Operation floating-point exception did not occur." 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/esr/hvc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for an HVC or SVC exception. 18 | pub fn decode_iss_hvc(iss: u64) -> Result, DecodeError> { 19 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 16, 25).check_res0()?; 20 | let imm16 = FieldInfo::get(iss, "imm16", Some("Value of the immediate field"), 0, 16); 21 | 22 | Ok(vec![res0, imm16]) 23 | } 24 | -------------------------------------------------------------------------------- /src/esr/ld64b.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for a trapped LD64B or ST64B* instruction. 18 | pub fn decode_iss_ld64b(iss: u64) -> Result, DecodeError> { 19 | let iss = FieldInfo::get(iss, "ISS", None, 0, 25).describe(describe_iss_ld64b)?; 20 | Ok(vec![iss]) 21 | } 22 | 23 | fn describe_iss_ld64b(iss: u64) -> Result<&'static str, DecodeError> { 24 | match iss { 25 | 0b00 => Ok("ST64BV trapped"), 26 | 0b01 => Ok("ST64BV0 trapped"), 27 | 0b10 => Ok("LD64B or ST64B trapped"), 28 | _ => Err(DecodeError::InvalidLd64bIss { iss }), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/esr/ldc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::common::describe_cv; 16 | use crate::{DecodeError, FieldInfo}; 17 | 18 | /// Decodes the ISS value for a trapped LDC or STC instruction. 19 | pub fn decode_iss_ldc(iss: u64) -> Result, DecodeError> { 20 | let cv = 21 | FieldInfo::get_bit(iss, "CV", Some("Condition code valid"), 24).describe_bit(describe_cv); 22 | let cond = FieldInfo::get( 23 | iss, 24 | "COND", 25 | Some("Condition code of the trapped instruction"), 26 | 20, 27 | 24, 28 | ); 29 | let imm8 = FieldInfo::get( 30 | iss, 31 | "imm8", 32 | Some("Immediate value of the trapped instruction"), 33 | 12, 34 | 20, 35 | ); 36 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 10, 12).check_res0()?; 37 | let rn = FieldInfo::get( 38 | iss, 39 | "Rn", 40 | Some("General-purpose register number of the trapped instruction"), 41 | 5, 42 | 10, 43 | ); 44 | let offset = FieldInfo::get_bit( 45 | iss, 46 | "Offset", 47 | Some("Whether the offset is added or subtracted"), 48 | 4, 49 | ) 50 | .describe_bit(describe_offset); 51 | let am = FieldInfo::get(iss, "AM", Some("Addressing Mode"), 1, 4).describe(describe_am)?; 52 | let direction = FieldInfo::get_bit( 53 | iss, 54 | "Direction", 55 | Some("Direction of the trapped instruction"), 56 | 0, 57 | ) 58 | .describe_bit(describe_direction); 59 | 60 | Ok(vec![cv, cond, imm8, res0, rn, offset, am, direction]) 61 | } 62 | 63 | fn describe_offset(offset: bool) -> &'static str { 64 | if offset { 65 | "Add offset" 66 | } else { 67 | "Subtract offset" 68 | } 69 | } 70 | 71 | fn describe_am(am: u64) -> Result<&'static str, DecodeError> { 72 | match am { 73 | 0b000 => Ok("Immediate unindexed"), 74 | 0b001 => Ok("Immediate post-indexed"), 75 | 0b010 => Ok("Immediate offset"), 76 | 0b011 => Ok("Immediate pre-indexed"), 77 | 0b100 => Ok("Reserved for trapped STR or T32 LDC"), 78 | 0b110 => Ok("Reserved for trapped STC"), 79 | _ => Err(DecodeError::InvalidAm { am }), 80 | } 81 | } 82 | 83 | fn describe_direction(direction: bool) -> &'static str { 84 | if direction { 85 | "Read from memory (LDC)" 86 | } else { 87 | "Write to memory (STC)" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/esr/mcr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::common::describe_cv; 16 | use crate::{DecodeError, FieldInfo}; 17 | 18 | /// Decodes the ISS value for an MCR or MRC access. 19 | pub fn decode_iss_mcr(iss: u64) -> Result, DecodeError> { 20 | let cv = 21 | FieldInfo::get_bit(iss, "CV", Some("Condition code valid"), 24).describe_bit(describe_cv); 22 | let cond = FieldInfo::get( 23 | iss, 24 | "COND", 25 | Some("Condition code of the trapped instruction"), 26 | 20, 27 | 24, 28 | ); 29 | let opc2 = FieldInfo::get(iss, "Opc2", None, 17, 20); 30 | let opc1 = FieldInfo::get(iss, "Opc1", None, 14, 17); 31 | let crn = FieldInfo::get(iss, "CRn", None, 10, 14); 32 | let rt = FieldInfo::get(iss, "Rt", None, 5, 10); 33 | let crm = FieldInfo::get(iss, "CRm", None, 1, 5); 34 | let direction = FieldInfo::get_bit( 35 | iss, 36 | "Direction", 37 | Some("Direction of the trapped instruction"), 38 | 0, 39 | ) 40 | .describe_bit(describe_direction); 41 | 42 | Ok(vec![cv, cond, opc2, opc1, crn, rt, crm, direction]) 43 | } 44 | 45 | /// Decodes the ISS value for an MCRR or MRRC access. 46 | pub fn decode_iss_mcrr(iss: u64) -> Result, DecodeError> { 47 | let cv = 48 | FieldInfo::get_bit(iss, "CV", Some("Condition code valid"), 24).describe_bit(describe_cv); 49 | let cond = FieldInfo::get( 50 | iss, 51 | "COND", 52 | Some("Condition code of the trapped instruction"), 53 | 20, 54 | 24, 55 | ); 56 | let opc1 = FieldInfo::get(iss, "Opc2", None, 16, 20); 57 | let res0 = FieldInfo::get_bit(iss, "RES0", Some("Reserved"), 15).check_res0()?; 58 | let rt2 = FieldInfo::get(iss, "Rt2", None, 10, 15); 59 | let rt = FieldInfo::get(iss, "Rt", None, 5, 10); 60 | let crm = FieldInfo::get(iss, "CRm", None, 1, 5); 61 | let direction = FieldInfo::get_bit( 62 | iss, 63 | "Direction", 64 | Some("Direction of the trapped instruction"), 65 | 0, 66 | ) 67 | .describe_bit(describe_direction); 68 | 69 | Ok(vec![cv, cond, opc1, res0, rt2, rt, crm, direction]) 70 | } 71 | 72 | fn describe_direction(direction: bool) -> &'static str { 73 | if direction { 74 | "Read from system register (MRC or VMRS)" 75 | } else { 76 | "Write to system register (MCR)" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/esr/mod.rs: -------------------------------------------------------------------------------- 1 | mod abort; 2 | mod breakpoint; 3 | mod bti; 4 | mod common; 5 | mod fp; 6 | mod hvc; 7 | mod ld64b; 8 | mod ldc; 9 | mod mcr; 10 | mod msr; 11 | mod pauth; 12 | mod serror; 13 | mod sve; 14 | #[cfg(test)] 15 | mod tests; 16 | mod wf; 17 | 18 | use super::{DecodeError, FieldInfo}; 19 | use abort::{decode_iss_data_abort, decode_iss_instruction_abort}; 20 | use breakpoint::{ 21 | decode_iss_breakpoint, decode_iss_breakpoint_vector_catch, decode_iss_software_step, 22 | decode_iss_watchpoint, 23 | }; 24 | use bti::decode_iss_bti; 25 | use fp::decode_iss_fp; 26 | use hvc::decode_iss_hvc; 27 | use ld64b::decode_iss_ld64b; 28 | use ldc::decode_iss_ldc; 29 | use mcr::{decode_iss_mcr, decode_iss_mcrr}; 30 | use msr::decode_iss_msr; 31 | use pauth::decode_iss_pauth; 32 | use serror::decode_iss_serror; 33 | use sve::decode_iss_sve; 34 | use wf::decode_iss_wf; 35 | 36 | fn decode_iss_res0(iss: u64) -> Result, DecodeError> { 37 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 0, 25) 38 | .check_res0()? 39 | .with_description("ISS is RES0".to_string()); 40 | Ok(vec![res0]) 41 | } 42 | 43 | /// Decodes the given Exception Syndrome Register value, or returns an error if it is not valid. 44 | pub fn decode(esr: u64) -> Result, DecodeError> { 45 | let res0 = FieldInfo::get(esr, "RES0", Some("Reserved"), 37, 64).check_res0()?; 46 | let iss2 = FieldInfo::get(esr, "ISS2", None, 32, 37); 47 | let ec = FieldInfo::get(esr, "EC", Some("Exception Class"), 26, 32); 48 | let il = 49 | FieldInfo::get_bit(esr, "IL", Some("Instruction Length"), 25).describe_bit(describe_il); 50 | let iss = FieldInfo::get(esr, "ISS", Some("Instruction Specific Syndrome"), 0, 25); 51 | let (class, iss_subfields, iss_description) = match ec.value { 52 | 0b000000 => ("Unknown reason", decode_iss_res0(iss.value)?, None), 53 | 0b000001 => ( 54 | "Wrapped WF* instruction execution", 55 | decode_iss_wf(iss.value)?, 56 | None, 57 | ), 58 | 0b000011 => ( 59 | "Trapped MCR or MRC access with coproc=0b1111", 60 | decode_iss_mcr(iss.value)?, 61 | None, 62 | ), 63 | 0b000100 => ( 64 | "Trapped MCRR or MRRC access with coproc=0b1111", 65 | decode_iss_mcrr(iss.value)?, 66 | None, 67 | ), 68 | 0b000101 => ( 69 | "Trapped MCR or MRC access with coproc=0b1110", 70 | decode_iss_mcr(iss.value)?, 71 | None, 72 | ), 73 | 0b000110 => ( 74 | "Trapped LDC or STC access", 75 | decode_iss_ldc(iss.value)?, 76 | None, 77 | ), 78 | 0b000111 => ( 79 | "Trapped access to SVE, Advanced SIMD or floating point", 80 | decode_iss_sve(iss.value)?, 81 | None, 82 | ), 83 | 0b001010 => ( 84 | "Trapped execution of an LD64B, ST64B, ST64BV, or ST64BV0 instruction", 85 | decode_iss_ld64b(iss.value)?, 86 | None, 87 | ), 88 | 0b001100 => ( 89 | "Trapped MRRC access with (coproc==0b1110)", 90 | decode_iss_mcrr(iss.value)?, 91 | None, 92 | ), 93 | 0b001101 => ("Branch Target Exception", decode_iss_bti(iss.value)?, None), 94 | 0b001110 => ("Illegal Execution state", decode_iss_res0(iss.value)?, None), 95 | 0b010001 => ( 96 | "SVC instruction execution in AArch32 state", 97 | decode_iss_hvc(iss.value)?, 98 | None, 99 | ), 100 | 0b010101 => ( 101 | "SVC instruction execution in AArch64 state", 102 | decode_iss_hvc(iss.value)?, 103 | None, 104 | ), 105 | 0b010110 => ( 106 | "HVC instruction execution in AArch64 state", 107 | decode_iss_hvc(iss.value)?, 108 | None, 109 | ), 110 | 0b010111 => ( 111 | "SMC instruction execution in AArch64 state", 112 | decode_iss_hvc(iss.value)?, 113 | None, 114 | ), 115 | 0b011000 => { 116 | let (subfields, description) = decode_iss_msr(iss.value)?; 117 | ( 118 | "Trapped MSR, MRS or System instruction execution in AArch64 state", 119 | subfields, 120 | description, 121 | ) 122 | } 123 | 0b011001 => ( 124 | "Access to SVE functionality trapped as a result of CPACR_EL1.ZEN, CPTR_EL2.ZEN, \ 125 | CPTR_EL2.TZ, or CPTR_EL3.EZ", 126 | decode_iss_res0(iss.value)?, 127 | None, 128 | ), 129 | 0b011100 => ( 130 | "Exception from a Pointer Authentication instruction authentication failure", 131 | decode_iss_pauth(iss.value)?, 132 | None, 133 | ), 134 | 0b100000 => ( 135 | "Instruction Abort from a lower Exception level", 136 | decode_iss_instruction_abort(iss.value)?, 137 | None, 138 | ), 139 | 0b100001 => ( 140 | "Instruction Abort taken without a change in Exception level", 141 | decode_iss_instruction_abort(iss.value)?, 142 | None, 143 | ), 144 | 0b100010 => ( 145 | "PC alignment fault exception", 146 | decode_iss_res0(iss.value)?, 147 | None, 148 | ), 149 | 0b100100 => ( 150 | "Data Abort from a lower Exception level", 151 | decode_iss_data_abort(iss.value)?, 152 | None, 153 | ), 154 | 0b100101 => ( 155 | "Data Abort taken without a change in Exception level", 156 | decode_iss_data_abort(iss.value)?, 157 | None, 158 | ), 159 | 0b100110 => ( 160 | "SP alignment fault exception", 161 | decode_iss_res0(iss.value)?, 162 | None, 163 | ), 164 | 0b101000 => ( 165 | "Trapped floating-point exception taken from AArch32 state", 166 | decode_iss_fp(iss.value)?, 167 | None, 168 | ), 169 | 0b101100 => ( 170 | "Trapped floating-point exception taken from AArch64 state", 171 | decode_iss_fp(iss.value)?, 172 | None, 173 | ), 174 | 0b101111 => ("SError interrupt", decode_iss_serror(iss.value)?, None), 175 | 0b110000 => ( 176 | "Breakpoint exception from a lower Exception level", 177 | decode_iss_breakpoint_vector_catch(iss.value)?, 178 | None, 179 | ), 180 | 0b110001 => ( 181 | "Breakpoint exception taken without a change in Exception level", 182 | decode_iss_breakpoint_vector_catch(iss.value)?, 183 | None, 184 | ), 185 | 0b110010 => ( 186 | "Software Step exception from a lower Exception level", 187 | decode_iss_software_step(iss.value)?, 188 | None, 189 | ), 190 | 0b110011 => ( 191 | "Software Step exception taken without a change in Exception level", 192 | decode_iss_software_step(iss.value)?, 193 | None, 194 | ), 195 | 0b110100 => ( 196 | "Watchpoint exception from a lower Exception level", 197 | decode_iss_watchpoint(iss.value)?, 198 | None, 199 | ), 200 | 0b110101 => ( 201 | "Watchpoint exception taken without a change in Exception level", 202 | decode_iss_watchpoint(iss.value)?, 203 | None, 204 | ), 205 | 0b111000 => ( 206 | "BKPT instruction execution in AArch32 state", 207 | decode_iss_breakpoint(iss.value)?, 208 | None, 209 | ), 210 | 0b111100 => ( 211 | "BRK instruction execution in AArch64 state", 212 | decode_iss_breakpoint(iss.value)?, 213 | None, 214 | ), 215 | _ => return Err(DecodeError::InvalidEc { ec: ec.value }), 216 | }; 217 | let iss = FieldInfo { 218 | description: iss_description, 219 | subfields: iss_subfields, 220 | ..iss 221 | }; 222 | let ec = ec.with_description(class.to_string()); 223 | Ok(vec![res0, iss2, ec, il, iss]) 224 | } 225 | 226 | fn describe_il(il: bool) -> &'static str { 227 | if il { 228 | "32-bit instruction trapped" 229 | } else { 230 | "16-bit instruction trapped" 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/esr/msr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for an MSR or MRS instruction. 18 | pub fn decode_iss_msr(iss: u64) -> Result<(Vec, Option), DecodeError> { 19 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 22, 25).check_res0()?; 20 | let op0 = FieldInfo::get(iss, "Op0", None, 20, 22); 21 | let op2 = FieldInfo::get(iss, "Op2", None, 17, 20); 22 | let op1 = FieldInfo::get(iss, "Op1", None, 14, 17); 23 | let crn = FieldInfo::get(iss, "CRn", None, 10, 14); 24 | let rt = FieldInfo::get( 25 | iss, 26 | "Rt", 27 | Some("General-purpose register number of the trapped instruction"), 28 | 5, 29 | 10, 30 | ); 31 | let crm = FieldInfo::get(iss, "CRm", None, 1, 5); 32 | let direction = FieldInfo::get_bit( 33 | iss, 34 | "Direction", 35 | Some("Direction of the trapped instruction"), 36 | 0, 37 | ) 38 | .describe_bit(describe_direction); 39 | 40 | let name = sysreg_name(op0.value, op1.value, op2.value, crn.value, crm.value); 41 | let description = if direction.value == 0 { 42 | format!("MSR {}, x{}", name, rt.value) 43 | } else { 44 | format!("MRS x{}, {}", rt.value, name) 45 | }; 46 | 47 | Ok(( 48 | vec![res0, op0, op2, op1, crn, rt, crm, direction], 49 | Some(description), 50 | )) 51 | } 52 | 53 | fn describe_direction(direction: bool) -> &'static str { 54 | if direction { 55 | "Read from system register (MRS)" 56 | } else { 57 | "Write to system register (MSR)" 58 | } 59 | } 60 | 61 | fn sysreg_name(op0: u64, op1: u64, op2: u64, crn: u64, crm: u64) -> &'static str { 62 | match (op0, crn, op1, crm, op2) { 63 | (3, 1, 0, 0, 1) => "ACTLR_EL1", 64 | (3, 1, 4, 0, 1) => "ACTLR_EL2", 65 | (3, 1, 6, 0, 1) => "ACTLR_EL3", 66 | (3, 0, 1, 0, 7) => "AIDR_EL1", 67 | (3, 5, 0, 1, 0) => "AFSR0_EL1", 68 | (3, 5, 4, 1, 0) => "AFSR0_EL2", 69 | (3, 5, 6, 1, 0) => "AFSR0_EL3", 70 | (3, 5, 0, 1, 1) => "AFSR1_EL1", 71 | (3, 5, 4, 1, 1) => "AFSR1_EL2", 72 | (3, 5, 6, 1, 1) => "AFSR1_EL3", 73 | (3, 10, 0, 3, 0) => "AMAIR_EL1", 74 | (3, 10, 4, 3, 0) => "AMAIR_EL2", 75 | (3, 10, 6, 3, 0) => "AMAIR_EL3", 76 | (3, 0, 1, 0, 0) => "CCSIDR_EL1", 77 | (3, 0, 1, 0, 1) => "CLIDR_EL1", 78 | (3, 1, 0, 0, 2) => "CPACR_EL1", 79 | (3, 1, 4, 1, 2) => "CPTR_EL2", 80 | (3, 1, 6, 1, 2) => "CPTR_EL3", 81 | (3, 0, 2, 0, 0) => "CSSELR_EL1", 82 | (3, 0, 3, 0, 1) => "CTR_EL0", 83 | (3, 12, 0, 1, 1) => "DISR_EL1", 84 | (3, 5, 0, 3, 0) => "ERRIDR_EL1", 85 | (3, 5, 0, 3, 1) => "ERRSELR_EL1", 86 | (3, 5, 0, 4, 3) => "ERXADDR_EL1", 87 | (3, 5, 0, 4, 1) => "ERXCTLR_EL1", 88 | (3, 5, 0, 4, 0) => "ERXFR_EL1", 89 | (3, 5, 0, 5, 0) => "ERXMISC0_EL1", 90 | (3, 5, 0, 5, 1) => "ERXMISC1_EL1", 91 | (3, 5, 0, 4, 2) => "ERXSTATUS_EL1", 92 | (3, 5, 0, 2, 0) => "ESR_EL1", 93 | (3, 5, 4, 2, 0) => "ESR_EL2", 94 | (3, 5, 6, 2, 0) => "ESR_EL3", 95 | (3, 1, 4, 1, 7) => "HACR_EL2", 96 | (3, 1, 4, 1, 0) => "HCR_EL2", 97 | (3, 0, 0, 1, 3) => "ID_AFR0_EL1", 98 | (3, 0, 0, 1, 2) => "ID_DFR0_EL1", 99 | (3, 0, 0, 2, 0) => "ID_ISAR0_EL1", 100 | (3, 0, 0, 2, 1) => "ID_ISAR1_EL1", 101 | (3, 0, 0, 2, 2) => "ID_ISAR2_EL1", 102 | (3, 0, 0, 2, 3) => "ID_ISAR3_EL1", 103 | (3, 0, 0, 2, 4) => "ID_ISAR4_EL1", 104 | (3, 0, 0, 2, 5) => "ID_ISAR5_EL1", 105 | (3, 0, 0, 2, 7) => "ID_ISAR6_EL1", 106 | (3, 0, 0, 1, 4) => "ID_MMFR0_EL1", 107 | (3, 0, 0, 1, 5) => "ID_MMFR1_EL1", 108 | (3, 0, 0, 1, 6) => "ID_MMFR2_EL1", 109 | (3, 0, 0, 1, 7) => "ID_MMFR3_EL1", 110 | (3, 0, 0, 2, 6) => "ID_MMFR4_EL1", 111 | (3, 0, 0, 1, 0) => "ID_PFR0_EL1", 112 | (3, 0, 0, 1, 1) => "ID_PFR1_EL1", 113 | (3, 0, 0, 3, 4) => "ID_PFR2_EL1", 114 | (3, 0, 0, 5, 0) => "ID_AA64DFR0_EL1", 115 | (3, 0, 0, 6, 0) => "ID_AA64ISAR0_EL1", 116 | (3, 0, 0, 6, 1) => "ID_AA64ISAR1_EL1", 117 | (3, 0, 0, 7, 0) => "ID_AA64MMFR0_EL1", 118 | (3, 0, 0, 7, 1) => "ID_AA64MMFR1_EL1", 119 | (3, 0, 0, 7, 2) => "ID_AA64MMFR2_EL1", 120 | (3, 0, 0, 4, 0) => "ID_AA64PFR0_EL1", 121 | (3, 5, 4, 0, 1) => "IFSR32_EL2", 122 | (3, 10, 0, 4, 3) => "LORC_EL1", 123 | (3, 10, 0, 4, 7) => "LORID_EL1", 124 | (3, 10, 0, 4, 2) => "LORN_EL1", 125 | (3, 1, 6, 3, 1) => "MDCR_EL3", 126 | (3, 0, 0, 0, 0) => "MIDR_EL1", 127 | (3, 0, 0, 0, 5) => "MPIDR_EL1", 128 | (3, 7, 0, 4, 0) => "PAR_EL1", 129 | (3, 12, 6, 0, 1) => "RVBAR_EL3", 130 | (3, 0, 0, 0, 6) => "REVIDR_EL1", 131 | (3, 1, 0, 0, 0) => "SCTLR_EL1", 132 | (3, 1, 6, 0, 0) => "SCTLR_EL3", 133 | (3, 2, 0, 0, 2) => "TCR_EL1", 134 | (3, 2, 4, 0, 2) => "TCR_EL2", 135 | (3, 2, 6, 0, 2) => "TCR_EL3", 136 | (3, 2, 0, 0, 0) => "TTBR0_EL1", 137 | (3, 2, 4, 0, 0) => "TTBR0_EL2", 138 | (3, 2, 6, 0, 0) => "TTBR0_EL3", 139 | (3, 2, 0, 0, 1) => "TTBR1_EL1", 140 | (3, 2, 4, 0, 1) => "TTBR1_EL2", 141 | (3, 12, 4, 1, 1) => "VDISR_EL2", 142 | (3, 5, 4, 2, 3) => "VSESR_EL2", 143 | (3, 2, 4, 1, 2) => "VTCR_EL2", 144 | (3, 2, 4, 1, 0) => "VTTBR_EL2", 145 | (3, 5, 5, 1, 0) => "AFSR0_EL12", 146 | (3, 5, 5, 1, 1) => "AFSR1_EL12", 147 | (3, 10, 5, 3, 0) => "AMAIR_EL12", 148 | (3, 14, 3, 0, 0) => "CNTFRQ_EL0", 149 | (3, 14, 4, 1, 0) => "CNTHCTL_EL2", 150 | (3, 14, 4, 2, 1) => "CNTHP_CTL_EL2", 151 | (3, 14, 4, 2, 2) => "CNTHP_CVAL_EL2", 152 | (3, 14, 4, 2, 0) => "CNTHP_TVAL_EL2", 153 | (3, 14, 4, 3, 1) => "CNTHV_CTL_EL2", 154 | (3, 14, 4, 3, 2) => "CNTHV_CVAL_EL2", 155 | (3, 14, 4, 3, 0) => "CNTHV_TVAL_EL2", 156 | (3, 14, 0, 1, 0) => "CNTKCTL_EL1", 157 | (3, 14, 5, 1, 0) => "CNTKCTL_EL12", 158 | (3, 14, 3, 2, 1) => "CNTP_CTL_EL0", 159 | (3, 14, 5, 2, 1) => "CNTP_CTL_EL02", 160 | (3, 14, 3, 2, 2) => "CNTP_CVAL_EL0", 161 | (3, 14, 5, 2, 2) => "CNTP_CVAL_EL02", 162 | (3, 14, 3, 2, 0) => "CNTP_TVAL_EL0", 163 | (3, 14, 5, 2, 0) => "CNTP_TVAL_EL02", 164 | (3, 14, 3, 0, 1) => "CNTPCT_EL0", 165 | (3, 14, 7, 2, 1) => "CNTPS_CTL_EL1", 166 | (3, 14, 7, 2, 2) => "CNTPS_CVAL_EL1", 167 | (3, 14, 7, 2, 0) => "CNTPS_TVAL_EL1", 168 | (3, 14, 3, 3, 1) => "CNTV_CTL_EL0", 169 | (3, 14, 5, 3, 1) => "CNTV_CTL_EL02", 170 | (3, 14, 3, 3, 2) => "CNTV_CVAL_EL0", 171 | (3, 14, 5, 3, 2) => "CNTV_CVAL_EL02", 172 | (3, 14, 3, 3, 0) => "CNTV_TVAL_EL0", 173 | (3, 14, 5, 3, 0) => "CNTV_TVAL_EL02", 174 | (3, 14, 3, 0, 2) => "CNTVCT_EL0", 175 | (3, 14, 4, 0, 3) => "CNTVOFF_EL2", 176 | (3, 13, 0, 0, 1) => "CONTEXTIDR_EL1", 177 | (3, 13, 5, 0, 1) => "CONTEXTIDR_EL12", 178 | (3, 13, 4, 0, 1) => "CONTEXTIDR_EL2", 179 | (3, 1, 5, 0, 2) => "CPACR_EL12", 180 | (3, 3, 4, 0, 0) => "DACR32_EL2", 181 | (3, 5, 5, 2, 0) => "ESR_EL12", 182 | (3, 6, 0, 0, 0) => "FAR_EL1", 183 | (3, 6, 5, 0, 0) => "FAR_EL12", 184 | (3, 6, 4, 0, 0) => "FAR_EL2", 185 | (3, 6, 6, 0, 0) => "FAR_EL3", 186 | (3, 5, 4, 3, 0) => "FPEXC32_EL2", 187 | (3, 6, 4, 0, 4) => "HPFAR_EL2", 188 | (3, 1, 4, 1, 3) => "HSTR_EL2", 189 | (3, 0, 0, 5, 4) => "ID_AA64AFR0_EL1", 190 | (3, 0, 0, 5, 5) => "ID_AA64AFR1_EL1", 191 | (3, 0, 0, 5, 1) => "ID_AA64DFR1_EL1", 192 | (3, 0, 0, 4, 1) => "ID_AA64PFR1_EL1", 193 | (3, 12, 0, 1, 0) => "ISR_EL1", 194 | (3, 10, 0, 4, 1) => "LOREA_EL1", 195 | (3, 10, 0, 4, 0) => "LORSA_EL1", 196 | (3, 10, 0, 2, 0) => "MAIR_EL1", 197 | (3, 10, 5, 2, 0) => "MAIR_EL12", 198 | (3, 10, 4, 2, 0) => "MAIR_EL2", 199 | (3, 10, 6, 2, 0) => "MAIR_EL3", 200 | (3, 1, 4, 1, 1) => "MDCR_EL2", 201 | (3, 0, 0, 3, 0) => "MVFR0_EL1", 202 | (3, 0, 0, 3, 1) => "MVFR1_EL1", 203 | (3, 0, 0, 3, 2) => "MVFR2_EL1", 204 | (3, 12, 6, 0, 2) => "RMR_EL3", 205 | (3, 1, 6, 1, 0) => "SCR_EL3", 206 | (3, 1, 5, 0, 0) => "SCTLR_EL12", 207 | (3, 1, 4, 0, 0) => "SCTLR_EL2", 208 | (3, 1, 6, 1, 1) => "SDER32_EL3", 209 | (3, 2, 5, 0, 2) => "TCR_EL12", 210 | (3, 13, 3, 0, 2) => "TPIDR_EL0", 211 | (3, 13, 0, 0, 4) => "TPIDR_EL1", 212 | (3, 13, 4, 0, 2) => "TPIDR_EL2", 213 | (3, 13, 6, 0, 2) => "TPIDR_EL3", 214 | (3, 13, 3, 0, 3) => "TPIDRRO_EL0", 215 | (3, 2, 5, 0, 0) => "TTBR0_EL12", 216 | (3, 2, 5, 0, 1) => "TTBR1_EL12", 217 | (3, 12, 0, 0, 0) => "VBAR_EL1", 218 | (3, 12, 5, 0, 0) => "VBAR_EL12", 219 | (3, 12, 4, 0, 0) => "VBAR_EL2", 220 | (3, 12, 6, 0, 0) => "VBAR_EL3", 221 | (3, 0, 4, 0, 5) => "VMPIDR_EL2", 222 | (3, 0, 4, 0, 0) => "VPIDR_EL2", 223 | _ => "unknown", 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/esr/pauth.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for a Pointer Authentication failure. 18 | pub fn decode_iss_pauth(iss: u64) -> Result, DecodeError> { 19 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 2, 25).check_res0()?; 20 | let instruction_or_data = 21 | FieldInfo::get_bit(iss, "IorD", Some("Instruction key or Data key"), 1) 22 | .describe_bit(describe_instruction_or_data); 23 | let a_or_b = 24 | FieldInfo::get_bit(iss, "AorB", Some("A key or B key"), 0).describe_bit(describe_a_or_b); 25 | 26 | Ok(vec![res0, instruction_or_data, a_or_b]) 27 | } 28 | 29 | fn describe_instruction_or_data(instruction_or_data: bool) -> &'static str { 30 | if instruction_or_data { 31 | "Data Key" 32 | } else { 33 | "Instruction Key" 34 | } 35 | } 36 | 37 | fn describe_a_or_b(a_or_b: bool) -> &'static str { 38 | if a_or_b { 39 | "B Key" 40 | } else { 41 | "A Key" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/esr/serror.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the ISS value for an SError interrupt. 18 | pub fn decode_iss_serror(iss: u64) -> Result, DecodeError> { 19 | let ids = FieldInfo::get_bit(iss, "IDS", Some("Implementation Defined Syndrome"), 24) 20 | .describe_bit(describe_ids); 21 | let platform_fields = if ids.as_bit() { 22 | let impdef = FieldInfo::get(iss, "IMPDEF", Some("Implementation defined"), 0, 24); 23 | vec![impdef] 24 | } else { 25 | let dfsc = FieldInfo::get(iss, "DFSC", Some("Data Fault Status Code"), 0, 6) 26 | .describe(describe_dfsc)?; 27 | 28 | let res0a = FieldInfo::get(iss, "RES0", Some("Reserved"), 14, 24).check_res0()?; 29 | let iesb = if dfsc.value == 0b010001 { 30 | FieldInfo::get_bit( 31 | iss, 32 | "IESB", 33 | Some("Implicit Error Synchronisation event"), 34 | 13, 35 | ) 36 | .describe_bit(describe_iesb) 37 | } else { 38 | FieldInfo::get_bit(iss, "RES0", Some("Reserved for this DFSC value"), 13) 39 | .check_res0()? 40 | }; 41 | let aet = FieldInfo::get(iss, "AET", Some("Asynchronous Error Type"), 10, 13) 42 | .describe(describe_aet)?; 43 | let ea = FieldInfo::get_bit(iss, "EA", Some("External Abort type"), 9); 44 | let res0b = FieldInfo::get(iss, "RES0", Some("Reserved"), 6, 9).check_res0()?; 45 | vec![res0a, iesb, aet, ea, res0b, dfsc] 46 | }; 47 | 48 | let mut fields = vec![ids]; 49 | fields.extend(platform_fields); 50 | Ok(fields) 51 | } 52 | 53 | fn describe_ids(ids: bool) -> &'static str { 54 | if ids { 55 | "The rest of the ISS is encoded in an implementation-defined format" 56 | } else { 57 | "The rest of the ISS is encoded according to the platform" 58 | } 59 | } 60 | 61 | fn describe_iesb(iesb: bool) -> &'static str { 62 | if iesb { 63 | "The SError interrupt was synchronized by the implicit error synchronization event and taken immediately." 64 | } else { 65 | "The SError interrupt was not synchronized by the implicit error synchronization event or not taken immediately." 66 | } 67 | } 68 | 69 | fn describe_aet(aet: u64) -> Result<&'static str, DecodeError> { 70 | match aet { 71 | 0b000 => Ok("Uncontainable (UC)"), 72 | 0b001 => Ok("Unrecoverable state (UEU)"), 73 | 0b010 => Ok("Restartable state (UEO)"), 74 | 0b011 => Ok("Recoverable state (UER)"), 75 | 0x110 => Ok("Corrected (CE)"), 76 | _ => Err(DecodeError::InvalidAet { aet }), 77 | } 78 | } 79 | 80 | fn describe_dfsc(dfsc: u64) -> Result<&'static str, DecodeError> { 81 | match dfsc { 82 | 0b000000 => Ok("Uncategorized error"), 83 | 0b010001 => Ok("Asynchronous SError interrupt"), 84 | _ => Err(DecodeError::InvalidFsc { fsc: dfsc }), 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/esr/sve.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::common::describe_cv; 16 | use crate::{DecodeError, FieldInfo}; 17 | 18 | /// Decodes the ISS value for a trapped SVE, Advanced SIMD or FP instruction. 19 | pub fn decode_iss_sve(iss: u64) -> Result, DecodeError> { 20 | let cv = 21 | FieldInfo::get_bit(iss, "CV", Some("Condition code valid"), 24).describe_bit(describe_cv); 22 | let cond = FieldInfo::get( 23 | iss, 24 | "COND", 25 | Some("Condition code of the trapped instruction"), 26 | 20, 27 | 24, 28 | ); 29 | let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 0, 20).check_res0()?; 30 | 31 | Ok(vec![cv, cond, res0]) 32 | } 33 | -------------------------------------------------------------------------------- /src/esr/tests.rs: -------------------------------------------------------------------------------- 1 | use super::decode; 2 | use crate::FieldInfo; 3 | 4 | #[test] 5 | fn unknown() { 6 | let decoded = decode(0).unwrap(); 7 | assert_eq!( 8 | decoded, 9 | vec![ 10 | FieldInfo { 11 | name: "RES0", 12 | long_name: Some("Reserved"), 13 | start: 37, 14 | width: 27, 15 | value: 0, 16 | description: None, 17 | subfields: vec![], 18 | }, 19 | FieldInfo { 20 | name: "ISS2", 21 | long_name: None, 22 | start: 32, 23 | width: 5, 24 | value: 0, 25 | description: None, 26 | subfields: vec![], 27 | }, 28 | FieldInfo { 29 | name: "EC", 30 | long_name: Some("Exception Class"), 31 | start: 26, 32 | width: 6, 33 | value: 0, 34 | description: Some("Unknown reason".to_string()), 35 | subfields: vec![], 36 | }, 37 | FieldInfo { 38 | name: "IL", 39 | long_name: Some("Instruction Length"), 40 | start: 25, 41 | width: 1, 42 | value: 0, 43 | description: Some("16-bit instruction trapped".to_string()), 44 | subfields: vec![], 45 | }, 46 | FieldInfo { 47 | name: "ISS", 48 | long_name: Some("Instruction Specific Syndrome"), 49 | start: 0, 50 | width: 25, 51 | value: 0, 52 | description: None, 53 | subfields: vec![FieldInfo { 54 | name: "RES0", 55 | long_name: Some("Reserved"), 56 | start: 0, 57 | width: 25, 58 | value: 0, 59 | description: Some("ISS is RES0".to_string()), 60 | subfields: vec![], 61 | }], 62 | }, 63 | ] 64 | ); 65 | } 66 | 67 | #[test] 68 | fn data_abort() { 69 | assert_eq!( 70 | decode(0x96000050).unwrap(), 71 | vec![ 72 | FieldInfo { 73 | name: "RES0", 74 | long_name: Some("Reserved"), 75 | start: 37, 76 | width: 27, 77 | value: 0, 78 | description: None, 79 | subfields: vec![], 80 | }, 81 | FieldInfo { 82 | name: "ISS2", 83 | long_name: None, 84 | start: 32, 85 | width: 5, 86 | value: 0, 87 | description: None, 88 | subfields: vec![], 89 | }, 90 | FieldInfo { 91 | name: "EC", 92 | long_name: Some("Exception Class"), 93 | start: 26, 94 | width: 6, 95 | value: 37, 96 | description: Some( 97 | "Data Abort taken without a change in Exception level".to_string() 98 | ), 99 | subfields: vec![], 100 | }, 101 | FieldInfo { 102 | name: "IL", 103 | long_name: Some("Instruction Length"), 104 | start: 25, 105 | width: 1, 106 | value: 1, 107 | description: Some("32-bit instruction trapped".to_string()), 108 | subfields: vec![], 109 | }, 110 | FieldInfo { 111 | name: "ISS", 112 | long_name: Some("Instruction Specific Syndrome"), 113 | start: 0, 114 | width: 25, 115 | value: 80, 116 | description: None, 117 | subfields: vec![ 118 | FieldInfo { 119 | name: "ISV", 120 | long_name: Some("Instruction Syndrome Valid"), 121 | start: 24, 122 | width: 1, 123 | value: 0, 124 | description: Some("No valid instruction syndrome".to_string()), 125 | subfields: vec![], 126 | }, 127 | FieldInfo { 128 | name: "RES0", 129 | long_name: Some("Reserved"), 130 | start: 14, 131 | width: 10, 132 | value: 0, 133 | description: None, 134 | subfields: vec![], 135 | }, 136 | FieldInfo { 137 | name: "VNCR", 138 | long_name: None, 139 | start: 13, 140 | width: 1, 141 | value: 0, 142 | description: None, 143 | subfields: vec![], 144 | }, 145 | FieldInfo { 146 | name: "SET", 147 | long_name: Some("Synchronous Error Type"), 148 | start: 11, 149 | width: 2, 150 | value: 0, 151 | description: Some("Recoverable state (UER)".to_string()), 152 | subfields: vec![], 153 | }, 154 | FieldInfo { 155 | name: "FnV", 156 | long_name: Some("FAR not Valid"), 157 | start: 10, 158 | width: 1, 159 | value: 0, 160 | description: Some("FAR is valid".to_string()), 161 | subfields: vec![], 162 | }, 163 | FieldInfo { 164 | name: "EA", 165 | long_name: Some("External abort type"), 166 | start: 9, 167 | width: 1, 168 | value: 0, 169 | description: None, 170 | subfields: vec![], 171 | }, 172 | FieldInfo { 173 | name: "CM", 174 | long_name: Some("Cache Maintenance"), 175 | start: 8, 176 | width: 1, 177 | value: 0, 178 | description: None, 179 | subfields: vec![], 180 | }, 181 | FieldInfo { 182 | name: "S1PTW", 183 | long_name: Some("Stage-1 translation table walk"), 184 | start: 7, 185 | width: 1, 186 | value: 0, 187 | description: None, 188 | subfields: vec![], 189 | }, 190 | FieldInfo { 191 | name: "WnR", 192 | long_name: Some("Write not Read"), 193 | start: 6, 194 | width: 1, 195 | value: 1, 196 | description: Some("Abort caused by writing to memory".to_string()), 197 | subfields: vec![], 198 | }, 199 | FieldInfo { 200 | name: "DFSC", 201 | long_name: Some("Data Fault Status Code"), 202 | start: 0, 203 | width: 6, 204 | value: 16, 205 | description: Some( 206 | "Synchronous External abort, not on translation table \ 207 | walk or hardware update of translation table." 208 | .to_string() 209 | ), 210 | subfields: vec![], 211 | } 212 | ] 213 | }, 214 | ], 215 | ); 216 | } 217 | 218 | #[test] 219 | fn data_abort_isv() { 220 | assert_eq!( 221 | decode(0x97523050).unwrap(), 222 | vec![ 223 | FieldInfo { 224 | name: "RES0", 225 | long_name: Some("Reserved"), 226 | start: 37, 227 | width: 27, 228 | value: 0, 229 | description: None, 230 | subfields: vec![], 231 | }, 232 | FieldInfo { 233 | name: "ISS2", 234 | long_name: None, 235 | start: 32, 236 | width: 5, 237 | value: 0, 238 | description: None, 239 | subfields: vec![], 240 | }, 241 | FieldInfo { 242 | name: "EC", 243 | long_name: Some("Exception Class"), 244 | start: 26, 245 | width: 6, 246 | value: 37, 247 | description: Some( 248 | "Data Abort taken without a change in Exception level".to_string() 249 | ), 250 | subfields: vec![], 251 | }, 252 | FieldInfo { 253 | name: "IL", 254 | long_name: Some("Instruction Length"), 255 | start: 25, 256 | width: 1, 257 | value: 1, 258 | description: Some("32-bit instruction trapped".to_string()), 259 | subfields: vec![], 260 | }, 261 | FieldInfo { 262 | name: "ISS", 263 | long_name: Some("Instruction Specific Syndrome"), 264 | start: 0, 265 | width: 25, 266 | value: 22163536, 267 | description: None, 268 | subfields: vec![ 269 | FieldInfo { 270 | name: "ISV", 271 | long_name: Some("Instruction Syndrome Valid"), 272 | start: 24, 273 | width: 1, 274 | value: 1, 275 | description: Some("Valid instruction syndrome".to_string()), 276 | subfields: vec![], 277 | }, 278 | FieldInfo { 279 | name: "SAS", 280 | long_name: Some("Syndrome Access Size"), 281 | start: 22, 282 | width: 2, 283 | value: 1, 284 | description: Some("halfword".to_string()), 285 | subfields: vec![], 286 | }, 287 | FieldInfo { 288 | name: "SSE", 289 | long_name: Some("Syndrome Sign Extend"), 290 | start: 21, 291 | width: 1, 292 | value: 0, 293 | description: None, 294 | subfields: vec![], 295 | }, 296 | FieldInfo { 297 | name: "SRT", 298 | long_name: Some("Syndrome Register Transfer"), 299 | start: 16, 300 | width: 5, 301 | value: 18, 302 | description: None, 303 | subfields: vec![], 304 | }, 305 | FieldInfo { 306 | name: "SF", 307 | long_name: Some("Sixty-Four"), 308 | start: 15, 309 | width: 1, 310 | value: 0, 311 | description: Some("32-bit wide register".to_string()), 312 | subfields: vec![], 313 | }, 314 | FieldInfo { 315 | name: "AR", 316 | long_name: Some("Acquire/Release"), 317 | start: 14, 318 | width: 1, 319 | value: 0, 320 | description: Some("No acquire/release semantics".to_string()), 321 | subfields: vec![], 322 | }, 323 | FieldInfo { 324 | name: "VNCR", 325 | long_name: None, 326 | start: 13, 327 | width: 1, 328 | value: 1, 329 | description: None, 330 | subfields: vec![], 331 | }, 332 | FieldInfo { 333 | name: "SET", 334 | long_name: Some("Synchronous Error Type"), 335 | start: 11, 336 | width: 2, 337 | value: 2, 338 | description: Some("Uncontainable (UC)".to_string()), 339 | subfields: vec![], 340 | }, 341 | FieldInfo { 342 | name: "FnV", 343 | long_name: Some("FAR not Valid"), 344 | start: 10, 345 | width: 1, 346 | value: 0, 347 | description: Some("FAR is valid".to_string()), 348 | subfields: vec![], 349 | }, 350 | FieldInfo { 351 | name: "EA", 352 | long_name: Some("External abort type"), 353 | start: 9, 354 | width: 1, 355 | value: 0, 356 | description: None, 357 | subfields: vec![], 358 | }, 359 | FieldInfo { 360 | name: "CM", 361 | long_name: Some("Cache Maintenance"), 362 | start: 8, 363 | width: 1, 364 | value: 0, 365 | description: None, 366 | subfields: vec![], 367 | }, 368 | FieldInfo { 369 | name: "S1PTW", 370 | long_name: Some("Stage-1 translation table walk"), 371 | start: 7, 372 | width: 1, 373 | value: 0, 374 | description: None, 375 | subfields: vec![], 376 | }, 377 | FieldInfo { 378 | name: "WnR", 379 | long_name: Some("Write not Read"), 380 | start: 6, 381 | width: 1, 382 | value: 1, 383 | description: Some("Abort caused by writing to memory".to_string()), 384 | subfields: vec![], 385 | }, 386 | FieldInfo { 387 | name: "DFSC", 388 | long_name: Some("Data Fault Status Code"), 389 | start: 0, 390 | width: 6, 391 | value: 16, 392 | description: Some( 393 | "Synchronous External abort, not on translation table \ 394 | walk or hardware update of translation table." 395 | .to_string() 396 | ), 397 | subfields: vec![], 398 | } 399 | ] 400 | } 401 | ], 402 | ); 403 | } 404 | 405 | #[test] 406 | fn instruction_abort() { 407 | assert_eq!( 408 | decode(0x82001e10).unwrap(), 409 | vec![ 410 | FieldInfo { 411 | name: "RES0", 412 | long_name: Some("Reserved"), 413 | start: 37, 414 | width: 27, 415 | value: 0, 416 | description: None, 417 | subfields: vec![], 418 | }, 419 | FieldInfo { 420 | name: "ISS2", 421 | long_name: None, 422 | start: 32, 423 | width: 5, 424 | value: 0, 425 | description: None, 426 | subfields: vec![], 427 | }, 428 | FieldInfo { 429 | name: "EC", 430 | long_name: Some("Exception Class"), 431 | start: 26, 432 | width: 6, 433 | value: 32, 434 | description: Some("Instruction Abort from a lower Exception level".to_string()), 435 | subfields: vec![], 436 | }, 437 | FieldInfo { 438 | name: "IL", 439 | long_name: Some("Instruction Length"), 440 | start: 25, 441 | width: 1, 442 | value: 1, 443 | description: Some("32-bit instruction trapped".to_string()), 444 | subfields: vec![], 445 | }, 446 | FieldInfo { 447 | name: "ISS", 448 | long_name: Some("Instruction Specific Syndrome"), 449 | start: 0, 450 | width: 25, 451 | value: 7696, 452 | description: None, 453 | subfields: vec![ 454 | FieldInfo { 455 | name: "RES0", 456 | long_name: Some("Reserved"), 457 | start: 13, 458 | width: 12, 459 | value: 0, 460 | description: None, 461 | subfields: vec![], 462 | }, 463 | FieldInfo { 464 | name: "SET", 465 | long_name: Some("Synchronous Error Type"), 466 | start: 11, 467 | width: 2, 468 | value: 3, 469 | description: Some("Restartable state (UEO)".to_string()), 470 | subfields: vec![], 471 | }, 472 | FieldInfo { 473 | name: "FnV", 474 | long_name: Some("FAR not Valid"), 475 | start: 10, 476 | width: 1, 477 | value: 1, 478 | description: Some( 479 | "FAR is not valid, it holds an unknown value".to_string() 480 | ), 481 | subfields: vec![], 482 | }, 483 | FieldInfo { 484 | name: "EA", 485 | long_name: Some("External abort type"), 486 | start: 9, 487 | width: 1, 488 | value: 1, 489 | description: None, 490 | subfields: vec![], 491 | }, 492 | FieldInfo { 493 | name: "RES0", 494 | long_name: Some("Reserved"), 495 | start: 8, 496 | width: 1, 497 | value: 0, 498 | description: None, 499 | subfields: vec![], 500 | }, 501 | FieldInfo { 502 | name: "S1PTW", 503 | long_name: Some("Stage-1 translation table walk"), 504 | start: 7, 505 | width: 1, 506 | value: 0, 507 | description: None, 508 | subfields: vec![], 509 | }, 510 | FieldInfo { 511 | name: "RES0", 512 | long_name: Some("Reserved"), 513 | start: 6, 514 | width: 1, 515 | value: 0, 516 | description: None, 517 | subfields: vec![], 518 | }, 519 | FieldInfo { 520 | name: "IFSC", 521 | long_name: Some("Instruction Fault Status Code"), 522 | start: 0, 523 | width: 6, 524 | value: 16, 525 | description: Some( 526 | "Synchronous External abort, not on translation table \ 527 | walk or hardware update of translation table." 528 | .to_string() 529 | ), 530 | subfields: vec![], 531 | } 532 | ] 533 | } 534 | ] 535 | ); 536 | } 537 | 538 | #[test] 539 | fn sve() { 540 | assert_eq!( 541 | decode(0x1f300000).unwrap(), 542 | vec![ 543 | FieldInfo { 544 | name: "RES0", 545 | long_name: Some("Reserved"), 546 | start: 37, 547 | width: 27, 548 | value: 0, 549 | description: None, 550 | subfields: vec![], 551 | }, 552 | FieldInfo { 553 | name: "ISS2", 554 | long_name: None, 555 | start: 32, 556 | width: 5, 557 | value: 0, 558 | description: None, 559 | subfields: vec![], 560 | }, 561 | FieldInfo { 562 | name: "EC", 563 | long_name: Some("Exception Class"), 564 | start: 26, 565 | width: 6, 566 | value: 7, 567 | description: Some( 568 | "Trapped access to SVE, Advanced SIMD or floating point".to_string() 569 | ), 570 | subfields: vec![] 571 | }, 572 | FieldInfo { 573 | name: "IL", 574 | long_name: Some("Instruction Length"), 575 | start: 25, 576 | width: 1, 577 | value: 1, 578 | description: Some("32-bit instruction trapped".to_string()), 579 | subfields: vec![] 580 | }, 581 | FieldInfo { 582 | name: "ISS", 583 | long_name: Some("Instruction Specific Syndrome"), 584 | start: 0, 585 | width: 25, 586 | value: 19922944, 587 | description: None, 588 | subfields: vec![ 589 | FieldInfo { 590 | name: "CV", 591 | long_name: Some("Condition code valid"), 592 | start: 24, 593 | width: 1, 594 | value: 1, 595 | description: Some("COND is valid".to_string()), 596 | subfields: vec![] 597 | }, 598 | FieldInfo { 599 | name: "COND", 600 | long_name: Some("Condition code of the trapped instruction"), 601 | start: 20, 602 | width: 4, 603 | value: 3, 604 | description: None, 605 | subfields: vec![] 606 | }, 607 | FieldInfo { 608 | name: "RES0", 609 | long_name: Some("Reserved"), 610 | start: 0, 611 | width: 20, 612 | value: 0, 613 | description: None, 614 | subfields: vec![] 615 | } 616 | ] 617 | }, 618 | ] 619 | ); 620 | } 621 | 622 | #[test] 623 | fn ld64b() { 624 | assert_eq!( 625 | decode(0x2a000002).unwrap(), 626 | vec![ 627 | FieldInfo { 628 | name: "RES0", 629 | long_name: Some("Reserved"), 630 | start: 37, 631 | width: 27, 632 | value: 0, 633 | description: None, 634 | subfields: vec![], 635 | }, 636 | FieldInfo { 637 | name: "ISS2", 638 | long_name: None, 639 | start: 32, 640 | width: 5, 641 | value: 0, 642 | description: None, 643 | subfields: vec![], 644 | }, 645 | FieldInfo { 646 | name: "EC", 647 | long_name: Some("Exception Class"), 648 | start: 26, 649 | width: 6, 650 | value: 10, 651 | description: Some( 652 | "Trapped execution of an LD64B, ST64B, ST64BV, or ST64BV0 instruction" 653 | .to_string() 654 | ), 655 | subfields: vec![] 656 | }, 657 | FieldInfo { 658 | name: "IL", 659 | long_name: Some("Instruction Length"), 660 | start: 25, 661 | width: 1, 662 | value: 1, 663 | description: Some("32-bit instruction trapped".to_string()), 664 | subfields: vec![] 665 | }, 666 | FieldInfo { 667 | name: "ISS", 668 | long_name: Some("Instruction Specific Syndrome"), 669 | start: 0, 670 | width: 25, 671 | value: 2, 672 | description: None, 673 | subfields: vec![FieldInfo { 674 | name: "ISS", 675 | long_name: None, 676 | start: 0, 677 | width: 25, 678 | value: 2, 679 | description: Some("LD64B or ST64B trapped".to_string()), 680 | subfields: vec![] 681 | }] 682 | } 683 | ] 684 | ); 685 | } 686 | -------------------------------------------------------------------------------- /src/esr/wf.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::common::describe_cv; 16 | use crate::{DecodeError, FieldInfo}; 17 | 18 | /// Decodes the ISS value for a trapped WF* instruction. 19 | pub fn decode_iss_wf(iss: u64) -> Result, DecodeError> { 20 | let cv = 21 | FieldInfo::get_bit(iss, "CV", Some("Condition code valid"), 24).describe_bit(describe_cv); 22 | let cond = FieldInfo::get( 23 | iss, 24 | "COND", 25 | Some("Condition code of the trapped instruction"), 26 | 20, 27 | 24, 28 | ); 29 | let res0a = FieldInfo::get(iss, "RES0", Some("Reserved"), 10, 20).check_res0()?; 30 | let rn = FieldInfo::get(iss, "RN", Some("Register Number"), 5, 10); 31 | let res0b = FieldInfo::get(iss, "RES0", Some("Reserved"), 3, 5).check_res0()?; 32 | let rv = FieldInfo::get_bit(iss, "RV", Some("Register Valid"), 2).describe_bit(describe_rv); 33 | let ti = FieldInfo::get(iss, "TI", Some("Trapped Instruction"), 0, 2).describe(describe_ti)?; 34 | 35 | Ok(vec![cv, cond, res0a, rn, res0b, rv, ti]) 36 | } 37 | 38 | fn describe_rv(rv: bool) -> &'static str { 39 | if rv { 40 | "RN is valid" 41 | } else { 42 | "RN is not valid" 43 | } 44 | } 45 | 46 | fn describe_ti(ti: u64) -> Result<&'static str, DecodeError> { 47 | Ok(match ti { 48 | 0b00 => "WFI trapped", 49 | 0b01 => "WFE trapped", 50 | 0b10 => "WFIT trapped", 51 | 0b11 => "WFET trapped", 52 | _ => unreachable!(), 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Library for decoding aarch64 Exception Syndrome Register and Main ID Register values. 16 | 17 | mod esr; 18 | mod midr; 19 | mod smccc; 20 | 21 | use bit_field::BitField; 22 | pub use esr::decode; 23 | pub use midr::decode_midr; 24 | pub use smccc::decode_smccc; 25 | use std::fmt::{self, Debug, Display, Formatter}; 26 | use std::num::ParseIntError; 27 | use thiserror::Error; 28 | 29 | /// Information about a particular field. 30 | #[derive(Clone, Debug, Eq, PartialEq)] 31 | pub struct FieldInfo { 32 | /// The short name of the field, e.g. "ISS". 33 | pub name: &'static str, 34 | /// The long name of the field, e.g. "Instruction Specific Syndrome". 35 | pub long_name: Option<&'static str>, 36 | /// The index of the lowest bit of the field. 37 | pub start: usize, 38 | /// The number of bits in the field. 39 | pub width: usize, 40 | /// The value of the field. 41 | pub value: u64, 42 | /// A description explaining the field value, if available. 43 | pub description: Option, 44 | /// Any sub-fields. 45 | pub subfields: Vec, 46 | } 47 | 48 | impl FieldInfo { 49 | fn get( 50 | register: u64, 51 | name: &'static str, 52 | long_name: Option<&'static str>, 53 | start: usize, 54 | end: usize, 55 | ) -> Self { 56 | let value = register.get_bits(start..end); 57 | Self { 58 | name, 59 | long_name, 60 | start, 61 | width: end - start, 62 | value, 63 | description: None, 64 | subfields: vec![], 65 | } 66 | } 67 | 68 | fn get_bit( 69 | register: u64, 70 | name: &'static str, 71 | long_name: Option<&'static str>, 72 | bit: usize, 73 | ) -> Self { 74 | Self::get(register, name, long_name, bit, bit + 1) 75 | } 76 | 77 | fn with_description(self, description: String) -> Self { 78 | Self { 79 | description: Some(description), 80 | ..self 81 | } 82 | } 83 | 84 | fn as_bit(&self) -> bool { 85 | assert!(self.width == 1); 86 | self.value == 1 87 | } 88 | 89 | /// Assuming this field has a width of exactly 1, describe it with the given function. 90 | /// 91 | /// Panics if `self.width != 1`. 92 | fn describe_bit(self, describer: F) -> Self 93 | where 94 | F: FnOnce(bool) -> &'static str, 95 | { 96 | let bit = self.as_bit(); 97 | let description = describer(bit).to_string(); 98 | self.with_description(description) 99 | } 100 | 101 | fn describe(self, describer: F) -> Result 102 | where 103 | F: FnOnce(u64) -> Result<&'static str, DecodeError>, 104 | { 105 | let description = describer(self.value)?.to_string(); 106 | Ok(self.with_description(description)) 107 | } 108 | 109 | fn check_res0(self) -> Result { 110 | if self.value != 0 { 111 | Err(DecodeError::InvalidRes0 { res0: self.value }) 112 | } else { 113 | Ok(self) 114 | } 115 | } 116 | 117 | /// Returns the value as a hexadecimal string, or "true" or "false" if it is a single bit. 118 | pub fn value_string(&self) -> String { 119 | if self.width == 1 { 120 | if self.value == 1 { "true" } else { "false" }.to_string() 121 | } else { 122 | format!("{:#01$x}", self.value, (self.width + 3) / 4 + 2,) 123 | } 124 | } 125 | 126 | /// Returns the value as a binary strings. 127 | pub fn value_binary_string(&self) -> String { 128 | format!("{:#01$b}", self.value, self.width + 2) 129 | } 130 | } 131 | 132 | impl Display for FieldInfo { 133 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 134 | if self.width == 1 { 135 | write!( 136 | f, 137 | "{}: {}", 138 | self.name, 139 | if self.value == 1 { "true" } else { "false" } 140 | ) 141 | } else { 142 | write!( 143 | f, 144 | "{}: {} {}", 145 | self.name, 146 | self.value_string(), 147 | self.value_binary_string(), 148 | ) 149 | } 150 | } 151 | } 152 | 153 | /// An error decoding a register value. 154 | #[derive(Debug, Error)] 155 | pub enum DecodeError { 156 | /// A RES0 field was not 0. 157 | #[error("Invalid ESR, res0 is {res0:#x}")] 158 | InvalidRes0 { res0: u64 }, 159 | /// The EC field had an invalid value. 160 | #[error("Invalid EC {ec:#x}")] 161 | InvalidEc { ec: u64 }, 162 | /// The DFSC or IFSC field had an invalid value. 163 | #[error("Invalid DFSC or IFSC {fsc:#x}")] 164 | InvalidFsc { fsc: u64 }, 165 | /// The SET field had an invalid value. 166 | #[error("Invalid SET {set:#x}")] 167 | InvalidSet { set: u64 }, 168 | /// The AET field had an invalid value. 169 | #[error("Invalid AET {aet:#x}")] 170 | InvalidAet { aet: u64 }, 171 | /// The AM field had an invalid value. 172 | #[error("Invalid AM {am:#x}")] 173 | InvalidAm { am: u64 }, 174 | /// The ISS field has an invalid value for a trapped LD64B or ST64B* exception. 175 | #[error("Invalid ISS {iss:#x} for trapped LD64B or ST64B*")] 176 | InvalidLd64bIss { iss: u64 }, 177 | } 178 | 179 | /// Parses a decimal or hexadecimal number from a string. 180 | /// 181 | /// If the string starts with `"0x"` then it will be parsed as hexadecimal, otherwise it will be 182 | /// assumed to be decimal. 183 | pub fn parse_number(s: &str) -> Result { 184 | if let Some(hex) = s.strip_prefix("0x") { 185 | u64::from_str_radix(hex, 16) 186 | } else { 187 | s.parse() 188 | } 189 | } 190 | 191 | #[cfg(test)] 192 | mod tests { 193 | use super::*; 194 | 195 | #[test] 196 | fn parse_decimal() { 197 | assert_eq!(parse_number("12345"), Ok(12345)); 198 | } 199 | 200 | #[test] 201 | fn parse_hex() { 202 | assert_eq!(parse_number("0x123abc"), Ok(0x123abc)); 203 | } 204 | 205 | #[test] 206 | fn parse_invalid() { 207 | assert!(parse_number("123abc").is_err()); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use aarch64_esr_decoder::{decode, decode_midr, decode_smccc, parse_number, FieldInfo}; 16 | use std::env; 17 | use std::ops::Deref; 18 | use std::process::exit; 19 | 20 | fn main() { 21 | let args = match parse_args() { 22 | Ok(args) => args, 23 | Err(error_code) => exit(error_code), 24 | }; 25 | 26 | let value = parse_number(&args.value).unwrap(); 27 | let decoded = match args.mode { 28 | Mode::Esr => { 29 | println!("ESR {:#034x}:", value); 30 | decode(value).unwrap() 31 | } 32 | Mode::Midr => { 33 | println!("MIDR {:#034x}:", value); 34 | decode_midr(value).unwrap() 35 | } 36 | Mode::Smccc => { 37 | println!("SMC ID {:#018x}:", value); 38 | decode_smccc(value).unwrap() 39 | } 40 | }; 41 | print_decoded(&decoded, args.verbose, 0); 42 | } 43 | 44 | fn print_decoded(fields: &[FieldInfo], verbose: bool, level: usize) { 45 | let indentation = " ".repeat(level * 2); 46 | for field in fields { 47 | let verbose_name = match field.long_name { 48 | Some(long_name) if verbose => format!(" ({})", long_name), 49 | _ => "".to_string(), 50 | }; 51 | if field.width == 1 { 52 | println!( 53 | "{}{:02} {}{}", 54 | indentation, field.start, field, verbose_name 55 | ); 56 | } else { 57 | println!( 58 | "{}{:02}..{:02} {}{}", 59 | indentation, 60 | field.start, 61 | field.start + field.width - 1, 62 | field, 63 | verbose_name, 64 | ); 65 | } 66 | if let Some(description) = &field.description { 67 | println!("{} # {}", indentation, description); 68 | } 69 | 70 | print_decoded(&field.subfields, verbose, level + 1); 71 | } 72 | } 73 | 74 | /// Parse and return command-line arguments, or an error code to return. 75 | fn parse_args() -> Result { 76 | let args: Vec = env::args().collect(); 77 | let args: Vec<&str> = args.iter().map(Deref::deref).collect(); 78 | match args.as_slice() { 79 | [_, esr] => Ok(Args { 80 | verbose: false, 81 | mode: Mode::Esr, 82 | value: esr.to_string(), 83 | }), 84 | [_, "-v", esr] => Ok(Args { 85 | verbose: true, 86 | mode: Mode::Esr, 87 | value: esr.to_string(), 88 | }), 89 | [_, "midr", midr] => Ok(Args { 90 | verbose: false, 91 | mode: Mode::Midr, 92 | value: midr.to_string(), 93 | }), 94 | [_, "-v", "midr", midr] => Ok(Args { 95 | verbose: true, 96 | mode: Mode::Midr, 97 | value: midr.to_string(), 98 | }), 99 | [_, "smccc", smccc] => Ok(Args { 100 | verbose: false, 101 | mode: Mode::Smccc, 102 | value: smccc.to_string(), 103 | }), 104 | [_, "-v", "smccc", smccc] => Ok(Args { 105 | verbose: true, 106 | mode: Mode::Smccc, 107 | value: smccc.to_string(), 108 | }), 109 | _ => { 110 | eprintln!("Usage:"); 111 | eprintln!(" {} [-v] ", args[0]); 112 | eprintln!(" {} [-v] midr ", args[0]); 113 | eprintln!(" {} [-v] smccc ", args[0]); 114 | Err(1) 115 | } 116 | } 117 | } 118 | 119 | /// Command-line arguments. 120 | #[derive(Clone, Debug, Eq, PartialEq)] 121 | struct Args { 122 | verbose: bool, 123 | mode: Mode, 124 | value: String, 125 | } 126 | 127 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 128 | enum Mode { 129 | Esr, 130 | Midr, 131 | Smccc, 132 | } 133 | -------------------------------------------------------------------------------- /src/midr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{DecodeError, FieldInfo}; 16 | 17 | /// Decodes the given Main ID Register value, or returns an error if it is not valid. 18 | pub fn decode_midr(midr: u64) -> Result, DecodeError> { 19 | let res0 = FieldInfo::get(midr, "RES0", Some("Reserved"), 32, 64).check_res0()?; 20 | let implementer = 21 | FieldInfo::get(midr, "Implementer", None, 24, 32).describe(describe_implementer)?; 22 | let variant = FieldInfo::get(midr, "Variant", None, 20, 24); 23 | let architecture = 24 | FieldInfo::get(midr, "Architecture", None, 16, 20).describe(describe_architecture)?; 25 | let part_num = FieldInfo::get(midr, "PartNum", Some("Part number"), 4, 16); 26 | let revision = FieldInfo::get(midr, "Revision", None, 0, 4); 27 | 28 | Ok(vec![ 29 | res0, 30 | implementer, 31 | variant, 32 | architecture, 33 | part_num, 34 | revision, 35 | ]) 36 | } 37 | 38 | fn describe_implementer(implementer: u64) -> Result<&'static str, DecodeError> { 39 | Ok(match implementer { 40 | 0x00 => "Reserved for software use", 41 | 0xC0 => "Ampere Computing", 42 | 0x41 => "Arm Limited", 43 | 0x42 => "Broadcom Corporation", 44 | 0x43 => "Cavium Inc.", 45 | 0x44 => "Digital Equipment Corporation", 46 | 0x46 => "Fujitsu Ltd.", 47 | 0x49 => "Infineon Technologies AG", 48 | 0x4D => "Motorola or Freescale Semiconductor Inc.", 49 | 0x4E => "NVIDIA Corporation", 50 | 0x50 => "Applied Micro Circuits Corporation", 51 | 0x51 => "Qualcomm Inc.", 52 | 0x56 => "Marvell International Ltd.", 53 | 0x69 => "Intel Corporation", 54 | _ => "Unknown", 55 | }) 56 | } 57 | 58 | fn describe_architecture(architecture: u64) -> Result<&'static str, DecodeError> { 59 | Ok(match architecture { 60 | 0b0001 => "Armv4", 61 | 0b0010 => "Armv4T", 62 | 0b0011 => "Armv5", 63 | 0b0100 => "Armv5T", 64 | 0b0101 => "Armv5TE", 65 | 0b0110 => "Armv5TEJ", 66 | 0b0111 => "Armv6", 67 | 0b1111 => "Architectural features are individually identified", 68 | _ => "Reserved", 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /src/smccc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Decoder for SMC Calling Convention ARM DEN 0028E v1.4 16 | 17 | mod arm; 18 | mod common; 19 | mod ffa; 20 | mod hyp; 21 | mod secure; 22 | mod tapp; 23 | 24 | use arm::decode_arm_service; 25 | use common::decode_common_service; 26 | use common::describe_general32_queries; 27 | use common::reserved_fids; 28 | use common::smccc_general32_queries; 29 | use hyp::decode_hyp_service; 30 | use secure::decode_secure_service; 31 | use tapp::decode_tapp_service; 32 | 33 | use super::{DecodeError, FieldInfo}; 34 | 35 | /// Decodes the function ID of an SMCCC (ARM DEN 0028E v1.4) call, or returns an error if it is not valid. 36 | pub fn decode_smccc(smccc: u64) -> Result, DecodeError> { 37 | let call_type = FieldInfo::get(smccc, "Call Type", None, 31, 32).describe(describe_call)?; 38 | 39 | let result = if call_type.value == 1 { 40 | parse_fastcall(smccc)? 41 | } else { 42 | parse_yieldcall(smccc)? 43 | }; 44 | 45 | Ok([vec![call_type], result].concat()) 46 | } 47 | 48 | pub fn parse_fastcall(smccc: u64) -> Result, DecodeError> { 49 | let call_convention = 50 | FieldInfo::get(smccc, "Call Convention", None, 30, 31).describe(describe_convention)?; 51 | let service_call = 52 | FieldInfo::get(smccc, "Service Call", None, 24, 30).describe(describe_service)?; 53 | 54 | let mbz = FieldInfo::get( 55 | smccc, 56 | "MBZ", 57 | Some("Some legacy Armv7 set this to 1"), 58 | 17, 59 | 24, 60 | ); 61 | let sve = FieldInfo::get( 62 | smccc, 63 | "SVE live state", 64 | Some("No live state[1] From SMCCCv1.3, before SMCCCv1.3 MBZ"), 65 | 16, 66 | 17, 67 | ); 68 | 69 | let function_number = match service_call.value { 70 | 0x00 => decode_arm_service(smccc, call_convention.value)?, 71 | 0x04 => decode_secure_service(smccc, call_convention.value)?, 72 | 0x05 => decode_hyp_service(smccc, call_convention.value)?, 73 | 0x30..=0x31 => decode_tapp_service(smccc, call_convention.value)?, 74 | _ => decode_common_service(smccc, call_convention.value)?, 75 | }; 76 | 77 | Ok(vec![ 78 | call_convention, 79 | service_call, 80 | mbz, 81 | sve, 82 | function_number, 83 | ]) 84 | } 85 | pub fn parse_yieldcall(smccc: u64) -> Result, DecodeError> { 86 | let yield_type = 87 | FieldInfo::get(smccc, "Service Type", None, 0, 31).describe(describe_yield_service)?; 88 | Ok(vec![yield_type]) 89 | } 90 | 91 | fn describe_yield_service(service: u64) -> Result<&'static str, DecodeError> { 92 | Ok(match service { 93 | 0x00000000..=0x0100FFFF => { 94 | "Reserved for existing APIs (in use by the existing Armv7 devices)" 95 | } 96 | 0x02000000..=0x1FFFFFFF => "Trusted OS Yielding Calls", 97 | 0x20000000..=0x7FFFFFFF => "Reserved for future expansion of Trusted OS Yielding Calls", 98 | _ => "Unknown", 99 | }) 100 | } 101 | 102 | fn describe_call(call: u64) -> Result<&'static str, DecodeError> { 103 | Ok(match call { 104 | 0x00 => "Yielding Call", 105 | 0x01 => "Fast Call", 106 | _ => "Unknown", 107 | }) 108 | } 109 | fn describe_convention(conv: u64) -> Result<&'static str, DecodeError> { 110 | Ok(match conv { 111 | 0x00 => "SMC32/HVC32", 112 | 0x01 => "SMC64/HVC64", 113 | _ => "Unknown", 114 | }) 115 | } 116 | fn describe_service(service: u64) -> Result<&'static str, DecodeError> { 117 | Ok(match service { 118 | 0x00 => "Arm Architecture Call", 119 | 0x01 => "CPU Service Call", 120 | 0x02 => "SiP Service Call", 121 | 0x03 => "OEM Service Call", 122 | 0x04 => "Standard Secure Service Call", 123 | 0x05 => "Standard Hypervisor Service Call", 124 | 0x06 => "Vendor Specific Hypervisor Service Call", 125 | 0x07..=0x2F => "Reserved for future use", 126 | 0x30..=0x31 => "Trusted Application Call", 127 | 0x32..=0x3F => "Trusted OS Call", 128 | _ => "Unknown", 129 | }) 130 | } 131 | -------------------------------------------------------------------------------- /src/smccc/arm.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{reserved_fids, DecodeError, FieldInfo}; 16 | 17 | pub fn decode_arm_service(smccc: u64, conv: u64) -> Result { 18 | if conv == 0 { 19 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_arm32_service) 20 | } else { 21 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_arm64_service) 22 | } 23 | } 24 | 25 | fn describe_arm32_service(service: u64) -> Result<&'static str, DecodeError> { 26 | Ok(match service { 27 | 0x0000 => "SMCCC_VERSION", 28 | 0x0001 => "SMCCC_ARCH_FEATURES", 29 | 0x0002 => "SMCCC_ARCH_SOC_ID", 30 | 0x3FFF => "SMCCC_ARCH_WORKAROUND_3", 31 | 0x7FFF => "SMCCC_ARCH_WORKAROUND_2", 32 | 0x8000 => "SMCCC_ARCH_WORKAROUND_1", 33 | 0xFF00 => "Call Count Query, deprecated from SMCCCv1.2", 34 | 0xFF01 => "Call UUID Query, deprecated from SMCCCv1.2", 35 | 0xFF03 => "Revision Query, deprecated from SMCCCv1.2", 36 | _ => reserved_fids(service), 37 | }) 38 | } 39 | fn describe_arm64_service(service: u64) -> Result<&'static str, DecodeError> { 40 | Ok(reserved_fids(service)) 41 | } 42 | -------------------------------------------------------------------------------- /src/smccc/common.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{DecodeError, FieldInfo}; 16 | 17 | pub fn decode_common_service(smccc: u64, conv: u64) -> Result { 18 | if conv == 0 { 19 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_general32_queries) 20 | } else { 21 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_general64_queries) 22 | } 23 | } 24 | 25 | pub fn reserved_fids(service: u64) -> &'static str { 26 | match service { 27 | 0xFF00..=0xFFFF => "Reserved for future expansion", 28 | _ => "", 29 | } 30 | } 31 | 32 | pub fn smccc_general32_queries(service: u64) -> &'static str { 33 | match service { 34 | 0xFF00 => "Call Count Query, deprecated from SMCCCv1.2", 35 | 0xFF01 => "Call UUID Query", 36 | 0xFF03 => "Revision Query", 37 | _ => reserved_fids(service), 38 | } 39 | } 40 | pub fn describe_general32_queries(service: u64) -> Result<&'static str, DecodeError> { 41 | Ok(smccc_general32_queries(service)) 42 | } 43 | pub fn describe_general64_queries(service: u64) -> Result<&'static str, DecodeError> { 44 | Ok(reserved_fids(service)) 45 | } 46 | -------------------------------------------------------------------------------- /src/smccc/ffa.rs: -------------------------------------------------------------------------------- 1 | const FFA_ERROR: u64 = 0x60; 2 | const FFA_SUCCESS: u64 = 0x61; 3 | const FFA_INTERRUPT: u64 = 0x62; 4 | const FFA_VERSION: u64 = 0x63; 5 | const FFA_FEATURES: u64 = 0x64; 6 | const FFA_RX_RELEASE: u64 = 0x65; 7 | const FFA_RXTX_MAP: u64 = 0x66; 8 | const FFA_RXTX_UNMAP: u64 = 0x67; 9 | const FFA_PARTITION_INFO_GET: u64 = 0x68; 10 | const FFA_ID_GET: u64 = 0x69; 11 | const FFA_MSG_POLL: u64 = 0x6A; 12 | const FFA_MSG_WAIT: u64 = 0x6B; 13 | const FFA_YIELD: u64 = 0x6C; 14 | const FFA_RUN: u64 = 0x6D; 15 | const FFA_MSG_SEND: u64 = 0x6E; 16 | const FFA_MSG_SEND_DIRECT_REQ: u64 = 0x6F; 17 | const FFA_MSG_SEND_DIRECT_RESP: u64 = 0x70; 18 | const FFA_MEM_DONATE: u64 = 0x71; 19 | const FFA_MEM_LEND: u64 = 0x72; 20 | const FFA_MEM_SHARE: u64 = 0x73; 21 | const FFA_MEM_RETRIEVE_REQ: u64 = 0x74; 22 | const FFA_MEM_RETRIEVE_RESP: u64 = 0x75; 23 | const FFA_MEM_RELINQUISH: u64 = 0x76; 24 | const FFA_MEM_RECLAIM: u64 = 0x77; 25 | const FFA_MEM_OP_PAUSE: u64 = 0x78; 26 | const FFA_MEM_OP_RESUME: u64 = 0x79; 27 | const FFA_MEM_FRAG_RX: u64 = 0x7A; 28 | const FFA_MEM_FRAG_TX: u64 = 0x7B; 29 | const FFA_NORMAL_WORLD_RESUME: u64 = 0x7C; 30 | 31 | pub fn ffa_32_function_id(function: u64) -> Option<&'static str> { 32 | match function { 33 | FFA_ERROR => Some("FFA_ERROR_32"), 34 | FFA_SUCCESS => Some("FFA_SUCCESS_32"), 35 | FFA_INTERRUPT => Some("FFA_INTERRUPT_32"), 36 | FFA_VERSION => Some("FFA_VERSION_32"), 37 | FFA_FEATURES => Some("FFA_FEATURES_32"), 38 | FFA_RX_RELEASE => Some("FFA_RX_RELEASE_32"), 39 | FFA_RXTX_MAP => Some("FFA_RXTX_MAP_32"), 40 | FFA_RXTX_UNMAP => Some("FFA_RXTX_UNMAP_32"), 41 | FFA_PARTITION_INFO_GET => Some("FFA_PARTITION_INFO_GET_32"), 42 | FFA_ID_GET => Some("FFA_ID_GET_32"), 43 | FFA_MSG_POLL => Some("FFA_MSG_POLL_32"), 44 | FFA_MSG_WAIT => Some("FFA_MSG_WAIT_32"), 45 | FFA_YIELD => Some("FFA_YIELD_32"), 46 | FFA_RUN => Some("FFA_RUN_32"), 47 | FFA_MSG_SEND => Some("FFA_MSG_SEND_32"), 48 | FFA_MSG_SEND_DIRECT_REQ => Some("FFA_MSG_SEND_DIRECT_REQ_32"), 49 | FFA_MSG_SEND_DIRECT_RESP => Some("FFA_MSG_SEND_DIRECT_RESP_32"), 50 | FFA_MEM_DONATE => Some("FFA_MEM_DONATE_32"), 51 | FFA_MEM_LEND => Some("FFA_MEM_LEND_32"), 52 | FFA_MEM_SHARE => Some("FFA_MEM_SHARE_32"), 53 | FFA_MEM_RETRIEVE_REQ => Some("FFA_MEM_RETRIEVE_REQ_32"), 54 | FFA_MEM_RETRIEVE_RESP => Some("FFA_MEM_RETRIEVE_RESP_32"), 55 | FFA_MEM_RELINQUISH => Some("FFA_MEM_RELINQUISH_32"), 56 | FFA_MEM_RECLAIM => Some("FFA_MEM_RECLAIM_32"), 57 | FFA_MEM_OP_PAUSE => Some("FFA_MEM_OP_PAUSE"), 58 | FFA_MEM_OP_RESUME => Some("FFA_MEM_OP_RESUME"), 59 | FFA_MEM_FRAG_RX => Some("FFA_MEM_FRAG_RX_32"), 60 | FFA_MEM_FRAG_TX => Some("FFA_MEM_FRAG_TX_32"), 61 | FFA_NORMAL_WORLD_RESUME => Some("FFA_NORMAL_WORLD_RESUME"), 62 | _ => None, 63 | } 64 | } 65 | 66 | pub fn ffa_64_function_id(function: u64) -> Option<&'static str> { 67 | match function { 68 | FFA_RXTX_MAP => Some("FFA_RXTX_MAP_64"), 69 | FFA_MSG_SEND_DIRECT_REQ => Some("FFA_MSG_SEND_DIRECT_REQ_64"), 70 | FFA_MSG_SEND_DIRECT_RESP => Some("FFA_MSG_SEND_DIRECT_RESP_64"), 71 | FFA_MEM_DONATE => Some("FFA_MEM_DONATE_64"), 72 | FFA_MEM_LEND => Some("FFA_MEM_LEND_64"), 73 | FFA_MEM_SHARE => Some("FFA_MEM_SHARE_64"), 74 | FFA_MEM_RETRIEVE_REQ => Some("FFA_MEM_RETRIEVE_REQ_64"), 75 | _ => None, 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/smccc/hyp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{describe_general32_queries, DecodeError, FieldInfo}; 16 | 17 | pub fn decode_hyp_service(smccc: u64, conv: u64) -> Result { 18 | if conv == 0 { 19 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_general32_queries) 20 | } else { 21 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_hyp64_service) 22 | } 23 | } 24 | 25 | fn describe_hyp64_service(service: u64) -> Result<&'static str, DecodeError> { 26 | Ok(match service { 27 | 0x20..=0x3F => "PV Time 64-bit calls", 28 | _ => "", 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /src/smccc/secure.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{ 16 | ffa::{ffa_32_function_id, ffa_64_function_id}, 17 | smccc_general32_queries, DecodeError, FieldInfo, 18 | }; 19 | 20 | pub fn decode_secure_service(smccc: u64, conv: u64) -> Result { 21 | let info = if conv == 0 { 22 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_secure32_service)? 23 | } else { 24 | FieldInfo::get(smccc, "Function Number", None, 0, 16).describe(describe_secure64_service)? 25 | }; 26 | Ok(info) 27 | } 28 | 29 | fn secure_service(service: u64) -> &'static str { 30 | match service { 31 | 0x000..=0x01F => "PSCI Call (Power Secure Control Interface)", 32 | 0x020..=0x03F => "SDEI Call (Software Delegated Exception Interface)", 33 | 0x040..=0x04F => "MM Call (Management Mode)", 34 | 0x050..=0x05F => "TRNG Call", 35 | 0x060..=0x0EF => "Unknown FF-A Call", 36 | 0x0F0..=0x10F => "Errata Call", 37 | 0x150..=0x1CF => "CCA Call", 38 | _ => "", 39 | } 40 | } 41 | 42 | fn describe_secure32_service(service: u64) -> Result<&'static str, DecodeError> { 43 | if let Some(ffa_call) = ffa_32_function_id(service) { 44 | return Ok(ffa_call); 45 | } 46 | 47 | Ok(match service { 48 | 0x000..=0x1CF => secure_service(service), 49 | _ => smccc_general32_queries(service), 50 | }) 51 | } 52 | fn describe_secure64_service(service: u64) -> Result<&'static str, DecodeError> { 53 | if let Some(ffa_call) = ffa_64_function_id(service) { 54 | return Ok(ffa_call); 55 | } 56 | Ok(secure_service(service)) 57 | } 58 | -------------------------------------------------------------------------------- /src/smccc/tapp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{DecodeError, FieldInfo}; 16 | 17 | pub fn decode_tapp_service(smccc: u64, _conv: u64) -> Result { 18 | Ok(FieldInfo::get(smccc, "Function Number", None, 0, 16)) 19 | } 20 | --------------------------------------------------------------------------------