Merge "Add a doc on running a graphical OS" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 33d46dd..db0b43a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -3,6 +3,12 @@
{
"avf-presubmit": [
{
+ "name": "AvfRkpdAppIntegrationTests"
+ },
+ {
+ "name": "AvfRkpdVmAttestationTestApp"
+ },
+ {
"name": "MicrodroidHostTestCases"
},
{
@@ -56,16 +62,8 @@
"name": "AVFHostTestCases"
},
{
- // TODO(b/325610326): Add this target to presubmit once there is enough
- // SLO data for it.
- "name": "AvfRkpdAppIntegrationTests"
- },
- {
"name": "AvfRkpdAppGoogleIntegrationTests",
"keywords": ["internal"]
- },
- {
- "name": "AvfRkpdVmAttestationTestApp"
}
],
"postsubmit": [
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 98a541f..ff17ed1 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -181,28 +181,28 @@
filename: "init.rc",
src: "init.rc",
relative_install_path: "init/hw",
- installable: false, // avoid collision with system partition's init.rc
+ no_full_install: true, // avoid collision with system partition's init.rc
}
prebuilt_etc {
name: "microdroid_ueventd_rc",
filename: "ueventd.rc",
src: "ueventd.rc",
- installable: false, // avoid collision with system partition's ueventd.rc
+ no_full_install: true, // avoid collision with system partition's ueventd.rc
}
prebuilt_etc {
name: "microdroid_etc_passwd",
src: "microdroid_passwd",
filename: "passwd",
- installable: false,
+ no_full_install: true,
}
prebuilt_etc {
name: "microdroid_etc_group",
src: "microdroid_group",
filename: "group",
- installable: false,
+ no_full_install: true,
}
prebuilt_root {
@@ -217,7 +217,7 @@
src: ":microdroid_build_prop_gen_arm64",
},
},
- installable: false,
+ no_full_install: true,
}
genrule {
@@ -389,7 +389,7 @@
name: "microdroid_fstab",
src: "fstab.microdroid",
filename: "fstab.microdroid",
- installable: false,
+ no_full_install: true,
}
// python -c "import hashlib; print(hashlib.sha256(b'bootloader').hexdigest())"
@@ -441,14 +441,14 @@
src: "microdroid_manifest.xml",
filename: "manifest.xml",
relative_install_path: "vintf",
- installable: false,
+ no_full_install: true,
}
prebuilt_etc {
name: "microdroid_event-log-tags",
src: "microdroid_event-log-tags",
filename: "event-log-tags",
- installable: false,
+ no_full_install: true,
}
filegroup {
diff --git a/microdroid/kdump/Android.bp b/microdroid/kdump/Android.bp
index 6c85c43..cd68539 100644
--- a/microdroid/kdump/Android.bp
+++ b/microdroid/kdump/Android.bp
@@ -7,7 +7,7 @@
defaults: ["avf_build_flags_cc"],
stem: "kexec_load",
srcs: ["kexec.c"],
- installable: false,
+ no_full_install: true,
static_executable: true, // required because this runs before linkerconfig
compile_multilib: "64",
}
@@ -18,7 +18,7 @@
stem: "crashdump",
srcs: ["crashdump.c"],
static_executable: true,
- installable: false,
+ no_full_install: true,
compile_multilib: "64",
sanitize: {
hwaddress: false, // HWASAN setup fails when run as init process
diff --git a/microdroid/kdump/kernel/Android.bp b/microdroid/kdump/kernel/Android.bp
index 0705875..2bab6a8 100644
--- a/microdroid/kdump/kernel/Android.bp
+++ b/microdroid/kdump/kernel/Android.bp
@@ -21,5 +21,5 @@
src: "x86_64/kernel-5.15",
},
},
- installable: false,
+ no_full_install: true,
}
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 025edff..11e67cb 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -234,4 +234,4 @@
}
main!(main);
-configure_heap!(SIZE_128KB);
+configure_heap!(SIZE_128KB * 2);
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index 08ee08e..cdbd60e 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -28,7 +28,7 @@
use core::result;
use coset::{iana, AsCborValue, CoseSign1, CoseSign1Builder, HeaderBuilder};
use diced_open_dice::{derive_cdi_leaf_priv, kdf, sign, DiceArtifacts, PrivateKey};
-use log::error;
+use log::{debug, error};
use service_vm_comm::{EcdsaP256KeyPair, GenerateCertificateRequestParams, RequestProcessingError};
use zeroize::Zeroizing;
@@ -78,6 +78,8 @@
let public_key = validate_public_key(&key_to_sign, hmac_key.as_ref())?;
public_keys.push(public_key.to_cbor_value()?);
}
+ debug!("Successfully validated all '{}' public keys.", public_keys.len());
+
// Builds `CsrPayload`.
let csr_payload = cbor!([
Value::Integer(CSR_PAYLOAD_SCHEMA_V3.into()),
@@ -91,6 +93,7 @@
let signed_data_payload =
cbor!([Value::Bytes(params.challenge.to_vec()), Value::Bytes(csr_payload)])?;
let signed_data = build_signed_data(&signed_data_payload, dice_artifacts)?.to_cbor_value()?;
+ debug!("Successfully signed the CSR payload.");
// Builds `AuthenticatedRequest<CsrPayload>`.
// Currently `UdsCerts` is left empty because it is only needed for Samsung devices.
@@ -104,6 +107,7 @@
dice_cert_chain,
signed_data,
])?;
+ debug!("Successfully built the CBOR authenticated request.");
Ok(cbor_util::serialize(&auth_req)?)
}
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index b176cfc..0280652 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -30,6 +30,7 @@
import com.android.microdroid.test.common.MetricsProcessor;
import com.android.microdroid.test.host.CommandRunner;
+import com.android.microdroid.test.host.KvmHypTracer;
import com.android.microdroid.test.host.MicrodroidHostTestCaseBase;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
@@ -37,6 +38,7 @@
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.SimpleStats;
import org.junit.After;
import org.junit.Before;
@@ -118,6 +120,20 @@
}
@Test
+ public void testNoLongHypSections() throws Exception {
+ assumeTrue("Skip without hypervisor tracing", KvmHypTracer.isSupported(getDevice()));
+
+ KvmHypTracer tracer = new KvmHypTracer(getDevice());
+ String result = tracer.run(COMPOSD_CMD_BIN + " test-compile");
+ assertWithMessage("Failed to test compilation VM.")
+ .that(result).ignoringCase().contains("all ok");
+
+ SimpleStats stats = tracer.getDurationStats();
+ reportMetric(stats.getData(), "hyp_sections", "s");
+ CLog.i("Hypervisor traces parsed successfully.");
+ }
+
+ @Test
public void testCameraAppStartupTime() throws Exception {
String[] launchIntentPackages = {
"com.android.camera2",
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/KvmHypTracer.java b/tests/hostside/helper/java/com/android/microdroid/test/host/KvmHypTracer.java
new file mode 100644
index 0000000..0d8ee96
--- /dev/null
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/KvmHypTracer.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2023 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
+ *
+ * http://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.
+ */
+
+package com.android.microdroid.test.host;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertNotNull;
+
+import com.android.microdroid.test.host.CommandRunner;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.SimpleStats;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
+
+/** This class provides utilities to interact with the hyp tracing subsystem */
+public final class KvmHypTracer {
+
+ private static final String HYP_TRACING_ROOT = "/sys/kernel/tracing/hyp/";
+ private static final String HYP_EVENTS[] = { "hyp_enter", "hyp_exit" };
+ private static final int DEFAULT_BUF_SIZE_KB = 4 * 1024;
+ private static final Pattern LOST_EVENT_PATTERN = Pattern.compile(
+ "^CPU:[0-9]* \\[LOST ([0-9]*) EVENTS\\]");
+ private static final Pattern EVENT_PATTERN = Pattern.compile(
+ "^\\[([0-9]*)\\][ \t]*([0-9]*\\.[0-9]*): (" + String.join("|", HYP_EVENTS) + ") (.*)");
+
+ private final CommandRunner mRunner;
+ private final ITestDevice mDevice;
+ private final int mNrCpus;
+
+ private final ArrayList<File> mTraces;
+
+ private void setNode(String node, int val) throws Exception {
+ mRunner.run("echo " + val + " > " + HYP_TRACING_ROOT + node);
+ }
+
+ private static String eventDir(String event) {
+ return "events/hyp/" + event + "/";
+ }
+
+ public static boolean isSupported(ITestDevice device) throws Exception {
+ for (String event: HYP_EVENTS) {
+ if (!device.doesFileExist(HYP_TRACING_ROOT + eventDir(event) + "/enable"))
+ return false;
+ }
+ return true;
+ }
+
+ public KvmHypTracer(@Nonnull ITestDevice device) throws Exception {
+ assertWithMessage("Hypervisor tracing not supported")
+ .that(isSupported(device)).isTrue();
+
+ mDevice = device;
+ mRunner = new CommandRunner(mDevice);
+ mTraces = new ArrayList<File>();
+ mNrCpus = Integer.parseInt(mRunner.run("nproc"));
+ }
+
+ public String run(String payload_cmd) throws Exception {
+ mTraces.clear();
+
+ setNode("tracing_on", 0);
+ mRunner.run("echo 0 | tee " + HYP_TRACING_ROOT + "events/*/*/enable");
+ setNode("buffer_size_kb", DEFAULT_BUF_SIZE_KB);
+ for (String event: HYP_EVENTS)
+ setNode(eventDir(event) + "/enable", 1);
+ setNode("trace", 0);
+
+ /* Cat each per-cpu trace_pipe in its own tmp file in the background */
+ String cmd = "cd " + HYP_TRACING_ROOT + ";";
+ String trace_pipes[] = new String[mNrCpus];
+ for (int i = 0; i < mNrCpus; i++) {
+ trace_pipes[i] = mRunner.run("mktemp -t trace_pipe.cpu" + i + ".XXXXXXXXXX");
+ cmd += "cat per_cpu/cpu" + i + "/trace_pipe > " + trace_pipes[i] + " &";
+ cmd += "CPU" + i + "_TRACE_PIPE_PID=$!;";
+ }
+
+ /* Run the payload with tracing enabled */
+ cmd += "echo 1 > tracing_on;";
+ String cmd_stdout = mRunner.run("mktemp -t cmd_stdout.XXXXXXXXXX");
+ cmd += payload_cmd + " > " + cmd_stdout + ";";
+ cmd += "echo 0 > tracing_on;";
+
+ /* Actively kill the cat subprocesses as trace_pipe is blocking */
+ for (int i = 0; i < mNrCpus; i++)
+ cmd += "kill -9 $CPU" + i + "_TRACE_PIPE_PID;";
+ cmd += "wait";
+
+ /*
+ * The whole thing runs in a single command for simplicity as `adb
+ * shell` doesn't play well with subprocesses outliving their parent,
+ * and cat-ing a trace_pipe is blocking, so doing so from separate Java
+ * threads wouldn't be much easier as we would need to actively kill
+ * them too.
+ */
+ mRunner.run(cmd);
+
+ for (String t: trace_pipes) {
+ File trace = mDevice.pullFile(t);
+ assertNotNull(trace);
+ mTraces.add(trace);
+ mRunner.run("rm -f " + t);
+ }
+
+ String res = mRunner.run("cat " + cmd_stdout);
+ mRunner.run("rm -f " + cmd_stdout);
+ return res;
+ }
+
+ public SimpleStats getDurationStats() throws Exception {
+ SimpleStats stats = new SimpleStats();
+
+ for (File trace: mTraces) {
+ BufferedReader br = new BufferedReader(new FileReader(trace));
+ double last = 0.0, hyp_enter = 0.0;
+ String l, prev_event = "";
+ while ((l = br.readLine()) != null) {
+ Matcher matcher = LOST_EVENT_PATTERN.matcher(l);
+ if (matcher.find())
+ throw new OutOfMemoryError("Lost " + matcher.group(1) + " events");
+
+ matcher = EVENT_PATTERN.matcher(l);
+ if (!matcher.find()) {
+ CLog.w("Failed to parse hyp event: " + l);
+ continue;
+ }
+
+ int cpu = Integer.parseInt(matcher.group(1));
+ if (cpu < 0 || cpu >= mNrCpus)
+ throw new ParseException("Incorrect CPU number: " + cpu, 0);
+
+ double cur = Double.parseDouble(matcher.group(2));
+ if (cur < last)
+ throw new ParseException("Time must not go backward: " + cur, 0);
+ last = cur;
+
+ String event = matcher.group(3);
+ if (event.equals(prev_event)) {
+ throw new ParseException("Hyp event found twice in a row: " + trace + " - " + l,
+ 0);
+ }
+
+ switch (event) {
+ case "hyp_exit":
+ if (prev_event.equals("hyp_enter"))
+ stats.add(cur - hyp_enter);
+ break;
+ case "hyp_enter":
+ hyp_enter = cur;
+ break;
+ default:
+ throw new ParseException("Unexpected line in trace" + l, 0);
+ }
+ prev_event = event;
+ }
+ }
+
+ return stats;
+ }
+}
diff --git a/vm_payload/Android.bp b/vm_payload/Android.bp
index 80d289b..97d4649 100644
--- a/vm_payload/Android.bp
+++ b/vm_payload/Android.bp
@@ -72,7 +72,7 @@
],
whole_static_libs: ["libvm_payload_impl"],
export_static_lib_headers: ["libvm_payload_impl"],
- installable: false,
+ no_full_install: true,
version_script: "libvm_payload.map.txt",
stubs: {
symbol_file: "libvm_payload.map.txt",