Merge "Fix errors from rustc 1.71.0" into main
diff --git a/libs/hyp/src/error.rs b/libs/hyp/src/error.rs
index b8498ca..3fdad70 100644
--- a/libs/hyp/src/error.rs
+++ b/libs/hyp/src/error.rs
@@ -26,7 +26,7 @@
#[derive(Debug, Clone)]
pub enum Error {
/// MMIO guard is not supported.
- MmioGuardNotsupported,
+ MmioGuardNotSupported,
/// Failed to invoke a certain KVM HVC function.
KvmError(KvmError, u32),
/// Failed to invoke GenieZone HVC function.
@@ -40,7 +40,7 @@
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- Self::MmioGuardNotsupported => write!(f, "MMIO guard is not supported"),
+ Self::MmioGuardNotSupported => write!(f, "MMIO guard is not supported"),
Self::KvmError(e, function_id) => {
write!(f, "Failed to invoke the HVC function with function ID {function_id}: {e}")
}
diff --git a/libs/hyp/src/hypervisor/common.rs b/libs/hyp/src/hypervisor/common.rs
index 7c030a1..70fdd0a 100644
--- a/libs/hyp/src/hypervisor/common.rs
+++ b/libs/hyp/src/hypervisor/common.rs
@@ -14,7 +14,7 @@
//! This module regroups some common traits shared by all the hypervisors.
-use crate::error::Result;
+use crate::error::{Error, Result};
use crate::util::SIZE_4KB;
/// Expected MMIO guard granule size, validated during MMIO guard initialization.
@@ -34,10 +34,9 @@
}
pub trait MmioGuardedHypervisor {
- /// Initializes the hypervisor by enrolling a MMIO guard and checking the memory granule size.
- /// By enrolling, all MMIO will be blocked unless allow-listed with `mmio_guard_map`.
- /// Protected VMs are auto-enrolled.
- fn init(&self) -> Result<()>;
+ /// Enrolls with the MMIO guard so that all MMIO will be blocked unless allow-listed with
+ /// `MmioGuardedHypervisor::map`.
+ fn enroll(&self) -> Result<()>;
/// Maps a page containing the given memory address to the hypervisor MMIO guard.
/// The page size corresponds to the MMIO guard granule size.
@@ -46,6 +45,18 @@
/// Unmaps a page containing the given memory address from the hypervisor MMIO guard.
/// The page size corresponds to the MMIO guard granule size.
fn unmap(&self, addr: usize) -> Result<()>;
+
+ /// Returns the MMIO guard granule size in bytes.
+ fn granule(&self) -> Result<usize>;
+
+ // TODO(ptosi): Fully move granule validation to client code.
+ /// Validates the MMIO guard granule size.
+ fn validate_granule(&self) -> Result<()> {
+ match self.granule()? {
+ MMIO_GUARD_GRANULE_SIZE => Ok(()),
+ granule => Err(Error::UnsupportedMmioGuardGranule(granule)),
+ }
+ }
}
pub trait MemSharingHypervisor {
diff --git a/libs/hyp/src/hypervisor/geniezone.rs b/libs/hyp/src/hypervisor/geniezone.rs
index 24eb89e..ad18e17 100644
--- a/libs/hyp/src/hypervisor/geniezone.rs
+++ b/libs/hyp/src/hypervisor/geniezone.rs
@@ -14,9 +14,7 @@
//! Wrappers around calls to the GenieZone hypervisor.
-use super::common::{
- Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor, MMIO_GUARD_GRANULE_SIZE,
-};
+use super::common::{Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
use crate::error::{Error, Result};
use crate::util::page_address;
use core::fmt::{self, Display, Formatter};
@@ -96,13 +94,15 @@
}
impl MmioGuardedHypervisor for GeniezoneHypervisor {
- fn init(&self) -> Result<()> {
- mmio_guard_enroll()?;
- let mmio_granule = mmio_guard_granule()?;
- if mmio_granule != MMIO_GUARD_GRANULE_SIZE {
- return Err(Error::UnsupportedMmioGuardGranule(mmio_granule));
+ fn enroll(&self) -> Result<()> {
+ let args = [0u64; 17];
+ match success_or_error_64(hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID, args)[0]) {
+ Ok(()) => Ok(()),
+ Err(GeniezoneError::NotSupported) | Err(GeniezoneError::NotRequired) => {
+ Err(Error::MmioGuardNotSupported)
+ }
+ Err(e) => Err(Error::GeniezoneError(e, VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID)),
}
- Ok(())
}
fn map(&self, addr: usize) -> Result<()> {
@@ -118,6 +118,12 @@
checked_hvc64_expect_zero(VENDOR_HYP_GZVM_MMIO_GUARD_UNMAP_FUNC_ID, args)
}
+
+ fn granule(&self) -> Result<usize> {
+ let args = [0u64; 17];
+ let granule = checked_hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_INFO_FUNC_ID, args)?;
+ Ok(granule.try_into().unwrap())
+ }
}
impl MemSharingHypervisor for GeniezoneHypervisor {
@@ -142,23 +148,6 @@
}
}
-fn mmio_guard_granule() -> Result<usize> {
- let args = [0u64; 17];
-
- let granule = checked_hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_INFO_FUNC_ID, args)?;
- Ok(granule.try_into().unwrap())
-}
-
-fn mmio_guard_enroll() -> Result<()> {
- let args = [0u64; 17];
- match success_or_error_64(hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID, args)[0]) {
- Ok(_) => Ok(()),
- Err(GeniezoneError::NotSupported) => Err(Error::MmioGuardNotsupported),
- Err(GeniezoneError::NotRequired) => Err(Error::MmioGuardNotsupported),
- Err(e) => Err(Error::GeniezoneError(e, VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID)),
- }
-}
-
fn checked_hvc64_expect_zero(function: u32, args: [u64; 17]) -> Result<()> {
success_or_error_64(hvc64(function, args)[0]).map_err(|e| Error::GeniezoneError(e, function))
}
diff --git a/libs/hyp/src/hypervisor/kvm.rs b/libs/hyp/src/hypervisor/kvm.rs
index a95b8de..5835346 100644
--- a/libs/hyp/src/hypervisor/kvm.rs
+++ b/libs/hyp/src/hypervisor/kvm.rs
@@ -14,9 +14,7 @@
//! Wrappers around calls to the KVM hypervisor.
-use super::common::{
- Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor, MMIO_GUARD_GRANULE_SIZE,
-};
+use super::common::{Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
use crate::error::{Error, Result};
use crate::util::page_address;
use core::fmt::{self, Display, Formatter};
@@ -95,13 +93,13 @@
}
impl MmioGuardedHypervisor for ProtectedKvmHypervisor {
- fn init(&self) -> Result<()> {
- mmio_guard_enroll()?;
- let mmio_granule = mmio_guard_granule()?;
- if mmio_granule != MMIO_GUARD_GRANULE_SIZE {
- return Err(Error::UnsupportedMmioGuardGranule(mmio_granule));
+ fn enroll(&self) -> Result<()> {
+ let args = [0u64; 17];
+ match success_or_error_64(hvc64(VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID, args)[0]) {
+ Ok(()) => Ok(()),
+ Err(KvmError::NotSupported) => Err(Error::MmioGuardNotSupported),
+ Err(e) => Err(Error::KvmError(e, VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID)),
}
- Ok(())
}
fn map(&self, addr: usize) -> Result<()> {
@@ -125,6 +123,12 @@
Err(e) => Err(Error::KvmError(e, VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID)),
}
}
+
+ fn granule(&self) -> Result<usize> {
+ let args = [0u64; 17];
+ let granule = checked_hvc64(VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID, args)?;
+ Ok(granule.try_into().unwrap())
+ }
}
impl MemSharingHypervisor for ProtectedKvmHypervisor {
@@ -149,22 +153,6 @@
}
}
-fn mmio_guard_granule() -> Result<usize> {
- let args = [0u64; 17];
-
- let granule = checked_hvc64(VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID, args)?;
- Ok(granule.try_into().unwrap())
-}
-
-fn mmio_guard_enroll() -> Result<()> {
- let args = [0u64; 17];
- match success_or_error_64(hvc64(VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID, args)[0]) {
- Ok(_) => Ok(()),
- Err(KvmError::NotSupported) => Err(Error::MmioGuardNotsupported),
- Err(e) => Err(Error::KvmError(e, VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID)),
- }
-}
-
fn checked_hvc64_expect_zero(function: u32, args: [u64; 17]) -> Result<()> {
success_or_error_64(hvc64(function, args)[0]).map_err(|e| Error::KvmError(e, function))
}
diff --git a/libs/hyp/src/hypervisor/mod.rs b/libs/hyp/src/hypervisor/mod.rs
index bc9e406..309f967 100644
--- a/libs/hyp/src/hypervisor/mod.rs
+++ b/libs/hyp/src/hypervisor/mod.rs
@@ -60,8 +60,10 @@
GeniezoneHypervisor::UUID => Ok(HypervisorBackend::Geniezone),
GunyahHypervisor::UUID => Ok(HypervisorBackend::Gunyah),
RegularKvmHypervisor::UUID => {
- // Protected KVM has the same UUID so differentiate based on MEM_SHARE.
- match ProtectedKvmHypervisor.as_mem_sharer().unwrap().granule() {
+ // Protected KVM has the same UUID as "regular" KVM so issue an HVC that is assumed
+ // to only be supported by pKVM: if it returns SUCCESS, deduce that this is pKVM
+ // and if it returns NOT_SUPPORTED assume that it is "regular" KVM.
+ match ProtectedKvmHypervisor.as_mmio_guard().unwrap().granule() {
Ok(_) => Ok(HypervisorBackend::ProtectedKvm),
Err(Error::KvmError(KvmError::NotSupported, _)) => {
Ok(HypervisorBackend::RegularKvm)
@@ -101,7 +103,7 @@
}
fn detect_hypervisor() -> HypervisorBackend {
- query_vendor_hyp_call_uid().try_into().expect("Unknown hypervisor")
+ query_vendor_hyp_call_uid().try_into().expect("Failed to detect hypervisor")
}
/// Gets the hypervisor singleton.
diff --git a/pvmfw/platform.dts b/pvmfw/platform.dts
index 74439d9..cb8e30d 100644
--- a/pvmfw/platform.dts
+++ b/pvmfw/platform.dts
@@ -225,6 +225,8 @@
0x3000 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 5) IRQ_TYPE_LEVEL_HIGH
0x3800 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 6) IRQ_TYPE_LEVEL_HIGH
0x4000 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 7) IRQ_TYPE_LEVEL_HIGH
+ 0x4800 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 8) IRQ_TYPE_LEVEL_HIGH
+ 0x5000 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 9) IRQ_TYPE_LEVEL_HIGH
>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7
0xf800 0x0 0x0 0x7
@@ -233,6 +235,8 @@
0xf800 0x0 0x0 0x7
0xf800 0x0 0x0 0x7
0xf800 0x0 0x0 0x7
+ 0xf800 0x0 0x0 0x7
+ 0xf800 0x0 0x0 0x7
0xf800 0x0 0x0 0x7>;
};
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 4e41331..244b192 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -209,7 +209,7 @@
impl PciInfo {
const IRQ_MASK_CELLS: usize = 4;
const IRQ_MAP_CELLS: usize = 10;
- const MAX_IRQS: usize = 8;
+ const MAX_IRQS: usize = 10;
}
type PciAddrRange = AddressRange<(u32, u64), u64, u64>;
@@ -248,14 +248,22 @@
let range1 = ranges.next().ok_or(FdtError::NotFound)?;
let irq_masks = node.getprop_cells(cstr!("interrupt-map-mask"))?.ok_or(FdtError::NotFound)?;
- let irq_masks = CellChunkIterator::<{ PciInfo::IRQ_MASK_CELLS }>::new(irq_masks);
- let irq_masks: ArrayVec<[PciIrqMask; PciInfo::MAX_IRQS]> =
- irq_masks.take(PciInfo::MAX_IRQS).collect();
+ let mut chunks = CellChunkIterator::<{ PciInfo::IRQ_MASK_CELLS }>::new(irq_masks);
+ let irq_masks = (&mut chunks).take(PciInfo::MAX_IRQS).collect();
+
+ if chunks.next().is_some() {
+ warn!("Input DT has more than {} PCI entries!", PciInfo::MAX_IRQS);
+ return Err(FdtError::NoSpace);
+ }
let irq_maps = node.getprop_cells(cstr!("interrupt-map"))?.ok_or(FdtError::NotFound)?;
- let irq_maps = CellChunkIterator::<{ PciInfo::IRQ_MAP_CELLS }>::new(irq_maps);
- let irq_maps: ArrayVec<[PciIrqMap; PciInfo::MAX_IRQS]> =
- irq_maps.take(PciInfo::MAX_IRQS).collect();
+ let mut chunks = CellChunkIterator::<{ PciInfo::IRQ_MAP_CELLS }>::new(irq_maps);
+ let irq_maps = (&mut chunks).take(PciInfo::MAX_IRQS).collect();
+
+ if chunks.next().is_some() {
+ warn!("Input DT has more than {} PCI entries!", PciInfo::MAX_IRQS);
+ return Err(FdtError::NoSpace);
+ }
Ok(PciInfo { ranges: [range0, range1], irq_masks, irq_maps })
}
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
index 9c512bf..90ba575 100644
--- a/tests/benchmark/Android.bp
+++ b/tests/benchmark/Android.bp
@@ -26,6 +26,7 @@
sdk_version: "test_current",
use_embedded_native_libs: true,
compile_multilib: "64",
+ required: ["perf-setup"],
host_required: ["MicrodroidTestPreparer"],
}
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index 46f4937..71b9e76 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -84,6 +84,7 @@
"libspin_nostd",
"libtinyvec_nostd",
"libvirtio_drivers",
+ "libzerocopy_nostd",
"libzeroize_nostd",
],
whole_static_libs: [
diff --git a/vmbase/src/entry.rs b/vmbase/src/entry.rs
index 24b5035..2ff66cc 100644
--- a/vmbase/src/entry.rs
+++ b/vmbase/src/entry.rs
@@ -26,7 +26,8 @@
console::init();
if let Some(mmio_guard) = get_mmio_guard() {
- mmio_guard.init()?;
+ mmio_guard.enroll()?;
+ mmio_guard.validate_granule()?;
mmio_guard.map(console::BASE_ADDRESS)?;
}
diff --git a/vmbase/src/hvc.rs b/vmbase/src/hvc.rs
index ebd1625..1197143 100644
--- a/vmbase/src/hvc.rs
+++ b/vmbase/src/hvc.rs
@@ -37,7 +37,7 @@
(version as u32 as i32).try_into()
}
-pub type TrngRng64Entropy = (u64, u64, u64);
+pub type TrngRng64Entropy = [u64; 3];
pub fn trng_rnd64(nbits: u64) -> trng::Result<TrngRng64Entropy> {
let mut args = [0u64; 17];
@@ -46,7 +46,7 @@
let regs = hvc64(ARM_SMCCC_TRNG_RND64, args);
success_or_error_64::<Error>(regs[0])?;
- Ok((regs[1], regs[2], regs[3]))
+ Ok([regs[1], regs[2], regs[3]])
}
pub fn trng_features(fid: u32) -> trng::Result<u64> {
diff --git a/vmbase/src/rand.rs b/vmbase/src/rand.rs
index 6b8d7e0..2acc390 100644
--- a/vmbase/src/rand.rs
+++ b/vmbase/src/rand.rs
@@ -14,10 +14,13 @@
//! Functions and drivers for obtaining true entropy.
-use crate::hvc::{self, TrngRng64Entropy};
+use crate::hvc;
use core::fmt;
use core::mem::size_of;
use smccc::{self, Hvc};
+use zerocopy::AsBytes as _;
+
+type Entropy = [u8; size_of::<u64>() * 3];
/// Error type for rand operations.
pub enum Error {
@@ -95,46 +98,55 @@
/// Fills a slice of bytes with true entropy.
pub fn fill_with_entropy(s: &mut [u8]) -> Result<()> {
- const MAX_BYTES_PER_CALL: usize = size_of::<TrngRng64Entropy>();
+ const MAX_BYTES_PER_CALL: usize = size_of::<Entropy>();
- let (aligned, remainder) = s.split_at_mut(s.len() - s.len() % MAX_BYTES_PER_CALL);
-
- for chunk in aligned.chunks_exact_mut(MAX_BYTES_PER_CALL) {
- let (r, s, t) = repeat_trng_rnd(chunk.len())?;
-
- let mut words = chunk.chunks_exact_mut(size_of::<u64>());
- words.next().unwrap().clone_from_slice(&t.to_ne_bytes());
- words.next().unwrap().clone_from_slice(&s.to_ne_bytes());
- words.next().unwrap().clone_from_slice(&r.to_ne_bytes());
- }
-
- if !remainder.is_empty() {
- let mut entropy = [0; MAX_BYTES_PER_CALL];
- let (r, s, t) = repeat_trng_rnd(remainder.len())?;
-
- let mut words = entropy.chunks_exact_mut(size_of::<u64>());
- words.next().unwrap().clone_from_slice(&t.to_ne_bytes());
- words.next().unwrap().clone_from_slice(&s.to_ne_bytes());
- words.next().unwrap().clone_from_slice(&r.to_ne_bytes());
-
- remainder.clone_from_slice(&entropy[..remainder.len()]);
+ for chunk in s.chunks_mut(MAX_BYTES_PER_CALL) {
+ let entropy = repeat_trng_rnd(chunk.len())?;
+ chunk.clone_from_slice(&entropy[..chunk.len()]);
}
Ok(())
}
-fn repeat_trng_rnd(n_bytes: usize) -> Result<TrngRng64Entropy> {
- let bits = usize::try_from(u8::BITS).unwrap();
- let n_bits = (n_bytes * bits).try_into().unwrap();
+/// Returns an array where the first `n_bytes` bytes hold entropy.
+///
+/// The rest of the array should be ignored.
+fn repeat_trng_rnd(n_bytes: usize) -> Result<Entropy> {
loop {
- match hvc::trng_rnd64(n_bits) {
- Ok(entropy) => return Ok(entropy),
- Err(hvc::trng::Error::NoEntropy) => (),
- Err(e) => return Err(e.into()),
+ if let Some(entropy) = rnd64(n_bytes)? {
+ return Ok(entropy);
}
}
}
+/// Returns an array where the first `n_bytes` bytes hold entropy, if available.
+///
+/// The rest of the array should be ignored.
+fn rnd64(n_bytes: usize) -> Result<Option<Entropy>> {
+ let bits = usize::try_from(u8::BITS).unwrap();
+ let result = hvc::trng_rnd64((n_bytes * bits).try_into().unwrap());
+ let entropy = if matches!(result, Err(hvc::trng::Error::NoEntropy)) {
+ None
+ } else {
+ let r = result?;
+ // From the SMCCC TRNG:
+ //
+ // A MAX_BITS-bits wide value (Entropy) is returned across X1 to X3.
+ // The requested conditioned entropy is returned in Entropy[N-1:0].
+ //
+ // X1 Entropy[191:128]
+ // X2 Entropy[127:64]
+ // X3 Entropy[63:0]
+ //
+ // The bits in Entropy[MAX_BITS-1:N] are 0.
+ let reordered = [r[2].to_le(), r[1].to_le(), r[0].to_le()];
+
+ Some(reordered.as_bytes().try_into().unwrap())
+ };
+
+ Ok(entropy)
+}
+
/// Generate an array of fixed-size initialized with true-random bytes.
pub fn random_array<const N: usize>() -> Result<[u8; N]> {
let mut arr = [0; N];