Merge "Revert^2 "dice: add sign and encode with CoseSign1"" into main
diff --git a/guest/forwarder_guest/.gitignore b/guest/forwarder_guest/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/guest/forwarder_guest/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/guest/forwarder_guest_launcher/.gitignore b/guest/forwarder_guest_launcher/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/guest/forwarder_guest_launcher/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/guest/pvmfw/src/instance.rs b/guest/pvmfw/src/instance.rs
index bb07f74..bbc58ed 100644
--- a/guest/pvmfw/src/instance.rs
+++ b/guest/pvmfw/src/instance.rs
@@ -26,7 +26,10 @@
use diced_open_dice::Hidden;
use log::trace;
use uuid::Uuid;
-use virtio_drivers::transport::{pci::bus::PciRoot, DeviceType, Transport};
+use virtio_drivers::transport::{
+ pci::bus::{ConfigurationAccess, PciRoot},
+ DeviceType, Transport,
+};
use vmbase::util::ceiling_div;
use vmbase::virtio::pci::{PciTransportIterator, VirtIOBlk};
use vmbase::virtio::HalImpl;
@@ -99,7 +102,7 @@
/// pvmfw in the instance.img as well as index corresponding to empty header which can be used to
/// record instance data with `record_instance_entry`.
pub(crate) fn get_recorded_entry(
- pci_root: &mut PciRoot,
+ pci_root: &mut PciRoot<impl ConfigurationAccess>,
secret: &[u8],
) -> Result<(Option<EntryBody>, Partition, usize)> {
let mut instance_img = find_instance_img(pci_root)?;
@@ -175,8 +178,8 @@
}
}
-fn find_instance_img(pci_root: &mut PciRoot) -> Result<Partition> {
- for transport in PciTransportIterator::<HalImpl>::new(pci_root)
+fn find_instance_img(pci_root: &mut PciRoot<impl ConfigurationAccess>) -> Result<Partition> {
+ for transport in PciTransportIterator::<HalImpl, _>::new(pci_root)
.filter(|t| DeviceType::Block == t.device_type())
{
let device =
diff --git a/guest/pvmfw/src/rollback.rs b/guest/pvmfw/src/rollback.rs
index 74b2cd8..004acdb 100644
--- a/guest/pvmfw/src/rollback.rs
+++ b/guest/pvmfw/src/rollback.rs
@@ -25,7 +25,7 @@
use log::{error, info};
use pvmfw_avb::Capability;
use pvmfw_avb::VerifiedBootData;
-use virtio_drivers::transport::pci::bus::PciRoot;
+use virtio_drivers::transport::pci::bus::{ConfigurationAccess, PciRoot};
use vmbase::fdt::{pci::PciInfo, SwiotlbInfo};
use vmbase::memory::init_shared_pool;
use vmbase::rand;
@@ -44,17 +44,15 @@
cdi_seal: &[u8],
instance_hash: Option<Hidden>,
) -> Result<(bool, Hidden, bool), RebootReason> {
- if should_defer_rollback_protection(fdt)?
- && verified_boot_data.has_capability(Capability::SecretkeeperProtection)
+ if (should_defer_rollback_protection(fdt)?
+ && verified_boot_data.has_capability(Capability::SecretkeeperProtection))
+ || verified_boot_data.has_capability(Capability::TrustySecurityVm)
{
perform_deferred_rollback_protection(verified_boot_data)?;
Ok((false, instance_hash.unwrap(), true))
} else if verified_boot_data.has_capability(Capability::RemoteAttest) {
perform_fixed_index_rollback_protection(verified_boot_data)?;
Ok((false, instance_hash.unwrap(), false))
- } else if verified_boot_data.has_capability(Capability::TrustySecurityVm) {
- skip_rollback_protection()?;
- Ok((false, instance_hash.unwrap(), false))
} else {
perform_legacy_rollback_protection(fdt, dice_inputs, cdi_seal, instance_hash)
}
@@ -88,11 +86,6 @@
}
}
-fn skip_rollback_protection() -> Result<(), RebootReason> {
- info!("Skipping rollback protection");
- Ok(())
-}
-
/// Performs RBP using instance.img where updates require clearing old entries, causing new CDIs.
fn perform_legacy_rollback_protection(
fdt: &Fdt,
@@ -167,7 +160,9 @@
}
/// Set up PCI bus and VirtIO-blk device containing the instance.img partition.
-fn initialize_instance_img_device(fdt: &Fdt) -> Result<PciRoot, RebootReason> {
+fn initialize_instance_img_device(
+ fdt: &Fdt,
+) -> Result<PciRoot<impl ConfigurationAccess>, RebootReason> {
let pci_info = PciInfo::from_fdt(fdt).map_err(|e| {
error!("Failed to detect PCI from DT: {e}");
RebootReason::InvalidFdt
diff --git a/guest/rialto/src/communication.rs b/guest/rialto/src/communication.rs
index 1b94912..6f5a59e 100644
--- a/guest/rialto/src/communication.rs
+++ b/guest/rialto/src/communication.rs
@@ -67,7 +67,7 @@
match event {
VsockEventType::Connected => return Ok(()),
VsockEventType::Disconnected { .. } => {
- return Err(SocketError::ConnectionFailed.into())
+ return Err(SocketError::NotConnected.into())
}
// We shouldn't receive the following event before the connection is
// established.
@@ -141,7 +141,7 @@
fn poll(&mut self) -> virtio_drivers::Result<Option<VsockEventType>> {
if let Some(event) = self.poll_event_from_peer()? {
match event {
- VsockEventType::Disconnected { .. } => Err(SocketError::ConnectionFailed.into()),
+ VsockEventType::Disconnected { .. } => Err(SocketError::NotConnected.into()),
VsockEventType::Connected | VsockEventType::ConnectionRequest => {
Err(SocketError::InvalidOperation.into())
}
diff --git a/guest/rialto/src/main.rs b/guest/rialto/src/main.rs
index 04d18be..c3d3604 100644
--- a/guest/rialto/src/main.rs
+++ b/guest/rialto/src/main.rs
@@ -38,7 +38,10 @@
use service_vm_requests::{process_request, RequestContext};
use virtio_drivers::{
device::socket::{VsockAddr, VMADDR_CID_HOST},
- transport::{pci::bus::PciRoot, DeviceType, Transport},
+ transport::{
+ pci::bus::{ConfigurationAccess, PciRoot},
+ DeviceType, Transport,
+ },
Hal,
};
use vmbase::{
@@ -123,7 +126,6 @@
let pci_info = PciInfo::from_fdt(fdt)?;
debug!("PCI: {pci_info:#x?}");
let mut pci_root = pci::initialize(pci_info).map_err(Error::PciInitializationFailed)?;
- debug!("PCI root: {pci_root:#x?}");
let socket_device = find_socket_device::<HalImpl>(&mut pci_root)?;
debug!("Found socket device: guest cid = {:?}", socket_device.guest_cid());
let vendor_hashtree_root_digest = read_vendor_hashtree_root_digest(fdt)?;
@@ -143,8 +145,10 @@
Ok(())
}
-fn find_socket_device<T: Hal>(pci_root: &mut PciRoot) -> Result<VirtIOSocket<T>> {
- PciTransportIterator::<T>::new(pci_root)
+fn find_socket_device<T: Hal>(
+ pci_root: &mut PciRoot<impl ConfigurationAccess>,
+) -> Result<VirtIOSocket<T>> {
+ PciTransportIterator::<T, _>::new(pci_root)
.find(|t| DeviceType::Socket == t.device_type())
.map(VirtIOSocket::<T>::new)
.transpose()
diff --git a/guest/vmbase_example/src/pci.rs b/guest/vmbase_example/src/pci.rs
index 32ab9f6..1e87682 100644
--- a/guest/vmbase_example/src/pci.rs
+++ b/guest/vmbase_example/src/pci.rs
@@ -20,7 +20,10 @@
use virtio_drivers::{
device::console::VirtIOConsole,
transport::{
- pci::{bus::PciRoot, PciTransport},
+ pci::{
+ bus::{ConfigurationAccess, PciRoot},
+ PciTransport,
+ },
DeviceType, Transport,
},
BufferDirection, Error, Hal, PhysAddr, PAGE_SIZE,
@@ -33,11 +36,11 @@
/// The size in sectors of the test block device we expect.
const EXPECTED_SECTOR_COUNT: usize = 4;
-pub fn check_pci(pci_root: &mut PciRoot) {
+pub fn check_pci(pci_root: &mut PciRoot<impl ConfigurationAccess>) {
let mut checked_virtio_device_count = 0;
let mut block_device_count = 0;
let mut socket_device_count = 0;
- for mut transport in PciTransportIterator::<HalImpl>::new(pci_root) {
+ for mut transport in PciTransportIterator::<HalImpl, _>::new(pci_root) {
info!(
"Detected virtio PCI device with device type {:?}, features {:#018x}",
transport.device_type(),
@@ -104,7 +107,10 @@
fn check_virtio_console_device(transport: PciTransport) {
let mut console = VirtIOConsole::<HalImpl, PciTransport>::new(transport)
.expect("Failed to create VirtIO console driver");
- info!("Found console device: {:?}", console.info());
+ info!(
+ "Found console device with size {:?}",
+ console.size().expect("Failed to get size of VirtIO console device")
+ );
for &c in b"Hello VirtIO console\n" {
console.send(c).expect("Failed to send character to VirtIO console device");
}
diff --git a/libs/libhypervisor_backends/Android.bp b/libs/libhypervisor_backends/Android.bp
index 27e3fe5..e9e8915 100644
--- a/libs/libhypervisor_backends/Android.bp
+++ b/libs/libhypervisor_backends/Android.bp
@@ -11,20 +11,27 @@
host_supported: false,
no_stdlibs: true,
srcs: ["src/lib.rs"],
- rustlibs: [
- "libonce_cell_nostd",
- "libsmccc",
- "libthiserror_nostd",
- "libuuid_nostd",
- ],
enabled: false,
+ stdlibs: [
+ "libcompiler_builtins.rust_sysroot",
+ "libcore.rust_sysroot",
+ ],
target: {
android_arm64: {
- enabled: true,
- stdlibs: [
- "libcompiler_builtins.rust_sysroot",
- "libcore.rust_sysroot",
+ rustlibs: [
+ "libonce_cell_nostd",
+ "libsmccc",
+ "libthiserror_nostd",
+ "libuuid_nostd",
],
+ enabled: true,
+ },
+ android_x86_64: {
+ rustlibs: [
+ "libonce_cell_nostd",
+ "libthiserror_nostd",
+ ],
+ enabled: true,
},
},
}
diff --git a/libs/libhypervisor_backends/src/error.rs b/libs/libhypervisor_backends/src/error.rs
index e9c37e1..3046b0c 100644
--- a/libs/libhypervisor_backends/src/error.rs
+++ b/libs/libhypervisor_backends/src/error.rs
@@ -16,7 +16,10 @@
use core::{fmt, result};
-use super::hypervisor::{GeniezoneError, KvmError};
+#[cfg(target_arch = "aarch64")]
+use super::hypervisor::GeniezoneError;
+use super::hypervisor::KvmError;
+#[cfg(target_arch = "aarch64")]
use uuid::Uuid;
/// Result type with hypervisor error.
@@ -29,10 +32,15 @@
MmioGuardNotSupported,
/// Failed to invoke a certain KVM HVC function.
KvmError(KvmError, u32),
+ #[cfg(target_arch = "aarch64")]
/// Failed to invoke GenieZone HVC function.
GeniezoneError(GeniezoneError, u32),
+ #[cfg(target_arch = "aarch64")]
/// Unsupported Hypervisor
UnsupportedHypervisorUuid(Uuid),
+ #[cfg(target_arch = "x86_64")]
+ /// Unsupported x86_64 Hypervisor
+ UnsupportedHypervisor(u128),
}
impl fmt::Display for Error {
@@ -42,15 +50,21 @@
Self::KvmError(e, function_id) => {
write!(f, "Failed to invoke the HVC function with function ID {function_id}: {e}")
}
+ #[cfg(target_arch = "aarch64")]
Self::GeniezoneError(e, function_id) => {
write!(
f,
"Failed to invoke GenieZone HVC function with function ID {function_id}: {e}"
)
}
+ #[cfg(target_arch = "aarch64")]
Self::UnsupportedHypervisorUuid(u) => {
write!(f, "Unsupported Hypervisor UUID {u}")
}
+ #[cfg(target_arch = "x86_64")]
+ Self::UnsupportedHypervisor(c) => {
+ write!(f, "Unsupported x86_64 Hypervisor {c}")
+ }
}
}
}
diff --git a/libs/libhypervisor_backends/src/hypervisor.rs b/libs/libhypervisor_backends/src/hypervisor.rs
index 1b45f38..aa65133 100644
--- a/libs/libhypervisor_backends/src/hypervisor.rs
+++ b/libs/libhypervisor_backends/src/hypervisor.rs
@@ -15,26 +15,42 @@
//! Wrappers around hypervisor back-ends.
mod common;
+#[cfg(target_arch = "aarch64")]
mod geniezone;
+#[cfg(target_arch = "aarch64")]
mod gunyah;
+#[cfg(target_arch = "aarch64")]
+#[path = "hypervisor/kvm_aarch64.rs"]
mod kvm;
-use super::{Error, Result};
+#[cfg(target_arch = "x86_64")]
+#[path = "hypervisor/kvm_x86.rs"]
+mod kvm;
+
+#[cfg(target_arch = "aarch64")]
+use {
+ super::{Error, Result},
+ geniezone::GeniezoneHypervisor,
+ gunyah::GunyahHypervisor,
+ smccc::hvc64,
+ uuid::Uuid,
+};
+
+#[cfg(target_arch = "aarch64")]
+pub use geniezone::GeniezoneError;
+
use alloc::boxed::Box;
use common::Hypervisor;
pub use common::{DeviceAssigningHypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
-pub use geniezone::GeniezoneError;
-use geniezone::GeniezoneHypervisor;
-use gunyah::GunyahHypervisor;
pub use kvm::KvmError;
use kvm::{ProtectedKvmHypervisor, RegularKvmHypervisor};
use once_cell::race::OnceBox;
-use smccc::hvc64;
-use uuid::Uuid;
enum HypervisorBackend {
RegularKvm,
+ #[cfg(target_arch = "aarch64")]
Gunyah,
+ #[cfg(target_arch = "aarch64")]
Geniezone,
ProtectedKvm,
}
@@ -43,13 +59,16 @@
fn get_hypervisor(&self) -> &'static dyn Hypervisor {
match self {
Self::RegularKvm => &RegularKvmHypervisor,
+ #[cfg(target_arch = "aarch64")]
Self::Gunyah => &GunyahHypervisor,
+ #[cfg(target_arch = "aarch64")]
Self::Geniezone => &GeniezoneHypervisor,
Self::ProtectedKvm => &ProtectedKvmHypervisor,
}
}
}
+#[cfg(target_arch = "aarch64")]
impl TryFrom<Uuid> for HypervisorBackend {
type Error = Error;
@@ -74,8 +93,10 @@
}
}
+#[cfg(target_arch = "aarch64")]
const ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID: u32 = 0x8600ff01;
+#[cfg(target_arch = "aarch64")]
fn query_vendor_hyp_call_uid() -> Uuid {
let args = [0u64; 17];
let res = hvc64(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, args);
@@ -101,7 +122,13 @@
}
fn detect_hypervisor() -> HypervisorBackend {
- query_vendor_hyp_call_uid().try_into().expect("Failed to detect hypervisor")
+ #[cfg(target_arch = "aarch64")]
+ {
+ query_vendor_hyp_call_uid().try_into().expect("Failed to detect hypervisor")
+ }
+
+ #[cfg(target_arch = "x86_64")]
+ kvm::determine_hyp_type().expect("Failed to detect hypervisor")
}
/// Gets the hypervisor singleton.
diff --git a/libs/libhypervisor_backends/src/hypervisor/kvm.rs b/libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs
similarity index 100%
rename from libs/libhypervisor_backends/src/hypervisor/kvm.rs
rename to libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs
diff --git a/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs b/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs
new file mode 100644
index 0000000..7f9ea4d
--- /dev/null
+++ b/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs
@@ -0,0 +1,172 @@
+// Copyright 2025, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Wrappers around calls to the KVM hypervisor.
+
+use super::{Hypervisor, MemSharingHypervisor};
+use crate::{mem::SIZE_4KB, Error, Result};
+use core::fmt::{self, Display, Formatter};
+
+const KVM_HC_PKVM_OP: u32 = 20;
+const PKVM_GHC_SHARE_MEM: u32 = KVM_HC_PKVM_OP + 1;
+const PKVM_GHC_UNSHARE_MEM: u32 = KVM_HC_PKVM_OP + 2;
+
+const KVM_ENOSYS: i64 = -1000;
+const KVM_EINVAL: i64 = -22;
+
+/// This CPUID returns the signature and can be used to determine if VM is running under pKVM, KVM
+/// or not.
+pub const KVM_CPUID_SIGNATURE: u32 = 0x40000000;
+
+/// Error from a KVM HVC call.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum KvmError {
+ /// The call is not supported by the implementation.
+ NotSupported,
+ /// One of the call parameters has a non-supported value.
+ InvalidParameter,
+ /// There was an unexpected return value.
+ Unknown(i64),
+}
+
+impl From<i64> for KvmError {
+ fn from(value: i64) -> Self {
+ match value {
+ KVM_ENOSYS => KvmError::NotSupported,
+ KVM_EINVAL => KvmError::InvalidParameter,
+ _ => KvmError::Unknown(value),
+ }
+ }
+}
+
+impl From<i32> for KvmError {
+ fn from(value: i32) -> Self {
+ i64::from(value).into()
+ }
+}
+
+impl Display for KvmError {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match self {
+ Self::NotSupported => write!(f, "KVM call not supported"),
+ Self::InvalidParameter => write!(f, "KVM call received non-supported value"),
+ Self::Unknown(e) => write!(f, "Unknown return value from KVM {} ({0:#x})", e),
+ }
+ }
+}
+
+pub(super) struct RegularKvmHypervisor;
+
+impl RegularKvmHypervisor {
+ pub(super) const CPUID: u128 = u128::from_le_bytes(*b"KVMKVMKVM\0\0\0\0\0\0\0");
+}
+
+impl Hypervisor for RegularKvmHypervisor {}
+
+pub(super) struct ProtectedKvmHypervisor;
+
+impl ProtectedKvmHypervisor {
+ pub(super) const CPUID: u128 = u128::from_le_bytes(*b"PKVMPKVMPKVM\0\0\0\0");
+}
+
+impl Hypervisor for ProtectedKvmHypervisor {
+ fn as_mem_sharer(&self) -> Option<&dyn MemSharingHypervisor> {
+ Some(self)
+ }
+}
+
+macro_rules! vmcall {
+ ($hypcall:expr, $base:expr, $size:expr) => {{
+ let ret;
+ // SAFETY:
+ // Any undeclared register aren't clobbered except rbx but rbx value is restored at the end
+ // of the asm block.
+ unsafe {
+ core::arch::asm!(
+ "xchg %rbx, {0:r}",
+ "vmcall",
+ "xchg %rbx, {0:r}",
+ in(reg) $base,
+ inout("rax") $hypcall => ret,
+ in("rcx") $size,
+ options(att_syntax, nomem));
+ };
+ ret
+ }};
+}
+
+macro_rules! cpuid {
+ ($hypcall:expr) => {{
+ let ret_1: u32;
+ let ret_2: u32;
+ let ret_3: u32;
+ // SAFETY:
+ // Any undeclared register aren't clobbered except rbx but rbx value is restored at the end
+ // of the asm block.
+ unsafe {
+ // The argument for cpuid is passed via rax and in case of KVM_CPUID_SIGNATURE returned
+ // via rbx, rcx and rdx. Ideally using named arguments in inline asm for rbx would be
+ // much more straightforward but when rbx is directly used LLVM complains that: error:
+ // cannot use register `bx`: rbx is used internally by LLVM and cannot be used as an
+ // operand for inline asm
+ //
+ // Therefore use temp register to store rbx content and restore it back after cpuid
+ // call.
+ core::arch::asm!(
+ "xchg %rbx, {0:r}",
+ "cpuid",
+ "xchg %rbx, {0:r}",
+ out(reg) ret_1, in("eax") $hypcall, out("rcx") ret_2, out ("rdx") ret_3,
+ options(att_syntax, nomem));
+ };
+ ((ret_3 as u128) << 64) | ((ret_2 as u128) << 32) | (ret_1 as u128)
+ }};
+}
+
+impl MemSharingHypervisor for ProtectedKvmHypervisor {
+ fn share(&self, base_ipa: u64) -> Result<()> {
+ let ret: u32 = vmcall!(PKVM_GHC_SHARE_MEM, base_ipa, SIZE_4KB);
+
+ if ret != 0 {
+ return Err(Error::KvmError(KvmError::from(ret as i32), PKVM_GHC_SHARE_MEM));
+ }
+
+ Ok(())
+ }
+
+ fn unshare(&self, base_ipa: u64) -> Result<()> {
+ let ret: u32 = vmcall!(PKVM_GHC_UNSHARE_MEM, base_ipa, SIZE_4KB);
+ if ret != 0 {
+ return Err(Error::KvmError(KvmError::from(ret as i32), PKVM_GHC_UNSHARE_MEM));
+ }
+
+ Ok(())
+ }
+
+ fn granule(&self) -> Result<usize> {
+ Ok(SIZE_4KB)
+ }
+}
+
+use crate::hypervisor::HypervisorBackend;
+
+pub(crate) fn determine_hyp_type() -> Result<HypervisorBackend> {
+ let cpuid: u128 = cpuid!(KVM_CPUID_SIGNATURE);
+
+ match cpuid {
+ RegularKvmHypervisor::CPUID => Ok(HypervisorBackend::RegularKvm),
+ ProtectedKvmHypervisor::CPUID => Ok(HypervisorBackend::ProtectedKvm),
+ c => Err(Error::UnsupportedHypervisor(c)),
+ }
+}
diff --git a/libs/libhypervisor_backends/src/mem.rs b/libs/libhypervisor_backends/src/mem.rs
index ff65c49..9f7eafc 100644
--- a/libs/libhypervisor_backends/src/mem.rs
+++ b/libs/libhypervisor_backends/src/mem.rs
@@ -15,6 +15,7 @@
/// The size of a 4KB memory in bytes.
pub const SIZE_4KB: usize = 4 << 10;
+#[cfg(target_arch = "aarch64")]
/// Computes the largest multiple of the provided alignment smaller or equal to the address.
///
/// Note: the result is undefined if alignment isn't a power of two.
@@ -22,6 +23,7 @@
addr & !(alignment - 1)
}
+#[cfg(target_arch = "aarch64")]
/// Computes the address of the 4KiB page containing a given address.
pub const fn page_4kb_of(addr: usize) -> usize {
unchecked_align_down(addr, SIZE_4KB)
diff --git a/libs/libvmbase/src/fdt/pci.rs b/libs/libvmbase/src/fdt/pci.rs
index 44ad455..b526f3d 100644
--- a/libs/libvmbase/src/fdt/pci.rs
+++ b/libs/libvmbase/src/fdt/pci.rs
@@ -18,7 +18,7 @@
use libfdt::{AddressRange, Fdt, FdtError, FdtNode};
use log::debug;
use thiserror::Error;
-use virtio_drivers::transport::pci::bus::{Cam, PciRoot};
+use virtio_drivers::transport::pci::bus::{Cam, ConfigurationAccess, MmioCam, PciRoot};
/// PCI MMIO configuration region size.
const PCI_CFG_SIZE: usize = 0x100_0000;
@@ -94,10 +94,10 @@
/// To prevent concurrent access, only one `PciRoot` should exist in the program. Thus this
/// method must only be called once, and there must be no other `PciRoot` constructed using the
/// same CAM.
- pub unsafe fn make_pci_root(&self) -> PciRoot {
+ pub unsafe fn make_pci_root(&self) -> PciRoot<impl ConfigurationAccess> {
// SAFETY: We trust that the FDT gave us a valid MMIO base address for the CAM. The caller
// guarantees to only call us once, so there are no other references to it.
- unsafe { PciRoot::new(self.cam_range.start as *mut u8, Cam::MmioCam) }
+ PciRoot::new(unsafe { MmioCam::new(self.cam_range.start as *mut u8, Cam::MmioCam) })
}
}
diff --git a/libs/libvmbase/src/virtio/pci.rs b/libs/libvmbase/src/virtio/pci.rs
index ec89b6b..591ae54 100644
--- a/libs/libvmbase/src/virtio/pci.rs
+++ b/libs/libvmbase/src/virtio/pci.rs
@@ -26,7 +26,7 @@
use virtio_drivers::{
device::{blk, socket},
transport::pci::{
- bus::{BusDeviceIterator, PciRoot},
+ bus::{BusDeviceIterator, ConfigurationAccess, PciRoot},
virtio_device_type, PciTransport,
},
Hal,
@@ -66,7 +66,7 @@
/// 3. Creates and returns a `PciRoot`.
///
/// This must only be called once and after having switched to the dynamic page tables.
-pub fn initialize(pci_info: PciInfo) -> Result<PciRoot, PciError> {
+pub fn initialize(pci_info: PciInfo) -> Result<PciRoot<impl ConfigurationAccess>, PciError> {
PCI_INFO.set(Box::new(pci_info.clone())).map_err(|_| PciError::DuplicateInitialization)?;
let cam_start = pci_info.cam_range.start;
@@ -90,21 +90,21 @@
pub type VirtIOSocket<T> = socket::VirtIOSocket<T, PciTransport>;
/// An iterator that iterates over the PCI transport for each device.
-pub struct PciTransportIterator<'a, T: Hal> {
- pci_root: &'a mut PciRoot,
- bus: BusDeviceIterator,
+pub struct PciTransportIterator<'a, T: Hal, C: ConfigurationAccess> {
+ pci_root: &'a mut PciRoot<C>,
+ bus: BusDeviceIterator<C>,
_hal: PhantomData<T>,
}
-impl<'a, T: Hal> PciTransportIterator<'a, T> {
+impl<'a, T: Hal, C: ConfigurationAccess> PciTransportIterator<'a, T, C> {
/// Creates a new iterator.
- pub fn new(pci_root: &'a mut PciRoot) -> Self {
+ pub fn new(pci_root: &'a mut PciRoot<C>) -> Self {
let bus = pci_root.enumerate_bus(0);
Self { pci_root, bus, _hal: PhantomData }
}
}
-impl<'a, T: Hal> Iterator for PciTransportIterator<'a, T> {
+impl<'a, T: Hal, C: ConfigurationAccess> Iterator for PciTransportIterator<'a, T, C> {
type Item = PciTransport;
fn next(&mut self) -> Option<Self::Item> {
@@ -121,7 +121,7 @@
};
debug!(" VirtIO {:?}", virtio_type);
- return PciTransport::new::<T>(self.pci_root, device_function).ok();
+ return PciTransport::new::<T, C>(self.pci_root, device_function).ok();
}
}
}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 7431a72..3ece140 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -1926,6 +1926,11 @@
@Test
public void rollbackProtectedDataCanBeAccessedPostConnectionExpiration() throws Exception {
+ assumeSupportedDevice();
+ // Rollback protected data is only possible if Updatable VMs is supported -
+ // which implies Secretkeeper support.
+ assumeTrue("Missing Updatable VM support", isUpdatableVmSupported());
+
final long vmSize = minMemoryRequired();
// The reference implementation of Secretkeeper maintains 4 live session keys,
// dropping the oldest one when new connections are requested. Therefore we spin 8 VMs