Merge changes I1b7d795a,I91d28982,Ia004b216,I93eca3eb,I6b91d837

* changes:
  Pass x0-x3 boot values to Rust main function.
  Load pvmfw as pVM firmware rather than bootloader.
  Add a heap allocator.
  Test BSS and data sections.
  Print addresses.
diff --git a/pvmfw/idmap.S b/pvmfw/idmap.S
index f1df6cc..62555f9 100644
--- a/pvmfw/idmap.S
+++ b/pvmfw/idmap.S
@@ -39,12 +39,14 @@
 idmap:
 	/* level 1 */
 	.quad		.L_BLOCK_DEV | 0x0		// 1 GB of device mappings
-	.quad		.L_BLOCK_DEV | 0x40000000	// Another 1 GB of device mapppings
-	.quad		.L_TT_TYPE_TABLE + 0f		// up to 1 GB of DRAM
+	.quad		.L_TT_TYPE_TABLE + 0f		// Unmapped device memory, and pVM firmware
+	.quad		.L_TT_TYPE_TABLE + 1f		// up to 1 GB of DRAM
 	.fill		509, 8, 0x0			// 509 GB of remaining VA space
 
 	/* level 2 */
-0:	.quad		.L_BLOCK_RO  | 0x80000000	// DT provided by VMM
-	.quad		.L_BLOCK_MEM_XIP | 0x80200000	// 2 MB of DRAM containing image
-	.quad		.L_BLOCK_MEM | 0x80400000	// 2 MB of writable DRAM
+0:	.fill		511, 8, 0x0
+	.quad		.L_BLOCK_MEM_XIP | 0x7fe00000	// pVM firmware image
+1:	.quad		.L_BLOCK_RO	 | 0x80000000	// DT provided by VMM
+	.quad		.L_BLOCK_RO	 | 0x80200000	// 2 MB of DRAM containing payload image
+	.quad		.L_BLOCK_MEM	 | 0x80400000	// Writable memory for stack, heap &c.
 	.fill		509, 8, 0x0
diff --git a/pvmfw/image.ld b/pvmfw/image.ld
index 4655f68..e122c72 100644
--- a/pvmfw/image.ld
+++ b/pvmfw/image.ld
@@ -16,8 +16,8 @@
 
 MEMORY
 {
+	image		: ORIGIN = 0x7fe00000, LENGTH = 2M
 	dtb_region	: ORIGIN = 0x80000000, LENGTH = 2M
-	image		: ORIGIN = 0x80200000, LENGTH = 2M
 	writable_data	: ORIGIN = 0x80400000, LENGTH = 2M
 }
 
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index d98ea8e..280e1ce 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -24,6 +24,10 @@
 main!(main);
 
 /// Entry point for pVM firmware.
-pub fn main() {
-    println!("Hello world");
+pub fn main(fdt_address: u64, payload_start: u64, payload_size: u64, arg3: u64) {
+    println!("pVM firmware");
+    println!(
+        "fdt_address={:#010x}, payload_start={:#010x}, payload_size={:#010x}, x3={:#010x}",
+        fdt_address, payload_start, payload_size, arg3,
+    );
 }
diff --git a/vmbase/entry.S b/vmbase/entry.S
index a12e1aa..490e841 100644
--- a/vmbase/entry.S
+++ b/vmbase/entry.S
@@ -74,31 +74,30 @@
 .set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1 | .L_SCTLR_EL1_WXN
 
 /**
- * This is a generic entry point for an image. It carries out the operations
- * required to prepare the loaded image to be run. Specifically, it zeroes the
- * bss section using registers x25 and above, prepares the stack, enables
- * floating point, and sets up the exception vector.
+ * This is a generic entry point for an image. It carries out the operations required to prepare the
+ * loaded image to be run. Specifically, it zeroes the bss section using registers x25 and above,
+ * prepares the stack, enables floating point, and sets up the exception vector. It preserves x0-x3
+ * for the Rust entry point, as these may contain boot parameters.
  */
 .section .init.entry, "ax"
 .global entry
 entry:
-	/* Enable MMU and caches. */
+	/* Load and apply the memory management configuration, ready to enable MMU and caches. */
 
-	/*
-	 * Load and apply the memory management configuration.
-	 */
-	adrp x1, idmap
-	mov_i x2, .Lmairval
-	mov_i x3, .Ltcrval
-	mov_i x4, .Lsctlrval
+	adrp x30, idmap
+	msr ttbr0_el1, x30
 
+	mov_i x30, .Lmairval
+	msr mair_el1, x30
+
+	mov_i x30, .Ltcrval
 	/* Copy the supported PA range into TCR_EL1.IPS. */
-	mrs x6, id_aa64mmfr0_el1
-	bfi x3, x6, #32, #4
+	mrs x29, id_aa64mmfr0_el1
+	bfi x30, x29, #32, #4
 
-	msr ttbr0_el1, x1
-	msr mair_el1, x2
-	msr tcr_el1, x3
+	msr tcr_el1, x30
+
+	mov_i x30, .Lsctlrval
 
 	/*
 	 * Ensure everything before this point has completed, then invalidate any potentially stale
@@ -111,10 +110,9 @@
 	isb
 
 	/*
-	 * Configure sctlr_el1 to enable MMU and cache and don't proceed until
-	 * this has completed.
+	 * Configure sctlr_el1 to enable MMU and cache and don't proceed until this has completed.
 	 */
-	msr sctlr_el1, x4
+	msr sctlr_el1, x30
 	isb
 
 	/* Disable trapping floating point access in EL1. */
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index 4cc4bf3..9c19693 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -13,6 +13,7 @@
         "libcore.rust_sysroot",
     ],
     rustlibs: [
+        "libbuddy_system_allocator",
         "libvmbase",
     ],
     enabled: false,
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index bbb64d9..3b1786c 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -16,14 +16,139 @@
 
 #![no_main]
 #![no_std]
+#![feature(default_alloc_error_handler)]
 
 mod exceptions;
 
+extern crate alloc;
+
+use alloc::{vec, vec::Vec};
+use buddy_system_allocator::LockedHeap;
 use vmbase::{main, println};
 
+static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
+static mut ZEROED_DATA: [u32; 10] = [0; 10];
+static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
+
+#[global_allocator]
+static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
+
+static mut HEAP: [u8; 65536] = [0; 65536];
+
 main!(main);
 
 /// Entry point for VM bootloader.
-pub fn main() {
+pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
     println!("Hello world");
+    println!("x0={:#010x}, x1={:#010x}, x2={:#010x}, x3={:#010x}", arg0, arg1, arg2, arg3);
+    print_addresses();
+    check_data();
+
+    unsafe {
+        HEAP_ALLOCATOR.lock().init(&mut HEAP as *mut u8 as usize, HEAP.len());
+    }
+
+    check_alloc();
+}
+
+fn print_addresses() {
+    unsafe {
+        println!(
+            "dtb:        {:#010x}-{:#010x} ({} bytes)",
+            &dtb_begin as *const u8 as usize,
+            &dtb_end as *const u8 as usize,
+            &dtb_end as *const u8 as usize - &dtb_begin as *const u8 as usize,
+        );
+        println!(
+            "text:       {:#010x}-{:#010x} ({} bytes)",
+            &text_begin as *const u8 as usize,
+            &text_end as *const u8 as usize,
+            &text_end as *const u8 as usize - &text_begin as *const u8 as usize,
+        );
+        println!(
+            "rodata:     {:#010x}-{:#010x} ({} bytes)",
+            &rodata_begin as *const u8 as usize,
+            &rodata_end as *const u8 as usize,
+            &rodata_end as *const u8 as usize - &rodata_begin as *const u8 as usize,
+        );
+        println!(
+            "data:       {:#010x}-{:#010x} ({} bytes, loaded at {:#010x})",
+            &data_begin as *const u8 as usize,
+            &data_end as *const u8 as usize,
+            &data_end as *const u8 as usize - &data_begin as *const u8 as usize,
+            &data_lma as *const u8 as usize,
+        );
+        println!(
+            "bss:        {:#010x}-{:#010x} ({} bytes)",
+            &bss_begin as *const u8 as usize,
+            &bss_end as *const u8 as usize,
+            &bss_end as *const u8 as usize - &bss_begin as *const u8 as usize,
+        );
+        println!(
+            "boot_stack: {:#010x}-{:#010x} ({} bytes)",
+            &boot_stack_begin as *const u8 as usize,
+            &boot_stack_end as *const u8 as usize,
+            &boot_stack_end as *const u8 as usize - &boot_stack_begin as *const u8 as usize,
+        );
+    }
+}
+
+fn check_data() {
+    println!("INITIALISED_DATA: {:#010x}", &INITIALISED_DATA as *const u32 as usize);
+    unsafe {
+        println!("ZEROED_DATA: {:#010x}", &ZEROED_DATA as *const u32 as usize);
+        println!("MUTABLE_DATA: {:#010x}", &MUTABLE_DATA as *const u32 as usize);
+        println!("HEAP: {:#010x}", &HEAP as *const u8 as usize);
+    }
+
+    assert_eq!(INITIALISED_DATA[0], 1);
+    assert_eq!(INITIALISED_DATA[1], 2);
+    assert_eq!(INITIALISED_DATA[2], 3);
+    assert_eq!(INITIALISED_DATA[3], 4);
+
+    unsafe {
+        for element in ZEROED_DATA.iter() {
+            assert_eq!(*element, 0);
+        }
+        ZEROED_DATA[0] = 13;
+        assert_eq!(ZEROED_DATA[0], 13);
+        ZEROED_DATA[0] = 0;
+        assert_eq!(ZEROED_DATA[0], 0);
+
+        assert_eq!(MUTABLE_DATA[0], 1);
+        assert_eq!(MUTABLE_DATA[1], 2);
+        assert_eq!(MUTABLE_DATA[2], 3);
+        assert_eq!(MUTABLE_DATA[3], 4);
+        MUTABLE_DATA[0] += 41;
+        assert_eq!(MUTABLE_DATA[0], 42);
+    }
+    println!("Data looks good");
+}
+
+fn check_alloc() {
+    println!("Allocating a Vec...");
+    let mut vector: Vec<u32> = vec![1, 2, 3, 4];
+    assert_eq!(vector[0], 1);
+    assert_eq!(vector[1], 2);
+    assert_eq!(vector[2], 3);
+    assert_eq!(vector[3], 4);
+    vector[2] = 42;
+    assert_eq!(vector[2], 42);
+    println!("Vec seems to work.");
+}
+
+extern "C" {
+    static dtb_begin: u8;
+    static dtb_end: u8;
+    static text_begin: u8;
+    static text_end: u8;
+    static rodata_begin: u8;
+    static rodata_end: u8;
+    static data_begin: u8;
+    static data_end: u8;
+    static data_lma: u8;
+    static bss_begin: u8;
+    static bss_end: u8;
+    static boot_stack_begin: u8;
+    static boot_stack_end: u8;
 }
diff --git a/vmbase/src/entry.rs b/vmbase/src/entry.rs
index dd7f6db..1510ae2 100644
--- a/vmbase/src/entry.rs
+++ b/vmbase/src/entry.rs
@@ -18,17 +18,17 @@
 
 /// 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() -> ! {
+extern "C" fn rust_entry(x0: u64, x1: u64, x2: u64, x3: u64) -> ! {
     console::init();
     unsafe {
-        main();
+        main(x0, x1, x2, x3);
     }
     shutdown();
 }
 
 extern "Rust" {
     /// Main function provided by the application using the `main!` macro.
-    fn main();
+    fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64);
 }
 
 /// Marks the main function of the binary.
@@ -49,9 +49,9 @@
     ($name:path) => {
         // Export a symbol with a name matching the extern declaration above.
         #[export_name = "main"]
-        fn __main() {
+        fn __main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
             // Ensure that the main function provided by the application has the correct type.
-            $name()
+            $name(arg0, arg1, arg2, arg3)
         }
     };
 }