Merge "Don't clear logcat on test cleanup"
diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md
index 0e4f2be..9dcd4fa 100644
--- a/docs/getting_started/index.md
+++ b/docs/getting_started/index.md
@@ -103,9 +103,12 @@
 on pVM. You can run a Microdroid with empty payload using the following command:
 
 ```shell
-adb shell /apex/com.android.virt/bin/vm run-microdroid --debug full
+adb shell /apex/com.android.virt/bin/vm run-microdroid
 ```
 
+which spawns a "debuggable" VM by default to allow access to guest kernel logs.
+To run a production non-debuggable VM, pass `--debug none`.
+
 ## Building and updating CrosVM and VirtualizationService {#building-and-updating}
 
 You can update CrosVM and the VirtualizationService by updating the `com.android.virt` APEX instead
diff --git a/libs/avb/Android.bp b/libs/avb/Android.bp
index 3a671e2..a2d9e1a 100644
--- a/libs/avb/Android.bp
+++ b/libs/avb/Android.bp
@@ -10,7 +10,6 @@
     visibility: ["//packages/modules/Virtualization:__subpackages__"],
     source_stem: "bindings",
     bindgen_flags: [
-        "--size_t-is-usize",
         "--constified-enum-module AvbDescriptorTag",
         "--default-enum-style rust",
         "--allowlist-type=AvbDescriptorTag",
diff --git a/libs/libfdt/Android.bp b/libs/libfdt/Android.bp
index 2a6e75f..0540f26 100644
--- a/libs/libfdt/Android.bp
+++ b/libs/libfdt/Android.bp
@@ -8,7 +8,6 @@
     wrapper_src: "bindgen/fdt.h",
     source_stem: "bindings",
     bindgen_flags: [
-        "--size_t-is-usize",
         "--allowlist-type=fdt_.*",
         "--allowlist-function=fdt_.*",
         "--allowlist-var=FDT_.*",
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index c9909e6..bbe00b5 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -7,7 +7,6 @@
     crate_name: "pvmfw",
     defaults: ["vmbase_ffi_defaults"],
     srcs: ["src/main.rs"],
-    edition: "2021",
     // Require unsafe blocks for inside unsafe functions.
     flags: ["-Dunsafe_op_in_unsafe_fn"],
     features: [
@@ -16,7 +15,6 @@
     rustlibs: [
         "libaarch64_paging",
         "libbssl_ffi_nostd",
-        "libbuddy_system_allocator",
         "libciborium_nostd",
         "libciborium_io_nostd",
         "libdiced_open_dice_nostd",
@@ -83,7 +81,6 @@
     // partition image. This is just to package the unstripped file into the
     // symbols zip file for debugging purpose.
     installable: true,
-    native_coverage: false,
 }
 
 raw_binary {
@@ -135,11 +132,9 @@
 
 rust_library_rlib {
     name: "libpvmfw_embedded_key",
-    defaults: ["vmbase_ffi_defaults"],
-    prefer_rlib: true,
+    defaults: ["vmbase_rlib_defaults"],
     srcs: [":pvmfw_embedded_key_rs"],
     crate_name: "pvmfw_embedded_key",
-    apex_available: ["com.android.virt"],
 }
 
 prebuilt_etc {
@@ -193,8 +188,7 @@
 
 rust_library_rlib {
     name: "libpvmfw_fdt_template",
-    defaults: ["vmbase_ffi_defaults"],
-    prefer_rlib: true,
+    defaults: ["vmbase_rlib_defaults"],
     srcs: [":pvmfw_fdt_template_rs"],
     crate_name: "pvmfw_fdt_template",
 }
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index 78383d2..6f96fc0 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -15,10 +15,8 @@
 //! Low-level entry and exit points of pvmfw.
 
 use crate::config;
-use crate::configure_global_allocator_size;
 use crate::crypto;
 use crate::fdt;
-use crate::heap;
 use crate::memory;
 use core::arch::asm;
 use core::mem::{drop, size_of};
@@ -33,7 +31,7 @@
 use log::LevelFilter;
 use vmbase::util::RangeExt as _;
 use vmbase::{
-    console,
+    configure_heap, console,
     layout::{self, crosvm},
     logger, main,
     memory::{min_dcache_line_size, MemoryTracker, MEMORY, SIZE_128KB, SIZE_4KB},
@@ -63,7 +61,7 @@
 }
 
 main!(start);
-configure_global_allocator_size!(SIZE_128KB);
+configure_heap!(SIZE_128KB);
 
 /// Entry point for pVM firmware.
 pub fn start(fdt_address: u64, payload_start: u64, payload_size: u64, _arg3: u64) {
@@ -71,9 +69,6 @@
     // - can't access non-pvmfw memory (only statically-mapped memory)
     // - can't access MMIO (therefore, no logging)
 
-    // SAFETY - This function should and will only be called once, here.
-    unsafe { heap::init() };
-
     match main_wrapper(fdt_address as usize, payload_start as usize, payload_size as usize) {
         Ok((entry, bcc)) => jump_to_payload(fdt_address, entry.try_into().unwrap(), bcc),
         Err(_) => reboot(), // TODO(b/220071963) propagate the reason back to the host.
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 8c5d5d5..61e2312 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -28,7 +28,6 @@
 mod exceptions;
 mod fdt;
 mod gpt;
-mod heap;
 mod helpers;
 mod instance;
 mod memory;
@@ -49,6 +48,7 @@
 use pvmfw_avb::Capability;
 use pvmfw_avb::DebugLevel;
 use pvmfw_embedded_key::PUBLIC_KEY;
+use vmbase::heap;
 use vmbase::memory::flush;
 use vmbase::memory::MEMORY;
 use vmbase::virtio::pci;
@@ -104,6 +104,11 @@
         error!("Failed to verify the payload: {e}");
         RebootReason::PayloadVerificationError
     })?;
+    let debuggable = verified_boot_data.debug_level != DebugLevel::None;
+    if debuggable {
+        info!("Successfully verified a debuggable payload.");
+        info!("Please disregard any previous libavb ERROR about initrd_normal.");
+    }
 
     if verified_boot_data.capabilities.contains(&Capability::RemoteAttest) {
         info!("Service VM capable of remote attestation detected");
@@ -146,7 +151,6 @@
     flush(next_bcc);
 
     let strict_boot = true;
-    let debuggable = verified_boot_data.debug_level != DebugLevel::None;
     modify_for_next_stage(fdt, next_bcc, new_instance, strict_boot, debug_policy, debuggable)
         .map_err(|e| {
             error!("Failed to configure device tree: {e}");
diff --git a/rialto/Android.bp b/rialto/Android.bp
index 59f8ba2..9aa4667 100644
--- a/rialto/Android.bp
+++ b/rialto/Android.bp
@@ -6,18 +6,15 @@
     name: "librialto",
     crate_name: "rialto",
     srcs: ["src/main.rs"],
-    edition: "2021",
     defaults: ["vmbase_ffi_defaults"],
     rustlibs: [
         "libaarch64_paging",
-        "libbuddy_system_allocator",
         "libhyp",
         "libfdtpci",
         "liblibfdt",
         "liblog_rust_nostd",
         "libvmbase",
     ],
-    apex_available: ["com.android.virt"],
 }
 
 cc_binary {
@@ -29,13 +26,11 @@
     ],
     static_libs: [
         "librialto",
-        "libvmbase_entry",
     ],
     linker_scripts: [
         "image.ld",
         ":vmbase_sections",
     ],
-    apex_available: ["com.android.virt"],
 }
 
 raw_binary {
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 29056f1..ce83624 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -23,7 +23,6 @@
 extern crate alloc;
 
 use crate::error::{Error, Result};
-use buddy_system_allocator::LockedHeap;
 use core::num::NonZeroUsize;
 use core::result;
 use core::slice;
@@ -32,28 +31,14 @@
 use libfdt::FdtError;
 use log::{debug, error, info};
 use vmbase::{
+    configure_heap,
     fdt::SwiotlbInfo,
     layout::{self, crosvm},
     main,
-    memory::{MemoryTracker, PageTable, MEMORY, PAGE_SIZE},
+    memory::{MemoryTracker, PageTable, MEMORY, PAGE_SIZE, SIZE_64KB},
     power::reboot,
 };
 
-const SZ_1K: usize = 1024;
-const SZ_64K: usize = 64 * SZ_1K;
-
-#[global_allocator]
-static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
-
-static mut HEAP: [u8; SZ_64K] = [0; SZ_64K];
-
-fn init_heap() {
-    // SAFETY: Allocator set to otherwise unused, static memory.
-    unsafe {
-        HEAP_ALLOCATOR.lock().init(&mut HEAP as *mut u8 as usize, HEAP.len());
-    }
-}
-
 fn new_page_table() -> Result<PageTable> {
     let mut page_table = PageTable::default();
 
@@ -163,7 +148,6 @@
 
 /// Entry point for Rialto.
 pub fn main(fdt_addr: u64, _a1: u64, _a2: u64, _a3: u64) {
-    init_heap();
     let Ok(mmio_guard_supported) = try_init_logger() else {
         // Don't log anything if the logger initialization fails.
         reboot();
@@ -181,3 +165,4 @@
 }
 
 main!(main);
+configure_heap!(SIZE_64KB);
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 663fa25..392fa1c 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -315,8 +315,13 @@
         .context("Failed to create VM")?;
     vm.start().context("Failed to start VM")?;
 
+    let debug_level = match config {
+        VirtualMachineConfig::AppConfig(config) => config.debugLevel,
+        _ => DebugLevel::NONE,
+    };
     println!(
-        "Created VM from {} with CID {}, state is {}.",
+        "Created {} from {} with CID {}, state is {}.",
+        if debug_level == DebugLevel::FULL { "debuggable VM" } else { "VM" },
         payload_config,
         vm.cid(),
         state_to_str(vm.state()?)
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index ac010b9..46f4937 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -2,11 +2,28 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// The hierarchy of Soong modules to produce a vmbase-based binary is
+//
+// 0. rlibs may be used to provide high-level code (see "vmbase_rlib_defaults");
+// 1. rust_ffi_static packages low-level Rust code and any rlib into a static
+//    library (see "vmbase_ffi_defaults") that cc_binary supports;
+// 2. cc_library_static may be used for extra C code (see "vmbase_cc_defaults");
+// 3. cc_binary produces an ELF from the (single) Rust-wrapping static library,
+//    optional extra C libraries, and linker script (see "vmbase_elf_defaults");
+// 4. raw_binary strips the ELF into an image that can be loaded to memory;
+
+// Used by intermediate rust_library_rlib for vmbase-based binaries.
 rust_defaults {
-    name: "vmbase_rust_defaults",
+    name: "vmbase_rlib_defaults",
     edition: "2021",
+    prefer_rlib: true,
     host_supported: false,
     enabled: false,
+    no_stdlibs: true,
+    stdlibs: [
+        "libcompiler_builtins.rust_sysroot",
+        "libcore.rust_sysroot",
+    ],
     target: {
         android_arm64: {
             enabled: true,
@@ -14,19 +31,17 @@
     },
 }
 
+// Used by the "top-level" rust_ffi_static of vmbase-based binaries.
 rust_defaults {
     name: "vmbase_ffi_defaults",
-    defaults: ["vmbase_rust_defaults"],
-    no_stdlibs: true,
-    stdlibs: [
-        "libcompiler_builtins.rust_sysroot",
-        "libcore.rust_sysroot",
-    ],
+    defaults: ["vmbase_rlib_defaults"],
 }
 
+// Used by extra cc_library_static linked into the final ELF.
 cc_defaults {
     name: "vmbase_cc_defaults",
     nocrt: true,
+    no_libcrt: true,
     system_shared_libs: [],
     stl: "none",
     installable: false,
@@ -39,8 +54,10 @@
     sanitize: {
         hwaddress: false,
     },
+    native_coverage: false,
 }
 
+// Used by cc_binary when producing the ELF of a vmbase-based binary.
 cc_defaults {
     name: "vmbase_elf_defaults",
     defaults: ["vmbase_cc_defaults"],
@@ -48,18 +65,11 @@
     static_libs: [
         "libvmbase_entry",
     ],
-    installable: false,
-    enabled: false,
-    target: {
-        android_arm64: {
-            enabled: true,
-        },
-    },
 }
 
 rust_library_rlib {
     name: "libvmbase",
-    defaults: ["vmbase_rust_defaults"],
+    defaults: ["vmbase_rlib_defaults"],
     crate_name: "vmbase",
     srcs: ["src/lib.rs"],
     rustlibs: [
@@ -76,14 +86,12 @@
         "libvirtio_drivers",
         "libzeroize_nostd",
     ],
-    no_stdlibs: true,
     whole_static_libs: [
         "librust_baremetal",
     ],
     features: [
         "cpu_feat_hafdbs",
     ],
-    apex_available: ["com.android.virt"],
 }
 
 cc_library_static {
@@ -94,8 +102,6 @@
         "exceptions.S",
         "exceptions_panic.S",
     ],
-    no_libcrt: true,
-    apex_available: ["com.android.virt"],
 }
 
 filegroup {
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index dc9a090..ae1a593 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -7,10 +7,8 @@
     defaults: ["vmbase_ffi_defaults"],
     crate_name: "vmbase_example",
     srcs: ["src/main.rs"],
-    edition: "2021",
     rustlibs: [
         "libaarch64_paging",
-        "libbuddy_system_allocator",
         "libdiced_open_dice_nostd",
         "libfdtpci",
         "liblibfdt",
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 1dd8517..b3b5732 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -30,11 +30,10 @@
 use crate::pci::{check_pci, get_bar_region};
 use aarch64_paging::{idmap::IdMap, paging::Attributes};
 use alloc::{vec, vec::Vec};
-use buddy_system_allocator::LockedHeap;
 use fdtpci::PciInfo;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn, LevelFilter};
-use vmbase::{cstr, logger, main};
+use vmbase::{configure_heap, cstr, logger, main, memory::SIZE_64KB};
 
 static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
 static mut ZEROED_DATA: [u32; 10] = [0; 10];
@@ -43,12 +42,8 @@
 const ASID: usize = 1;
 const ROOT_LEVEL: usize = 1;
 
-#[global_allocator]
-static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
-
-static mut HEAP: [u8; 65536] = [0; 65536];
-
 main!(main);
+configure_heap!(SIZE_64KB);
 
 /// Entry point for VM bootloader.
 pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
@@ -74,10 +69,6 @@
 
     modify_fdt(fdt);
 
-    unsafe {
-        HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
-    }
-
     check_alloc();
 
     let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
@@ -164,7 +155,6 @@
     unsafe {
         info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
         info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
-        info!("HEAP: {:?}", HEAP.as_ptr());
     }
 
     assert_eq!(INITIALISED_DATA[0], 1);
diff --git a/vmbase/src/entry.rs b/vmbase/src/entry.rs
index 8cdfe77..df0bb7c 100644
--- a/vmbase/src/entry.rs
+++ b/vmbase/src/entry.rs
@@ -14,11 +14,13 @@
 
 //! Rust entry point.
 
-use crate::{console, power::shutdown};
+use crate::{console, heap, power::shutdown};
 
 /// This is the entry point to the Rust code, called from the binary entry point in `entry.S`.
 #[no_mangle]
 extern "C" fn rust_entry(x0: u64, x1: u64, x2: u64, x3: u64) -> ! {
+    // SAFETY - Only called once, from here, and inaccessible to client code.
+    unsafe { heap::init() };
     console::init();
     unsafe {
         main(x0, x1, x2, x3);
diff --git a/pvmfw/src/heap.rs b/vmbase/src/heap.rs
similarity index 97%
rename from pvmfw/src/heap.rs
rename to vmbase/src/heap.rs
index a28a02c..b00ca6f 100644
--- a/pvmfw/src/heap.rs
+++ b/vmbase/src/heap.rs
@@ -29,7 +29,7 @@
 
 /// Configures the size of the global allocator.
 #[macro_export]
-macro_rules! configure_global_allocator_size {
+macro_rules! configure_heap {
     ($len:expr) => {
         static mut __HEAP_ARRAY: [u8; $len] = [0; $len];
         #[export_name = "HEAP"]
@@ -39,7 +39,7 @@
 }
 
 extern "Rust" {
-    /// Slice used by the global allocator, configured using configure_global_allocator_size!().
+    /// Slice used by the global allocator, configured using configure_heap!().
     static mut HEAP: &'static mut [u8];
 }
 
@@ -51,7 +51,7 @@
 /// # Safety
 ///
 /// Must be called no more than once.
-pub unsafe fn init() {
+pub(crate) unsafe fn init() {
     // SAFETY: Nothing else accesses this memory, and we hand it over to the heap to manage and
     // never touch it again. The heap is locked, so there cannot be any races.
     let (start, size) = unsafe { (HEAP.as_mut_ptr() as usize, HEAP.len()) };
diff --git a/vmbase/src/lib.rs b/vmbase/src/lib.rs
index 7fc7b20..88bad8b 100644
--- a/vmbase/src/lib.rs
+++ b/vmbase/src/lib.rs
@@ -23,6 +23,7 @@
 pub mod console;
 mod entry;
 pub mod fdt;
+pub mod heap;
 mod hvc;
 pub mod layout;
 mod linker;
diff --git a/vmbase/src/memory/mod.rs b/vmbase/src/memory/mod.rs
index 6bc600d..5e78565 100644
--- a/vmbase/src/memory/mod.rs
+++ b/vmbase/src/memory/mod.rs
@@ -25,5 +25,5 @@
 pub use shared::{alloc_shared, dealloc_shared, MemoryRange, MemoryTracker, MEMORY};
 pub use util::{
     flush, flushed_zeroize, min_dcache_line_size, page_4kb_of, phys_to_virt, virt_to_phys,
-    PAGE_SIZE, SIZE_128KB, SIZE_2MB, SIZE_4KB, SIZE_4MB,
+    PAGE_SIZE, SIZE_128KB, SIZE_2MB, SIZE_4KB, SIZE_4MB, SIZE_64KB,
 };
diff --git a/vmbase/src/memory/util.rs b/vmbase/src/memory/util.rs
index 48007f3..b9ef5c9 100644
--- a/vmbase/src/memory/util.rs
+++ b/vmbase/src/memory/util.rs
@@ -22,6 +22,8 @@
 
 /// The size of a 4KB memory in bytes.
 pub const SIZE_4KB: usize = 4 << 10;
+/// The size of a 64KB memory in bytes.
+pub const SIZE_64KB: usize = 64 << 10;
 /// The size of a 128KB memory in bytes.
 pub const SIZE_128KB: usize = 128 << 10;
 /// The size of a 2MB memory in bytes.