blob: 462a9ccd998f75f96973fff304b4f98da5e42c67 [file] [log] [blame]
Andrew Walbrandfb73372022-04-21 10:52:27 +00001// Copyright 2022, The Android Open Source Project
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// http://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//! Exception handlers.
16
Jakob Vukalovicc9afb512023-03-30 16:04:32 +000017use crate::{helpers::page_4kb_of, read_sysreg};
Jakob Vukalovicd3fe9ed2023-04-20 15:43:09 +010018use core::fmt;
Pierre-Clément Tosida4440a2022-08-22 18:06:32 +010019use vmbase::console;
Jakob Vukalovicd3fe9ed2023-04-20 15:43:09 +010020use vmbase::logger;
Jakob Vukalovicbff22e12023-04-18 14:50:47 +010021use vmbase::{eprintln, power::reboot};
Andrew Walbrandfb73372022-04-21 10:52:27 +000022
Pierre-Clément Tosi446136e2022-10-19 10:10:42 +010023const UART_PAGE: usize = page_4kb_of(console::BASE_ADDRESS);
Pierre-Clément Tosida4440a2022-08-22 18:06:32 +010024
Jakob Vukalovicd3fe9ed2023-04-20 15:43:09 +010025#[derive(Debug)]
26enum HandleExceptionError {
27 UnknownException,
28}
29
30impl fmt::Display for HandleExceptionError {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 match self {
33 Self::UnknownException => write!(f, "An unknown exception occurred, not handled."),
34 }
35 }
36}
37
38#[derive(Debug, PartialEq, Copy, Clone)]
39enum Esr {
40 DataAbortTranslationFault,
41 DataAbortPermissionFault,
42 DataAbortSyncExternalAbort,
43 Unknown(usize),
44}
45
46impl Esr {
47 const EXT_DABT_32BIT: usize = 0x96000010;
48 const TRANSL_FAULT_BASE_32BIT: usize = 0x96000004;
49 const TRANSL_FAULT_ISS_MASK_32BIT: usize = !0x143;
50 const PERM_FAULT_BASE_32BIT: usize = 0x9600004C;
51 const PERM_FAULT_ISS_MASK_32BIT: usize = !0x103;
52}
53
54impl From<usize> for Esr {
55 fn from(esr: usize) -> Self {
56 if esr == Self::EXT_DABT_32BIT {
57 Self::DataAbortSyncExternalAbort
58 } else if esr & Self::TRANSL_FAULT_ISS_MASK_32BIT == Self::TRANSL_FAULT_BASE_32BIT {
59 Self::DataAbortTranslationFault
60 } else if esr & Self::PERM_FAULT_ISS_MASK_32BIT == Self::PERM_FAULT_BASE_32BIT {
61 Self::DataAbortPermissionFault
62 } else {
63 Self::Unknown(esr)
64 }
65 }
66}
67
68impl fmt::Display for Esr {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 match self {
71 Self::DataAbortSyncExternalAbort => write!(f, "Synchronous external abort"),
72 Self::DataAbortTranslationFault => write!(f, "Translation fault"),
73 Self::DataAbortPermissionFault => write!(f, "Permission fault"),
74 Self::Unknown(v) => write!(f, "Unknown exception esr={v:#08x}"),
75 }
76 }
77}
78
79fn handle_exception(_esr: Esr, _far: usize) -> Result<(), HandleExceptionError> {
80 Err(HandleExceptionError::UnknownException)
81}
82
83#[inline]
84fn handling_uart_exception(esr: Esr, far: usize) -> bool {
85 esr == Esr::DataAbortSyncExternalAbort && page_4kb_of(far) == UART_PAGE
86}
87
Andrew Walbrandfb73372022-04-21 10:52:27 +000088#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +010089extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
Jakob Vukalovicd3fe9ed2023-04-20 15:43:09 +010090 // Disable logging in exception handler to prevent unsafe writes to UART.
91 let _guard = logger::suppress();
92 let esr: Esr = read_sysreg!("esr_el1").into();
Jakob Vukalovicc9afb512023-03-30 16:04:32 +000093 let far = read_sysreg!("far_el1");
Jakob Vukalovicd3fe9ed2023-04-20 15:43:09 +010094
95 if let Err(e) = handle_exception(esr, far) {
96 // Don't print to the UART if we are handling an exception it could raise.
97 if !handling_uart_exception(esr, far) {
98 eprintln!("sync_exception_current");
99 eprintln!("{e}");
100 eprintln!("{esr}, far={far:#08x}");
101 }
102 reboot()
Pierre-Clément Tosida4440a2022-08-22 18:06:32 +0100103 }
Andrew Walbrandfb73372022-04-21 10:52:27 +0000104}
105
106#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100107extern "C" fn irq_current(_elr: u64, _spsr: u64) {
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100108 eprintln!("irq_current");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000109 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000110}
111
112#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100113extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100114 eprintln!("fiq_current");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000115 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000116}
117
118#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100119extern "C" fn serr_current(_elr: u64, _spsr: u64) {
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000120 let esr = read_sysreg!("esr_el1");
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100121 eprintln!("serr_current");
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000122 eprintln!("esr={esr:#08x}");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000123 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000124}
125
126#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100127extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000128 let esr = read_sysreg!("esr_el1");
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100129 eprintln!("sync_lower");
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000130 eprintln!("esr={esr:#08x}");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000131 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000132}
133
134#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100135extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100136 eprintln!("irq_lower");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000137 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000138}
139
140#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100141extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100142 eprintln!("fiq_lower");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000143 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000144}
145
146#[no_mangle]
Pierre-Clément Tosi8cbd4b72022-08-11 13:59:31 +0100147extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000148 let esr = read_sysreg!("esr_el1");
Jakob Vukalovicbff22e12023-04-18 14:50:47 +0100149 eprintln!("serr_lower");
Jakob Vukalovicc9afb512023-03-30 16:04:32 +0000150 eprintln!("esr={esr:#08x}");
Andrew Walbrandd74b902022-04-14 16:12:50 +0000151 reboot();
Andrew Walbrandfb73372022-04-21 10:52:27 +0000152}