Merge "add option for custom vCPU count" into main
diff --git a/android/virtmgr/Android.bp b/android/virtmgr/Android.bp
index 3883c34..ad63995 100644
--- a/android/virtmgr/Android.bp
+++ b/android/virtmgr/Android.bp
@@ -69,7 +69,7 @@
         "liblibfdt",
         "libfsfdt",
         "libhypervisor_props",
-        "libzerocopy-0.7.35",
+        "libzerocopy",
         "libuuid",
         // TODO(b/202115393) stabilize the interface
         "packagemanager_aidl-rust",
diff --git a/android/virtmgr/src/composite.rs b/android/virtmgr/src/composite.rs
index 1219150..cfd65c3 100644
--- a/android/virtmgr/src/composite.rs
+++ b/android/virtmgr/src/composite.rs
@@ -22,9 +22,9 @@
 use std::os::unix::fs::FileExt;
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
-use zerocopy::AsBytes;
 use zerocopy::FromBytes;
-use zerocopy::FromZeroes;
+use zerocopy::FromZeros;
+use zerocopy::IntoBytes;
 
 use uuid::Uuid;
 
@@ -132,7 +132,7 @@
         ImageType::AndroidSparse => {
             // Source: system/core/libsparse/sparse_format.h
             #[repr(C)]
-            #[derive(Clone, Copy, Debug, AsBytes, FromZeroes, FromBytes)]
+            #[derive(Clone, Copy, Debug, IntoBytes, FromBytes)]
             struct SparseHeader {
                 magic: u32,
                 major_version: u16,
diff --git a/android/virtualizationservice/vfio_handler/Android.bp b/android/virtualizationservice/vfio_handler/Android.bp
index fec61f1..3635cf1 100644
--- a/android/virtualizationservice/vfio_handler/Android.bp
+++ b/android/virtualizationservice/vfio_handler/Android.bp
@@ -28,7 +28,7 @@
         "liblog_rust",
         "libnix",
         "librustutils",
-        "libzerocopy-0.7.35",
+        "libzerocopy",
     ],
     apex_available: ["com.android.virt"],
 }
diff --git a/android/virtualizationservice/vfio_handler/src/aidl.rs b/android/virtualizationservice/vfio_handler/src/aidl.rs
index 3b4d0c5..d6b79e2 100644
--- a/android/virtualizationservice/vfio_handler/src/aidl.rs
+++ b/android/virtualizationservice/vfio_handler/src/aidl.rs
@@ -29,7 +29,6 @@
 use rustutils::system_properties;
 use zerocopy::{
     byteorder::{BigEndian, U32},
-    FromZeroes,
     FromBytes,
 };
 
@@ -131,7 +130,7 @@
 /// The structure of DT table header in dtbo.img.
 /// https://source.android.com/docs/core/architecture/dto/partitions
 #[repr(C)]
-#[derive(Debug, FromZeroes, FromBytes)]
+#[derive(Debug, FromBytes)]
 struct DtTableHeader {
     /// DT_TABLE_MAGIC
     magic: U32<BigEndian>,
@@ -155,7 +154,7 @@
 /// The structure of each DT table entry (v0) in dtbo.img.
 /// https://source.android.com/docs/core/architecture/dto/partitions
 #[repr(C)]
-#[derive(Debug, FromZeroes, FromBytes)]
+#[derive(Debug, FromBytes)]
 struct DtTableEntry {
     /// size of each DT
     dt_size: U32<BigEndian>,
diff --git a/build/Android.bp b/build/Android.bp
index 2b97927..ef70fe4 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -75,3 +75,20 @@
     tools: ["dtc"],
     cmd: "FILES=($(in)) && $(location dtc) -@ -I dts -O dtb $${FILES[-1]} -o $(out)",
 }
+
+// This is a temporary workaround until b/343795511 is implemented.
+aconfig_declarations {
+    name: "avf_aconfig_flags",
+    package: "com.android.system.virtualmachine.flags",
+    container: "com.android.virt",
+    srcs: [
+        "avf_flags.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "avf_aconfig_flags_java",
+    aconfig_declarations: "avf_aconfig_flags",
+    sdk_version: "module_current",
+    apex_available: ["com.android.virt"],
+}
diff --git a/build/apex/product_packages.mk b/build/apex/product_packages.mk
index 0646e67..edc8618 100644
--- a/build/apex/product_packages.mk
+++ b/build/apex/product_packages.mk
@@ -65,11 +65,3 @@
     $(error RELEASE_AVF_ENABLE_LLPVM_CHANGES must also be enabled)
   endif
 endif
-
-ifdef RELEASE_AVF_ENABLE_EARLY_VM
-  # We can't query TARGET_RELEASE from here, so we use RELEASE_AIDL_USE_UNFROZEN as a proxy value of
-  # whether we are building -next release.
-  ifneq ($(RELEASE_AIDL_USE_UNFROZEN),true)
-    $(error RELEASE_AVF_ENABLE_EARLY_VM can only be enabled in trunk_staging until b/357025924 is fixed)
-  endif
-endif
diff --git a/build/avf_flags.aconfig b/build/avf_flags.aconfig
new file mode 100644
index 0000000..9815c60
--- /dev/null
+++ b/build/avf_flags.aconfig
@@ -0,0 +1,11 @@
+package: "com.android.system.virtualmachine.flags"
+container: "com.android.virt"
+
+flag {
+  name: "promote_set_should_use_hugepages_to_system_api"
+  is_exported: true
+  namespace: "virtualization"
+  description: "Flag used in @FlaggedApi annotation for setShouldUseHugepages"
+  bug: "383347947"
+  is_fixed_read_only: true
+}
diff --git a/guest/apkdmverity/Android.bp b/guest/apkdmverity/Android.bp
index 64dde3e..3f45bb4 100644
--- a/guest/apkdmverity/Android.bp
+++ b/guest/apkdmverity/Android.bp
@@ -22,7 +22,6 @@
         "libnum_traits",
         "libscopeguard",
         "libuuid",
-        "libzerocopy-0.7.35",
     ],
     proc_macros: ["libnum_derive"],
     multilib: {
diff --git a/guest/microdroid_manager/src/dice.rs b/guest/microdroid_manager/src/dice.rs
index 7cfeb21..edc4d63 100644
--- a/guest/microdroid_manager/src/dice.rs
+++ b/guest/microdroid_manager/src/dice.rs
@@ -53,11 +53,7 @@
     let debuggable = is_debuggable()?;
 
     // Send the details to diced
-    let hidden = if cfg!(llpvm_changes) {
-        hidden_input_from_instance_id()?
-    } else {
-        instance_data.salt.clone().try_into().unwrap()
-    };
+    let hidden = hidden_input_from_instance_id()?;
     dice.derive(code_hash, &config_descriptor, authority_hash, debuggable, hidden)
 }
 
diff --git a/guest/microdroid_manager/src/instance.rs b/guest/microdroid_manager/src/instance.rs
index 2d39cd8..d3a597a 100644
--- a/guest/microdroid_manager/src/instance.rs
+++ b/guest/microdroid_manager/src/instance.rs
@@ -273,9 +273,6 @@
 
 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
 pub struct MicrodroidData {
-    // `salt` is obsolete, it was used as a differentiator for non-protected VM instances running
-    // same payload. Instance-id (present in DT) is used for that now.
-    pub salt: Vec<u8>, // Should be [u8; 64] but that isn't serializable.
     pub apk_data: ApkData,
     pub extra_apks_data: Vec<ApkData>,
     pub apex_data: Vec<ApexData>,
diff --git a/guest/microdroid_manager/src/verify.rs b/guest/microdroid_manager/src/verify.rs
index 90671a6..e5d26fc 100644
--- a/guest/microdroid_manager/src/verify.rs
+++ b/guest/microdroid_manager/src/verify.rs
@@ -14,7 +14,7 @@
 
 use crate::instance::{ApexData, ApkData, MicrodroidData};
 use crate::payload::{get_apex_data_from_payload, to_metadata};
-use crate::{is_strict_boot, MicrodroidError};
+use crate::MicrodroidError;
 use anyhow::{anyhow, ensure, Context, Result};
 use apkmanifest::get_manifest_info;
 use apkverify::{extract_signed_data, verify, V4Signature};
@@ -23,7 +23,6 @@
 use log::{info, warn};
 use microdroid_metadata::{write_metadata, Metadata};
 use openssl::sha::sha512;
-use rand::Fill;
 use rustutils::system_properties;
 use std::fs::OpenOptions;
 use std::path::Path;
@@ -168,21 +167,7 @@
     // verified is consistent with the root hash) or because we have the saved APK data which will
     // be checked as identical to the data we have verified.
 
-    let salt = if cfg!(llpvm_changes) || is_strict_boot() {
-        // Salt is obsolete with llpvm_changes.
-        vec![0u8; 64]
-    } else if let Some(saved_data) = saved_data {
-        // Use the salt from a verified instance.
-        saved_data.salt.clone()
-    } else {
-        // Generate a salt for a new instance.
-        let mut salt = vec![0u8; 64];
-        salt.as_mut_slice().try_fill(&mut rand::thread_rng())?;
-        salt
-    };
-
     Ok(MicrodroidData {
-        salt,
         apk_data: main_apk_data,
         extra_apks_data,
         apex_data: apex_data_from_payload,
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index 23755cf..51f7802 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -32,7 +32,7 @@
         "libuuid_nostd",
         "libvirtio_drivers",
         "libvmbase",
-        "libzerocopy-0.7.35_nostd",
+        "libzerocopy_nostd",
         "libzeroize_nostd",
     ],
 }
@@ -77,7 +77,7 @@
         "liblibfdt",
         "liblog_rust",
         "libpvmfw_fdt_template",
-        "libzerocopy-0.7.35",
+        "libzerocopy",
     ],
     data: [
         ":test_pvmfw_devices_vm_dtbo",
@@ -119,7 +119,7 @@
         "libdiced_open_dice_nostd",
         "libpvmfw_avb_nostd",
         "libdiced_sample_inputs_nostd",
-        "libzerocopy-0.7.35_nostd",
+        "libzerocopy_nostd",
         "libhex",
     ],
     static_libs: ["libopen_dice_clear_memory"],
diff --git a/guest/pvmfw/src/config.rs b/guest/pvmfw/src/config.rs
index 5a3d138..dbfde15 100644
--- a/guest/pvmfw/src/config.rs
+++ b/guest/pvmfw/src/config.rs
@@ -22,11 +22,14 @@
 use log::{info, warn};
 use static_assertions::const_assert_eq;
 use vmbase::util::RangeExt;
-use zerocopy::{FromBytes, FromZeroes};
+use zerocopy::FromBytes;
+use zerocopy::Immutable;
+use zerocopy::KnownLayout;
+use zerocopy::Ref;
 
 /// Configuration data header.
 #[repr(C, packed)]
-#[derive(Clone, Copy, Debug, FromZeroes, FromBytes)]
+#[derive(Clone, Copy, Debug, FromBytes, Immutable, KnownLayout)]
 struct Header {
     /// Magic number; must be `Header::MAGIC`.
     magic: u32,
@@ -145,14 +148,14 @@
 }
 
 #[repr(packed)]
-#[derive(Clone, Copy, Debug, FromZeroes, FromBytes)]
+#[derive(Clone, Copy, Debug, FromBytes, Immutable, KnownLayout)]
 struct HeaderEntry {
     offset: u32,
     size: u32,
 }
 
 #[repr(C, packed)]
-#[derive(Clone, Copy, Debug, Eq, FromZeroes, FromBytes, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, FromBytes, Immutable, KnownLayout, PartialEq)]
 pub struct Version {
     minor: u16,
     major: u16,
@@ -209,8 +212,8 @@
         }
 
         let (header, rest) =
-            zerocopy::Ref::<_, Header>::new_from_prefix(bytes).ok_or(Error::HeaderMisaligned)?;
-        let header = header.into_ref();
+            Ref::<_, Header>::new_from_prefix(bytes).ok_or(Error::HeaderMisaligned)?;
+        let header = Ref::into_ref(header);
 
         if header.magic != Header::MAGIC {
             return Err(Error::InvalidMagic);
diff --git a/guest/pvmfw/src/dice.rs b/guest/pvmfw/src/dice.rs
index 6694881..a72c1fc 100644
--- a/guest/pvmfw/src/dice.rs
+++ b/guest/pvmfw/src/dice.rs
@@ -24,7 +24,9 @@
     bcc_handover_main_flow, hash, Config, DiceContext, DiceMode, Hash, InputValues, HIDDEN_SIZE,
 };
 use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
-use zerocopy::AsBytes;
+use zerocopy::Immutable;
+use zerocopy::IntoBytes;
+use zerocopy::KnownLayout;
 
 // pVM firmware (like other VM components) is expected to populate some fields in DICE
 // Configuration Descriptor. See dice_for_avf_guest.cddl
@@ -134,7 +136,7 @@
         // descriptor do not).
         // Since the hidden input has to be a fixed size, create it as a hash of the values we
         // want included.
-        #[derive(AsBytes)]
+        #[derive(Immutable, IntoBytes, KnownLayout)]
         #[repr(C, packed)]
         struct HiddenInput {
             rkp_vm_marker: bool,
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index bfbd2e6..4370675 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -50,7 +50,7 @@
 use vmbase::layout::{crosvm::MEM_START, MAX_VIRT_ADDR};
 use vmbase::memory::SIZE_4KB;
 use vmbase::util::RangeExt as _;
-use zerocopy::AsBytes as _;
+use zerocopy::IntoBytes as _;
 
 // SAFETY: The template DT is automatically generated through DTC, which should produce valid DTBs.
 const FDT_TEMPLATE: &Fdt = unsafe { Fdt::unchecked_from_slice(pvmfw_fdt_template::RAW) };
diff --git a/guest/pvmfw/src/gpt.rs b/guest/pvmfw/src/gpt.rs
index 71eb569..70b3cf8 100644
--- a/guest/pvmfw/src/gpt.rs
+++ b/guest/pvmfw/src/gpt.rs
@@ -26,7 +26,6 @@
 use vmbase::util::ceiling_div;
 use vmbase::virtio::{pci, HalImpl};
 use zerocopy::FromBytes;
-use zerocopy::FromZeroes;
 
 type VirtIOBlk = pci::VirtIOBlk<HalImpl>;
 
@@ -105,7 +104,7 @@
     fn new(mut device: VirtIOBlk) -> Result<Self> {
         let mut blk = [0; Self::LBA_SIZE];
         device.read_blocks(Header::LBA, &mut blk).map_err(Error::FailedRead)?;
-        let header = Header::read_from_prefix(blk.as_slice()).unwrap();
+        let header = Header::read_from_prefix(blk.as_slice()).unwrap().0;
         if !header.is_valid() {
             return Err(Error::InvalidHeader);
         }
@@ -157,7 +156,7 @@
 type Lba = u64;
 
 /// Structure as defined in release 2.10 of the UEFI Specification (5.3.2 GPT Header).
-#[derive(FromZeroes, FromBytes)]
+#[derive(FromBytes)]
 #[repr(C, packed)]
 struct Header {
     signature: u64,
diff --git a/guest/pvmfw/src/instance.rs b/guest/pvmfw/src/instance.rs
index 0ef57dc..bb07f74 100644
--- a/guest/pvmfw/src/instance.rs
+++ b/guest/pvmfw/src/instance.rs
@@ -30,9 +30,10 @@
 use vmbase::util::ceiling_div;
 use vmbase::virtio::pci::{PciTransportIterator, VirtIOBlk};
 use vmbase::virtio::HalImpl;
-use zerocopy::AsBytes;
 use zerocopy::FromBytes;
-use zerocopy::FromZeroes;
+use zerocopy::Immutable;
+use zerocopy::IntoBytes;
+use zerocopy::KnownLayout;
 
 pub enum Error {
     /// Unexpected I/O error while accessing the underlying disk.
@@ -154,7 +155,7 @@
     Ok(())
 }
 
-#[derive(FromZeroes, FromBytes)]
+#[derive(Clone, Debug, FromBytes, Immutable, KnownLayout)]
 #[repr(C, packed)]
 struct Header {
     magic: [u8; Header::MAGIC.len()],
@@ -208,7 +209,7 @@
     let header_index = indices.next().ok_or(Error::MissingInstanceImageHeader)?;
     partition.read_block(header_index, &mut blk).map_err(Error::FailedIo)?;
     // The instance.img header is only used for discovery/validation.
-    let header = Header::read_from_prefix(blk.as_slice()).unwrap();
+    let header = Header::read_from_prefix(blk.as_slice()).unwrap().0;
     if !header.is_valid() {
         return Err(Error::InvalidInstanceImageHeader);
     }
@@ -216,7 +217,7 @@
     while let Some(header_index) = indices.next() {
         partition.read_block(header_index, &mut blk).map_err(Error::FailedIo)?;
 
-        let header = EntryHeader::read_from_prefix(blk.as_slice()).unwrap();
+        let header = EntryHeader::read_from_prefix(blk.as_slice()).unwrap().0;
         match (header.uuid(), header.payload_size()) {
             (uuid, _) if uuid.is_nil() => return Ok(PvmfwEntry::New { header_index }),
             (PvmfwEntry::UUID, payload_size) => {
@@ -238,7 +239,7 @@
 /// Marks the start of an instance.img entry.
 ///
 /// Note: Virtualization/guest/microdroid_manager/src/instance.rs uses the name "partition".
-#[derive(AsBytes, FromZeroes, FromBytes)]
+#[derive(Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
 #[repr(C, packed)]
 struct EntryHeader {
     uuid: u128,
@@ -259,7 +260,7 @@
     }
 }
 
-#[derive(AsBytes, FromZeroes, FromBytes)]
+#[derive(Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
 #[repr(C)]
 pub(crate) struct EntryBody {
     pub code_hash: Hash,
diff --git a/guest/trusty/security_vm/launcher/src/main.rs b/guest/trusty/security_vm/launcher/src/main.rs
index f0af9b6..62febf4 100644
--- a/guest/trusty/security_vm/launcher/src/main.rs
+++ b/guest/trusty/security_vm/launcher/src/main.rs
@@ -32,6 +32,10 @@
     #[arg(long)]
     kernel: PathBuf,
 
+    // Whether the kernel should be loaded as a bootloader
+    #[arg(long)]
+    load_kernel_as_bootloader: bool,
+
     /// Whether the VM is protected or not.
     #[arg(long)]
     protected: bool,
@@ -70,10 +74,16 @@
 
     let kernel =
         File::open(&args.kernel).with_context(|| format!("Failed to open {:?}", &args.kernel))?;
+    let kernel = ParcelFileDescriptor::new(kernel);
+
+    // If --load-kernel-as-bootloader option is present, then load kernel as bootloader
+    let (kernel, bootloader) =
+        if args.load_kernel_as_bootloader { (None, Some(kernel)) } else { (Some(kernel), None) };
 
     let vm_config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
         name: args.name.to_owned(),
-        kernel: Some(ParcelFileDescriptor::new(kernel)),
+        kernel,
+        bootloader,
         protectedVm: args.protected,
         memoryMib: args.memory_size_mib,
         cpuTopology: args.cpu_topology,
diff --git a/libs/devicemapper/Android.bp b/libs/devicemapper/Android.bp
index 17727f1..5332469 100644
--- a/libs/devicemapper/Android.bp
+++ b/libs/devicemapper/Android.bp
@@ -16,7 +16,7 @@
         "libhex",
         "libnix",
         "libuuid",
-        "libzerocopy-0.7.35",
+        "libzerocopy",
     ],
     multilib: {
         lib32: {
diff --git a/libs/devicemapper/src/crypt.rs b/libs/devicemapper/src/crypt.rs
index 3afd374..75417ed 100644
--- a/libs/devicemapper/src/crypt.rs
+++ b/libs/devicemapper/src/crypt.rs
@@ -23,7 +23,7 @@
 use std::io::Write;
 use std::mem::size_of;
 use std::path::Path;
-use zerocopy::AsBytes;
+use zerocopy::IntoBytes;
 
 const SECTOR_SIZE: u64 = 512;
 
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index 5656743..a8f3049 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -37,8 +37,9 @@
 use std::mem::size_of;
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
-use zerocopy::AsBytes;
-use zerocopy::FromZeroes;
+use zerocopy::FromZeros;
+use zerocopy::Immutable;
+use zerocopy::IntoBytes;
 
 /// Exposes DmCryptTarget & related builder
 pub mod crypt;
@@ -88,7 +89,7 @@
 // `DmTargetSpec` is the header of the data structure for a device-mapper target. When doing the
 // ioctl, one of more `DmTargetSpec` (and its body) are appened to the `DmIoctl` struct.
 #[repr(C)]
-#[derive(Copy, Clone, AsBytes, FromZeroes)]
+#[derive(Copy, Clone, Immutable, IntoBytes, FromZeros)]
 struct DmTargetSpec {
     sector_start: u64,
     length: u64, // number of 512 sectors
diff --git a/libs/devicemapper/src/loopdevice.rs b/libs/devicemapper/src/loopdevice.rs
index 9dc722b..113a946 100644
--- a/libs/devicemapper/src/loopdevice.rs
+++ b/libs/devicemapper/src/loopdevice.rs
@@ -32,7 +32,7 @@
 use std::path::{Path, PathBuf};
 use std::thread;
 use std::time::{Duration, Instant};
-use zerocopy::FromZeroes;
+use zerocopy::FromZeros;
 
 use crate::loopdevice::sys::*;
 
@@ -184,7 +184,7 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /*direct_io*/ true, /*writable*/ false).unwrap();
+        let dev = attach(a_file, 0, a_size, /* direct_io */ true, /* writable */ false).unwrap();
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
@@ -197,7 +197,7 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /*direct_io*/ false, /*writable*/ false).unwrap();
+        let dev = attach(a_file, 0, a_size, /* direct_io */ false, /* writable */ false).unwrap();
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
@@ -210,7 +210,7 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /*direct_io*/ true, /*writable*/ true).unwrap();
+        let dev = attach(a_file, 0, a_size, /* direct_io */ true, /* writable */ true).unwrap();
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
diff --git a/libs/devicemapper/src/loopdevice/sys.rs b/libs/devicemapper/src/loopdevice/sys.rs
index ce4ef61..47d2c08 100644
--- a/libs/devicemapper/src/loopdevice/sys.rs
+++ b/libs/devicemapper/src/loopdevice/sys.rs
@@ -15,7 +15,7 @@
  */
 
 use bitflags::bitflags;
-use zerocopy::FromZeroes;
+use zerocopy::FromZeros;
 
 // This UAPI is copied and converted from include/uapi/linux/loop.h Note that this module doesn't
 // implement all the features introduced in loop(4). Only the features that are required to support
@@ -28,7 +28,7 @@
 pub const LOOP_CLR_FD: libc::c_ulong = 0x4C01;
 
 #[repr(C)]
-#[derive(Copy, Clone, FromZeroes)]
+#[derive(Copy, Clone, FromZeros)]
 pub struct loop_config {
     pub fd: u32,
     pub block_size: u32,
@@ -37,7 +37,7 @@
 }
 
 #[repr(C)]
-#[derive(Copy, Clone, FromZeroes)]
+#[derive(Copy, Clone, FromZeros)]
 pub struct loop_info64 {
     pub lo_device: u64,
     pub lo_inode: u64,
@@ -55,7 +55,7 @@
 }
 
 #[repr(transparent)]
-#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromZeroes)]
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromZeros)]
 pub struct Flag(u32);
 
 bitflags! {
diff --git a/libs/devicemapper/src/sys.rs b/libs/devicemapper/src/sys.rs
index bd1e165..bbf7e45 100644
--- a/libs/devicemapper/src/sys.rs
+++ b/libs/devicemapper/src/sys.rs
@@ -15,8 +15,9 @@
  */
 
 use bitflags::bitflags;
-use zerocopy::AsBytes;
-use zerocopy::FromZeroes;
+use zerocopy::FromZeros;
+use zerocopy::Immutable;
+use zerocopy::IntoBytes;
 
 // UAPI for device mapper can be found at include/uapi/linux/dm-ioctl.h
 
@@ -45,7 +46,7 @@
 }
 
 #[repr(C)]
-#[derive(Copy, Clone, AsBytes, FromZeroes)]
+#[derive(Copy, Clone, Immutable, IntoBytes, FromZeros)]
 pub struct DmIoctl {
     pub version: [u32; 3],
     pub data_size: u32,
@@ -70,7 +71,9 @@
 pub const DM_MAX_TYPE_NAME: usize = 16;
 
 #[repr(transparent)]
-#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, AsBytes, FromZeroes)]
+#[derive(
+    Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Immutable, IntoBytes, FromZeros,
+)]
 pub struct Flag(u32);
 
 bitflags! {
diff --git a/libs/devicemapper/src/verity.rs b/libs/devicemapper/src/verity.rs
index eb342a8..09087da 100644
--- a/libs/devicemapper/src/verity.rs
+++ b/libs/devicemapper/src/verity.rs
@@ -22,7 +22,7 @@
 use std::io::Write;
 use std::mem::size_of;
 use std::path::Path;
-use zerocopy::AsBytes;
+use zerocopy::IntoBytes;
 
 use crate::DmTargetSpec;
 
diff --git a/libs/framework-virtualization/Android.bp b/libs/framework-virtualization/Android.bp
index d5ac878..98fa53d 100644
--- a/libs/framework-virtualization/Android.bp
+++ b/libs/framework-virtualization/Android.bp
@@ -15,6 +15,7 @@
     ],
     static_libs: [
         "android.system.virtualizationservice-java",
+        "avf_aconfig_flags_java",
         // For android.sysprop.HypervisorProperties
         "PlatformProperties",
     ],
@@ -51,6 +52,9 @@
             "FlaggedApi",
         ],
     },
+    aconfig_declarations: [
+        "avf_aconfig_flags",
+    ],
 }
 
 gensrcs {
diff --git a/libs/framework-virtualization/api/system-current.txt b/libs/framework-virtualization/api/system-current.txt
index d9bafa1..233491f 100644
--- a/libs/framework-virtualization/api/system-current.txt
+++ b/libs/framework-virtualization/api/system-current.txt
@@ -66,6 +66,7 @@
     method public boolean isEncryptedStorageEnabled();
     method public boolean isProtectedVm();
     method public boolean isVmOutputCaptured();
+    method @FlaggedApi("com.android.system.virtualmachine.flags.promote_set_should_use_hugepages_to_system_api") public boolean shouldUseHugepages();
     field public static final int CPU_TOPOLOGY_MATCH_HOST = 1; // 0x1
     field public static final int CPU_TOPOLOGY_ONE_CPU = 0; // 0x0
     field public static final int DEBUG_LEVEL_FULL = 1; // 0x1
@@ -82,6 +83,7 @@
     method @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setMemoryBytes(@IntRange(from=1) long);
     method @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setPayloadBinaryName(@NonNull String);
     method @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setProtectedVm(boolean);
+    method @FlaggedApi("com.android.system.virtualmachine.flags.promote_set_should_use_hugepages_to_system_api") @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setShouldUseHugepages(boolean);
     method @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setVmOutputCaptured(boolean);
   }
 
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index 4508573..d6b38ea 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -22,6 +22,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -49,6 +50,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.system.virtualmachine.flags.Flags;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -601,6 +604,18 @@
     }
 
     /**
+     * Returns whether this VM enabled the hint to use transparent huge pages.
+     *
+     * @see Builder#setShouldUseHugepages
+     * @hide
+     */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_PROMOTE_SET_SHOULD_USE_HUGEPAGES_TO_SYSTEM_API)
+    public boolean shouldUseHugepages() {
+        return mShouldUseHugepages;
+    }
+
+    /**
      * Tests if this config is compatible with other config. Being compatible means that the configs
      * can be interchangeably used for the same virtual machine; they do not change the VM identity
      * or secrets. Such changes include varying the number of CPUs or the size of the RAM. Changes
@@ -1364,7 +1379,26 @@
             return this;
         }
 
-        /** @hide */
+        /**
+         * Hints whether the VM should make use of the transparent huge pages feature.
+         *
+         * <p>Note: this API just provides a hint, whether the VM will actually use transparent huge
+         * pages additionally depends on the following:
+         *
+         * <ul>
+         *   <li>{@code /sys/kernel/mm/transparent_hugepages/shmem_enabled} should be configured
+         *       with the value {@code 'advise'}.
+         *   <li>Android host kernel version should be at least {@code android15-5.15}
+         * </ul>
+         *
+         * @see https://docs.kernel.org/admin-guide/mm/transhuge.html
+         * @see
+         *     https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/docs/hugepages.md
+         * @hide
+         */
+        @SystemApi
+        @FlaggedApi(Flags.FLAG_PROMOTE_SET_SHOULD_USE_HUGEPAGES_TO_SYSTEM_API)
+        @NonNull
         public Builder setShouldUseHugepages(boolean shouldUseHugepages) {
             mShouldUseHugepages = shouldUseHugepages;
             return this;
diff --git a/libs/libavf/include/android/virtualization.h b/libs/libavf/include/android/virtualization.h
index 85bf3a2..7ab7431 100644
--- a/libs/libavf/include/android/virtualization.h
+++ b/libs/libavf/include/android/virtualization.h
@@ -323,6 +323,19 @@
 int AVirtualMachine_stop(AVirtualMachine* _Nonnull vm) __INTRODUCED_IN(36);
 
 /**
+ * Open a vsock connection to the VM on the given port. The caller takes ownership of the returned
+ * file descriptor, and is responsible for closing the file descriptor.
+ *
+ * This operation is synchronous and `AVirtualMachine_connectVsock` may block.
+ *
+ * \param vm a handle on a virtual machine.
+ * \param port a vsock port number.
+ *
+ * \return If successful, it returns a valid file descriptor. Otherwise, it returns `-EIO`.
+ */
+int AVirtualMachine_connectVsock(AVirtualMachine* _Nonnull vm, uint32_t port) __INTRODUCED_IN(36);
+
+/**
  * Wait until a virtual machine stops or the given timeout elapses.
  *
  * \param vm a handle on a virtual machine.
diff --git a/libs/libavf/libavf.map.txt b/libs/libavf/libavf.map.txt
index f476566..efc368a 100644
--- a/libs/libavf/libavf.map.txt
+++ b/libs/libavf/libavf.map.txt
@@ -16,6 +16,7 @@
     AVirtualMachine_createRaw; # apex llndk
     AVirtualMachine_start; # apex llndk
     AVirtualMachine_stop; # apex llndk
+    AVirtualMachine_connectVsock; # apex llndk
     AVirtualMachine_waitForStop; # apex llndk
     AVirtualMachine_destroy; # apex llndk
   local:
diff --git a/libs/libavf/src/lib.rs b/libs/libavf/src/lib.rs
index 5988fae..56cdfb7 100644
--- a/libs/libavf/src/lib.rs
+++ b/libs/libavf/src/lib.rs
@@ -16,7 +16,7 @@
 
 use std::ffi::CStr;
 use std::fs::File;
-use std::os::fd::FromRawFd;
+use std::os::fd::{FromRawFd, IntoRawFd};
 use std::os::raw::{c_char, c_int};
 use std::ptr;
 use std::time::Duration;
@@ -353,6 +353,21 @@
     }
 }
 
+/// Open a vsock connection to the CID of the virtual machine on the given vsock port.
+///
+/// # Safety
+/// `vm` must be a pointer returned by `AVirtualMachine_create`.
+#[no_mangle]
+pub unsafe extern "C" fn AVirtualMachine_connectVsock(vm: *const VmInstance, port: u32) -> c_int {
+    // SAFETY: `vm` is assumed to be a valid, non-null pointer returned by
+    // `AVirtualMachine_createRaw`. It's the only reference to the object.
+    let vm = unsafe { &*vm };
+    match vm.connect_vsock(port) {
+        Ok(pfd) => pfd.into_raw_fd(),
+        Err(_) => -libc::EIO,
+    }
+}
+
 fn death_reason_to_stop_reason(death_reason: DeathReason) -> AVirtualMachineStopReason {
     match death_reason {
         DeathReason::VirtualizationServiceDied => {
diff --git a/libs/libfdt/Android.bp b/libs/libfdt/Android.bp
index 1e24ff4..09f288d 100644
--- a/libs/libfdt/Android.bp
+++ b/libs/libfdt/Android.bp
@@ -38,7 +38,7 @@
         "libcstr",
         "liblibfdt_bindgen",
         "libstatic_assertions",
-        "libzerocopy-0.7.35_nostd",
+        "libzerocopy_nostd",
     ],
 }
 
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 5883567..c969749 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -33,7 +33,7 @@
 use core::ops::Range;
 use cstr::cstr;
 use libfdt::get_slice_at_ptr;
-use zerocopy::AsBytes as _;
+use zerocopy::IntoBytes as _;
 
 use crate::libfdt::{Libfdt, LibfdtMut};
 
diff --git a/libs/libfdt/src/safe_types.rs b/libs/libfdt/src/safe_types.rs
index 03b5bc2..0e79a42 100644
--- a/libs/libfdt/src/safe_types.rs
+++ b/libs/libfdt/src/safe_types.rs
@@ -21,7 +21,7 @@
 use crate::{FdtError, Result};
 
 use zerocopy::byteorder::big_endian;
-use zerocopy::{FromBytes, FromZeroes};
+use zerocopy::FromBytes;
 
 macro_rules! assert_offset_eq {
     // TODO(const_feature(assert_eq)): assert_eq!()
@@ -32,7 +32,7 @@
 
 /// Thin wrapper around `libfdt_bindgen::fdt_header` for transparent endianness handling.
 #[repr(C)]
-#[derive(Debug, FromZeroes, FromBytes)]
+#[derive(Debug, FromBytes)]
 pub struct FdtHeader {
     /// magic word FDT_MAGIC
     pub magic: big_endian::U32,
diff --git a/libs/libvmbase/Android.bp b/libs/libvmbase/Android.bp
index 7bcdc1d..3088633 100644
--- a/libs/libvmbase/Android.bp
+++ b/libs/libvmbase/Android.bp
@@ -91,7 +91,7 @@
         "libtinyvec_nostd",
         "libuuid_nostd",
         "libvirtio_drivers",
-        "libzerocopy-0.7.35_nostd",
+        "libzerocopy_nostd",
         "libzeroize_nostd",
     ],
     whole_static_libs: [
diff --git a/libs/libvmbase/src/rand.rs b/libs/libvmbase/src/rand.rs
index b31bd4b..16c7b6a 100644
--- a/libs/libvmbase/src/rand.rs
+++ b/libs/libvmbase/src/rand.rs
@@ -18,7 +18,7 @@
 use core::fmt;
 use core::mem::size_of;
 use smccc::{self, Hvc};
-use zerocopy::AsBytes as _;
+use zerocopy::IntoBytes as _;
 
 type Entropy = [u8; size_of::<u64>() * 3];
 
diff --git a/libs/libvmclient/src/lib.rs b/libs/libvmclient/src/lib.rs
index c0baea5..8dd3cd3 100644
--- a/libs/libvmclient/src/lib.rs
+++ b/libs/libvmclient/src/lib.rs
@@ -312,6 +312,11 @@
             }
         })
     }
+
+    /// Opens a vsock connection to the CID of the VM on the given vsock port.
+    pub fn connect_vsock(&self, port: u32) -> BinderResult<ParcelFileDescriptor> {
+        self.vm.connectVsock(port as i32)
+    }
 }
 
 impl Debug for VmInstance {
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 e2ee381..109c5e0 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -48,6 +48,7 @@
 import com.android.microdroid.test.device.MicrodroidDeviceTestBase;
 import com.android.microdroid.testservice.IBenchmarkService;
 import com.android.microdroid.testservice.ITestService;
+import com.android.virt.vm_attestation.testservice.IAttestationService;
 
 import org.junit.After;
 import org.junit.Before;
@@ -74,6 +75,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.OptionalLong;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 
@@ -81,6 +83,7 @@
 public class MicrodroidBenchmarks extends MicrodroidDeviceTestBase {
     private static final String TAG = "MicrodroidBenchmarks";
     private static final String METRIC_NAME_PREFIX = getMetricPrefix() + "microdroid/";
+    private static final String VM_ATTESTATION_PAYLOAD = "libvm_attestation_test_payload.so";
     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;
@@ -872,4 +875,56 @@
         }
         reportMetrics(vmKillTime, "vm_kill_time", "microsecond");
     }
+
+    @Test
+    public void requestAttestationTime() throws Exception {
+        assume().withMessage("Remote attestation is only supported on protected VM")
+                .that(mProtectedVm)
+                .isTrue();
+        assume().withMessage("Test needs Remote Attestation support")
+                .that(getVirtualMachineManager().isRemoteAttestationSupported())
+                .isTrue();
+
+        VirtualMachineConfig.Builder builder =
+                newVmConfigBuilderWithPayloadBinary(VM_ATTESTATION_PAYLOAD)
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .setVmOutputCaptured(true);
+        VirtualMachineConfig config = builder.build();
+
+        List<Double> requestAttestationTime = new ArrayList<>(TEST_TRIAL_COUNT);
+
+        for (int i = 0; i < TEST_TRIAL_COUNT; ++i) {
+            VirtualMachine vm = forceCreateNewVirtualMachine("attestation_client", config);
+
+            vm.enableTestAttestation();
+            CompletableFuture<Exception> exception = new CompletableFuture<>();
+            CompletableFuture<Boolean> payloadReady = new CompletableFuture<>();
+            VmEventListener listener =
+                    new VmEventListener() {
+                        @Override
+                        public void onPayloadReady(VirtualMachine vm) {
+                            payloadReady.complete(true);
+                            try {
+                                IAttestationService service =
+                                        IAttestationService.Stub.asInterface(
+                                                vm.connectToVsockServer(IAttestationService.PORT));
+                                long start = System.nanoTime();
+                                service.requestAttestationForTesting();
+                                requestAttestationTime.add(
+                                        (double) (System.nanoTime() - start) / NANO_TO_MICRO);
+                                service.validateAttestationResult();
+                            } catch (Exception e) {
+                                exception.complete(e);
+                            } finally {
+                                forceStop(vm);
+                            }
+                        }
+                    };
+
+            listener.runToFinish(TAG, vm);
+            assertThat(payloadReady.getNow(false)).isTrue();
+            assertThat(exception.getNow(null)).isNull();
+        }
+        reportMetrics(requestAttestationTime, "request_attestation_time", "microsecond");
+    }
 }
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 01af51c..cb374a5 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -16,9 +16,11 @@
 java_defaults {
     name: "MicrodroidTestAppsDefaults",
     static_libs: [
+        "avf_aconfig_flags_java",
         "com.android.microdroid.testservice-java",
         "com.android.microdroid.test.vmshare_service-java",
         "com.android.virt.vm_attestation.testservice-java",
+        "platform-test-annotations",
     ],
     certificate: ":MicrodroidTestAppCert",
     sdk_version: "test_current",
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 97a5e78..e69b8f6 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -25,6 +25,8 @@
 import static android.system.virtualmachine.VirtualMachineManager.CAPABILITY_NON_PROTECTED_VM;
 import static android.system.virtualmachine.VirtualMachineManager.CAPABILITY_PROTECTED_VM;
 
+import static com.android.system.virtualmachine.flags.Flags.promoteSetShouldUseHugepagesToSystemApi;
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 import static com.google.common.truth.TruthJUnit.assume;
@@ -52,6 +54,7 @@
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
 import android.os.SystemProperties;
+import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.system.OsConstants;
 import android.system.virtualmachine.VirtualMachine;
 import android.system.virtualmachine.VirtualMachineCallback;
@@ -69,6 +72,7 @@
 import com.android.microdroid.testservice.IAppCallback;
 import com.android.microdroid.testservice.ITestService;
 import com.android.microdroid.testservice.IVmCallback;
+import com.android.system.virtualmachine.flags.Flags;
 import com.android.virt.vm_attestation.testservice.IAttestationService.AttestationStatus;
 import com.android.virt.vm_attestation.testservice.IAttestationService.SigningResult;
 import com.android.virt.vm_attestation.util.X509Utils;
@@ -175,15 +179,19 @@
 
     private static final String VM_SHARE_APP_PACKAGE_NAME = "com.android.microdroid.vmshare_app";
 
-    private void createAndConnectToVmHelper(int cpuTopology) throws Exception {
+    private void createAndConnectToVmHelper(int cpuTopology, boolean shouldUseHugepages)
+            throws Exception {
         assumeSupportedDevice();
 
-        VirtualMachineConfig config =
+        VirtualMachineConfig.Builder builder =
                 newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
                         .setMemoryBytes(minMemoryRequired())
                         .setDebugLevel(DEBUG_LEVEL_FULL)
-                        .setCpuTopology(cpuTopology)
-                        .build();
+                        .setCpuTopology(cpuTopology);
+        if (promoteSetShouldUseHugepagesToSystemApi()) {
+            builder.setShouldUseHugepages(shouldUseHugepages);
+        }
+        VirtualMachineConfig config = builder.build();
         VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
 
         TestResults testResults =
@@ -210,13 +218,33 @@
     @Test
     @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
     public void createAndConnectToVm() throws Exception {
-        createAndConnectToVmHelper(CPU_TOPOLOGY_ONE_CPU);
+        createAndConnectToVmHelper(CPU_TOPOLOGY_ONE_CPU, /* shouldUseHugepages= */ false);
     }
 
     @Test
     @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
     public void createAndConnectToVm_HostCpuTopology() throws Exception {
-        createAndConnectToVmHelper(CPU_TOPOLOGY_MATCH_HOST);
+        createAndConnectToVmHelper(CPU_TOPOLOGY_MATCH_HOST, /* shouldUseHugepages= */ false);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_PROMOTE_SET_SHOULD_USE_HUGEPAGES_TO_SYSTEM_API)
+    public void createAndConnectToVm_WithHugepages() throws Exception {
+        // Note: setting shouldUseHugepages to true only hints that VM wants to use transparent huge
+        // pages. Whether it will actually be used depends on the value in the
+        // /sys/kernel/mm/transparent_hugepages/shmem_enabled.
+        // See packages/modules/Virtualization/docs/hugepages.md
+        createAndConnectToVmHelper(CPU_TOPOLOGY_ONE_CPU, /* shouldUseHugepages= */ true);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_PROMOTE_SET_SHOULD_USE_HUGEPAGES_TO_SYSTEM_API)
+    public void createAndConnectToVm_HostCpuTopology_WithHugepages() throws Exception {
+        // Note: setting shouldUseHugepages to true only hints that VM wants to use transparent huge
+        // pages. Whether it will actually be used depends on the value in the
+        // /sys/kernel/mm/transparent_hugepages/shmem_enabled.
+        // See packages/modules/Virtualization/docs/hugepages.md
+        createAndConnectToVmHelper(CPU_TOPOLOGY_MATCH_HOST, /* shouldUseHugepages= */ true);
     }
 
     @Test
@@ -579,6 +607,9 @@
         assertThat(minimal.getEncryptedStorageBytes()).isEqualTo(0);
         assertThat(minimal.isVmOutputCaptured()).isFalse();
         assertThat(minimal.getOs()).isEqualTo("microdroid");
+        if (promoteSetShouldUseHugepagesToSystemApi()) {
+            assertThat(minimal.shouldUseHugepages()).isFalse();
+        }
 
         // Maximal has everything that can be set to some non-default value. (And has different
         // values than minimal for the required fields.)
@@ -595,6 +626,9 @@
                         .setEncryptedStorageBytes(1_000_000)
                         .setVmOutputCaptured(true)
                         .setOs("microdroid_gki-android14-6.1");
+        if (promoteSetShouldUseHugepagesToSystemApi()) {
+            maximalBuilder.setShouldUseHugepages(true);
+        }
         VirtualMachineConfig maximal = maximalBuilder.build();
 
         assertThat(maximal.getApkPath()).isEqualTo("/apk/path");
@@ -611,6 +645,9 @@
         assertThat(maximal.getEncryptedStorageBytes()).isEqualTo(1_000_000);
         assertThat(maximal.isVmOutputCaptured()).isTrue();
         assertThat(maximal.getOs()).isEqualTo("microdroid_gki-android14-6.1");
+        if (promoteSetShouldUseHugepagesToSystemApi()) {
+            assertThat(maximal.shouldUseHugepages()).isTrue();
+        }
 
         assertThat(minimal.isCompatibleWith(maximal)).isFalse();
         assertThat(minimal.isCompatibleWith(minimal)).isTrue();
@@ -680,6 +717,10 @@
         assertConfigCompatible(
                         baseline, newBaselineBuilder().setCpuTopology(CPU_TOPOLOGY_MATCH_HOST))
                 .isTrue();
+        if (promoteSetShouldUseHugepagesToSystemApi()) {
+            assertConfigCompatible(baseline, newBaselineBuilder().setShouldUseHugepages(true))
+                    .isTrue();
+        }
 
         // Changes that must be incompatible, since they must change the VM identity.
         assertConfigCompatible(baseline, newBaselineBuilder().addExtraApk("foo")).isFalse();