Entry point for Rust pvmfw.

Bug: 223166344
Test: Ran unprotected VM under crosvm.
Change-Id: I89b1c01f9b1ae3bbbe477044f11ed8b87287535a
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index a5e4920..d94334c 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -16,3 +16,27 @@
     },
     apex_available: ["com.android.virt"],
 }
+
+cc_binary {
+    name: "pvmfw",
+    srcs: [
+        "entry.S",
+    ],
+    static_libs: [
+        "libpvmfw",
+    ],
+    static_executable: true,
+    no_libcrt: true,
+    nocrt: true,
+    system_shared_libs: [],
+    ldflags: [
+        "-Tpackages/modules/Virtualization/pvmfw/image.ld",
+    ],
+    enabled: false,
+    target: {
+        android_arm64: {
+            enabled: true,
+        },
+    },
+    apex_available: ["com.android.virt"],
+}
diff --git a/pvmfw/entry.S b/pvmfw/entry.S
new file mode 100644
index 0000000..25631cb
--- /dev/null
+++ b/pvmfw/entry.S
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.macro adr_l, reg:req, sym:req
+	adrp \reg, \sym
+	add \reg, \reg, :lo12:\sym
+.endm
+
+/**
+ * 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.
+ */
+.section .init.entry, "ax"
+.global entry
+entry:
+	/* Disable trapping floating point access in EL1. */
+	mrs x30, cpacr_el1
+	orr x30, x30, #(0x3 << 20)
+	msr cpacr_el1, x30
+	isb
+
+	/* Zero out the bss section. */
+	adr_l x29, bss_begin
+	adr_l x30, bss_end
+0:	cmp x29, x30
+	b.hs 1f
+	stp xzr, xzr, [x29], #16
+	b 0b
+
+1:	/* Prepare the stack. */
+	adr x30, boot_stack_end
+	mov sp, x30
+
+	/* Call into Rust code. */
+	bl main
+
+	/* Loop forever waiting for interrupts. */
+2:	wfi
+	b 2b
diff --git a/pvmfw/image.ld b/pvmfw/image.ld
new file mode 100644
index 0000000..e08fbe2
--- /dev/null
+++ b/pvmfw/image.ld
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+MEMORY
+{
+	dtb_region	: ORIGIN = 0x80000000, LENGTH = 2M
+	image		: ORIGIN = 0x80200000, LENGTH = 2M
+}
+
+/*
+ * Code will start running at this symbol which is placed at the start of the
+ * image.
+ */
+ENTRY(entry)
+
+/*
+ * The following would be useful to check that .init code is not called back
+ * into once it has completed but it isn't supported by ld.lld.
+ *
+ * NOCROSSREFS_TO(.init .text)
+ */
+
+SECTIONS
+{
+	.dtb (NOLOAD) : {
+		dtb_begin = .;
+		. += LENGTH(dtb_region);
+		dtb_end = .;
+	} >dtb_region
+
+	/*
+	 * Collect together the code. This is page aligned so it can be mapped
+	 * as executable-only.
+	 */
+	.init : ALIGN(4096) {
+		text_begin = .;
+		*(.init.entry)
+		*(.init.*)
+	} >image
+	.text : {
+		*(.text.*)
+	} >image
+	text_end = .;
+
+	/*
+	 * Collect together read-only data. This is page aligned so it can be
+	 * mapped as read-only and non-executable.
+	 */
+	.rodata : ALIGN(4096) {
+		rodata_begin = .;
+		*(.rodata.*)
+	} >image
+	.got : {
+		*(.got)
+	} >image
+	rodata_end = .;
+
+	/*
+	 * Collect together the read-write data including .bss at the end which
+	 * will be zero'd by the entry code. This is page aligned so it can be
+	 * mapped as non-executable.
+	 */
+	.data : ALIGN(4096) {
+		data_begin = .;
+		*(.data.*)
+		/*
+		 * The entry point code assumes that .data is a multiple of 32
+		 * bytes long.
+		 */
+		. = ALIGN(32);
+		data_end = .;
+	} >image
+	/* Everything beyond this point will not be included in the binary. */
+	bin_end = .;
+
+	/* The entry point code assumes that .bss is 16-byte aligned. */
+	.bss : ALIGN(16)  {
+		bss_begin = .;
+		*(.bss.*)
+		*(COMMON)
+		. = ALIGN(16);
+		bss_end = .;
+	} >image
+
+	.stack (NOLOAD) : ALIGN(4096) {
+		boot_stack_begin = .;
+		. += 40 * 4096;
+		. = ALIGN(4096);
+		boot_stack_end = .;
+	} >image
+
+	/*
+	 * Remove unused sections from the image.
+	 */
+	/DISCARD/ : {
+		/* The image loads itself so doesn't need these sections. */
+		*(.gnu.hash)
+		*(.hash)
+		*(.interp)
+		*(.eh_frame_hdr)
+		*(.eh_frame)
+		*(.note.gnu.build-id)
+	}
+}