Skip to content

Commit f9febdc

Browse files
committed
WIP: Add CI build/run image for aarch64
Add Dockerfile that builds xen, copies oxerun.bin from host, runs it with qemu-system-aarch64 and checks that the hello world output was correctly shown in the VM's serial output. Build with: podman build . Run with: podman run IMAGE_ID Signed-off-by: Manos Pitsidianakis <[email protected]>
1 parent 12b00c3 commit f9febdc

File tree

9 files changed

+285
-0
lines changed

9 files changed

+285
-0
lines changed

.buildkite/smoke-tests.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"tests": [
3+
{
4+
"test_name": "oxerun: run hello world unikernel",
5+
"command": "cd tests && cargo test test_run_aarch64_smoke_test_in_qemu -- --nocapture",
6+
"soft_fail": "true",
7+
"docker_plugin": {
8+
"privileged": true
9+
},
10+
"platform": [
11+
"x86_64"
12+
]
13+
}
14+
]
15+
}

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ exclude = [
1111
"oxerun",
1212
"examples/ioctls",
1313
"examples/xstore",
14+
"tests",
1415
]

oxerun/Dockerfile

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
2+
FROM debian:bookworm-slim
3+
RUN <<EOF
4+
#!/bin/sh
5+
6+
apt-get update -y
7+
apt-get install -y \
8+
--no-install-suggests \
9+
--no-install-recommends \
10+
ca-certificates \
11+
wget \
12+
qemu-system-arm \
13+
ipxe-qemu \
14+
gcc-aarch64-linux-gnu \
15+
libc6-dev-arm64-cross \
16+
crossbuild-essential-arm64 \
17+
build-essential \
18+
flex \
19+
bison \
20+
ninja-build \
21+
make \
22+
gpg \
23+
gpg-agent \
24+
git \
25+
curl
26+
rm -rf /var/lib/apt/lists/*
27+
EOF
28+
29+
30+
-----BEGIN PGP PUBLIC KEY BLOCK-----
31+
32+
mQENBEu7PVUBCADN/1+JPpAxp3fDk8jZQ3cUKA3W0maOlyI/4+nlDai1gh83m9CN
33+
uGyY5kYLPBIR/sdG2hN5TVxTcE8qPCD9MivJXzOhBAmhQl0eXra0qmBBNu9kv+ZP
34+
qtPORPg2Jch1zZL5jOMawIE0xARZPgu21rPKNJo7V+HejWAHh0/LfFxzzI8LZ1LJ
35+
ACUuHEgfDJEi+u2wxDfjVaTO8HluNXm4TUIr16ExTx+61VDIE9qd3ikXkHgjp8xF
36+
sH0qG5IfcFDTPx9L2Fyk0utTnuNW014P4R31n32U9OolFm1MyOzWrMwVBoTi34aE
37+
nJRT6Aq/WaRfhjIWWkxhWnUgFbPPjMAkWL9fABEBAAG0WFhlbi5vcmcgWGVuIHRy
38+
ZWUgY29kZSBzaWduaW5nIChzaWduYXR1cmVzIG9uIHRoZSB4ZW4gaHlwZXJ2aXNv
39+
ciBhbmQgdG9vbHMpIDxwZ3BAeGVuLm9yZz6JAU0EEwECACAFAku7PVUCGwMGCwkI
40+
BwMCBBUCCAMEFgIDAQIeAQIXgAAhCRCD/hTJV+gr2RYhBCPjIiwUX0R1+oBgp4P+
41+
FMlX6CvZbMsH/jTs0LU/GouRrkjP71eOuEN/j127hYNbeDmTNclIz0PIhs0Ojsa4
42+
hu6nPZkKuLniHBSgSo3MHwYYYzuiqaCFN4JtoRAZPtVpUPsGj/qgXeSgSBv0gKWk
43+
TOIdpqAtlJCvo2QgI2qC68tRDlraLAyX1Ert/HGx8uAJ44a4RorhBmSJuWt0NiEu
44+
LrlWoRJech/G7VO6gC0CLzaxmxwu3HuTfZqCYnnNEUgszAi+KShdZUMZkwffuFpd
45+
6H8+pguFqIaGsXQIWBG1+FVCi9kdiN7Eme8Mxz75nKQnmEsP+d1p9uCzIui24me3
46+
XGXPw9dq7cCDIXZv+iq5Si7zMPm76S74Yyc=
47+
=h6NI
48+
-----END PGP PUBLIC KEY BLOCK-----
49+
EOF
50+
51+
RUN <<EOF
52+
#!/bin/sh
53+
54+
set -ve
55+
56+
gpg --import [email protected]
57+
EOF
58+
59+
RUN <<EOF
60+
#!/bin/sh
61+
62+
set -ve
63+
64+
wget https://downloads.xenproject.org/release/xen/4.18.3/xen-4.18.3.tar.gz
65+
EOF
66+
67+
RUN <<EOF
68+
#!/bin/sh
69+
70+
set -ve
71+
72+
wget https://downloads.xenproject.org/release/xen/4.18.3/xen-4.18.3.tar.gz.sig
73+
gpg --verify xen-4.18.3.tar.gz.sig xen-4.18.3.tar.gz
74+
EOF
75+
76+
RUN <<EOF
77+
#!/bin/sh
78+
79+
set -ve
80+
81+
tar xzf xen-4.18.3.tar.gz
82+
EOF
83+
84+
RUN <<EOF
85+
#!/bin/sh
86+
87+
set -ve
88+
89+
export WORKING_DIR="$(realpath `pwd`)"
90+
echo WORKING_DIR=${WORKING_DIR}
91+
cd ./xen-4.18.3/
92+
export EXTRA_CFLAGS_XEN_CORE=" -Wno-array-bounds "
93+
./configure --build=x86_64-unknown-linux-gnu --host=aarch64-linux-gnu \
94+
--disable-monitors \
95+
--disable-ocamltools \
96+
--disable-tools \
97+
--disable-docs \
98+
--disable-systemd \
99+
--enable-debug
100+
make debug=y debug_symbols=y XEN_TARGET_ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
101+
ls $(pwd)/dist/install/boot/
102+
file $(pwd)/dist/install/boot/*
103+
export XEN_KERNEL=$(realpath dist/install/boot/xen-4.18.3)
104+
echo XEN_KERNEL=${XEN_KERNEL}
105+
cp "${XEN_KERNEL}" "${WORKING_DIR}"/xen-4.18.3-kernel
106+
EOF
107+
108+
#RUN <<EOF
109+
##!/bin/sh
110+
111+
#curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y
112+
#. "${HOME}/.cargo/env"
113+
#rustup toolchain install --profile minimal nightly --target aarch64-linux-none
114+
#EOF
115+
116+
COPY ./target/aarch64-xen-hvm/release/oxerun.bin /oxerun.bin
117+
118+
COPY <<"EOF" /run_qemu_oxerun.sh
119+
#!/bin/sh
120+
121+
QEMU_OUTPUT=${QEMU_OUTPUT:-/qemu_output.stdout}
122+
XEN_KERNEL=${XEN_KERNEL:-/xen-4.18.3-kernel}
123+
DOM0_UNIKERNEL=${DOM0_UNIKERNEL:-/oxerun.bin}
124+
125+
echo QEMU_OUTPUT="${QEMU_OUTPUT}"
126+
echo XEN_KERNEL="${XEN_KERNEL}"
127+
echo DOM0_UNIKERNEL="${DOM0_UNIKERNEL}"
128+
129+
if [ ! -f "${XEN_KERNEL}" ]; then
130+
printf 'XEN_KERNEL value %s does not exist!\n' "${XEN_KERNEL}" 1>&2
131+
fi
132+
133+
if [ ! -f "${DOM0_UNIKERNEL}" ]; then
134+
printf 'DOM0_UNIKERNEL value %s does not exist!\n' "${DOM0_UNIKERNEL}" 1>&2
135+
fi
136+
137+
qemu-system-aarch64 \
138+
-D qemu.log \
139+
-d guest_errors \
140+
-machine virt,virtualization=on,gic-version=3 \
141+
-cpu cortex-a57 \
142+
-chardev file,id=char0,path="${QEMU_OUTPUT}" \
143+
-serial chardev:char0 \
144+
-monitor none \
145+
-display none \
146+
-m 8192 \
147+
-smp 4 \
148+
-kernel "${XEN_KERNEL}" \
149+
-append 'dom0_mem=4G loglvl=none guest_loglvl=none sync_console=true' \
150+
-device guest-loader,addr=0x80000000,kernel="${DOM0_UNIKERNEL}",bootargs='dom0_mem=4G loglvl=none guest_loglvl=none sync_console=true'
151+
152+
cat > /tmp/expected_output <<DOF
153+
Xen 4.18.3
154+
oxerun hello world
155+
DOF
156+
157+
if ! diff -w -u /tmp/expected_output "${QEMU_OUTPUT}"> /dev/null 2>&1; then
158+
diff -w -u /tmp/expected_output "${QEMU_OUTPUT}"
159+
exit 1
160+
fi
161+
162+
exit 0
163+
EOF
164+
165+
CMD ["/bin/sh", "/run_qemu_oxerun.sh"]

tests/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "tests"
3+
authors = ["Manos Pitsidianakis <[email protected]>"]
4+
version = "0.1.0"
5+
edition = "2021"
6+
publish = false
7+
license = "Apache-2.0 OR BSD-3-Clause"
8+
9+
[dependencies]

tests/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-APACHE

tests/LICENSE-BSD-3-Clause

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-BSD-3-Clause

tests/rust-toolchain.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel = "nightly"

tests/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause

tests/tests/oxerun_smoke_test.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
2+
3+
use std::{
4+
io::BufRead,
5+
path::Path,
6+
process::{Command, Stdio},
7+
sync::{Arc, Mutex},
8+
thread::sleep,
9+
time::{Duration, Instant},
10+
};
11+
12+
#[test]
13+
fn test_run_aarch64_smoke_test_in_qemu() {
14+
let repo_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../oxerun");
15+
let cargo_bin_path = Path::new(env!("CARGO"));
16+
//cargo build --target aarch64-xen-hvm.json -Zbuild-std=core
17+
// -Zbuild-std-features=compiler-builtins-mem --release
18+
19+
dbg!(Command::new(&cargo_bin_path)
20+
.args([
21+
"build",
22+
"--target",
23+
"./aarch64-xen-hvm.json",
24+
"-Zbuild-std=core",
25+
"-Zbuild-std-features=compiler-builtins-mem",
26+
"--release"
27+
])
28+
.current_dir(&repo_path)
29+
.stdin(Stdio::null())
30+
.stdout(Stdio::inherit())
31+
.stderr(Stdio::inherit())
32+
.output()
33+
.unwrap());
34+
35+
// aarch64-linux-gnu-objcopy target/aarch64-xen-hvm/release/oxerun -O binary
36+
// target/aarch64-xen-hvm/release/oxerun.bin
37+
dbg!(Command::new("aarch64-linux-gnu-objcopy")
38+
.args([
39+
"./target/aarch64-xen-hvm/release/oxerun",
40+
"-O",
41+
"binary",
42+
"./target/aarch64-xen-hvm/release/oxerun.bin"
43+
])
44+
.current_dir(&repo_path)
45+
.stdin(Stdio::null())
46+
.stdout(Stdio::inherit())
47+
.stderr(Stdio::inherit())
48+
.output()
49+
.unwrap());
50+
51+
// podman build . | tail -n 1
52+
let output = dbg!(Command::new("podman")
53+
.args(["build", "."])
54+
.current_dir(&repo_path)
55+
.stdin(Stdio::null())
56+
.stdout(Stdio::piped())
57+
.stderr(Stdio::inherit())
58+
.output()
59+
.unwrap());
60+
let id = dbg!(output.stdout.lines().last().unwrap().unwrap());
61+
62+
// podman run $img
63+
let mut child = dbg!(Command::new("podman")
64+
.args(["run", &id])
65+
.current_dir(&repo_path)
66+
.stdin(Stdio::null())
67+
.stdout(Stdio::piped())
68+
.stderr(Stdio::piped())
69+
.spawn()
70+
.unwrap());
71+
// wait 30 secs max
72+
let start = Instant::now();
73+
while Instant::now() - start <= Duration::from_secs(30) {
74+
if child.try_wait().is_ok() {
75+
let output = child.wait_with_output().unwrap();
76+
eprintln!("output:\n{:?}", &output);
77+
eprintln!("{}", String::from_utf8_lossy(&output.stdout));
78+
return;
79+
}
80+
sleep(Duration::from_millis(250));
81+
}
82+
if child.try_wait().is_err() {
83+
if let Err(err) = child.kill() {
84+
eprintln!("Could not wait for podmun run: {}", err);
85+
}
86+
let output = child.wait_with_output().unwrap();
87+
eprintln!("output:\n{:?}", &output);
88+
eprintln!("{}", String::from_utf8_lossy(&output.stdout));
89+
}
90+
}

0 commit comments

Comments
 (0)