Merge "pvmfw: Clarify docs about BCC generation in ABL"
diff --git a/authfs/Android.bp b/authfs/Android.bp
index 154a1d6..2532026 100644
--- a/authfs/Android.bp
+++ b/authfs/Android.bp
@@ -23,7 +23,7 @@
"liblog_rust",
"libnix",
"libopenssl",
- "libprotobuf",
+ "libprotobuf_deprecated",
"librpcbinder_rs",
"libthiserror",
],
diff --git a/compos/Android.bp b/compos/Android.bp
index 2f6be98..c120b0f 100644
--- a/compos/Android.bp
+++ b/compos/Android.bp
@@ -18,7 +18,7 @@
"libminijail_rust",
"libnix",
"libodsign_proto_rust",
- "libprotobuf",
+ "libprotobuf_deprecated",
"libregex",
"librpcbinder_rs",
"librustutils",
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 96c8147..bf4c678 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -19,7 +19,7 @@
use crate::timeouts::TIMEOUTS;
use crate::{
get_vm_config_path, BUILD_MANIFEST_APK_PATH, BUILD_MANIFEST_SYSTEM_EXT_APK_PATH,
- COMPOS_APEX_ROOT, COMPOS_DATA_ROOT, COMPOS_VSOCK_PORT,
+ COMPOS_APEX_ROOT, COMPOS_VSOCK_PORT,
};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
CpuTopology::CpuTopology,
@@ -80,7 +80,6 @@
let instance_fd = ParcelFileDescriptor::new(instance_image);
let apex_dir = Path::new(COMPOS_APEX_ROOT);
- let data_dir = Path::new(COMPOS_DATA_ROOT);
let config_apk = locate_config_apk(apex_dir)?;
let apk_fd = File::open(config_apk).context("Failed to open config APK file")?;
@@ -110,18 +109,6 @@
let debug_level = if parameters.debug_mode { DebugLevel::FULL } else { DebugLevel::NONE };
- let (console_fd, log_fd) = if debug_level == DebugLevel::NONE {
- (None, None)
- } else {
- // Console output and the system log output from the VM are redirected to file.
- let console_fd = File::create(data_dir.join("vm_console.log"))
- .context("Failed to create console log file")?;
- let log_fd = File::create(data_dir.join("vm.log"))
- .context("Failed to create system log file")?;
- info!("Running in debug level {:?}", debug_level);
- (Some(console_fd), Some(log_fd))
- };
-
let cpu_topology = match parameters.cpu_topology {
VmCpuTopology::OneCpu => CpuTopology::ONE_CPU,
VmCpuTopology::MatchHost => CpuTopology::MATCH_HOST,
@@ -143,6 +130,8 @@
gdbPort: 0, // Don't start gdb-server
});
+ // Let logs go to logcat.
+ let (console_fd, log_fd) = (None, None);
let callback = Box::new(Callback {});
let instance = VmInstance::create(service, &config, console_fd, log_fd, Some(callback))
.context("Failed to create VM")?;
diff --git a/compos/composd/Android.bp b/compos/composd/Android.bp
index b0294dd..f66de32 100644
--- a/compos/composd/Android.bp
+++ b/compos/composd/Android.bp
@@ -22,7 +22,7 @@
"liblibc",
"liblog_rust",
"libodsign_proto_rust",
- "libprotobuf",
+ "libprotobuf_deprecated",
"librustutils",
"libshared_child",
"libvmclient",
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index 4e3d0a8..eb2e072 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -27,7 +27,6 @@
import com.android.microdroid.test.host.CommandRunner;
import com.android.microdroid.test.host.MicrodroidHostTestCaseBase;
-import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.LogDataType;
@@ -81,7 +80,7 @@
@Before
public void setUp() throws Exception {
- testIfDeviceIsCapable(getDevice());
+ assumeDeviceIsCapable(getDevice());
String value = getDevice().getProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME);
if (value == null) {
@@ -95,8 +94,6 @@
public void tearDown() throws Exception {
killVmAndReconnectAdb();
- archiveVmLogsThenDelete("teardown");
-
CommandRunner android = new CommandRunner(getDevice());
// Clear up any CompOS instance files we created
@@ -113,19 +110,6 @@
}
}
- private void archiveVmLogsThenDelete(String suffix) throws DeviceNotAvailableException {
- archiveLogThenDelete(
- mTestLogs,
- getDevice(),
- COMPOS_APEXDATA_DIR + "/vm_console.log",
- "vm_console.log-" + suffix + "-" + mTestName.getMethodName());
- archiveLogThenDelete(
- mTestLogs,
- getDevice(),
- COMPOS_APEXDATA_DIR + "/vm.log",
- "vm.log-" + suffix + "-" + mTestName.getMethodName());
- }
-
@Test
public void testOdrefreshSpeed() throws Exception {
getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME, "speed");
@@ -170,10 +154,6 @@
}
killVmAndReconnectAdb();
- // These logs are potentially useful, capture them before they are overwritten by
- // compos_verify.
- archiveVmLogsThenDelete("compile");
-
// Expect the BCC extracted from the BCC to be well-formed.
assertVmBccIsValid();
diff --git a/demo/README.md b/demo/README.md
index c5c87d8..fa4e38a 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -8,13 +8,18 @@
## Installing
+You can install the app like this:
```
-adb install -t out/dist/MicrodroidDemoApp.apk
-adb shell pm grant com.android.microdroid.demo android.permission.MANAGE_VIRTUAL_MACHINE
+adb install -t -g out/dist/MicrodroidDemoApp.apk
```
-Don't run the app before granting the permission. Or you will have to uninstall
-the app, and then re-install it.
+(-t allows it to be installed even though it is marked as a test app, -g grants
+the necessary permission.)
+
+You can also explicitly grant or revoke the permission, e.g.
+```
+adb shell pm grant com.android.microdroid.demo android.permission.MANAGE_VIRTUAL_MACHINE
+```
## Running
diff --git a/encryptedstore/src/main.rs b/encryptedstore/src/main.rs
index 7a41f13..86fa6da 100644
--- a/encryptedstore/src/main.rs
+++ b/encryptedstore/src/main.rs
@@ -125,9 +125,13 @@
fn format_ext4(device: &Path) -> Result<()> {
let mkfs_options = [
- "-j", // Create appropriate sized journal
- "-O metadata_csum", // Metadata checksum for filesystem integrity
- "-b 4096", // block size in the filesystem
+ "-j", // Create appropriate sized journal
+ /* metadata_csum: enabled for filesystem integrity
+ * extents: Not enabling extents reduces the coverage of metadata checksumming.
+ * 64bit: larger fields afforded by this feature enable full-strength checksumming.
+ */
+ "-O metadata_csum, extents, 64bit",
+ "-b 4096", // block size in the filesystem
];
let mut cmd = Command::new(MK2FS_BIN);
let status = cmd
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index 4cf4e99..fec0114 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -227,8 +227,8 @@
let context = Context::new(0);
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
let ts = Timestamp::from_unix(context, now.as_secs(), now.subsec_nanos());
- let uuid = Uuid::new_v1(ts, node_id)?;
- Ok(String::from(uuid.to_hyphenated().encode_lower(&mut Uuid::encode_buffer())))
+ let uuid = Uuid::new_v1(ts, node_id.try_into()?);
+ Ok(String::from(uuid.hyphenated().encode_lower(&mut Uuid::encode_buffer())))
}
#[cfg(test)]
diff --git a/microdroid/payload/metadata/Android.bp b/microdroid/payload/metadata/Android.bp
index cd182fc..e3138e8 100644
--- a/microdroid/payload/metadata/Android.bp
+++ b/microdroid/payload/metadata/Android.bp
@@ -12,7 +12,7 @@
rustlibs: [
"libanyhow",
"libmicrodroid_metadata_proto_rust",
- "libprotobuf",
+ "libprotobuf_deprecated",
],
apex_available: [
"com.android.virt",
diff --git a/pvmfw/src/exceptions.rs b/pvmfw/src/exceptions.rs
index 03fc220..42f4c3b 100644
--- a/pvmfw/src/exceptions.rs
+++ b/pvmfw/src/exceptions.rs
@@ -14,22 +14,21 @@
//! Exception handlers.
-use crate::helpers::page_4kb_of;
-use core::arch::asm;
+use crate::{helpers::page_4kb_of, read_sysreg};
use vmbase::console;
use vmbase::{console::emergency_write_str, eprintln, power::reboot};
-const ESR_32BIT_EXT_DABT: u64 = 0x96000010;
+const ESR_32BIT_EXT_DABT: usize = 0x96000010;
const UART_PAGE: usize = page_4kb_of(console::BASE_ADDRESS);
#[no_mangle]
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
- let esr = read_esr();
- let far = read_far();
+ let esr = read_sysreg!("esr_el1");
+ let far = read_sysreg!("far_el1");
// Don't print to the UART if we're handling the exception it could raise.
- if esr != ESR_32BIT_EXT_DABT || page_4kb_of(far as usize) != UART_PAGE {
+ if esr != ESR_32BIT_EXT_DABT || page_4kb_of(far) != UART_PAGE {
emergency_write_str("sync_exception_current\n");
- print_esr(esr);
+ eprintln!("esr={esr:#08x}");
}
reboot();
}
@@ -48,17 +47,17 @@
#[no_mangle]
extern "C" fn serr_current(_elr: u64, _spsr: u64) {
- let esr = read_esr();
+ let esr = read_sysreg!("esr_el1");
emergency_write_str("serr_current\n");
- print_esr(esr);
+ eprintln!("esr={esr:#08x}");
reboot();
}
#[no_mangle]
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
- let esr = read_esr();
+ let esr = read_sysreg!("esr_el1");
emergency_write_str("sync_lower\n");
- print_esr(esr);
+ eprintln!("esr={esr:#08x}");
reboot();
}
@@ -76,31 +75,8 @@
#[no_mangle]
extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
- let esr = read_esr();
+ let esr = read_sysreg!("esr_el1");
emergency_write_str("serr_lower\n");
- print_esr(esr);
+ eprintln!("esr={esr:#08x}");
reboot();
}
-
-#[inline]
-fn read_esr() -> u64 {
- let mut esr: u64;
- unsafe {
- asm!("mrs {esr}, esr_el1", esr = out(reg) esr);
- }
- esr
-}
-
-#[inline]
-fn print_esr(esr: u64) {
- eprintln!("esr={:#08x}", esr);
-}
-
-#[inline]
-fn read_far() -> u64 {
- let mut far: u64;
- unsafe {
- asm!("mrs {far}, far_el1", far = out(reg) far);
- }
- far
-}
diff --git a/pvmfw/src/helpers.rs b/pvmfw/src/helpers.rs
index 4df9386..6310826 100644
--- a/pvmfw/src/helpers.rs
+++ b/pvmfw/src/helpers.rs
@@ -22,6 +22,39 @@
pub const GUEST_PAGE_SIZE: usize = SIZE_4KB;
+/// Read a value from a system register.
+#[macro_export]
+macro_rules! read_sysreg {
+ ($sysreg:literal) => {{
+ let mut r: usize;
+ // Safe because it reads a system register and does not affect Rust.
+ unsafe {
+ core::arch::asm!(
+ concat!("mrs {}, ", $sysreg),
+ out(reg) r,
+ options(nomem, nostack, preserves_flags),
+ )
+ }
+ r
+ }};
+}
+
+/// Write a value to a system register.
+#[macro_export]
+macro_rules! write_sysreg {
+ ($sysreg:literal, $val:expr) => {{
+ let value: usize = $val;
+ // Safe because it writes a system register and does not affect Rust.
+ unsafe {
+ core::arch::asm!(
+ concat!("msr ", $sysreg, ", {}"),
+ in(reg) value,
+ options(nomem, nostack, preserves_flags),
+ )
+ }
+ }};
+}
+
/// 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.
@@ -78,9 +111,7 @@
fn min_dcache_line_size() -> usize {
const DMINLINE_SHIFT: usize = 16;
const DMINLINE_MASK: usize = 0xf;
- let ctr_el0: usize;
-
- unsafe { asm!("mrs {x}, ctr_el0", x = out(reg) ctr_el0) }
+ let ctr_el0 = read_sysreg!("ctr_el0");
// DminLine: log2 of the number of words in the smallest cache line of all the data caches.
let dminline = (ctr_el0 >> DMINLINE_SHIFT) & DMINLINE_MASK;
@@ -97,7 +128,13 @@
for line in (start..end).step_by(line_size) {
// SAFETY - Clearing cache lines shouldn't have Rust-visible side effects.
- unsafe { asm!("dc cvau, {x}", x = in(reg) line) }
+ unsafe {
+ asm!(
+ "dc cvau, {x}",
+ x = in(reg) line,
+ options(nomem, nostack, preserves_flags),
+ )
+ }
}
}
diff --git a/pvmfw/src/instance.rs b/pvmfw/src/instance.rs
index fbf2040..a974543 100644
--- a/pvmfw/src/instance.rs
+++ b/pvmfw/src/instance.rs
@@ -258,11 +258,11 @@
impl EntryHeader {
fn new(uuid: Uuid, payload_size: usize) -> Self {
- Self { uuid: uuid.as_u128(), payload_size: u64::try_from(payload_size).unwrap().to_le() }
+ Self { uuid: uuid.to_u128_le(), payload_size: u64::try_from(payload_size).unwrap().to_le() }
}
fn uuid(&self) -> Uuid {
- Uuid::from_u128(self.uuid)
+ Uuid::from_u128_le(self.uuid)
}
fn payload_size(&self) -> usize {
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 577ad6e..00ff61f 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -16,7 +16,6 @@
#![no_main]
#![no_std]
-#![feature(default_alloc_error_handler)]
extern crate alloc;
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 3b730f4..59ee0b6 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -16,7 +16,6 @@
#![no_main]
#![no_std]
-#![feature(default_alloc_error_handler)]
mod exceptions;
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index 9c8714f..8c6218c 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -85,9 +85,14 @@
private boolean mNeedTearDown = false;
+ private boolean mNeedToRestartPkvmStatus = false;
+
@Before
public void setUp() throws Exception {
- testIfDeviceIsCapable(getDevice());
+ mNeedTearDown = false;
+ mNeedToRestartPkvmStatus = false;
+
+ assumeDeviceIsCapable(getDevice());
mNeedTearDown = true;
getDevice().installPackage(findTestFile(APK_NAME), /* reinstall */ false);
@@ -99,12 +104,12 @@
public void tearDown() throws Exception {
if (!mNeedTearDown) {
// If we skipped setUp, we don't need to undo it, and that avoids potential exceptions
- // incompatible hardware. (Note that tests can change what testIfDeviceIsCapable()
+ // incompatible hardware. (Note that tests can change what assumeDeviceIsCapable()
// sees, so we can't rely on that - b/268688303.)
return;
}
- // Set PKVM enable and reboot to prevent previous staged session.
- if (!isCuttlefish()) {
+ // Restore PKVM status and reboot to prevent previous staged session, if switched.
+ if (mNeedToRestartPkvmStatus) {
setPKVMStatusWithRebootToBootloader(true);
rebootFromBootloaderAndWaitBootCompleted();
}
@@ -422,7 +427,7 @@
}
private void enableDisablePKVMTestHelper(boolean isEnable) throws Exception {
- skipIfPKVMStatusSwitchNotSupported();
+ assumePKVMStatusSwitchSupported();
List<Double> bootDmesgTime = new ArrayList<>(ROUND_COUNT);
Map<String, List<Double>> bootloaderTime = new HashMap<>();
@@ -478,9 +483,15 @@
reportMetric(bootDmesgTime, "dmesg_boot_time_" + suffix, "s");
}
- private void skipIfPKVMStatusSwitchNotSupported() throws Exception {
+ private void assumePKVMStatusSwitchSupported() throws Exception {
assumeFalse("Skip on CF; can't reboot to bootloader", isCuttlefish());
+ // This is an overkill. The intention is to exclude remote_device_proxy, which uses
+ // different serial for fastboot. But there's no good way to distinguish from regular IP
+ // transport. This is currently not a problem until someone really needs to run the test
+ // over regular IP transport.
+ assumeFalse("Skip over IP (overkill for remote_device_proxy)", getDevice().isAdbTcp());
+
if (!getDevice().isStateBootloaderOrFastbootd()) {
getDevice().rebootIntoBootloader();
}
@@ -513,6 +524,7 @@
}
private void setPKVMStatusWithRebootToBootloader(boolean isEnable) throws Exception {
+ mNeedToRestartPkvmStatus = true;
if (!getDevice().isStateBootloaderOrFastbootd()) {
getDevice().rebootIntoBootloader();
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index a7f7906..4807c0f 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -97,7 +97,7 @@
DeviceProperties.create(getDevice()::getProperty).getMetricsTag());
}
- public static void testIfDeviceIsCapable(ITestDevice androidDevice) throws Exception {
+ public static void assumeDeviceIsCapable(ITestDevice androidDevice) throws Exception {
assumeTrue("Need an actual TestDevice", androidDevice instanceof TestDevice);
TestDevice testDevice = (TestDevice) androidDevice;
assumeTrue(
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 687756e..2027fcd 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -24,7 +24,6 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -82,6 +81,7 @@
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
@RunWith(DeviceJUnit4ClassRunner.class)
public class MicrodroidHostTests extends MicrodroidHostTestCaseBase {
@@ -682,19 +682,24 @@
microdroid.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
device.shutdownMicrodroid(microdroid);
+ // Try to collect atoms for 60000 milliseconds.
List<StatsLog.EventMetricData> data = new ArrayList<>();
- assertThatEventually(
- 10000,
- () -> {
- data.addAll(ReportUtils.getEventMetricDataList(getDevice()));
- return data.size();
- },
- is(3)
- );
+ long start = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - start < 60000) && data.size() < 3) {
+ data.addAll(ReportUtils.getEventMetricDataList(getDevice()));
+ Thread.sleep(500);
+ }
+ assertThat(
+ data.stream()
+ .map(x -> x.getAtom().getPushedCase().getNumber())
+ .collect(Collectors.toList()))
+ .containsExactly(
+ AtomsProto.Atom.VM_CREATION_REQUESTED_FIELD_NUMBER,
+ AtomsProto.Atom.VM_BOOTED_FIELD_NUMBER,
+ AtomsProto.Atom.VM_EXITED_FIELD_NUMBER)
+ .inOrder();
// Check VmCreationRequested atom
- assertThat(data.get(0).getAtom().getPushedCase().getNumber()).isEqualTo(
- AtomsProto.Atom.VM_CREATION_REQUESTED_FIELD_NUMBER);
AtomsProto.VmCreationRequested atomVmCreationRequested =
data.get(0).getAtom().getVmCreationRequested();
assertThat(atomVmCreationRequested.getHypervisor())
@@ -711,14 +716,10 @@
.isEqualTo("com.android.art:com.android.compos:com.android.sdkext");
// Check VmBooted atom
- assertThat(data.get(1).getAtom().getPushedCase().getNumber())
- .isEqualTo(AtomsProto.Atom.VM_BOOTED_FIELD_NUMBER);
AtomsProto.VmBooted atomVmBooted = data.get(1).getAtom().getVmBooted();
assertThat(atomVmBooted.getVmIdentifier()).isEqualTo("VmRunApp");
// Check VmExited atom
- assertThat(data.get(2).getAtom().getPushedCase().getNumber())
- .isEqualTo(AtomsProto.Atom.VM_EXITED_FIELD_NUMBER);
AtomsProto.VmExited atomVmExited = data.get(2).getAtom().getVmExited();
assertThat(atomVmExited.getVmIdentifier()).isEqualTo("VmRunApp");
assertThat(atomVmExited.getDeathReason()).isEqualTo(AtomsProto.VmExited.DeathReason.KILLED);
@@ -970,7 +971,7 @@
@Before
public void setUp() throws Exception {
- testIfDeviceIsCapable(getDevice());
+ assumeDeviceIsCapable(getDevice());
mMetricPrefix = getMetricPrefix() + "microdroid/";
mMicrodroidDevice = null;
diff --git a/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
index 18aa273..22131f1 100644
--- a/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
@@ -112,7 +112,7 @@
getTestInformation().getDependencyFile(BCC_FILE_NAME, /* targetFirst= */ false);
// Check device capability
- testIfDeviceIsCapable(mAndroidDevice);
+ assumeDeviceIsCapable(mAndroidDevice);
assumeTrue(
"Protected VMs are not supported",
mAndroidDevice.supportsMicrodroid(/*protectedVm=*/ true));
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 b7dbcd8..7044ae7 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -66,7 +66,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
@@ -1183,7 +1182,6 @@
}
@Test
- @Ignore("b/249723852")
@CddTest(requirements = {
"9.17/C-1-1",
"9.17/C-2-7"
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 3b0e9db..9ec2dc4 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -16,7 +16,6 @@
#![no_main]
#![no_std]
-#![feature(default_alloc_error_handler)]
mod exceptions;
mod layout;
diff --git a/vmbase/example/src/pci.rs b/vmbase/example/src/pci.rs
index c0a2d2b..117cbc8 100644
--- a/vmbase/example/src/pci.rs
+++ b/vmbase/example/src/pci.rs
@@ -20,7 +20,7 @@
use fdtpci::PciInfo;
use log::{debug, info};
use virtio_drivers::{
- device::blk::VirtIOBlk,
+ device::{blk::VirtIOBlk, console::VirtIOConsole},
transport::{
pci::{bus::PciRoot, virtio_device_type, PciTransport},
DeviceType, Transport,
@@ -53,29 +53,41 @@
}
}
- assert_eq!(checked_virtio_device_count, 1);
+ assert_eq!(checked_virtio_device_count, 4);
}
/// Checks the given VirtIO device, if we know how to.
///
/// Returns true if the device was checked, or false if it was ignored.
fn check_virtio_device(transport: impl Transport, device_type: DeviceType) -> bool {
- if device_type == DeviceType::Block {
- let mut blk = VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
- info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
- assert_eq!(blk.capacity(), EXPECTED_SECTOR_COUNT as u64);
- let mut data = [0; SECTOR_SIZE_BYTES * EXPECTED_SECTOR_COUNT];
- for i in 0..EXPECTED_SECTOR_COUNT {
- blk.read_block(i, &mut data[i * SECTOR_SIZE_BYTES..(i + 1) * SECTOR_SIZE_BYTES])
- .expect("Failed to read block device.");
+ match device_type {
+ DeviceType::Block => {
+ let mut blk =
+ VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
+ info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
+ assert_eq!(blk.capacity(), EXPECTED_SECTOR_COUNT as u64);
+ let mut data = [0; SECTOR_SIZE_BYTES * EXPECTED_SECTOR_COUNT];
+ for i in 0..EXPECTED_SECTOR_COUNT {
+ blk.read_block(i, &mut data[i * SECTOR_SIZE_BYTES..(i + 1) * SECTOR_SIZE_BYTES])
+ .expect("Failed to read block device.");
+ }
+ for (i, chunk) in data.chunks(size_of::<u32>()).enumerate() {
+ assert_eq!(chunk, &(i as u32).to_le_bytes());
+ }
+ info!("Read expected data from block device.");
+ true
}
- for (i, chunk) in data.chunks(size_of::<u32>()).enumerate() {
- assert_eq!(chunk, &(i as u32).to_le_bytes());
+ DeviceType::Console => {
+ let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
+ .expect("Failed to create VirtIO console driver");
+ info!("Found console device: {:?}", console.info());
+ for &c in b"Hello VirtIO console\n" {
+ console.send(c).expect("Failed to send character to VirtIO console device");
+ }
+ info!("Wrote to VirtIO console.");
+ true
}
- info!("Read expected data from block device.");
- true
- } else {
- false
+ _ => false,
}
}
diff --git a/vmbase/example/tests/test.rs b/vmbase/example/tests/test.rs
index 930e137..8f0eaa5 100644
--- a/vmbase/example/tests/test.rs
+++ b/vmbase/example/tests/test.rs
@@ -25,7 +25,7 @@
use log::info;
use std::{
fs::File,
- io::{self, BufRead, BufReader, Write},
+ io::{self, BufRead, BufReader, Read, Write},
os::unix::io::FromRawFd,
panic, thread,
};
@@ -90,8 +90,8 @@
gdbPort: 0, // no gdb
});
let console = android_log_fd()?;
- let log = android_log_fd()?;
- let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log), None)
+ let (mut log_reader, log_writer) = pipe()?;
+ let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log_writer), None)
.context("Failed to create VM")?;
vm.start().context("Failed to start VM")?;
info!("Started example VM.");
@@ -100,15 +100,17 @@
let death_reason = vm.wait_for_death();
assert_eq!(death_reason, DeathReason::Shutdown);
+ // Check that the expected string was written to the log VirtIO console device.
+ let expected = "Hello VirtIO console\n";
+ let mut log_output = String::new();
+ assert_eq!(log_reader.read_to_string(&mut log_output)?, expected.len());
+ assert_eq!(log_output, expected);
+
Ok(())
}
fn android_log_fd() -> io::Result<File> {
- let (reader_fd, writer_fd) = nix::unistd::pipe()?;
-
- // SAFETY: These are new FDs with no previous owner.
- let reader = unsafe { File::from_raw_fd(reader_fd) };
- let writer = unsafe { File::from_raw_fd(writer_fd) };
+ let (reader, writer) = pipe()?;
thread::spawn(|| {
for line in BufReader::new(reader).lines() {
@@ -117,3 +119,13 @@
});
Ok(writer)
}
+
+fn pipe() -> io::Result<(File, File)> {
+ let (reader_fd, writer_fd) = nix::unistd::pipe()?;
+
+ // SAFETY: These are new FDs with no previous owner.
+ let reader = unsafe { File::from_raw_fd(reader_fd) };
+ let writer = unsafe { File::from_raw_fd(writer_fd) };
+
+ Ok((reader, writer))
+}