Merge "cleanup:Limit the scope of dead_code in v3"
diff --git a/pvmfw/src/exceptions.rs b/pvmfw/src/exceptions.rs
index 0e637ac..596ecc7 100644
--- a/pvmfw/src/exceptions.rs
+++ b/pvmfw/src/exceptions.rs
@@ -19,8 +19,9 @@
 
 #[no_mangle]
 extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("sync_exception_current\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
@@ -38,15 +39,17 @@
 
 #[no_mangle]
 extern "C" fn serr_current(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("serr_current\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
 #[no_mangle]
 extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("sync_lower\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
@@ -64,16 +67,22 @@
 
 #[no_mangle]
 extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("serr_lower\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
 #[inline]
-fn print_esr() {
+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);
 }
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 c9ceaae..7bf3c4e 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -143,11 +143,7 @@
 
             // To grab boot events from log, set debug mode to FULL
             VirtualMachineConfig normalConfig =
-                    builder.debugLevel(DebugLevel.FULL)
-                            .memoryMib(256)
-                            .numCpus(2)
-                            .cpuAffinity("0=0:1=1")
-                            .build();
+                    builder.debugLevel(DebugLevel.FULL).memoryMib(256).build();
             mInner.forceCreateNewVirtualMachine("test_vm_boot_time", normalConfig);
 
             BootResult result = tryBootVm(TAG, "test_vm_boot_time");
@@ -194,8 +190,6 @@
         VirtualMachineConfig config =
                 mInner.newVmConfigBuilder("assets/vm_config_io.json")
                         .debugLevel(DebugLevel.FULL)
-                        .numCpus(2)
-                        .cpuAffinity("0=0:1=1")
                         .build();
         List<Double> transferRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
 
@@ -223,8 +217,6 @@
         VirtualMachineConfig config =
                 mInner.newVmConfigBuilder("assets/vm_config_io.json")
                         .debugLevel(DebugLevel.FULL)
-                        .numCpus(2)
-                        .cpuAffinity("0=0:1=1")
                         .build();
         List<Double> readRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
 
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index 045be94..c7ee0f2 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -34,6 +34,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -66,6 +67,7 @@
     private static final String METRIC_PREFIX = "avf_perf/hostside/";
 
     private final MetricsProcessor mMetricsProcessor = new MetricsProcessor(METRIC_PREFIX);
+    @Rule public TestMetrics mMetrics = new TestMetrics();
 
     @Before
     public void setUp() throws Exception {
@@ -161,14 +163,13 @@
         assumeTrue(!result.getStderr().contains("Invalid oem command"));
         // Skip the test if running on a build with pkvm_enabler. Disabling pKVM
         // for such builds results in a bootloop.
-        assumeTrue(result.getStdout().contains("misc=auto"));
+        assumeTrue(result.getStderr().contains("misc=auto"));
     }
 
     private void reportMetric(List<Double> data, String name, String unit) {
         Map<String, Double> stats = mMetricsProcessor.computeStats(data, name, unit);
-        TestMetrics metrics = new TestMetrics();
         for (Map.Entry<String, Double> entry : stats.entrySet()) {
-            metrics.addTestMetric(entry.getKey(), Double.toString(entry.getValue()));
+            mMetrics.addTestMetric(entry.getKey(), entry.getValue().toString());
         }
     }
 
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index d86f2bf..a6b228d 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -68,11 +68,15 @@
      * Comma-separated list of CPUs or CPU ranges to run vCPUs on (e.g. 0,1-3,5), or
      * colon-separated list of assignments of vCPU to host CPU assignments (e.g. 0=0:1=1:2=2).
      * Default is no mask which means a vCPU can run on any host CPU.
+     *
+     * Note: Using a non-null value requires android.permission.USE_CUSTOM_VIRTUAL_MACHINE.
      */
     @nullable String cpuAffinity;
 
     /**
      * List of task profile names to apply for the VM
+     *
+     * Note: Specifying a value here requires android.permission.USE_CUSTOM_VIRTUAL_MACHINE.
      */
     String[] taskProfiles;
 }
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 352b4f1..dcc2d48 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -596,6 +596,12 @@
     config: &VirtualMachineAppConfig,
     temporary_directory: &Path,
 ) -> Result<VirtualMachineRawConfig> {
+    // Controlling CPUs is reserved for platform apps only, even when using
+    // VirtualMachineAppConfig.
+    if config.cpuAffinity.is_some() || !config.taskProfiles.is_empty() {
+        check_use_custom_virtual_machine()?
+    }
+
     let apk_file = clone_file(config.apk.as_ref().unwrap())?;
     let idsig_file = clone_file(config.idsig.as_ref().unwrap())?;
     let instance_file = clone_file(config.instanceImage.as_ref().unwrap())?;