Merge "vmbase: bionic: Implement perror()" into main
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 b3d0402..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>;
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/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index aed28a8..625f26a 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -78,6 +78,7 @@
     private static final String TAG = "MicrodroidBenchmarks";
     private static final String METRIC_NAME_PREFIX = getMetricPrefix() + "microdroid/";
     private static final int IO_TEST_TRIAL_COUNT = 5;
+    private static final int TEST_TRIAL_COUNT = 5;
     private static final long ONE_MEBI = 1024 * 1024;
 
     @Rule public Timeout globalTimeout = Timeout.seconds(300);
@@ -767,4 +768,35 @@
         }
         reportMetrics(requestLatencies, "latency/vsock", "us");
     }
+
+    @Test
+    public void testVmKillTime() throws Exception {
+        VirtualMachineConfig config =
+                newVmConfigBuilder()
+                        .setPayloadConfigPath("assets/vm_config_io.json")
+                        .setDebugLevel(DEBUG_LEVEL_NONE)
+                        .build();
+        List<Double> vmKillTime = new ArrayList<>(TEST_TRIAL_COUNT);
+
+        for (int i = 0; i < TEST_TRIAL_COUNT; ++i) {
+            VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_kill_time" + i, config);
+            VmEventListener listener =
+                    new VmEventListener() {
+                        @Override
+                        public void onPayloadReady(VirtualMachine vm) {
+                            long start = System.nanoTime();
+                            try {
+                                vm.stop();
+                            } catch (Exception e) {
+                                Log.e(TAG, "Error in vm.stop():" + e);
+                                throw new RuntimeException(e);
+                            }
+                            vmKillTime.add((double) (System.nanoTime() - start) / NANO_TO_MICRO);
+                            super.onPayloadReady(vm);
+                        }
+                    };
+            listener.runToFinish(TAG, vm);
+        }
+        reportMetrics(vmKillTime, "vm_kill_time", "microsecond");
+    }
 }
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index 8c6218c..f98d1d9 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -60,9 +60,6 @@
     // Files that define the "test" instance of CompOS
     private static final String COMPOS_TEST_ROOT = "/data/misc/apexdata/com.android.compos/test/";
 
-    private static final String SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME =
-            "dalvik.vm.systemservercompilerfilter";
-
     private static final String BOOTLOADER_TIME_PROP_NAME = "ro.boot.boottime";
     private static final String BOOTLOADER_PREFIX = "bootloader-";
     private static final String BOOTLOADER_TIME = "bootloader_time";
@@ -74,7 +71,6 @@
     private static final int COMPILE_STAGED_APEX_RETRY_INTERVAL_MS = 10 * 1000;
     private static final int COMPILE_STAGED_APEX_TIMEOUT_SEC = 540;
     private static final int BOOT_COMPLETE_TIMEOUT_MS = 10 * 60 * 1000;
-    private static final double NANOS_IN_SEC = 1_000_000_000.0;
     private static final int ROUND_COUNT = 5;
     private static final int ROUND_IGNORE_STARTUP_TIME = 3;
     private static final String APK_NAME = "MicrodroidTestApp.apk";
@@ -262,32 +258,34 @@
                         .memoryMib(vm_mem_mb)
                         .cpuTopology("match_host")
                         .build(device);
-        microdroidDevice.waitForBootComplete(30000);
-        microdroidDevice.enableAdbRoot();
-
-        CommandRunner microdroid = new CommandRunner(microdroidDevice);
-
-        microdroid.run("mkdir -p /mnt/ramdisk && chmod 777 /mnt/ramdisk");
-        microdroid.run("mount -t tmpfs -o size=32G tmpfs /mnt/ramdisk");
-
-        // Allocate memory for the VM until it fails and make sure that we touch
-        // the allocated memory in the guest to be able to create stage2 fragmentation.
         try {
-            microdroid.tryRun(
-                    String.format(
-                            "cd /mnt/ramdisk && truncate -s %dM sprayMemory"
-                                    + " && dd if=/dev/zero of=sprayMemory bs=1MB count=%d",
-                            vm_mem_mb, vm_mem_mb));
-        } catch (Exception ex) {
-        }
+            microdroidDevice.waitForBootComplete(30000);
+            microdroidDevice.enableAdbRoot();
 
-        // Run the app during the VM run and collect cold startup time.
-        for (int i = 0; i < ROUND_COUNT; i++) {
-            AmStartupTimeCmdParser duringVmStartApp = getColdRunStartupTimes(android, pkgName);
-            metricColector.addStartupTimeMetricDuringVmRun(duringVmStartApp);
-        }
+            CommandRunner microdroid = new CommandRunner(microdroidDevice);
 
-        device.shutdownMicrodroid(microdroidDevice);
+            microdroid.run("mkdir -p /mnt/ramdisk && chmod 777 /mnt/ramdisk");
+            microdroid.run("mount -t tmpfs -o size=32G tmpfs /mnt/ramdisk");
+
+            // Allocate memory for the VM until it fails and make sure that we touch
+            // the allocated memory in the guest to be able to create stage2 fragmentation.
+            try {
+                microdroid.tryRun(
+                        String.format(
+                                "cd /mnt/ramdisk && truncate -s %dM sprayMemory"
+                                        + " && dd if=/dev/zero of=sprayMemory bs=1MB count=%d",
+                                vm_mem_mb, vm_mem_mb));
+            } catch (Exception expected) {
+            }
+
+            // Run the app during the VM run and collect cold startup time.
+            for (int i = 0; i < ROUND_COUNT; i++) {
+                AmStartupTimeCmdParser duringVmStartApp = getColdRunStartupTimes(android, pkgName);
+                metricColector.addStartupTimeMetricDuringVmRun(duringVmStartApp);
+            }
+        } finally {
+            device.shutdownMicrodroid(microdroidDevice);
+        }
 
         // Run the app after the VM run and collect cold startup time.
         for (int i = 0; i < ROUND_COUNT; i++) {
@@ -304,12 +302,12 @@
             String[] lines = startAppLog.split("[\r\n]+");
             mTotalTime = mWaitTime = 0;
 
-            for (int i = 0; i < lines.length; i++) {
-                if (lines[i].contains("TotalTime:")) {
-                    mTotalTime = Integer.parseInt(lines[i].replaceAll("\\D+", ""));
+            for (String line : lines) {
+                if (line.contains("TotalTime:")) {
+                    mTotalTime = Integer.parseInt(line.replaceAll("\\D+", ""));
                 }
-                if (lines[i].contains("WaitTime:")) {
-                    mWaitTime = Integer.parseInt(lines[i].replaceAll("\\D+", ""));
+                if (line.contains("WaitTime:")) {
+                    mWaitTime = Integer.parseInt(line.replaceAll("\\D+", ""));
                 }
             }
         }
@@ -365,9 +363,9 @@
         String content = android.runForResult("cat /proc/meminfo").getStdout().trim();
         String[] lines = content.split("[\r\n]+");
 
-        for (int i = 0; i < lines.length; i++) {
-            if (lines[i].contains("MemFree:")) {
-                freeMemory = Integer.parseInt(lines[i].replaceAll("\\D+", "")) / 1024;
+        for (String line : lines) {
+            if (line.contains("MemFree:")) {
+                freeMemory = Integer.parseInt(line.replaceAll("\\D+", "")) / 1024;
                 return freeMemory;
             }
         }
@@ -416,7 +414,7 @@
 
         CommandRunner android = new CommandRunner(getDevice());
         String result = android.run("dmesg");
-        Pattern pattern = Pattern.compile("\\[(.*)\\].*sys.boot_completed=1.*");
+        Pattern pattern = Pattern.compile("\\[(.*)].*sys.boot_completed=1.*");
         for (String line : result.split("[\r\n]+")) {
             Matcher matcher = pattern.matcher(line);
             if (matcher.find()) {
@@ -568,7 +566,7 @@
     private void compileStagedApex(int timeoutSec) throws Exception {
 
         long timeStart = System.currentTimeMillis();
-        long timeEnd = timeStart + timeoutSec * 1000;
+        long timeEnd = timeStart + timeoutSec * 1000L;
 
         while (true) {
 
@@ -599,7 +597,7 @@
     private void reInstallApex(int timeoutSec) throws Exception {
 
         long timeStart = System.currentTimeMillis();
-        long timeEnd = timeStart + timeoutSec * 1000;
+        long timeEnd = timeStart + timeoutSec * 1000L;
 
         while (true) {
 
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index deaf08a..092325e 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -42,7 +42,6 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.TestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
 import com.android.tradefed.util.CommandResult;
@@ -62,12 +61,8 @@
 import org.xml.sax.Attributes;
 import org.xml.sax.helpers.DefaultHandler;
 
-import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 import java.util.ArrayList;
@@ -75,7 +70,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
@@ -95,15 +89,11 @@
 
     private static final int BOOT_COMPLETE_TIMEOUT = 30000; // 30 seconds
 
-    private static final Pattern sCIDPattern = Pattern.compile("with CID (\\d+)");
-
     private static class VmInfo {
         final Process mProcess;
-        final String mCid;
 
-        VmInfo(Process process, String cid) {
+        VmInfo(Process process) {
             mProcess = process;
-            mCid = cid;
         }
     }
 
@@ -376,44 +366,14 @@
 
         PipedInputStream pis = new PipedInputStream();
         Process process = RunUtil.getDefault().runCmdInBackground(args, new PipedOutputStream(pis));
-        return new VmInfo(process, extractCidFrom(pis));
-    }
-
-    private static Optional<String> tryExtractCidFrom(String str) {
-        Matcher matcher = sCIDPattern.matcher(str);
-        if (matcher.find()) {
-            return Optional.of(matcher.group(1));
-        }
-        return Optional.empty();
-    }
-
-    private static String extractCidFrom(InputStream input) throws IOException {
-        String cid = null;
-        String line;
-        try (BufferedReader out = new BufferedReader(new InputStreamReader(input))) {
-            while ((line = out.readLine()) != null) {
-                CLog.i("VM output: " + line);
-                Optional<String> result = tryExtractCidFrom(line);
-                if (result.isPresent()) {
-                    cid = result.get();
-                    break;
-                }
-            }
-        }
-        assertWithMessage("The output does not contain the expected pattern for CID.")
-                .that(cid)
-                .isNotNull();
-        return cid;
+        return new VmInfo(process);
     }
 
     @Test
     @CddTest(requirements = {"9.17/C-2-1", "9.17/C-2-2", "9.17/C-2-6"})
     public void protectedVmRunsPvmfw() throws Exception {
         // Arrange
-        boolean protectedVm = true;
-        assumeTrue(
-                "Skip if protected VMs are not supported",
-                getAndroidDevice().supportsMicrodroid(protectedVm));
+        assumeProtectedVmSupported();
         final String configPath = "assets/vm_config_apex.json";
 
         // Act
@@ -422,7 +382,7 @@
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
-                        .protectedVm(protectedVm)
+                        .protectedVm(true)
                         .build(getAndroidDevice());
 
         // Assert
@@ -441,16 +401,16 @@
     @CddTest(requirements = {"9.17/C-2-1", "9.17/C-2-2", "9.17/C-2-6"})
     public void protectedVmWithImageSignedWithDifferentKeyRunsPvmfw() throws Exception {
         // Arrange
-        boolean protectedVm = true;
-        assumeTrue(
-                "Skip if protected VMs are not supported",
-                getAndroidDevice().supportsMicrodroid(protectedVm));
+        assumeProtectedVmSupported();
         File key = findTestFile("test.com.android.virt.pem");
 
         // Act
         VmInfo vmInfo =
                 runMicrodroidWithResignedImages(
-                        key, /*keyOverrides=*/ Map.of(), protectedVm, /*updateBootconfigs=*/ true);
+                        key,
+                        /*keyOverrides=*/ Map.of(),
+                        /*isProtected=*/ true,
+                        /*updateBootconfigs=*/ true);
 
         // Assert
         vmInfo.mProcess.waitFor(5L, TimeUnit.SECONDS);
@@ -465,6 +425,7 @@
     @CddTest(requirements = {"9.17/C-2-2", "9.17/C-2-6"})
     public void testBootSucceedsWhenNonProtectedVmStartsWithImagesSignedWithDifferentKey()
             throws Exception {
+        assumeNonProtectedVmSupported();
         File key = findTestFile("test.com.android.virt.pem");
         Map<String, File> keyOverrides = Map.of();
         VmInfo vmInfo =
@@ -481,6 +442,8 @@
     @Test
     @CddTest(requirements = {"9.17/C-2-2", "9.17/C-2-6"})
     public void testBootFailsWhenVbMetaDigestDoesNotMatchBootconfig() throws Exception {
+        // protectedVmWithImageSignedWithDifferentKeyRunsPvmfw() is the protected case.
+        assumeNonProtectedVmSupported();
         // Sign everything with key1 except vbmeta
         File key = findTestFile("test.com.android.virt.pem");
         // To be able to stop it, it should be a daemon.
@@ -558,10 +521,22 @@
     }
 
     @Test
-    public void testTombstonesAreGeneratedUponUserspaceCrash() throws Exception {
+    public void testTombstonesAreGeneratedUponUserspaceCrashOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        testTombstonesAreGeneratedUponUserspaceCrash(false);
+    }
+
+    @Test
+    public void testTombstonesAreGeneratedUponUserspaceCrashOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        testTombstonesAreGeneratedUponUserspaceCrash(true);
+    }
+
+    private void testTombstonesAreGeneratedUponUserspaceCrash(boolean protectedVm)
+            throws Exception {
         assertThat(
                         isTombstoneGeneratedWithCmd(
-                                false,
+                                protectedVm,
                                 "assets/vm_config.json",
                                 "kill",
                                 "-SIGSEGV",
@@ -570,10 +545,24 @@
     }
 
     @Test
-    public void testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrash() throws Exception {
+    public void testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrashOnNonPvm()
+            throws Exception {
+        assumeNonProtectedVmSupported();
+        testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrash(false);
+    }
+
+    @Test
+    public void testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrashOnPvm()
+            throws Exception {
+        assumeProtectedVmSupported();
+        testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrash(true);
+    }
+
+    private void testTombstonesAreNotGeneratedIfNotExportedUponUserspaceCrash(boolean protectedVm)
+            throws Exception {
         assertThat(
                         isTombstoneGeneratedWithCmd(
-                                false,
+                                protectedVm,
                                 "assets/vm_config_no_tombstone.json",
                                 "kill",
                                 "-SIGSEGV",
@@ -597,19 +586,18 @@
 
     @Test
     public void testTombstonesAreGeneratedUponKernelCrashOnNonPvm() throws Exception {
-        testTombstonesAreGeneratedUponKernelCrash(false);
+        assumeNonProtectedVmSupported();
+        testTombstonesAreGeneratedUponKernelCrash(/* protectedVm=*/ false);
     }
 
     @Test
     public void testTombstonesAreGeneratedUponKernelCrashOnPvm() throws Exception {
-        assumeTrue(
-                "Protected VMs are not supported",
-                getAndroidDevice().supportsMicrodroid(/*protectedVm=*/ true));
-        testTombstonesAreGeneratedUponKernelCrash(true);
+        assumeProtectedVmSupported();
+        testTombstonesAreGeneratedUponKernelCrash(/* protectedVm=*/ true);
     }
 
-    private boolean isTombstoneGeneratedWithVmRunApp(boolean debuggable, String... additionalArgs)
-            throws Exception {
+    private boolean isTombstoneGeneratedWithVmRunApp(
+            boolean protectedVm, boolean debuggable, String... additionalArgs) throws Exception {
         // we can't use microdroid builder as it wants ADB connection (debuggable)
         CommandRunner android = new CommandRunner(getDevice());
         String testStartTime = android.runWithTimeout(1000, "date", "'+%Y-%m-%d %H:%M:%S.%N'");
@@ -630,44 +618,114 @@
                                 apkPath,
                                 idsigPath,
                                 instanceImgPath));
+        if (protectedVm) {
+            cmd.add("--protected");
+        }
         Collections.addAll(cmd, additionalArgs);
 
         android.run(cmd.toArray(new String[0]));
         return isTombstoneReceivedFromHostLogcat(testStartTime);
     }
 
-    private boolean isTombstoneGeneratedWithCrashPayload(boolean debuggable) throws Exception {
+    private boolean isTombstoneGeneratedWithCrashPayload(boolean protectedVm, boolean debuggable)
+            throws Exception {
         return isTombstoneGeneratedWithVmRunApp(
-                debuggable, "--payload-binary-name", "MicrodroidCrashNativeLib.so");
+                protectedVm, debuggable, "--payload-binary-name", "MicrodroidCrashNativeLib.so");
     }
 
     @Test
-    public void testTombstonesAreGeneratedWithCrashPayload() throws Exception {
-        assertThat(isTombstoneGeneratedWithCrashPayload(true /* debuggable */)).isTrue();
+    public void testTombstonesAreGeneratedWithCrashPayloadOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashPayload(
+                                /*protectedVm=*/ true, /*debuggable=*/ true))
+                .isTrue();
     }
 
     @Test
-    public void testTombstonesAreNotGeneratedWithCrashPayloadWhenNonDebuggable() throws Exception {
-        assertThat(isTombstoneGeneratedWithCrashPayload(false /* debuggable */)).isFalse();
+    public void testTombstonesAreGeneratedWithCrashPayloadOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashPayload(
+                                /*protectedVm=*/ false, /*debuggable=*/ true))
+                .isTrue();
     }
 
-    private boolean isTombstoneGeneratedWithCrashConfig(boolean debuggable) throws Exception {
+    @Test
+    public void testTombstonesAreNotGeneratedWithCrashPayloadWhenNonDebuggableOnPvm()
+            throws Exception {
+        assumeProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashPayload(
+                                /*protectedVm=*/ true, /*debuggable=*/ false))
+                .isFalse();
+    }
+
+    @Test
+    public void testTombstonesAreNotGeneratedWithCrashPayloadWhenNonDebuggableOnNonPvm()
+            throws Exception {
+        assumeNonProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashPayload(
+                                /*protectedVm=*/ false, /*debuggable=*/ false))
+                .isFalse();
+    }
+
+    private boolean isTombstoneGeneratedWithCrashConfig(boolean protectedVm, boolean debuggable)
+            throws Exception {
         return isTombstoneGeneratedWithVmRunApp(
-                debuggable, "--config-path", "assets/vm_config_crash.json");
+                protectedVm, debuggable, "--config-path", "assets/vm_config_crash.json");
     }
 
     @Test
-    public void testTombstonesAreGeneratedWithCrashConfig() throws Exception {
-        assertThat(isTombstoneGeneratedWithCrashConfig(true /* debuggable */)).isTrue();
+    public void testTombstonesAreGeneratedWithCrashConfigOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        assertThat(isTombstoneGeneratedWithCrashConfig(/*protectedVm=*/ true, /*debuggable=*/ true))
+                .isTrue();
     }
 
     @Test
-    public void testTombstonesAreNotGeneratedWithCrashConfigWhenNonDebuggable() throws Exception {
-        assertThat(isTombstoneGeneratedWithCrashConfig(false /* debuggable */)).isFalse();
+    public void testTombstonesAreGeneratedWithCrashConfigOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashConfig(
+                                /*protectedVm=*/ false, /*debuggable=*/ true))
+                .isTrue();
     }
 
     @Test
-    public void testTelemetryPushedAtoms() throws Exception {
+    public void testTombstonesAreNotGeneratedWithCrashConfigWhenNonDebuggableOnPvm()
+            throws Exception {
+        assumeProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashConfig(
+                                /*protectedVm=*/ true, /*debuggable=*/ false))
+                .isFalse();
+    }
+
+    @Test
+    public void testTombstonesAreNotGeneratedWithCrashConfigWhenNonDebuggableOnNonPvm()
+            throws Exception {
+        assumeNonProtectedVmSupported();
+        assertThat(
+                        isTombstoneGeneratedWithCrashConfig(
+                                /*protectedVm=*/ false, /*debuggable=*/ false))
+                .isFalse();
+    }
+
+    @Test
+    public void testTelemetryPushedAtomsOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        testTelemetryPushedAtoms(false);
+    }
+
+    @Test
+    public void testTelemetryPushedAtomsOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        testTelemetryPushedAtoms(true);
+    }
+
+    private void testTelemetryPushedAtoms(boolean protectedVm) throws Exception {
         // Reset statsd config and report before the test
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
@@ -688,6 +746,7 @@
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
+                        .protectedVm(protectedVm)
                         .build(device);
         microdroid.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         device.shutdownMicrodroid(microdroid);
@@ -714,7 +773,7 @@
                 data.get(0).getAtom().getVmCreationRequested();
         assertThat(atomVmCreationRequested.getHypervisor())
                 .isEqualTo(AtomsProto.VmCreationRequested.Hypervisor.PKVM);
-        assertThat(atomVmCreationRequested.getIsProtected()).isFalse();
+        assertThat(atomVmCreationRequested.getIsProtected()).isEqualTo(protectedVm);
         assertThat(atomVmCreationRequested.getCreationSucceeded()).isTrue();
         assertThat(atomVmCreationRequested.getBinderExceptionCode()).isEqualTo(0);
         assertThat(atomVmCreationRequested.getVmIdentifier()).isEqualTo("VmRunApp");
@@ -743,7 +802,19 @@
 
     @Test
     @CddTest(requirements = {"9.17/C-1-1", "9.17/C-1-2", "9.17/C/1-3"})
-    public void testMicrodroidBoots() throws Exception {
+    public void testMicrodroidBootsOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        testMicrodroidBoots(true);
+    }
+
+    @Test
+    @CddTest(requirements = {"9.17/C-1-1", "9.17/C-1-2", "9.17/C/1-3"})
+    public void testMicrodroidBootsOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        testMicrodroidBoots(false);
+    }
+
+    private void testMicrodroidBoots(boolean protectedVm) throws Exception {
         CommandRunner android = new CommandRunner(getDevice());
 
         final String configPath = "assets/vm_config.json"; // path inside the APK
@@ -752,6 +823,7 @@
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
+                        .protectedVm(protectedVm)
                         .build(getAndroidDevice());
         mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         CommandRunner microdroid = new CommandRunner(mMicrodroidDevice);
@@ -810,13 +882,25 @@
     }
 
     @Test
-    public void testMicrodroidRamUsage() throws Exception {
+    public void testMicrodroidRamUsageOnPvm() throws Exception {
+        assumeProtectedVmSupported();
+        testMicrodroidRamUsage(true);
+    }
+
+    @Test
+    public void testMicrodroidRamUsageOnNonPvm() throws Exception {
+        assumeNonProtectedVmSupported();
+        testMicrodroidRamUsage(false);
+    }
+
+    private void testMicrodroidRamUsage(boolean protectedVm) throws Exception {
         final String configPath = "assets/vm_config.json";
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
+                        .protectedVm(protectedVm)
                         .build(getAndroidDevice());
         mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         mMicrodroidDevice.enableAdbRoot();
@@ -990,6 +1074,18 @@
                         "android.permission.USE_CUSTOM_VIRTUAL_MACHINE");
     }
 
+    private void assumeProtectedVmSupported() throws Exception {
+        assumeTrue(
+                "Test skipped because protected VMs are not supported",
+                getAndroidDevice().supportsMicrodroid(true));
+    }
+
+    private void assumeNonProtectedVmSupported() throws Exception {
+        assumeTrue(
+                "Test skipped because non-protected VMs are not supported",
+                getAndroidDevice().supportsMicrodroid(false));
+    }
+
     private TestDevice getAndroidDevice() {
         TestDevice androidDevice = (TestDevice) getDevice();
         assertThat(androidDevice).isNotNull();
diff --git a/vm/src/main.rs b/vm/src/main.rs
index d7c2c4d..0c99acb 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -82,8 +82,8 @@
         #[clap(long)]
         log: Option<PathBuf>,
 
-        /// Debug level of the VM. Supported values: "none" (default), and "full".
-        #[clap(long, default_value = "none", value_parser = parse_debug_level)]
+        /// Debug level of the VM. Supported values: "full" (default), and "none".
+        #[clap(long, default_value = "full", value_parser = parse_debug_level)]
         debug: DebugLevel,
 
         /// Run VM in protected mode.
@@ -154,7 +154,7 @@
         #[clap(long)]
         log: Option<PathBuf>,
 
-        /// Debug level of the VM. Supported values: "none" (default), and "full".
+        /// Debug level of the VM. Supported values: "full" (default), and "none".
         #[clap(long, default_value = "full", value_parser = parse_debug_level)]
         debug: DebugLevel,
 
diff --git a/zipfuse/src/inode.rs b/zipfuse/src/inode.rs
index ea63422..ef48389 100644
--- a/zipfuse/src/inode.rs
+++ b/zipfuse/src/inode.rs
@@ -210,7 +210,7 @@
                     parent = found;
                     // Update the mode if this is a directory leaf.
                     if !is_file && is_leaf {
-                        let mut inode = table.get_mut(parent).unwrap();
+                        let inode = table.get_mut(parent).unwrap();
                         inode.mode = file.unix_mode().unwrap_or(DEFAULT_DIR_MODE);
                     }
                     continue;