pvmfw: Hack MMIO_GUARD_MAP to expect i32
Until aosp/2254520, pKVM returned a signed 32-bit integer instead of the
SMCCC-compliant i64 so parse results that could be negative i32 values
as their sign-extended i64 counterparts. The fact that this masks the
range 0x8000_0000-0xFFFF_FFFF, which should otherwise be interpreted as
positive u64 values, should not be an issue as the only non-negative
value that should be expected from MMIO_GUARD_MAP is zero ("SUCCESS").
Log the workaround, to help with debugging.
Note: this commit is intended to be reverted once the bug is fixed.
Bug: 253586500
Test: crosvm run --protected-vm-without-firmware <pvmfw.bin>
Test: # Issue MMIO_GUARD_MAP without first MMIO_GUARD_ENROLL-ing
Change-Id: I974e9783f114fb2d821b3806fdb69fb6c8eefdc7
diff --git a/pvmfw/src/mmio_guard.rs b/pvmfw/src/mmio_guard.rs
index ce74abb..eb6c1fa 100644
--- a/pvmfw/src/mmio_guard.rs
+++ b/pvmfw/src/mmio_guard.rs
@@ -83,7 +83,20 @@
let mut args = [0u64; 17];
args[0] = ipa;
- smccc::checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID, args)
+ // TODO(b/253586500): pKVM currently returns a i32 instead of a i64.
+ let is_i32_error_code = |n| u32::try_from(n).ok().filter(|v| (*v as i32) < 0).is_some();
+ match smccc::checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID, args) {
+ Err(smccc::Error::Unexpected(e)) if is_i32_error_code(e) => {
+ info!("Handled a pKVM bug by interpreting the MMIO_GUARD_MAP return value as i32");
+ match e as u32 as i32 {
+ -1 => Err(smccc::Error::NotSupported),
+ -2 => Err(smccc::Error::NotRequired),
+ -3 => Err(smccc::Error::InvalidParameter),
+ ret => Err(smccc::Error::Unknown(ret as i64)),
+ }
+ }
+ res => res,
+ }
}
fn mmio_guard_unmap(ipa: u64) -> smccc::Result<()> {