Skip to content

Commit e1078a3

Browse files
committed
Fix cargo feature 'crashdump'
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent a165293 commit e1078a3

File tree

15 files changed

+164
-229
lines changed

15 files changed

+164
-229
lines changed

.github/workflows/Benchmarks.yml

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,12 @@ jobs:
1717
strategy:
1818
fail-fast: true
1919
matrix:
20-
include:
21-
- build: windows-2022-release-amd
22-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-amd"]
23-
hypervisor: hyperv
24-
arch: amd
25-
- build: linux-kvm-release-amd
26-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-amd"]
27-
hypervisor: kvm
28-
arch: amd
29-
- build: linux-mshv-release-amd
30-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-amd"]
31-
hypervisor: mshv
32-
arch: amd
33-
- build: windows-2022-release-intel
34-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-intel"]
35-
hypervisor: hyperv
36-
arch: intel
37-
- build: linux-kvm-release-intel
38-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-intel"]
39-
hypervisor: kvm
40-
arch: intel
41-
- build: linux-mshv-release-intel
42-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-intel"]
43-
hypervisor: mshv
44-
arch: intel
20+
hypervisor: [hyperv, mshv, kvm] # hyperv is windows, mshv and kvm are linux
21+
cpu: [amd, intel]
22+
config: [release] # don't want to benchmark debug-builds
4523

46-
runs-on: ${{ matrix.os }}
24+
runs-on: ${{ fromJson(format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor, matrix.cpu)) }}
25+
4726
steps:
4827
### Setup ###
4928

@@ -82,7 +61,7 @@ jobs:
8261
run: git fetch --tags origin
8362

8463
- name: Download benchmarks from most recent release
85-
run: just bench-download ${{ runner.os }} ${{ matrix.hypervisor }} ${{ matrix.arch }} # skip tag parameter to compare to latest stable release
64+
run: just bench-download ${{ runner.os }} ${{ matrix.hypervisor }} ${{ matrix.cpu }} # skip tag parameter to compare to latest stable release
8665
continue-on-error: true
8766
env:
8867
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -92,6 +71,6 @@ jobs:
9271

9372
- uses: actions/upload-artifact@v4
9473
with:
95-
name: benchmarks_${{runner.os}}_${{matrix.hypervisor}}_${{ matrix.arch }}
74+
name: benchmarks_${{runner.os}}_${{matrix.hypervisor}}_${{ matrix.cpu }}
9675
path: ./target/criterion/
9776
if-no-files-found: error

.github/workflows/ValidatePullRequest.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ on:
77
branches: [main, "release/**"]
88
merge_group:
99

10+
# Cancels old running job if a new one is triggered (e.g. by a push onto the same branch).
11+
# This will cancel dependent jobs as well, such as dep_rust and dep_fuzzing
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
1016
permissions:
1117
id-token: write
1218
contents: read
@@ -42,6 +48,7 @@ jobs:
4248
secrets: inherit
4349
with:
4450
docs_only: ${{needs.docs-pr.outputs.docs-only}}
51+
4552
fuzzing:
4653
needs:
4754
- docs-pr
@@ -50,6 +57,7 @@ jobs:
5057
max_total_time: 300 # 5 minutes in seconds
5158
docs_only: ${{needs.docs-pr.outputs.docs-only}}
5259
secrets: inherit
60+
5361
spelling:
5462
name: spell check with typos
5563
runs-on: ubuntu-latest

.github/workflows/dep_rust.yml

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -26,69 +26,11 @@ jobs:
2626
strategy:
2727
fail-fast: true
2828
matrix:
29-
include:
30-
- build: windows-2022-debug-amd
31-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-amd"]
32-
hypervisor: hyperv
33-
config: debug
34-
arch: amd
35-
- build: linux-kvm-debug-amd
36-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-amd"]
37-
hypervisor: kvm
38-
config: debug
39-
arch: amd
40-
- build: linux-mshv-debug-amd
41-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-amd"]
42-
hypervisor: mshv
43-
config: debug
44-
arch: amd
45-
- build: windows-2022-release-amd
46-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-amd"]
47-
hypervisor: hyperv
48-
config: release
49-
arch: amd
50-
- build: linux-kvm-release-amd
51-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-amd"]
52-
hypervisor: kvm
53-
config: release
54-
arch: amd
55-
- build: linux-mshv-release-amd
56-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-amd"]
57-
hypervisor: mshv
58-
config: release
59-
arch: amd
60-
- build: windows-2022-debug-intel
61-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-intel"]
62-
hypervisor: hyperv
63-
config: debug
64-
arch: intel
65-
- build: linux-kvm-debug-intel
66-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-intel"]
67-
hypervisor: kvm
68-
config: debug
69-
arch: intel
70-
- build: linux-mshv-debug-intel
71-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-intel"]
72-
hypervisor: mshv
73-
config: debug
74-
arch: intel
75-
- build: windows-2022-release-intel
76-
os: [self-hosted, Windows, X64, "1ES.Pool=hld-win2022-intel"]
77-
hypervisor: hyperv
78-
config: release
79-
arch: intel
80-
- build: linux-kvm-release-intel
81-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-intel"]
82-
hypervisor: kvm
83-
config: release
84-
arch: intel
85-
- build: linux-mshv-release-intel
86-
os: [self-hosted, Linux, X64, "1ES.Pool=hld-mshv-intel"]
87-
hypervisor: mshv
88-
config: release
89-
arch: intel
90-
91-
runs-on: ${{ matrix.os }}
29+
hypervisor: [hyperv, mshv, kvm] # hyperv is windows, mshv and kvm are linux
30+
cpu: [amd, intel]
31+
config: [debug, release]
32+
33+
runs-on: ${{ fromJson(format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor, matrix.cpu)) }}
9234
steps:
9335
- uses: actions/checkout@v4
9436

@@ -132,6 +74,9 @@ jobs:
13274
# with only one driver enabled (driver mshv/kvm feature is ignored on windows) + seccomp + inprocess
13375
just test-rust ${{ matrix.config }} inprocess,seccomp,${{ matrix.hypervisor == 'mshv' && 'mshv' || 'kvm' }}
13476
77+
# make sure certain cargo features compile
78+
cargo check -p hyperlight-host --features crashdump
79+
13580
# without any driver (shouldn't compile)
13681
just test-rust-feature-compilation-fail ${{ matrix.config }}
13782
@@ -160,7 +105,7 @@ jobs:
160105
run: sudo apt install gh -y
161106

162107
- name: Download benchmarks from "latest"
163-
run: just bench-download ${{ runner.os }} ${{ matrix.hypervisor }} ${{ matrix.arch}} dev-latest # compare to prerelease
108+
run: just bench-download ${{ runner.os }} ${{ matrix.hypervisor }} ${{ matrix.cpu}} dev-latest # compare to prerelease
164109
env:
165110
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
166111
continue-on-error: true

Justfile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,13 @@ run-rust-examples-linux target=default-target: (build-rust target) (run-rust-exa
165165
# Downloads the benchmarks result from the given release tag.
166166
# If tag is not given, defaults to latest release
167167
# Options for os: "Windows", or "Linux"
168-
# Options for Linux hypervisor: "kvm", "hyperv"
168+
# Options for Linux hypervisor: "kvm", "mshv"
169169
# Options for Windows hypervisor: "hyperv"
170-
# Options for arch: "amd", "intel"
171-
bench-download os hypervisor arch tag="":
172-
gh release download {{ tag }} -D ./target/ -p benchmarks_{{ os }}_{{ hypervisor }}_{{ arch }}.tar.gz
170+
# Options for cpu: "amd", "intel"
171+
bench-download os hypervisor cpu tag="":
172+
gh release download {{ tag }} -D ./target/ -p benchmarks_{{ os }}_{{ hypervisor }}_{{ cpu }}.tar.gz
173173
mkdir -p target/criterion {{ if os() == "windows" { "-Force" } else { "" } }}
174-
tar -zxvf target/benchmarks_{{ os }}_{{ hypervisor }}_{{ arch }}.tar.gz -C target/criterion/ --strip-components=1
174+
tar -zxvf target/benchmarks_{{ os }}_{{ hypervisor }}_{{ cpu }}.tar.gz -C target/criterion/ --strip-components=1
175175

176176
# Warning: compares to and then OVERWRITES the given baseline
177177
bench-ci baseline target=default-target:

docs/debugging-hyperlight.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ cargo test --package hyperlight-host --test integration_test --features print_de
3939

4040
## Dumping the memory configuration, virtual processor register state and memory contents on a crash or unexpected VM Exit
4141

42-
To dump the details of the memory configuration, the virtual processors register state and the contents of the VM memory set the feature `dump_on_crash` and run a debug build. This will result in a dump file being created in the temporary directory. The name and location of the dump file will be printed to the console and logged as an error message.
42+
To dump the details of the memory configuration, the virtual processors register state and the contents of the VM memory set the feature `crashdump` and run a debug build. This will result in a dump file being created in the temporary directory. The name and location of the dump file will be printed to the console and logged as an error message.
4343

4444
There are no tools at this time to analyze the dump file, but it can be useful for debugging.

src/hyperlight_host/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,7 @@ function_call_metrics = []
118118
executable_heap = []
119119
# This feature enables printing of debug information to stdout in debug builds
120120
print_debug = []
121-
# This feature enables dunping of the VMs details to a file when an unexpected or error exit occurs in a VM in debug mode
122-
# the name of the file is output to stdout and logged.
123-
dump_on_crash = ["dep:tempfile"]
121+
crashdump = ["dep:tempfile"] # Dumps the VM state to a file on unexpected errors or crashes. The path of the file will be printed on stdout and logged. This feature can only be used in debug builds.
124122
kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"]
125123
mshv = ["dep:mshv-bindings", "dep:mshv-ioctls"]
126124
inprocess = []

src/hyperlight_host/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ fn main() -> Result<()> {
9494
// inprocess feature is aliased with debug_assertions to make it only available in debug-builds.
9595
// You should never use #[cfg(feature = "inprocess")] in the codebase. Use #[cfg(inprocess)] instead.
9696
inprocess: { all(feature = "inprocess", debug_assertions) },
97+
// crashdump feature is aliased with debug_assertions to make it only available in debug-builds.
98+
crashdump: { all(feature = "crashdump", debug_assertions) },
9799
}
98100

99101
write_built_file()?;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::io::Write;
2+
3+
use tempfile::NamedTempFile;
4+
5+
use super::Hypervisor;
6+
use crate::{new_error, Result};
7+
8+
/// Dump registers + memory regions + raw memory to a tempfile
9+
#[cfg(crashdump)]
10+
pub(crate) fn crashdump_to_tempfile(hv: &dyn Hypervisor) -> Result<()> {
11+
let mem_regions = hv.get_memory_regions();
12+
let mem_size = mem_regions
13+
.iter()
14+
.map(|region| region.host_region.len())
15+
.sum();
16+
let mem_start_addr = mem_regions[0].host_region.start as *const u8;
17+
18+
if mem_start_addr.is_null() || mem_size == 0 {
19+
return Err(new_error!(
20+
"Invalid address or size while creating crashdump"
21+
));
22+
}
23+
24+
let mut temp_file = NamedTempFile::with_prefix("mem")?;
25+
26+
let hv_details = format!("{:#x?}", hv);
27+
28+
// write hypervisor details such as registers, memory regions, etc.
29+
temp_file.write_all(hv_details.as_bytes())?;
30+
// write memory dump
31+
temp_file.write_all(b"================ MEMORY DUMP =================\n")?;
32+
// SAFETY: Address and size non-null and non-zero
33+
unsafe {
34+
let slice = std::slice::from_raw_parts(mem_start_addr, mem_size);
35+
temp_file.write_all(slice)?;
36+
temp_file.flush()?;
37+
}
38+
let persist_path = temp_file.path().with_extension("dmp");
39+
temp_file
40+
.persist(&persist_path)
41+
.map_err(|e| new_error!("Failed to persist crashdump file: {:?}", e))?;
42+
43+
println!("Memory dumped to file: {:?}", persist_path);
44+
log::error!("Memory dumped to file: {:?}", persist_path);
45+
46+
Ok(())
47+
}

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,6 @@ impl Hypervisor for HypervLinuxDriver {
311311
"mshv MMIO unmapped GPA -Details: Address: {} \n {:#?}",
312312
addr, &self
313313
);
314-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
315-
self.dump_on_crash(self.mem_regions.clone());
316314
HyperlightExit::Mmio(addr)
317315
}
318316
INVALID_GPA_ACCESS_MESSAGE => {
@@ -323,8 +321,6 @@ impl Hypervisor for HypervLinuxDriver {
323321
"mshv MMIO invalid GPA access -Details: Address: {} \n {:#?}",
324322
gpa, &self
325323
);
326-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
327-
self.dump_on_crash(self.mem_regions.clone());
328324
match self.get_memory_access_violation(
329325
gpa as usize,
330326
&self.mem_regions,
@@ -336,8 +332,6 @@ impl Hypervisor for HypervLinuxDriver {
336332
}
337333
other => {
338334
debug!("mshv Other Exit: Exit: {:#?} \n {:#?}", other, &self);
339-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
340-
self.dump_on_crash(self.mem_regions.clone());
341335
log_then_return!("unknown Hyper-V run message type {:?}", other);
342336
}
343337
},
@@ -347,8 +341,6 @@ impl Hypervisor for HypervLinuxDriver {
347341
libc::EAGAIN => HyperlightExit::Retry(),
348342
_ => {
349343
debug!("mshv Error - Details: Error: {} \n {:#?}", e, &self);
350-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
351-
self.dump_on_crash(self.mem_regions.clone());
352344
log_then_return!("Error running VCPU {:?}", e);
353345
}
354346
},
@@ -360,6 +352,11 @@ impl Hypervisor for HypervLinuxDriver {
360352
fn as_mut_hypervisor(&mut self) -> &mut dyn Hypervisor {
361353
self as &mut dyn Hypervisor
362354
}
355+
356+
#[cfg(crashdump)]
357+
fn get_memory_regions(&self) -> &[MemoryRegion] {
358+
&self.mem_regions
359+
}
363360
}
364361

365362
impl Drop for HypervLinuxDriver {

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -508,18 +508,6 @@ impl Hypervisor for HypervWindowsDriver {
508508
"HyperV Memory Access Details :\n GPA: {:#?}\n Access Info :{:#?}\n {:#?} ",
509509
gpa, access_info, &self
510510
);
511-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
512-
{
513-
if let Err(e) = unsafe {
514-
self.write_dump_file(
515-
self.mem_regions.clone(),
516-
self.source_address.add(PAGE_SIZE_USIZE) as *const u8,
517-
self.size,
518-
)
519-
} {
520-
println!("Error dumping memory: {}", e);
521-
}
522-
}
523511

524512
match self.get_memory_access_violation(gpa as usize, &self.mem_regions, access_info)
525513
{
@@ -539,18 +527,6 @@ impl Hypervisor for HypervWindowsDriver {
539527
"HyperV Unexpected Exit Details :#nReason {:#?}\n {:#?}",
540528
exit_context.ExitReason, &self
541529
);
542-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
543-
{
544-
if let Err(e) = unsafe {
545-
self.write_dump_file(
546-
self.mem_regions.clone(),
547-
self.source_address.add(PAGE_SIZE_USIZE) as *const u8,
548-
self.size,
549-
)
550-
} {
551-
println!("Error dumping memory: {}", e);
552-
}
553-
}
554530
match self.get_exit_details(exit_context.ExitReason) {
555531
Ok(error) => HyperlightExit::Unknown(error),
556532
Err(e) => HyperlightExit::Unknown(format!("Error getting exit details: {}", e)),
@@ -569,6 +545,11 @@ impl Hypervisor for HypervWindowsDriver {
569545
fn as_mut_hypervisor(&mut self) -> &mut dyn Hypervisor {
570546
self as &mut dyn Hypervisor
571547
}
548+
549+
#[cfg(crashdump)]
550+
fn get_memory_regions(&self) -> &[MemoryRegion] {
551+
&self.mem_regions
552+
}
572553
}
573554

574555
#[cfg(test)]

0 commit comments

Comments
 (0)