Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ jobs:
pushd $t
cargo fmt --check
cargo clippy -- -D warnings
cargo test --no-fail-fast --all-features
popd
done

Expand All @@ -52,14 +51,18 @@ jobs:
- name: Install rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt, clippy
toolchain: nightly
components: llvm-tools
target: wasm32-unknown-unknown, x86_64-unknown-uefi
cache-workspaces: |
pixie-server
pixie-shared
pixie-uefi
pixie-web

- name: Install rustfilt
run: cargo install rustfilt

- name: Install trunk
uses: jetli/trunk-action@v0.5.0

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ buildroot/pixie.tar.gz
pixie-web/dist
.*.swp
pixie-shared/Cargo.lock
/prof-out
54 changes: 54 additions & 0 deletions pixie-uefi/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pixie-uefi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ path = "src/main.rs"
test = false
bench = false

[features]
coverage = ["dep:minicov"]

[dependencies]
anstyle = { version = "1.0.11", default-features = false }
blake3 = { version = "1.8.2", default-features = false, features = ["prefer_intrinsics", "no_avx512", "pure"] }
Expand All @@ -18,6 +21,7 @@ gpt_disk_io = "0.16.2"
log = "0.4.27"
lz4_flex = { version = "0.11.5", default-features = false }
managed = { version = "0.8.0", default-features = false, features = ["alloc"] }
minicov = { version = "0.3.7", optional = true }
postcard = { version = "1.1.3", default-features = false, features = ["alloc"] }
rand = { version = "0.8.5", default-features = false }
rand_xoshiro = { version = "0.6.0", default-features = false }
Expand Down
10 changes: 10 additions & 0 deletions pixie-uefi/src/export_cov.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::os::{disk::Disk, UefiOS};

pub async fn export(os: UefiOS) {
let mut disk = Disk::open_with_size(os, 500 << 20);

let mut coverage = vec![];
// SAFETY: we never create threads anyway.
unsafe { minicov::capture_coverage(&mut coverage).unwrap() };
disk.write_(0, &coverage).unwrap();
}
6 changes: 6 additions & 0 deletions pixie-uefi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ mod reboot_to_os;
mod register;
mod store;

#[cfg(feature = "coverage")]
mod export_cov;

const MIN_MEMORY: u64 = 500 << 20;

async fn server_discover(os: UefiOS) -> Result<SocketAddrV4> {
Expand Down Expand Up @@ -63,6 +66,9 @@ async fn server_discover(os: UefiOS) -> Result<SocketAddrV4> {
}

async fn shutdown(os: UefiOS) -> ! {
#[cfg(feature = "coverage")]
export_cov::export(os).await;

log::info!("Shutting down...");
os.sleep_us(1_000_000).await;
os.shutdown()
Expand Down
51 changes: 43 additions & 8 deletions pixie-uefi/src/os/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,46 @@ pub struct Disk {
// available; support having more than one disk.
impl Disk {
pub fn new(os: UefiOS) -> Disk {
let handle = uefi::boot::find_handles::<DiskIo>()
let (_size, handle) = uefi::boot::find_handles::<DiskIo>()
.unwrap()
.into_iter()
.find(|handle| {
let op = open_disk(*handle);
if let Ok((_, block)) = op {
if block.media().is_media_present() {
return true;
}
.filter_map(|handle| {
let op = open_disk(handle);
let Ok((_, block)) = op else {
return None;
};
let m = block.media();
if !m.is_media_present() {
return None;
}
false
let size = (m.last_block() as u128 + 1) * (m.block_size() as u128);
Some((size, handle))
})
.max_by_key(|(size, _)| *size)
.expect("Disk not found");

let (disk, block) = open_disk(handle).unwrap();
Disk { disk, block, os }
}

#[cfg(feature = "coverage")]
pub fn open_with_size(os: UefiOS, base_size: i64) -> Disk {
let (_size, handle) = uefi::boot::find_handles::<DiskIo>()
.unwrap()
.into_iter()
.filter_map(|handle| {
let op = open_disk(handle);
let Ok((_, block)) = op else {
return None;
};
let m = block.media();
if !m.is_media_present() {
return None;
}
let size = (m.last_block() as i64 + 1) * (m.block_size() as i64);
Some(((size - base_size).abs(), handle))
})
.min_by_key(|(size, _)| *size)
.expect("Disk not found");

let (disk, block) = open_disk(handle).unwrap();
Expand All @@ -83,6 +111,13 @@ impl Disk {
.read_disk(self.block.media().media_id(), offset, buf)?)
}

#[cfg(feature = "coverage")]
pub fn write_(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
Ok(self
.disk
.write_disk(self.block.media().media_id(), offset, buf)?)
}

pub async fn write(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
self.os.schedule().await;
Ok(self
Expand Down
5 changes: 4 additions & 1 deletion run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,16 @@ if ! ip link show br-pixie; then
ip addr add 10.0.0.1/8 brd 10.255.255.255 dev br-pixie
fi

RUST_BACKTRACE=short RUST_LOG=debug RUST_LOG_STYLE=always ./pixie-server/target/debug/pixie-server -s $TEMPDIR/storage &
RUST_BACKTRACE=short RUST_LOG=debug RUST_LOG_STYLE=always LLVM_PROFILE_FILE=prof-out/pixie-server-%m-%p.profraw ./pixie-server/target/debug/pixie-server -s $TEMPDIR/storage &

run_qemu() {
OVMF=/usr/share/OVMF/OVMF_CODE_4M.fd
if ! [ -e $OVMF ]
then
OVMF=/usr/share/edk2/x64/OVMF_CODE.4m.fd
fi
FILE=prof-out/pixie-uefi-$RANDOM.profraw
truncate -s 500M $FILE
qemu-system-x86_64 \
-nographic \
-chardev stdio,id=char0,logfile=$1,signal=off \
Expand All @@ -61,6 +63,7 @@ run_qemu() {
-m 1G \
-drive if=pflash,format=raw,file=$OVMF \
-drive file=$TEMPDIR/disk.img,if=none,id=nvm,format=raw \
-drive file=$FILE,format=raw \
-device nvme,serial=deadbeef,drive=nvm \
-nic bridge,mac=52:54:00:12:34:56,br=br-pixie,model=virtio-net-pci
}
Expand Down
57 changes: 56 additions & 1 deletion test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,62 @@ set -xe
SELFDIR="$(realpath "$(dirname "$0")")"
cd "$SELFDIR"

./setup.sh
STORAGE_DIR="${SELFDIR}/storage"

rm -rf prof-out
mkdir -p prof-out

SYSROOT=$(rustc +nightly --print sysroot)
LLVM_TOOLS_DIR="$SYSROOT/lib/rustlib/$(rustc +nightly -Vv | grep host | awk '{print $2}')/bin"
LLVM_COV="$LLVM_TOOLS_DIR/llvm-cov"
LLVM_PROFDATA="$LLVM_TOOLS_DIR/llvm-profdata"

pushd pixie-shared
RUSTFLAGS='-C instrument-coverage' LLVM_PROFILE_FILE=../prof-out/pixie-shared-test-%m-%p.profraw cargo +nightly test --no-fail-fast --all-features
popd

pushd pixie-uefi
RUSTFLAGS='-Cinstrument-coverage -Zno-profiler-runtime' cargo +nightly build -F coverage
popd

pushd pixie-web
trunk build
popd

pushd pixie-server
RUSTFLAGS='-C instrument-coverage' cargo +nightly build
popd

mkdir -p "${STORAGE_DIR}/tftpboot" "${STORAGE_DIR}/images" "${STORAGE_DIR}/chunks" "${STORAGE_DIR}/admin"
cp "pixie-uefi/target/x86_64-unknown-uefi/debug/pixie-uefi.efi" "${STORAGE_DIR}/tftpboot/"
cp -r pixie-web/dist/* "${STORAGE_DIR}/admin/"

[ -f "${STORAGE_DIR}/config.yaml" ] || cp pixie-server/example.config.yaml "${STORAGE_DIR}/config.yaml"

trap '' SIGTERM
sudo ./run_test.sh ${SELFDIR}/storage

TEST_OBJECTS=$( \
for file in \
$( \
RUSTFLAGS="-C instrument-coverage" \
cargo +nightly test --manifest-path pixie-shared/Cargo.toml --no-fail-fast --all-features --no-run --message-format=json \
| jq -r "select(.profile.test == true) | .filenames[]" \
| grep -v dSYM - \
); \
do \
printf "%s %s " -object $file; \
done \
)

"$LLVM_PROFDATA" merge -sparse prof-out/*.profraw -o prof-out/pixie.profdata
"$LLVM_COV" show \
-instr-profile=prof-out/pixie.profdata \
-object pixie-server/target/debug/pixie-server \
-object pixie-uefi/target/x86_64-unknown-uefi/debug/pixie-uefi.efi \
$TEST_OBJECTS \
-Xdemangler=rustfilt \
--ignore-filename-regex='/.cargo' \
--ignore-filename-regex='/.rustup' \
--format html \
-o prof-out/html