Merge "OWNERS += fmayle@" into main
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index b87e816..9ba1c04 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -31,7 +31,6 @@
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
     AssignedDevices::AssignedDevices,
     AssignableDevice::AssignableDevice,
-    CpuTopology::CpuTopology,
     DiskImage::DiskImage,
     SharedPath::SharedPath,
     InputDevice::InputDevice,
@@ -712,24 +711,6 @@
 
         let shared_paths = assemble_shared_paths(&config.sharedPaths, &temporary_directory)?;
 
-        let (cpus, host_cpu_topology) = match config.cpuTopology {
-            CpuTopology::MATCH_HOST => (None, true),
-            CpuTopology::ONE_CPU => (NonZeroU32::new(1), false),
-            CpuTopology::CUSTOM => (
-                NonZeroU32::new(
-                    u32::try_from(config.customVcpuCount)
-                        .context("bad customVcpuCount")
-                        .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?,
-                ),
-                false,
-            ),
-            val => {
-                return Err(anyhow!("Failed to parse CPU topology value {:?}", val))
-                    .with_log()
-                    .or_service_specific_exception(-1);
-            }
-        };
-
         let (vfio_devices, dtbo) = match &config.devices {
             AssignedDevices::Devices(devices) if !devices.is_empty() => {
                 let mut set = HashSet::new();
@@ -840,8 +821,7 @@
                 .and_then(NonZeroU32::new)
                 .unwrap_or(NonZeroU32::new(256).unwrap()),
             swiotlb_mib: config.swiotlbMib.try_into().ok().and_then(NonZeroU32::new),
-            cpus,
-            host_cpu_topology,
+            cpus: config.cpuOptions.clone(),
             console_out_fd,
             console_in_fd,
             log_fd,
@@ -1305,10 +1285,7 @@
 
     vm_config.name.clone_from(&config.name);
     vm_config.protectedVm = config.protectedVm;
-    vm_config.cpuTopology = config.cpuTopology;
-    if config.cpuTopology == CpuTopology::CUSTOM {
-        bail!("AppConfig doesn't support CpuTopology::CUSTOM");
-    }
+    vm_config.cpuOptions = config.cpuOptions.clone();
     vm_config.hugePages = config.hugePages || vm_payload_config.hugepages;
     vm_config.boostUclamp = config.boostUclamp;
 
diff --git a/android/virtmgr/src/atom.rs b/android/virtmgr/src/atom.rs
index e0fed85..33299aa 100644
--- a/android/virtmgr/src/atom.rs
+++ b/android/virtmgr/src/atom.rs
@@ -19,7 +19,8 @@
 use crate::get_calling_uid;
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    CpuTopology::CpuTopology,
+    CpuOptions::CpuOptions,
+    CpuOptions::CpuTopology::CpuTopology,
     IVirtualMachine::IVirtualMachine,
     VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
     VirtualMachineConfig::VirtualMachineConfig,
@@ -92,23 +93,15 @@
     }
 }
 
-fn get_num_vcpus(cpu_topology: CpuTopology, custom_vcpu_count: Option<i32>) -> i32 {
-    match cpu_topology {
-        CpuTopology::ONE_CPU => 1,
-        CpuTopology::MATCH_HOST => {
+fn get_num_vcpus(cpu_options: &CpuOptions) -> i32 {
+    match cpu_options.cpuTopology {
+        CpuTopology::MatchHost(_) => {
             get_num_cpus().and_then(|v| v.try_into().ok()).unwrap_or_else(|| {
                 warn!("Failed to determine the number of CPUs in the host");
                 INVALID_NUM_CPUS
             })
         }
-        CpuTopology::CUSTOM => custom_vcpu_count.unwrap_or_else(|| {
-            warn!("AppConfig doesn't support CpuTopology::CUSTOM");
-            INVALID_NUM_CPUS
-        }),
-        _ => {
-            warn!("invalid CpuTopology: {cpu_topology:?}");
-            INVALID_NUM_CPUS
-        }
+        CpuTopology::CpuCount(count) => count,
     }
 }
 
@@ -140,14 +133,14 @@
         VirtualMachineConfig::AppConfig(config) => (
             config.name.clone(),
             vm_creation_requested::ConfigType::VirtualMachineAppConfig,
-            get_num_vcpus(config.cpuTopology, None),
+            get_num_vcpus(&config.cpuOptions),
             config.memoryMib,
             get_apex_list(config),
         ),
         VirtualMachineConfig::RawConfig(config) => (
             config.name.clone(),
             vm_creation_requested::ConfigType::VirtualMachineRawConfig,
-            get_num_vcpus(config.cpuTopology, Some(config.customVcpuCount)),
+            get_num_vcpus(&config.cpuOptions),
             config.memoryMib,
             String::new(),
         ),
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 00858cb..bb7712e 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -47,6 +47,8 @@
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
     VirtualMachineAppConfig::DebugLevel::DebugLevel,
     AudioConfig::AudioConfig as AudioConfigParcelable,
+    CpuOptions::CpuOptions,
+    CpuOptions::CpuTopology::CpuTopology,
     DisplayConfig::DisplayConfig as DisplayConfigParcelable,
     GpuConfig::GpuConfig as GpuConfigParcelable,
     UsbConfig::UsbConfig as UsbConfigParcelable,
@@ -113,8 +115,7 @@
     pub debug_config: DebugConfig,
     pub memory_mib: NonZeroU32,
     pub swiotlb_mib: Option<NonZeroU32>,
-    pub cpus: Option<NonZeroU32>,
-    pub host_cpu_topology: bool,
+    pub cpus: CpuOptions,
     pub console_out_fd: Option<File>,
     pub console_in_fd: Option<File>,
     pub log_fd: Option<File>,
@@ -1109,30 +1110,31 @@
 
     command.arg("--mem").arg(memory_mib.to_string());
 
-    if let Some(cpus) = config.cpus {
+    fn cpu_arg_command(command: &mut Command, count: usize) {
         #[cfg(target_arch = "aarch64")]
-        command.arg("--cpus").arg(cpus.to_string() + ",sve=[auto=true]");
+        command.arg("--cpus").arg(count.to_string() + ",sve=[auto=true]");
         #[cfg(not(target_arch = "aarch64"))]
-        command.arg("--cpus").arg(cpus.to_string());
+        command.arg("--cpus").arg(count.to_string());
     }
-
-    if config.host_cpu_topology {
-        if cfg!(virt_cpufreq) && check_if_all_cpus_allowed()? {
-            command.arg("--host-cpu-topology");
-            cfg_if::cfg_if! {
-                if #[cfg(any(target_arch = "aarch64"))] {
+    match config.cpus.cpuTopology {
+        CpuTopology::MatchHost(_) => {
+            if cfg!(virt_cpufreq) && check_if_all_cpus_allowed()? {
+                command.arg("--host-cpu-topology");
+                #[cfg(target_arch = "aarch64")]
+                {
                     command.arg("--virt-cpufreq");
+                    command.arg("--cpus").arg("sve=[auto=true]");
                 }
+            } else {
+                cpu_arg_command(
+                    &mut command,
+                    get_num_cpus()
+                        .context("Could not determine the number of CPUs in the system")?,
+                )
             }
-            #[cfg(target_arch = "aarch64")]
-            command.arg("--cpus").arg("sve=[auto=true]");
-        } else if let Some(cpus) = get_num_cpus() {
-            #[cfg(target_arch = "aarch64")]
-            command.arg("--cpus").arg(cpus.to_string() + ",sve=[auto=true]");
-            #[cfg(not(target_arch = "aarch64"))]
-            command.arg("--cpus").arg(cpus.to_string());
-        } else {
-            bail!("Could not determine the number of CPUs in the system");
+        }
+        CpuTopology::CpuCount(count) => {
+            cpu_arg_command(&mut command, count.try_into().context("invalid cpu count")?)
         }
     }
 
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/CpuTopology.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/CpuOptions.aidl
similarity index 63%
rename from android/virtualizationservice/aidl/android/system/virtualizationservice/CpuTopology.aidl
rename to android/virtualizationservice/aidl/android/system/virtualizationservice/CpuOptions.aidl
index 31a33f4..ae5044f 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/CpuTopology.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/CpuOptions.aidl
@@ -15,13 +15,17 @@
  */
 package android.system.virtualizationservice;
 
-/** The vCPU topology that will be generated for the VM. */
-@Backing(type="byte")
-enum CpuTopology {
-    /** One vCPU */
-    ONE_CPU = 0,
-    /** Match physical CPU topology of the host. */
-    MATCH_HOST = 1,
-    /** Number of vCPUs specified in the config. */
-    CUSTOM = 2,
+/** CPU options that will be used for the VM's Vcpus. */
+@RustDerive(Clone=true)
+parcelable CpuOptions {
+    @RustDerive(Clone=true, PartialEq=true)
+    union CpuTopology {
+        /** Number of Vcpus to boot the VM with. */
+        int cpuCount = 1;
+
+        /** Match host number of Vcpus to boot the VM with. */
+        boolean matchHost;
+    }
+
+    CpuTopology cpuTopology;
 }
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index 114a851..5193e21 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -15,7 +15,7 @@
  */
 package android.system.virtualizationservice;
 
-import android.system.virtualizationservice.CpuTopology;
+import android.system.virtualizationservice.CpuOptions;
 import android.system.virtualizationservice.VirtualMachinePayloadConfig;
 
 /** Configuration for running an App in a VM */
@@ -93,8 +93,8 @@
      */
     int memoryMib;
 
-    /** The vCPU topology that will be generated for the VM. Default to 1 vCPU. */
-    CpuTopology cpuTopology = CpuTopology.ONE_CPU;
+    /** The vCPU options that will be generated for the VM. */
+    CpuOptions cpuOptions;
 
     /**
      * Encapsulates parameters that require android.permission.USE_CUSTOM_VIRTUAL_MACHINE.
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
index b6eff64..a822423 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -17,7 +17,7 @@
 
 import android.system.virtualizationservice.AssignedDevices;
 import android.system.virtualizationservice.AudioConfig;
-import android.system.virtualizationservice.CpuTopology;
+import android.system.virtualizationservice.CpuOptions;
 import android.system.virtualizationservice.DiskImage;
 import android.system.virtualizationservice.DisplayConfig;
 import android.system.virtualizationservice.GpuConfig;
@@ -66,11 +66,8 @@
     /** The amount of swiotlb to give the VM, in MiB. 0 or negative to use the default. */
     int swiotlbMib;
 
-    /** The vCPU topology that will be generated for the VM. Default to 1 vCPU. */
-    CpuTopology cpuTopology = CpuTopology.ONE_CPU;
-
-    /** The number of vCPUs. Ignored unless `cpuTopology == CUSTOM`. */
-    int customVcpuCount;
+    /** The vCPU options that will be generated for the VM. */
+    CpuOptions cpuOptions;
 
     /**
      * A version or range of versions of the virtual platform that this config is compatible with.
diff --git a/android/vm/src/main.rs b/android/vm/src/main.rs
index 830d56c..ff846a1 100644
--- a/android/vm/src/main.rs
+++ b/android/vm/src/main.rs
@@ -19,7 +19,7 @@
 mod run;
 
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
+    CpuOptions::CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
     PartitionType::PartitionType, VirtualMachineAppConfig::DebugLevel::DebugLevel,
 };
 #[cfg(not(llpvm_changes))]
@@ -379,8 +379,13 @@
 
 fn parse_cpu_topology(s: &str) -> Result<CpuTopology, String> {
     match s {
-        "one_cpu" => Ok(CpuTopology::ONE_CPU),
-        "match_host" => Ok(CpuTopology::MATCH_HOST),
+        "one_cpu" => Ok(CpuTopology::CpuCount(1)),
+        "match_host" => Ok(CpuTopology::MatchHost(true)),
+        _ if s.starts_with("cpu_count=") => {
+            // Safe to unwrap as it's validated the string starts with cpu_count=
+            let val = s.strip_prefix("cpu_count=").unwrap();
+            Ok(CpuTopology::CpuCount(val.parse().map_err(|e| format!("Invalid CPU Count: {}", e))?))
+        }
         _ => Err(format!("Invalid cpu topology {}", s)),
     }
 }
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index 0037327..eaf2522 100644
--- a/android/vm/src/run.rs
+++ b/android/vm/src/run.rs
@@ -17,6 +17,7 @@
 use crate::create_partition::command_create_partition;
 use crate::{get_service, RunAppConfig, RunCustomVmConfig, RunMicrodroidConfig};
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    CpuOptions::CpuOptions,
     IVirtualizationService::IVirtualizationService,
     PartitionType::PartitionType,
     VirtualMachineAppConfig::{
@@ -160,6 +161,7 @@
         ..Default::default()
     };
 
+    let cpu_options = CpuOptions { cpuTopology: config.common.cpu_topology };
     if config.debug.enable_earlycon() {
         if config.debug.debug != DebugLevel::FULL {
             bail!("earlycon is only supported for debuggable VMs")
@@ -188,7 +190,7 @@
         debugLevel: config.debug.debug,
         protectedVm: config.common.protected,
         memoryMib: config.common.mem.unwrap_or(0) as i32, // 0 means use the VM default
-        cpuTopology: config.common.cpu_topology,
+        cpuOptions: cpu_options,
         customConfig: Some(custom_config),
         osName: os_name.to_string(),
         hugePages: config.common.hugepages,
@@ -273,7 +275,7 @@
     if let Some(gdb) = config.debug.gdb {
         vm_config.gdbPort = gdb.get() as i32;
     }
-    vm_config.cpuTopology = config.common.cpu_topology;
+    vm_config.cpuOptions = CpuOptions { cpuTopology: config.common.cpu_topology.clone() };
     vm_config.hugePages = config.common.hugepages;
     vm_config.boostUclamp = config.common.boost_uclamp;
     vm_config.teeServices = config.common.tee_services().to_vec();
diff --git a/guest/trusty/security_vm/launcher/src/main.rs b/guest/trusty/security_vm/launcher/src/main.rs
index 8dd7c43..3c8d599 100644
--- a/guest/trusty/security_vm/launcher/src/main.rs
+++ b/guest/trusty/security_vm/launcher/src/main.rs
@@ -15,8 +15,9 @@
 //! A client for trusty security VMs during early boot.
 
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
-    VirtualMachineConfig::VirtualMachineConfig, VirtualMachineRawConfig::VirtualMachineRawConfig,
+    CpuOptions::CpuOptions, CpuOptions::CpuTopology::CpuTopology,
+    IVirtualizationService::IVirtualizationService, VirtualMachineConfig::VirtualMachineConfig,
+    VirtualMachineRawConfig::VirtualMachineRawConfig,
 };
 use android_system_virtualizationservice::binder::{ParcelFileDescriptor, Strong};
 use anyhow::{Context, Result};
@@ -61,8 +62,8 @@
 
 fn parse_cpu_topology(s: &str) -> Result<CpuTopology, String> {
     match s {
-        "one-cpu" => Ok(CpuTopology::ONE_CPU),
-        "match-host" => Ok(CpuTopology::MATCH_HOST),
+        "one-cpu" => Ok(CpuTopology::CpuCount(1)),
+        "match-host" => Ok(CpuTopology::MatchHost(true)),
         _ => Err(format!("Invalid cpu topology {}", s)),
     }
 }
@@ -86,7 +87,7 @@
         bootloader,
         protectedVm: args.protected,
         memoryMib: args.memory_size_mib,
-        cpuTopology: args.cpu_topology,
+        cpuOptions: CpuOptions { cpuTopology: args.cpu_topology },
         platformVersion: "~1.0".to_owned(),
         // TODO: add instanceId
         ..Default::default()
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index 6311168..83b234d 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -41,6 +41,7 @@
 import android.os.PersistableBundle;
 import android.sysprop.HypervisorProperties;
 import android.system.virtualizationservice.AssignedDevices;
+import android.system.virtualizationservice.CpuOptions;
 import android.system.virtualizationservice.DiskImage;
 import android.system.virtualizationservice.Partition;
 import android.system.virtualizationservice.SharedPath;
@@ -806,7 +807,16 @@
                         .orElse(null);
         config.protectedVm = this.mProtectedVm;
         config.memoryMib = bytesToMebiBytes(mMemoryBytes);
-        config.cpuTopology = (byte) this.mCpuTopology;
+        switch (this.mCpuTopology) {
+            case CPU_TOPOLOGY_MATCH_HOST:
+                config.cpuOptions = new CpuOptions();
+                config.cpuOptions.cpuTopology = CpuOptions.CpuTopology.matchHost(true);
+                break;
+            default:
+                config.cpuOptions = new CpuOptions();
+                config.cpuOptions.cpuTopology = CpuOptions.CpuTopology.cpuCount(1);
+                break;
+        }
         config.consoleInputDevice = mConsoleInputDevice;
         config.devices = AssignedDevices.devices(EMPTY_STRING_ARRAY);
         config.platformVersion = "~1.0";
@@ -867,10 +877,12 @@
         vsConfig.memoryMib = bytesToMebiBytes(mMemoryBytes);
         switch (mCpuTopology) {
             case CPU_TOPOLOGY_MATCH_HOST:
-                vsConfig.cpuTopology = android.system.virtualizationservice.CpuTopology.MATCH_HOST;
+                vsConfig.cpuOptions = new CpuOptions();
+                vsConfig.cpuOptions.cpuTopology = CpuOptions.CpuTopology.matchHost(true);
                 break;
             default:
-                vsConfig.cpuTopology = android.system.virtualizationservice.CpuTopology.ONE_CPU;
+                vsConfig.cpuOptions = new CpuOptions();
+                vsConfig.cpuOptions.cpuTopology = CpuOptions.CpuTopology.cpuCount(1);
                 break;
         }
 
diff --git a/libs/libavf/src/lib.rs b/libs/libavf/src/lib.rs
index 6532ace..3fa1b75 100644
--- a/libs/libavf/src/lib.rs
+++ b/libs/libavf/src/lib.rs
@@ -23,7 +23,8 @@
 
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
-        AssignedDevices::AssignedDevices, CpuTopology::CpuTopology, DiskImage::DiskImage,
+        AssignedDevices::AssignedDevices, CpuOptions::CpuOptions,
+        CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage,
         IVirtualizationService::IVirtualizationService, VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
     },
@@ -218,8 +219,7 @@
     // SAFETY: `config` is assumed to be a valid, non-null pointer returned by
     // AVirtualMachineRawConfig_create. It's the only reference to the object.
     let config = unsafe { &mut *config };
-    config.cpuTopology = CpuTopology::CUSTOM;
-    config.customVcpuCount = n;
+    config.cpuOptions = CpuOptions { cpuTopology: CpuTopology::CpuCount(n) };
 }
 
 /// Set whether a virtual machine is protected or not.
diff --git a/libs/libcompos_common/compos_client.rs b/libs/libcompos_common/compos_client.rs
index 6872582..a52104d 100644
--- a/libs/libcompos_common/compos_client.rs
+++ b/libs/libcompos_common/compos_client.rs
@@ -22,7 +22,8 @@
     COMPOS_APEX_ROOT, COMPOS_VSOCK_PORT,
 };
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    CpuTopology::CpuTopology,
+    CpuOptions::CpuOptions,
+    CpuOptions::CpuTopology::CpuTopology,
     IVirtualizationService::IVirtualizationService,
     VirtualMachineAppConfig::{
         CustomConfig::CustomConfig, DebugLevel::DebugLevel, Payload::Payload,
@@ -120,9 +121,10 @@
         let debug_level = if parameters.debug_mode { DebugLevel::FULL } else { DebugLevel::NONE };
 
         let cpu_topology = match parameters.cpu_topology {
-            VmCpuTopology::OneCpu => CpuTopology::ONE_CPU,
-            VmCpuTopology::MatchHost => CpuTopology::MATCH_HOST,
+            VmCpuTopology::OneCpu => CpuTopology::CpuCount(1),
+            VmCpuTopology::MatchHost => CpuTopology::MatchHost(true),
         };
+        let cpu_options = CpuOptions { cpuTopology: cpu_topology };
 
         // The CompOS VM doesn't need to be updatable (by design it should run exactly twice,
         // with the same APKs and APEXes each time). And having it so causes some interesting
@@ -141,7 +143,7 @@
             extraIdsigs: extra_idsigs,
             protectedVm: true,
             memoryMib: parameters.memory_mib.unwrap_or(0), // 0 means use the default
-            cpuTopology: cpu_topology,
+            cpuOptions: cpu_options,
             customConfig: custom_config,
             ..Default::default()
         });
diff --git a/libs/libservice_vm_manager/src/lib.rs b/libs/libservice_vm_manager/src/lib.rs
index 0f322bb..667731f 100644
--- a/libs/libservice_vm_manager/src/lib.rs
+++ b/libs/libservice_vm_manager/src/lib.rs
@@ -17,7 +17,7 @@
 
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
-        CpuTopology::CpuTopology, DiskImage::DiskImage,
+        CpuOptions::CpuOptions, CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage,
         IVirtualizationService::IVirtualizationService, Partition::Partition,
         PartitionType::PartitionType, VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
@@ -226,6 +226,7 @@
         writable: true,
         guid: None,
     }];
+    let cpu_options = CpuOptions { cpuTopology: CpuTopology::CpuCount(1) };
     let rialto = File::open(RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
     let instance_id_file = Path::new(VIRT_DATA_DIR).join(INSTANCE_ID_FILENAME);
     let instance_id = get_or_allocate_instance_id(service.as_ref(), instance_id_file)?;
@@ -236,7 +237,7 @@
         instanceId: instance_id,
         protectedVm: true,
         memoryMib: VM_MEMORY_MB,
-        cpuTopology: CpuTopology::ONE_CPU,
+        cpuOptions: cpu_options,
         platformVersion: "~1.0".to_string(),
         gdbPort: 0, // No gdb
         ..Default::default()
diff --git a/libs/vmconfig/src/lib.rs b/libs/vmconfig/src/lib.rs
index 8357f99..859ca77 100644
--- a/libs/vmconfig/src/lib.rs
+++ b/libs/vmconfig/src/lib.rs
@@ -15,14 +15,14 @@
 //! Struct for VM configuration with JSON (de)serialization and AIDL parcelables
 
 use android_system_virtualizationservice::{
-    aidl::android::system::virtualizationservice::AssignedDevices::AssignedDevices,
-    aidl::android::system::virtualizationservice::CpuTopology::CpuTopology,
-    aidl::android::system::virtualizationservice::DiskImage::DiskImage as AidlDiskImage,
-    aidl::android::system::virtualizationservice::Partition::Partition as AidlPartition,
-    aidl::android::system::virtualizationservice::UsbConfig::UsbConfig as AidlUsbConfig,
-    aidl::android::system::virtualizationservice::VirtualMachineAppConfig::DebugLevel::DebugLevel,
-    aidl::android::system::virtualizationservice::VirtualMachineConfig::VirtualMachineConfig,
-    aidl::android::system::virtualizationservice::VirtualMachineRawConfig::VirtualMachineRawConfig,
+    aidl::android::system::virtualizationservice::{
+        AssignedDevices::AssignedDevices, CpuOptions::CpuOptions,
+        CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage as AidlDiskImage,
+        Partition::Partition as AidlPartition, UsbConfig::UsbConfig as AidlUsbConfig,
+        VirtualMachineAppConfig::DebugLevel::DebugLevel,
+        VirtualMachineConfig::VirtualMachineConfig,
+        VirtualMachineRawConfig::VirtualMachineRawConfig,
+    },
     binder::ParcelFileDescriptor,
 };
 
@@ -109,11 +109,12 @@
             0
         };
         let cpu_topology = match self.cpu_topology.as_deref() {
-            None => CpuTopology::ONE_CPU,
-            Some("one_cpu") => CpuTopology::ONE_CPU,
-            Some("match_host") => CpuTopology::MATCH_HOST,
+            None => CpuTopology::CpuCount(1),
+            Some("one_cpu") => CpuTopology::CpuCount(1),
+            Some("match_host") => CpuTopology::MatchHost(true),
             Some(cpu_topology) => bail!("Invalid cpu topology {}", cpu_topology),
         };
+        let cpu_options = CpuOptions { cpuTopology: cpu_topology };
         let usb_config = self.usb_config.clone().map(|x| x.to_parcelable()).transpose()?;
         Ok(VirtualMachineRawConfig {
             kernel: maybe_open_parcel_file(&self.kernel, false)?,
@@ -123,7 +124,7 @@
             disks: self.disks.iter().map(DiskImage::to_parcelable).collect::<Result<_, Error>>()?,
             protectedVm: self.protected,
             memoryMib: memory_mib,
-            cpuTopology: cpu_topology,
+            cpuOptions: cpu_options,
             platformVersion: self.platform_version.to_string(),
             devices: AssignedDevices::Devices(
                 self.devices
diff --git a/microfuchsia/microfuchsiad/src/instance_starter.rs b/microfuchsia/microfuchsiad/src/instance_starter.rs
index e3c4e8d..55c946e 100644
--- a/microfuchsia/microfuchsiad/src/instance_starter.rs
+++ b/microfuchsia/microfuchsiad/src/instance_starter.rs
@@ -17,8 +17,9 @@
 //! Responsible for starting an instance of the Microfuchsia VM.
 
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
-    VirtualMachineConfig::VirtualMachineConfig, VirtualMachineRawConfig::VirtualMachineRawConfig,
+    CpuOptions::CpuOptions, CpuOptions::CpuTopology::CpuTopology,
+    IVirtualizationService::IVirtualizationService, VirtualMachineConfig::VirtualMachineConfig,
+    VirtualMachineRawConfig::VirtualMachineRawConfig,
 };
 use anyhow::{ensure, Context, Result};
 use binder::{LazyServiceGuard, ParcelFileDescriptor};
@@ -82,7 +83,7 @@
             disks: vec![],
             protectedVm: false,
             memoryMib: 256,
-            cpuTopology: CpuTopology::ONE_CPU,
+            cpuOptions: CpuOptions { cpuTopology: CpuTopology::CpuCount(1) },
             platformVersion: "1.0.0".into(),
             #[cfg(enable_console)]
             consoleInputDevice: Some("ttyS0".into()),
diff --git a/tests/backcompat_test/src/main.rs b/tests/backcompat_test/src/main.rs
index aa69eec..b0cd042 100644
--- a/tests/backcompat_test/src/main.rs
+++ b/tests/backcompat_test/src/main.rs
@@ -16,7 +16,8 @@
 
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
-        CpuTopology::CpuTopology, DiskImage::DiskImage, VirtualMachineConfig::VirtualMachineConfig,
+        CpuOptions::CpuOptions, CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage,
+        VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
     },
     binder::{ParcelFileDescriptor, ProcessState},
@@ -98,7 +99,7 @@
         disks: vec![disk_image, empty_disk_image],
         protectedVm: protected,
         memoryMib: 300,
-        cpuTopology: CpuTopology::ONE_CPU,
+        cpuOptions: CpuOptions { cpuTopology: CpuTopology::CpuCount(1) },
         platformVersion: "~1.0".to_string(),
         ..Default::default()
     });
diff --git a/tests/vmbase_example/src/main.rs b/tests/vmbase_example/src/main.rs
index cbe90d8..81812cd 100644
--- a/tests/vmbase_example/src/main.rs
+++ b/tests/vmbase_example/src/main.rs
@@ -16,7 +16,8 @@
 
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
-        CpuTopology::CpuTopology, DiskImage::DiskImage, VirtualMachineConfig::VirtualMachineConfig,
+        CpuOptions::CpuOptions, CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage,
+        VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
     },
     binder::{ParcelFileDescriptor, ProcessState},
@@ -101,7 +102,7 @@
         disks: vec![disk_image, empty_disk_image],
         protectedVm: false,
         memoryMib: 300,
-        cpuTopology: CpuTopology::ONE_CPU,
+        cpuOptions: CpuOptions { cpuTopology: CpuTopology::CpuCount(1) },
         platformVersion: "~1.0".to_string(),
         gdbPort: 0, // no gdb
         ..Default::default()