Add debug policy tests for ramdump
Bug: 243671509, Bug: 243630590
Test: atest
Change-Id: Id414b6efb1c84bd5d77deb176b40819da9dbdf5d
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 0d6a9a4..9cb997b 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -65,6 +65,22 @@
},
}
+// Provide pvmfw.bin binary regardless of the architecture for building test.
+// Note that skipping tests on unsupported device is easy
+// while configuring server configuration to make such tests to run on working
+// devices.
+prebuilt_etc {
+ name: "pvmfw_test",
+ filename: "pvmfw_test.bin",
+ target: {
+ android_arm64: {
+ src: ":pvmfw_bin",
+ },
+ },
+ src: "empty_file",
+ installable: false,
+}
+
prebuilt_etc {
name: "pvmfw_embedded_key",
src: ":avb_testkey_rsa4096_pub_bin",
diff --git a/pvmfw/empty_file b/pvmfw/empty_file
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pvmfw/empty_file
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 6e0cf5a..046a9d6 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -2,6 +2,26 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+genrule_defaults {
+ name: "test_avf_debug_policy_overlay",
+ tools: ["dtc"],
+ cmd: "$(location dtc) -I dts -O dtb $(in) -o $(out)",
+}
+
+genrule {
+ name: "test_avf_debug_policy_with_ramdump",
+ defaults: ["test_avf_debug_policy_overlay"],
+ srcs: ["assets/avf_debug_policy_with_ramdump.dts"],
+ out: ["avf_debug_policy_with_ramdump.dtbo"],
+}
+
+genrule {
+ name: "test_avf_debug_policy_without_ramdump",
+ defaults: ["test_avf_debug_policy_overlay"],
+ srcs: ["assets/avf_debug_policy_without_ramdump.dts"],
+ out: ["avf_debug_policy_without_ramdump.dtbo"],
+}
+
java_test_host {
name: "MicrodroidHostTestCases",
srcs: ["java/**/*.java"],
@@ -10,6 +30,7 @@
"general-tests",
],
libs: [
+ "androidx.annotation_annotation",
"tradefed",
],
static_libs: [
@@ -23,6 +44,10 @@
":microdroid_general_sepolicy.conf",
":test.com.android.virt.pem",
":test2.com.android.virt.pem",
+ ":pvmfw_test",
+ ":test_avf_debug_policy_with_ramdump",
+ ":test_avf_debug_policy_without_ramdump",
+ "assets/bcc.dat",
],
data_native_bins: [
"sepolicy-analyze",
diff --git a/tests/hostside/assets/avf_debug_policy_with_ramdump.dts b/tests/hostside/assets/avf_debug_policy_with_ramdump.dts
new file mode 100644
index 0000000..f1a5196
--- /dev/null
+++ b/tests/hostside/assets/avf_debug_policy_with_ramdump.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ fragment@avf {
+ target-path = "/";
+
+ __overlay__ {
+ avf {
+ guest {
+ common {
+ ramdump = <1>;
+ };
+ };
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/tests/hostside/assets/avf_debug_policy_without_ramdump.dts b/tests/hostside/assets/avf_debug_policy_without_ramdump.dts
new file mode 100644
index 0000000..5b15d51
--- /dev/null
+++ b/tests/hostside/assets/avf_debug_policy_without_ramdump.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ fragment@avf {
+ target-path = "/";
+
+ __overlay__ {
+ avf {
+ guest {
+ common {
+ ramdump = <0>;
+ };
+ };
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/tests/hostside/assets/bcc.dat b/tests/hostside/assets/bcc.dat
new file mode 100644
index 0000000..7ab71f1
--- /dev/null
+++ b/tests/hostside/assets/bcc.dat
Binary files differ
diff --git a/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
new file mode 100644
index 0000000..bda52dd
--- /dev/null
+++ b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package com.android.microdroid.test;
+
+import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.microdroid.test.host.CommandRunner;
+import com.android.microdroid.test.host.MicrodroidHostTestCaseBase;
+import com.android.microdroid.test.host.Pvmfw;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.TestDevice;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.FileUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.Objects;
+import java.io.FileNotFoundException;
+
+/** Tests debug policy of pvmfw.bin with custom debug policy */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class PvmfwDebugPolicyHostTests extends MicrodroidHostTestCaseBase {
+ @NonNull private static final String PVMFW_FILE_NAME = "pvmfw_test.bin";
+ @NonNull private static final String BCC_FILE_NAME = "bcc.dat";
+ @NonNull private static final String PACKAGE_FILE_NAME = "MicrodroidTestApp.apk";
+ @NonNull private static final String PACKAGE_NAME = "com.android.microdroid.test";
+ @NonNull private static final String MICRODROID_DEBUG_LEVEL = "full";
+ @NonNull private static final String MICRODROID_CONFIG_PATH = "assets/vm_config_apex.json";
+ private static final int BOOT_COMPLETE_TIMEOUT = 30000; // 30 seconds
+
+ @NonNull private static final String CUSTOM_PVMFW_FILE_PREFIX = "pvmfw";
+ @NonNull private static final String CUSTOM_PVMFW_FILE_SUFFIX = ".bin";
+ @NonNull private static final String CUSTOM_PVMFW_IMG_PATH = TEST_ROOT + "/" + PVMFW_FILE_NAME;
+ @NonNull private static final String CUSTOM_PVMFW_IMG_PATH_PROP = "hypervisor.pvmfw.path";
+
+ @NonNull private static final String MICRODROID_CMDLINE_PATH = "/proc/cmdline";
+ @NonNull private static final String MICRODROID_DT_ROOT_PATH = "/proc/device-tree";
+
+ @NonNull
+ private static final String MICRODROID_DT_BOOTARGS_PATH =
+ MICRODROID_DT_ROOT_PATH + "/chosen/bootargs";
+
+ @NonNull
+ private static final String MICRODROID_DT_RAMDUMP_PATH =
+ MICRODROID_DT_ROOT_PATH + "/avf/guest/common/ramdump";
+
+ @NonNull private static final String HEX_STRING_ZERO = "00000000";
+ @NonNull private static final String HEX_STRING_ONE = "00000001";
+
+ @Nullable private static File mPvmfwBinFileOnHost;
+ @Nullable private static File mBccFileOnHost;
+
+ @Nullable private TestDevice mAndroidDevice;
+ @Nullable private ITestDevice mMicrodroidDevice;
+ @Nullable private File mCustomPvmfwBinFileOnHost;
+
+ @Before
+ public void setUp() throws Exception {
+ mAndroidDevice = (TestDevice) Objects.requireNonNull(getDevice());
+ assumeTrue(
+ "Skip if protected VMs are not supported",
+ mAndroidDevice.supportsMicrodroid(/* protectedVm= */ true));
+
+ mAndroidDevice.enableAdbRoot();
+
+ // tradefed copies the test artfacts under /tmp when running tests,
+ // so we should *find* the artifacts with the file name.
+ mPvmfwBinFileOnHost =
+ getTestInformation().getDependencyFile(PVMFW_FILE_NAME, /* targetFirst= */ false);
+ mBccFileOnHost =
+ getTestInformation().getDependencyFile(BCC_FILE_NAME, /* targetFirst= */ false);
+
+ // Check device capability
+ testIfDeviceIsCapable(mAndroidDevice);
+ assumeTrue(
+ "Protected VMs are not supported",
+ mAndroidDevice.supportsMicrodroid(/*protectedVm=*/ true));
+
+ // Prepare for loading pvmfw.bin
+ // File will be setup in individual test,
+ // and then pushed to device in launchProtectedVmAndWaitForBootCompleted.
+ mCustomPvmfwBinFileOnHost =
+ FileUtil.createTempFile(CUSTOM_PVMFW_FILE_PREFIX, CUSTOM_PVMFW_FILE_SUFFIX);
+ mAndroidDevice.setProperty(CUSTOM_PVMFW_IMG_PATH_PROP, CUSTOM_PVMFW_IMG_PATH);
+
+ // Prepare for launching microdroid
+ mAndroidDevice.installPackage(findTestFile(PACKAGE_FILE_NAME), /* reinstall */ false);
+ prepareVirtualizationTestSetup(mAndroidDevice);
+ mMicrodroidDevice = null;
+ }
+
+ @After
+ public void shutdown() throws Exception {
+ if (!mAndroidDevice.supportsMicrodroid(/* protectedVm= */ true)) {
+ return;
+ }
+ if (mMicrodroidDevice != null) {
+ mAndroidDevice.shutdownMicrodroid(mMicrodroidDevice);
+ mMicrodroidDevice = null;
+ }
+ mAndroidDevice.uninstallPackage(PACKAGE_NAME);
+
+ // Cleanup for custom pvmfw.bin
+ mAndroidDevice.setProperty(CUSTOM_PVMFW_IMG_PATH_PROP, "");
+ FileUtil.deleteFile(mCustomPvmfwBinFileOnHost);
+
+ cleanUpVirtualizationTestSetup(mAndroidDevice);
+
+ mAndroidDevice.disableAdbRoot();
+ }
+
+ @Test
+ public void testRamdump() throws Exception {
+ Pvmfw pvmfw = createPvmfw("avf_debug_policy_with_ramdump.dtbo");
+ pvmfw.serialize(mCustomPvmfwBinFileOnHost);
+ mMicrodroidDevice = launchProtectedVmAndWaitForBootCompleted();
+
+ assertThat(readMicrodroidFileAsString(MICRODROID_CMDLINE_PATH)).contains("crashkernel=");
+ assertThat(readMicrodroidFileAsString(MICRODROID_DT_BOOTARGS_PATH))
+ .contains("crashkernel=");
+ assertThat(readMicrodroidFileAsHexString(MICRODROID_DT_RAMDUMP_PATH))
+ .isEqualTo(HEX_STRING_ONE);
+ }
+
+ @Test
+ public void testNoRamdump() throws Exception {
+ Pvmfw pvmfw = createPvmfw("avf_debug_policy_without_ramdump.dtbo");
+ pvmfw.serialize(mCustomPvmfwBinFileOnHost);
+ mMicrodroidDevice = launchProtectedVmAndWaitForBootCompleted();
+
+ assertThat(readMicrodroidFileAsString(MICRODROID_CMDLINE_PATH))
+ .doesNotContain("crashkernel=");
+ assertThat(readMicrodroidFileAsString(MICRODROID_DT_BOOTARGS_PATH))
+ .doesNotContain("crashkernel=");
+ assertThat(readMicrodroidFileAsHexString(MICRODROID_DT_RAMDUMP_PATH))
+ .isEqualTo(HEX_STRING_ZERO);
+ }
+
+ @NonNull
+ private String readMicrodroidFileAsString(@NonNull String path)
+ throws DeviceNotAvailableException {
+ return new CommandRunner(mMicrodroidDevice).run("cat", path);
+ }
+
+ @NonNull
+ private String readMicrodroidFileAsHexString(@NonNull String path)
+ throws DeviceNotAvailableException {
+ return new CommandRunner(mMicrodroidDevice).run("xxd", "-p", path);
+ }
+
+ @NonNull
+ private Pvmfw createPvmfw(@NonNull String debugPolicyFileName) throws FileNotFoundException {
+ File file =
+ getTestInformation()
+ .getDependencyFile(debugPolicyFileName, /* targetFirst= */ false);
+ return new Pvmfw.Builder(mPvmfwBinFileOnHost, mBccFileOnHost)
+ .setDebugPolicyOverlay(file)
+ .build();
+ }
+
+ private ITestDevice launchProtectedVmAndWaitForBootCompleted()
+ throws DeviceNotAvailableException {
+ mMicrodroidDevice =
+ MicrodroidBuilder.fromDevicePath(
+ getPathForPackage(PACKAGE_NAME), MICRODROID_CONFIG_PATH)
+ .debugLevel(MICRODROID_DEBUG_LEVEL)
+ .protectedVm(/* protectedVm= */ true)
+ .addBootFile(mCustomPvmfwBinFileOnHost, PVMFW_FILE_NAME)
+ .build(mAndroidDevice);
+ assertThat(mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT)).isTrue();
+ assertThat(mMicrodroidDevice.enableAdbRoot()).isTrue();
+
+ return mMicrodroidDevice;
+ }
+}