From c0d9b40d9d61aecd59677d9bc4337fe31c812b67 Mon Sep 17 00:00:00 2001 From: bunnie Date: Thu, 28 Mar 2024 10:18:27 +0800 Subject: [PATCH] add logic to catch suspend/resume and opcode errors also fix a bug where the engine was not being powered off on release. Things to note: - in case of an opcode error, the system will enter an infinite loop complaining about the error. Maybe i should promote that to a panic -- it's a thing that should be fixed and should just never happen - in case of a suspend/resume during an operation, this is detected by the loaded microcode length not matching what we had written. This is a heuristic, but relies on the assumption that the microcode length would change when the engine is put through a clean reboot (i.e., it is unlikely that it matches what we had previously written). --- .../src/backend/serial/u32e/mod.rs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/curve25519-dalek/src/backend/serial/u32e/mod.rs b/curve25519-dalek/src/backend/serial/u32e/mod.rs index bd0299b..f29cdaf 100644 --- a/curve25519-dalek/src/backend/serial/u32e/mod.rs +++ b/curve25519-dalek/src/backend/serial/u32e/mod.rs @@ -39,7 +39,7 @@ pub fn free_engine() { log::debug!("free engine"); if let Some(base) = unsafe { ENGINE_BASE.take() } { let mut engine = utralib::CSR::new(base.as_mut_ptr() as *mut u32); - engine.rmwf(utra::engine::POWER_ON, 1); + engine.rmwf(utra::engine::POWER_ON, 0); xous::unmap_memory(base).unwrap(); } if let Some(mem) = unsafe { ENGINE_MEM.take() } { @@ -47,6 +47,26 @@ pub fn free_engine() { } } +/// Only safe to call this after ensure_engine() has been called. +pub fn was_engine_error(job_len: usize) -> bool { + let mut engine = utralib::CSR::new(unsafe { ENGINE_BASE.unwrap() }.as_mut_ptr() as *mut u32); + + let reason = engine.r(utra::engine::EV_PENDING); + if reason & engine.ms(utra::engine::EV_PENDING_ILLEGAL_OPCODE, 1) != 0 { + log::warn!("Illegal opcode encountered in engine25519"); + return true; + } + // if the job length isn't what we had set it to, conclude that the + // microcode engine went through a suspend/resume cycle + if engine.rf(utra::engine::MPLEN_MPLEN) != job_len as u32 { + log::warn!("Suspend during engine25519 hw acceleration"); + return true; + } + + engine.wo(utra::engine::EV_PENDING, reason); + false +} + /// It is safe to call this multiple times. pub fn ensure_engine() -> Result<(), xous::Error> { if unsafe { ENGINE_BASE.is_none() } { @@ -73,6 +93,7 @@ pub fn ensure_engine() -> Result<(), xous::Error> { } let mut engine = utralib::CSR::new(unsafe { ENGINE_BASE.unwrap() }.as_mut_ptr() as *mut u32); engine.rmwf(utra::engine::POWER_ON, 1); + engine.wo(utra::engine::EV_PENDING, 0xFFFF_FFFF); // clear all pending bits Ok(()) }