[rialto] Handle page table exceptions in rialto

As the MemoryTracker maps the MMIO memory range as lazy device
memory, users of the MemoryTracker need to handle translation
faults during MMIO memory mapping for normal flow.

This change implements this handling in rialto.

Bug: 284462758
Test: atest rialto_test
Change-Id: Iaef203e2282bcb1e00ce426f4de5bd75caae387a
diff --git a/rialto/src/exceptions.rs b/rialto/src/exceptions.rs
index 3c12c25..b806b08 100644
--- a/rialto/src/exceptions.rs
+++ b/rialto/src/exceptions.rs
@@ -14,13 +14,37 @@
 
 //! Exception handlers.
 
-use vmbase::{console::emergency_write_str, eprintln, power::reboot, read_sysreg};
+use vmbase::{
+    console::emergency_write_str,
+    eprintln,
+    exceptions::{ArmException, Esr, HandleExceptionError},
+    logger,
+    memory::{handle_permission_fault, handle_translation_fault},
+    power::reboot,
+    read_sysreg,
+};
+
+fn handle_exception(exception: &ArmException) -> Result<(), HandleExceptionError> {
+    // Handle all translation faults on both read and write, and MMIO guard map
+    // flagged invalid pages or blocks that caused the exception.
+    // Handle permission faults for DBM flagged entries, and flag them as dirty on write.
+    match exception.esr {
+        Esr::DataAbortTranslationFault => handle_translation_fault(exception.far),
+        Esr::DataAbortPermissionFault => handle_permission_fault(exception.far),
+        _ => Err(HandleExceptionError::UnknownException),
+    }
+}
 
 #[no_mangle]
-extern "C" fn sync_exception_current() {
-    emergency_write_str("sync_exception_current\n");
-    print_esr();
-    reboot();
+extern "C" fn sync_exception_current(elr: u64, _spsr: u64) {
+    // Disable logging in exception handler to prevent unsafe writes to UART.
+    let _guard = logger::suppress();
+
+    let exception = ArmException::from_el1_regs();
+    if let Err(e) = handle_exception(&exception) {
+        exception.print("sync_exception_current", e, elr);
+        reboot()
+    }
 }
 
 #[no_mangle]