Merge changes I85a89553,I453939a0,Iff7a015a,Id8f542ae into main
* changes:
Remove unused code
Force Portrait mode only if there is no hw keyboard
Portrait-mode if it's a phone or small tablet
Don't show modifier keys when HW qwerty keyboard is present
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
index f616b87..f318358 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
@@ -113,6 +113,7 @@
* 1024;
return roundUp(minSize);
} catch (NumberFormatException e) {
+ Log.e(TAG, "Failed to parse min size, p=" + p + ", result=" + result);
throw new IOException(e);
}
}
@@ -168,7 +169,12 @@
try {
Process process = new ProcessBuilder(command).redirectErrorStream(true).start();
process.waitFor();
- return new String(process.getInputStream().readAllBytes());
+ String result = new String(process.getInputStream().readAllBytes());
+ if (process.exitValue() != 0) {
+ Log.w(TAG, "Process returned with error, command=" + String.join(" ", command)
+ + ", exitValue=" + process.exitValue() + ", result=" + result);
+ }
+ return result;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Command interrupted", e);
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 303a932..30475f5 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -17,6 +17,7 @@
import android.content.Context
import android.content.Intent
+import android.content.SharedPreferences
import android.icu.text.MeasureFormat
import android.icu.text.NumberFormat
import android.icu.util.Measure
@@ -26,11 +27,12 @@
import android.text.Spanned
import android.text.TextUtils
import android.text.style.RelativeSizeSpan
+import android.view.View
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
-import com.google.android.material.button.MaterialButton
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.Locale
import java.util.regex.Pattern
@@ -40,6 +42,10 @@
private var diskSizeStepMb: Long = 0
private var diskSizeMb: Long = 0
+ private lateinit var sharedPref: SharedPreferences
+ private lateinit var buttons: View
+ private lateinit var cancelButton: View
+ private lateinit var resizeButton: View
private lateinit var diskSizeText: TextView
private lateinit var diskSizeSlider: SeekBar
@@ -65,7 +71,7 @@
diskSizeStepMb = 1L shl resources.getInteger(R.integer.disk_size_round_up_step_size_in_mb)
- val sharedPref =
+ sharedPref =
this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)
diskSizeMb =
bytesToMb(
@@ -82,9 +88,10 @@
localizedFileSize(maxDiskSizeMb, /* isShort= */ true),
)
+ buttons = findViewById<View>(R.id.buttons)
diskSizeSlider = findViewById<SeekBar>(R.id.settings_disk_resize_disk_size_slider)!!
- val cancelButton = findViewById<MaterialButton>(R.id.settings_disk_resize_cancel_button)
- val resizeButton = findViewById<MaterialButton>(R.id.settings_disk_resize_resize_button)
+ cancelButton = findViewById<View>(R.id.settings_disk_resize_cancel_button)
+ resizeButton = findViewById<View>(R.id.settings_disk_resize_resize_button)
diskSizeSlider.min = mbToProgress(minDiskSizeMb)
diskSizeSlider.max = mbToProgress(maxDiskSizeMb)
diskSizeSlider.progress = mbToProgress(diskSizeMb)
@@ -94,6 +101,7 @@
object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
updateSliderText(progressToMb(progress))
+ buttons.isVisible = true
cancelButton.isVisible = true
resizeButton.isVisible = true
}
@@ -108,27 +116,41 @@
}
)
- cancelButton.setOnClickListener {
- diskSizeSlider.progress = mbToProgress(diskSizeMb)
- cancelButton.isVisible = false
- resizeButton.isVisible = false
- }
+ cancelButton.setOnClickListener { cancel() }
- resizeButton.setOnClickListener {
- diskSizeMb = progressToMb(diskSizeSlider.progress)
- cancelButton.isVisible = false
- resizeButton.isVisible = false
- val editor = sharedPref.edit()
- editor.putLong(getString(R.string.preference_disk_size_key), mbToBytes(diskSizeMb))
- editor.apply()
+ resizeButton.setOnClickListener { showConfirmationDialog() }
+ }
- // Restart terminal
- val intent =
- baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
- intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
- finish()
- startActivity(intent)
- }
+ fun cancel() {
+ diskSizeSlider.progress = mbToProgress(diskSizeMb)
+ buttons.isVisible = false
+ }
+
+ fun showConfirmationDialog() {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(R.string.settings_disk_resize_title)
+ .setMessage(R.string.settings_disk_resize_resize_confirm_dialog_message)
+ .setPositiveButton(R.string.settings_disk_resize_resize_confirm_dialog_confirm) { _, _
+ ->
+ resize()
+ }
+ .setNegativeButton(R.string.settings_disk_resize_resize_cancel) { _, _ -> cancel() }
+ .create()
+ .show()
+ }
+
+ fun resize() {
+ diskSizeMb = progressToMb(diskSizeSlider.progress)
+ buttons.isVisible = false
+ val editor = sharedPref.edit()
+ editor.putLong(getString(R.string.preference_disk_size_key), mbToBytes(diskSizeMb))
+ editor.apply()
+
+ // Restart terminal
+ val intent = baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
+ intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ finish()
+ startActivity(intent)
}
fun updateSliderText(sizeMb: Long) {
diff --git a/android/TerminalApp/res/layout/settings_disk_resize.xml b/android/TerminalApp/res/layout/settings_disk_resize.xml
index fb7f85b..55fb7af 100644
--- a/android/TerminalApp/res/layout/settings_disk_resize.xml
+++ b/android/TerminalApp/res/layout/settings_disk_resize.xml
@@ -65,14 +65,18 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
+ <androidx.constraintlayout.widget.Group
+ android:id="@+id/buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="invisible"
+ app:constraint_referenced_ids="settings_disk_resize_cancel_button,settings_disk_resize_resize_button" />
+
<com.google.android.material.button.MaterialButton
android:id="@+id/settings_disk_resize_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxWidth="150sp"
- android:hyphenationFrequency="full"
android:text="@string/settings_disk_resize_resize_cancel"
- android:visibility="invisible"
android:layout_marginTop="48dp"
android:layout_marginHorizontal="8dp"
app:layout_constraintTop_toTopOf="@+id/settings_disk_resize_disk_size_slider"
@@ -83,10 +87,7 @@
android:id="@+id/settings_disk_resize_resize_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxWidth="150sp"
- android:hyphenationFrequency="full"
android:text="@string/settings_disk_resize_resize_restart_vm_to_apply"
- android:visibility="invisible"
android:layout_marginTop="48dp"
app:layout_constraintTop_toTopOf="@+id/settings_disk_resize_disk_size_slider"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/android/TerminalApp/res/values/strings.xml b/android/TerminalApp/res/values/strings.xml
index 6fb256b..44d88a2 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -74,8 +74,12 @@
<string name="settings_disk_resize_resize_gb_max_format"><xliff:g id="max_size" example="256GB">%1$s</xliff:g> max</string>
<!-- Settings menu button to cancel disk resize. [CHAR LIMIT=16] -->
<string name="settings_disk_resize_resize_cancel">Cancel</string>
- <!-- Settings menu button to apply change that requires to restart Terminal app. [CHAR LIMIT=40] -->
- <string name="settings_disk_resize_resize_restart_vm_to_apply">Restart to apply</string>
+ <!-- Settings menu button to apply change Terminal app. This will launch a confirmation dialog [CHAR LIMIT=16] -->
+ <string name="settings_disk_resize_resize_restart_vm_to_apply">Apply</string>
+ <!-- Dialog description for applying disk resize Terminal app, which requires to restart the terminal [CHAR LIMIT=none] -->
+ <string name="settings_disk_resize_resize_confirm_dialog_message">Terminal will be restarted to resize disk</string>
+ <!-- Dialog confirmation button for restarting the terminal [CHAR LIMIT=16] -->
+ <string name="settings_disk_resize_resize_confirm_dialog_confirm">Confirm</string>
<!-- Settings menu title for 'port forwarding' [CHAR LIMIT=none] -->
<string name="settings_port_forwarding_title">Port forwarding</string>
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 9a733b6..55de0af 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -445,20 +445,25 @@
let context = EarlyVmContext::new(cid, temp_dir.clone())
.context(format!("Can't create early vm contexts for {cid}"))
.or_service_specific_exception(-1)?;
- let service = VirtualMachineService::new_binder(self.state.clone(), cid).as_binder();
- // Start VM service listening for connections from the new CID on port=CID.
- let port = cid;
- let (vm_server, _) = RpcServer::new_vsock(service, cid, port)
- .context(format!("Could not start RpcServer on port {port}"))
- .or_service_specific_exception(-1)?;
- vm_server.start();
- Ok((VmContext::new(Strong::new(Box::new(context)), vm_server), cid, temp_dir))
+ if requires_vm_service(config) {
+ // Start VM service listening for connections from the new CID on port=CID.
+ let service = VirtualMachineService::new_binder(self.state.clone(), cid).as_binder();
+ let port = cid;
+ let (vm_server, _) = RpcServer::new_vsock(service, cid, port)
+ .context(format!("Could not start RpcServer on port {port}"))
+ .or_service_specific_exception(-1)?;
+ vm_server.start();
+ Ok((VmContext::new(Strong::new(Box::new(context)), Some(vm_server)), cid, temp_dir))
+ } else {
+ Ok((VmContext::new(Strong::new(Box::new(context)), None), cid, temp_dir))
+ }
}
fn create_vm_context(
&self,
requester_debug_pid: pid_t,
+ config: &VirtualMachineConfig,
) -> binder::Result<(VmContext, Cid, PathBuf)> {
const NUM_ATTEMPTS: usize = 5;
@@ -466,6 +471,12 @@
let vm_context = GLOBAL_SERVICE.allocateGlobalVmContext(requester_debug_pid)?;
let cid = vm_context.getCid()? as Cid;
let temp_dir: PathBuf = vm_context.getTemporaryDirectory()?.into();
+
+ // We don't need to start the VM service for custom VMs.
+ if !requires_vm_service(config) {
+ return Ok((VmContext::new(vm_context, None), cid, temp_dir));
+ }
+
let service = VirtualMachineService::new_binder(self.state.clone(), cid).as_binder();
// Start VM service listening for connections from the new CID on port=CID.
@@ -473,7 +484,7 @@
match RpcServer::new_vsock(service, cid, port) {
Ok((vm_server, _)) => {
vm_server.start();
- return Ok((VmContext::new(vm_context, vm_server), cid, temp_dir));
+ return Ok((VmContext::new(vm_context, Some(vm_server)), cid, temp_dir));
}
Err(err) => {
warn!("Could not start RpcServer on port {}: {}", port, err);
@@ -509,7 +520,7 @@
let (vm_context, cid, temporary_directory) = if cfg!(early) {
self.create_early_vm_context(config)?
} else {
- self.create_vm_context(requester_debug_pid)?
+ self.create_vm_context(requester_debug_pid, config)?
};
if is_custom_config(config) {
@@ -820,6 +831,17 @@
}
}
+/// Returns whether a VM config requires VirtualMachineService running on the host. Only Microdroid
+/// VM (i.e. AppConfig) requires it. However, a few Microdroid tests use RawConfig for Microdroid
+/// VM. To handle the exceptional case, we use name as a second criteria; if the name is
+/// "microdroid" we run VirtualMachineService
+fn requires_vm_service(config: &VirtualMachineConfig) -> bool {
+ match config {
+ VirtualMachineConfig::AppConfig(_) => true,
+ VirtualMachineConfig::RawConfig(config) => config.name == "microdroid",
+ }
+}
+
fn extract_vendor_hashtree_digest(config: &VirtualMachineConfig) -> Result<Option<Vec<u8>>> {
let VirtualMachineConfig::AppConfig(config) = config else {
return Ok(None);
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 46f4e80..1ccabec 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -360,12 +360,15 @@
#[allow(dead_code)] // Keeps the global context alive
pub(crate) global_context: Strong<dyn IGlobalVmContext>,
#[allow(dead_code)] // Keeps the server alive
- vm_server: RpcServer,
+ vm_server: Option<RpcServer>,
}
impl VmContext {
/// Construct new VmContext.
- pub fn new(global_context: Strong<dyn IGlobalVmContext>, vm_server: RpcServer) -> VmContext {
+ pub fn new(
+ global_context: Strong<dyn IGlobalVmContext>,
+ vm_server: Option<RpcServer>,
+ ) -> VmContext {
VmContext { global_context, vm_server }
}
}
@@ -655,7 +658,9 @@
// Now that the VM has been killed, shut down the VirtualMachineService
// server to eagerly free up the server threads.
- self.vm_context.vm_server.shutdown()?;
+ if let Some(vm_server) = &self.vm_context.vm_server {
+ vm_server.shutdown()?;
+ }
Ok(())
}
diff --git a/android/vm/vm_shell.sh b/android/vm/vm_shell.sh
index b73a9dc..60d9329 100755
--- a/android/vm/vm_shell.sh
+++ b/android/vm/vm_shell.sh
@@ -30,7 +30,7 @@
echo " /apex/com.android.virt/bin/vm run-microdroid binary."
echo ""
echo " E.g.:"
- echo " vm_shell start-microdroid -- --cpu 5"
+ echo " vm_shell start-microdroid -- --protected --debug full"
echo ""
echo " --auto-connect - automatically connects to the started VMs"
echo ""
diff --git a/build/debian/build.sh b/build/debian/build.sh
index dfcffb6..bd918dd 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -12,6 +12,7 @@
echo "-h Print usage and this help message and exit."
echo "-a ARCH Architecture of the image [default is aarch64]"
echo "-r Release mode build"
+ echo "-w Save temp work directory (for debugging)"
}
check_sudo() {
@@ -22,7 +23,7 @@
}
parse_options() {
- while getopts "hra:" option; do
+ while getopts "a:hrw" option; do
case ${option} in
h)
show_help
@@ -40,6 +41,9 @@
r)
mode=release
;;
+ w)
+ save_workdir=1
+ ;;
*)
echo "Invalid option: $OPTARG"
exit
@@ -51,6 +55,16 @@
fi
}
+prepare_build_id() {
+ local file=${workdir}/build_id
+ if [ -z "${KOKORO_BUILD_NUMBER}" ]; then
+ echo eng-$(hostname)-$(date --utc) > ${file}
+ else
+ echo ${KOKOR_BUILD_NUMBER} > ${file}
+ fi
+ echo ${file}
+}
+
install_prerequisites() {
apt update
packages=(
@@ -203,7 +217,7 @@
}
clean_up() {
- rm -rf "${workdir}"
+ [ "$save_workdir" -eq 0 ] || rm -rf "${workdir}"
}
set -e
@@ -211,6 +225,7 @@
built_image=image.raw
workdir=$(mktemp -d)
+build_id=$(prepare_build_id)
debian_cloud_image=${workdir}/debian_cloud_image
debian_version=bookworm
config_space=${debian_cloud_image}/config_space/${debian_version}
@@ -218,6 +233,8 @@
arch=aarch64
debian_arch=arm64
mode=debug
+save_workdir=0
+
parse_options "$@"
check_sudo
install_prerequisites
@@ -252,4 +269,4 @@
fi
# --sparse option isn't supported in apache-commons-compress
-tar czv -f images.tar.gz "${images[@]}" vm_config.json
+tar czv -f images.tar.gz ${build_id} "${images[@]}" vm_config.json
diff --git a/build/debian/build_in_container.sh b/build/debian/build_in_container.sh
index ef64254..7fd4c00 100755
--- a/build/debian/build_in_container.sh
+++ b/build/debian/build_in_container.sh
@@ -4,7 +4,9 @@
arch=aarch64
release_flag=
-while getopts "ra:" option; do
+save_workdir_flag=
+
+while getopts "a:rw" option; do
case ${option} in
a)
if [[ "$OPTARG" != "aarch64" && "$OPTARG" != "x86_64" ]]; then
@@ -16,6 +18,9 @@
r)
release_flag="-r"
;;
+ w)
+ save_workdir_flag="-w"
+ ;;
*)
echo "Invalid option: $OPTARG"
exit
@@ -27,4 +32,4 @@
-v "$ANDROID_BUILD_TOP/packages/modules/Virtualization:/root/Virtualization" \
--workdir /root/Virtualization/build/debian \
ubuntu:22.04 \
- bash -c "/root/Virtualization/build/debian/build.sh -a "$arch" $release_flag || bash"
+ bash -c "/root/Virtualization/build/debian/build.sh -a $arch $release_flag $save_workdir_flag || bash"
diff --git a/build/debian/release.sh b/build/debian/release.sh
new file mode 100755
index 0000000..437f9c8
--- /dev/null
+++ b/build/debian/release.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+
+# This is a script to release the Debian image built by Kokoro to Lorry.
+
+set -e
+
+show_help() {
+ echo "Usage: $0 [OPTION]..."
+ echo "Fetches a debian image from Placer and releases it to /android/ferrochrome/ARCH/TAG"
+ echo "Options:"
+ echo "-h Print usage and this help message and exit."
+ echo "-a ARCH Architecture of the image. Defaults to all supported architectures."
+ echo "-b BUILD_ID Build ID to fetch. If omitted, latest build ID is selected."
+ echo "-t TAG Tag name to attach to the release. Defaults to BUILD_ID."
+}
+
+parse_opt() {
+ while getopts "ha:b:t:" option; do
+ case ${option} in
+ h)
+ show_help
+ exit;;
+ a)
+ if [[ "$OPTARG" != "aarch64" && "$OPTARG" != "x86_64" ]]; then
+ echo "Invalid architecture: $OPTARG"
+ exit
+ fi
+ arch="$OPTARG"
+ ;;
+ b)
+ build_id="$OPTARG"
+ ;;
+ t)
+ tag="$OPTARG"
+ ;;
+ *)
+ echo "Invalid option: $OPTARG"
+ exit
+ ;;
+ esac
+ done
+
+ if [ "${build_id}" != "latest" ]; then
+ echo "Build ID is ambiguous when architecture is not set"
+ exit
+ fi
+}
+
+arch=all
+build_id=latest
+tag=
+placer_url="/placer/test/home/kokoro-dedicated-qa/build_artifacts/qa/android-ferrochrome"
+image_filename="images.tar.gz"
+
+get_build_id() {
+ local arch=$1
+ local build_id=$2
+ if [ "${build_id}" == "latest" ]; then
+ local pattern=${placer_url}/${arch}/continuous
+ build_id=$(basename $(fileutil ls ${pattern} | sort -V | tail -1))
+ fi
+ echo ${build_id}
+}
+
+get_image_path() {
+ local arch=$1
+ local build_id=$2
+ local pattern=${placer_url}/${arch}/continuous/${build_id}/*/${image_filename}
+ image=$(fileutil ls ${pattern} | tail -1)
+ if [ $? -ne 0 ]; then
+ echo "Cannot find image"
+ exit
+ fi
+ echo ${image}
+}
+
+do_release() {
+ local arch=$1
+ local build_id=$2
+
+ build_id=$(get_build_id ${arch} ${build_id})
+ echo "Using build ID ${build_id} for ${arch}"
+ local image=$(get_image_path ${arch} ${build_id})
+
+ local tag=${tag:-${build_id}}
+ local serving_url=/android/ferrochrome/${arch}/${tag}/${image_filename}
+ echo "Releasing ${image} to ${serving_url}"
+
+ local request='payload : { url_path: '"\"${serving_url}\""' source_path : '"\"${image}\""' }'
+ local id=$(stubby call blade:download-lorry-api LorryService.CreatePayloads "${request}" | cut -d\ -f2)
+ echo "Done. Visit https://lorry.corp.google.com/view/${id} to get an approval for the release."
+}
+
+parse_opt "$@"
+
+if [ "${arch}" == "all" ]; then
+ do_release aarch64 ${build_id}
+ do_release x86_64 ${build_id}
+else
+ do_release ${arch} ${build_id}
+fi
diff --git a/guest/pvmfw/README.md b/guest/pvmfw/README.md
index 50fe3d3..8c8314d 100644
--- a/guest/pvmfw/README.md
+++ b/guest/pvmfw/README.md
@@ -450,6 +450,18 @@
[soong-udroid]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/microdroid/Android.bp;l=425;drc=b94a5cf516307c4279f6c16a63803527a8affc6d
+#### VBMeta Properties
+
+AVF defines special keys for AVB VBMeta descriptor properties that pvmfw
+recognizes, allowing VM owners to ensure that pvmfw performs its role in a way
+that is compatible with their guest kernel. These are:
+
+- `"com.android.virt.cap"`: a `|`-separated list of "capabilities" from
+ - `remote_attest`: pvmfw uses a hard-coded index for rollback protection
+ - `secretkeeper_protection`: pvmfw defers rollback protection to the guest
+ - `supports_uefi_boot`: pvmfw boots the VM as a EFI payload (experimental)
+ - `trusty_security_vm`: pvmfw skips rollback protection
+
## Development
For faster iteration, you can build pvmfw, adb-push it to the device, and use
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 6bbb05e..027f163 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -1140,10 +1140,15 @@
RebootReason::InvalidFdt
})?;
- let swiotlb_info = SwiotlbInfo::new_from_fdt(fdt).map_err(|e| {
- error!("Failed to read swiotlb info from DT: {e}");
- RebootReason::InvalidFdt
- })?;
+ let swiotlb_info = SwiotlbInfo::new_from_fdt(fdt)
+ .map_err(|e| {
+ error!("Failed to read swiotlb info from DT: {e}");
+ RebootReason::InvalidFdt
+ })?
+ .ok_or_else(|| {
+ error!("Swiotlb info missing from DT");
+ RebootReason::InvalidFdt
+ })?;
validate_swiotlb_info(&swiotlb_info, &memory_range)?;
let device_assignment = match vm_dtbo {
diff --git a/guest/rialto/src/main.rs b/guest/rialto/src/main.rs
index 0b79e1e..ec26e0f 100644
--- a/guest/rialto/src/main.rs
+++ b/guest/rialto/src/main.rs
@@ -117,7 +117,7 @@
MEMORY.lock().as_mut().unwrap().init_dynamic_shared_pool(granule).inspect_err(|_| {
error!("Failed to initialize dynamically shared pool.");
})?;
- } else if let Ok(swiotlb_info) = SwiotlbInfo::new_from_fdt(fdt) {
+ } else if let Ok(Some(swiotlb_info)) = SwiotlbInfo::new_from_fdt(fdt) {
let range = swiotlb_info.fixed_range().ok_or_else(|| {
error!("Pre-shared pool range not specified in swiotlb node");
Error::from(FdtError::BadValue)
diff --git a/guest/vmbase_example/src/layout.rs b/guest/vmbase_example/src/layout.rs
index 55c7283..4e87e4e 100644
--- a/guest/vmbase_example/src/layout.rs
+++ b/guest/vmbase_example/src/layout.rs
@@ -14,14 +14,11 @@
//! Memory layout.
-use aarch64_paging::paging::{MemoryRegion, VirtualAddress};
+use aarch64_paging::paging::VirtualAddress;
use core::ops::Range;
use log::info;
use vmbase::{layout, memory::PAGE_SIZE};
-pub const DEVICE_REGION: MemoryRegion =
- MemoryRegion::new(layout::crosvm::MMIO_START, layout::crosvm::MMIO_END);
-
/// Writable data region for the stack.
pub fn boot_stack_range() -> Range<VirtualAddress> {
layout::stack_range(40 * PAGE_SIZE)
diff --git a/guest/vmbase_example/src/main.rs b/guest/vmbase_example/src/main.rs
index 1466d1e..c7ef061 100644
--- a/guest/vmbase_example/src/main.rs
+++ b/guest/vmbase_example/src/main.rs
@@ -23,8 +23,8 @@
extern crate alloc;
-use crate::layout::{boot_stack_range, print_addresses, DEVICE_REGION};
-use crate::pci::{check_pci, get_bar_region};
+use crate::layout::{boot_stack_range, print_addresses};
+use crate::pci::{check_pci, get_bar_region, get_cam_region};
use aarch64_paging::paging::VirtualAddress;
use aarch64_paging::MapError;
use alloc::{vec, vec::Vec};
@@ -37,10 +37,9 @@
bionic, configure_heap,
fdt::pci::PciInfo,
generate_image_header,
- layout::{crosvm::FDT_MAX_SIZE, rodata_range, scratch_range, text_range},
+ layout::{console_uart_page, crosvm::FDT_MAX_SIZE, rodata_range, scratch_range, text_range},
linker, logger, main,
memory::{PageTable, SIZE_64KB},
- util::RangeExt as _,
};
static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
@@ -52,7 +51,7 @@
configure_heap!(SIZE_64KB);
fn init_page_table(page_table: &mut PageTable) -> Result<(), MapError> {
- page_table.map_device(&DEVICE_REGION)?;
+ page_table.map_device(&console_uart_page().into())?;
page_table.map_code(&text_range().into())?;
page_table.map_rodata(&rodata_range().into())?;
page_table.map_data(&scratch_range().into())?;
@@ -99,13 +98,10 @@
check_alloc();
+ let cam_region = get_cam_region(&pci_info);
+ page_table.map_device(&cam_region).unwrap();
let bar_region = get_bar_region(&pci_info);
- if bar_region.is_within(&DEVICE_REGION) {
- // Avoid a MapError::BreakBeforeMakeViolation.
- info!("BAR region is within already mapped device region: skipping page table ops.");
- } else {
- page_table.map_device(&bar_region).unwrap();
- }
+ page_table.map_device(&bar_region).unwrap();
check_data();
check_dice();
diff --git a/guest/vmbase_example/src/pci.rs b/guest/vmbase_example/src/pci.rs
index 563f24a..379425d 100644
--- a/guest/vmbase_example/src/pci.rs
+++ b/guest/vmbase_example/src/pci.rs
@@ -120,6 +120,11 @@
MemoryRegion::new(pci_info.bar_range.start as usize, pci_info.bar_range.end as usize)
}
+/// Gets the PCI CAM memory region.
+pub fn get_cam_region(pci_info: &PciInfo) -> MemoryRegion {
+ MemoryRegion::new(pci_info.cam_range.start, pci_info.cam_range.end)
+}
+
struct HalImpl;
/// SAFETY: See the 'Implementation Safety' comments on methods below for how they fulfill the
diff --git a/libs/libvmbase/sections.ld b/libs/libvmbase/sections.ld
index 7d464bc..5ca5ff4 100644
--- a/libs/libvmbase/sections.ld
+++ b/libs/libvmbase/sections.ld
@@ -96,11 +96,16 @@
bss_end = .;
} >writable_data
- init_stack_pointer = ORIGIN(writable_data) + LENGTH(writable_data);
+ /* Left unmapped, to catch overflows of the stack. */
+ .stack_guard_page (NOLOAD) : ALIGN(4096) {
+ . += 4096;
+ } >writable_data
+
+ /* Stack, mapped read-write (possibly partially). */
.stack (NOLOAD) : ALIGN(4096) {
- . += 4096; /* Ensure we have one guard page for overflow. */
stack_limit = .;
- . = init_stack_pointer;
+ . = ALIGN(LENGTH(writable_data));
+ init_stack_pointer = .;
} >writable_data
/* Make our Bionic stack protector compatible with mainline LLVM */
diff --git a/libs/libvmbase/src/fdt.rs b/libs/libvmbase/src/fdt.rs
index ff0eaf0..aaf354e 100644
--- a/libs/libvmbase/src/fdt.rs
+++ b/libs/libvmbase/src/fdt.rs
@@ -33,20 +33,20 @@
impl SwiotlbInfo {
/// Creates a `SwiotlbInfo` struct from the given device tree.
- pub fn new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo> {
- let node =
- fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next().ok_or(FdtError::NotFound)?;
-
+ pub fn new_from_fdt(fdt: &Fdt) -> libfdt::Result<Option<SwiotlbInfo>> {
+ let Some(node) = fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next() else {
+ return Ok(None);
+ };
let (addr, size, align) = if let Some(mut reg) = node.reg()? {
- let reg = reg.next().ok_or(FdtError::NotFound)?;
- let size = reg.size.ok_or(FdtError::NotFound)?;
+ let reg = reg.next().ok_or(FdtError::BadValue)?;
+ let size = reg.size.ok_or(FdtError::BadValue)?;
(Some(reg.addr.try_into().unwrap()), size.try_into().unwrap(), None)
} else {
let size = node.getprop_u64(cstr!("size"))?.ok_or(FdtError::NotFound)?;
let align = node.getprop_u64(cstr!("alignment"))?.ok_or(FdtError::NotFound)?;
(None, size.try_into().unwrap(), Some(align.try_into().unwrap()))
};
- Ok(Self { addr, size, align })
+ Ok(Some(Self { addr, size, align }))
}
/// Returns the fixed range of memory mapped by the SWIOTLB buffer, if available.
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index fefedc9..630df87 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -405,6 +405,7 @@
VIRT_APEX + "bin/vm run",
"--console " + CONSOLE_PATH,
"--log " + LOG_PATH,
+ "--name " + "microdroid", // to still be seen as microdroid vm
configPath);
PipedInputStream pis = new PipedInputStream();