Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@n0toose
Copy link
Member

@n0toose n0toose commented Oct 25, 2025

Experimental branch/pull request built on top of #754

@codecov
Copy link

codecov bot commented Oct 25, 2025

Codecov Report

❌ Patch coverage is 44.70046% with 120 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.26%. Comparing base (c1b5916) to head (87ff950).

Files with missing lines Patch % Lines
src/linux/x86_64/kvm_cpu.rs 23.40% 72 Missing ⚠️
src/hypercall.rs 60.00% 36 Missing ⚠️
uhyve-interface/src/lib.rs 50.00% 4 Missing ⚠️
uhyve-interface/src/v1/mod.rs 0.00% 3 Missing ⚠️
uhyve-interface/src/v2/mod.rs 0.00% 3 Missing ⚠️
src/vm.rs 83.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1145      +/-   ##
==========================================
- Coverage   76.70%   75.26%   -1.45%     
==========================================
  Files          29       31       +2     
  Lines        3490     3626     +136     
==========================================
+ Hits         2677     2729      +52     
- Misses        813      897      +84     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

let sysunlink = unsafe { mem.get_ref_mut(data).unwrap() };
Hypercall::FileUnlink(sysunlink)
}
HypercallAddress::Exit => Hypercall::Exit(data.as_u64() as i32),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... I frankly forgot why I just decided to pass the integer instead of dereferencing a pointer, but perhaps it might be worth thinking about?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understand.
Just passing the exit code directly is fine here - no further information is necessary when exiting.

};
}

let _ = unsafe {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment explaining this is likely needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment explaining this is likely needed.

Agreed; it's just that things do actually break if we use a non-relocatable image as of now, so I can't really justify that it's safe using a // SAFETY: comment just yet :D


let _ = unsafe {
pagetable_mapping.identity_map(
PhysFrame::<Size2MiB>::from_start_address(PhysAddr::new(0)).unwrap(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it also work when only mapping a 4KiB Page? Would that impact performance?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that impact performance?

You mentioned you wanted measurements for the MMIO-based hypercalls, is this in-scope?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be interesting to check the difference. Mapping a single 4KiB page is better from a memory point of view, but 2MiB pages are faster to access. Just a note here for later measurements.

@n0toose n0toose force-pushed the uhyve_if_v2-mmiowrite branch 2 times, most recently from 520e639 to 3aa5f14 Compare October 28, 2025 12:40
src/hypercall.rs Outdated
return peripherals.serial.output(bytes);
} else if !file_map.fdmap.is_fd_present(syswrite.fd.into_raw_fd()) {
// We don't write anything if the file descriptor is not available,
// but this is OK for now, as we have no means of returning an error code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is a new interface version that isn't currently deployed, wouldn't it make sense to adjust the write hypercall params to also have a way of returning non-fatal errors?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you envision?
I'm all open for extra fields here — the reasoning behind the current params is to be close to Linux/POSIX write. Since that is the de-facto interface to all applications as well as the file system interface on the Uhyve side, we save transformations when keeping things close.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm solely complaining about the lack of being able to emit non-fatal write errors back to the guest (currently all errors from writes afaik terminate the guest).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discussed this with @jounathaen last week and was mildly unsure as to what type of errors we could report here; it's not like we can use POSIX as a reference, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? Like, we could pick any arbitrary standard, we just have to make sure that it fits the constants defined in hermit-abi and isn't extremely cumbersome to use from the kernel side.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main errors that would make sense to forward are EPIPE, ECONNRESET (for host-side IPC stuff, i.e. anything that uses pipes or sockets on host-side) and ENOSPC (we can't expect the guest to know how much disk space it has available).

/// The discriminants of this enum are the respective addresses, so one can get the code by calling
/// e.g., `HypercallAddress::Exit as u64`.
#[non_exhaustive]
#[repr(u64)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this (e.g. HypercallAddress::Exit as u64) also work with #[repr(u16)] or such?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yes. But as this is intended to represent a GuestPhysAddr, I've opted for an u64 to reduce as 64 statements in the call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes a difference, and subsequently #[repr(u16)] should be preferred: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=610243c9a13c895b8140a3a22bddc5d4

@fogti fogti self-requested a review October 30, 2025 13:45
@fogti fogti marked this pull request as draft October 30, 2025 13:45
@fogti
Copy link
Contributor

fogti commented Oct 30, 2025

Given that this PR depends upon another PR that is currently marked as a draft, it makes to sense to mark this one as non-draft, yet.

@fogti
Copy link
Contributor

fogti commented Oct 30, 2025

tbqh, d1d002c took me way too long, but I think it does massively cut down on code duplication.

@fogti fogti force-pushed the uhyve_if_v2-mmiowrite branch from d1d002c to 3d13bb4 Compare October 30, 2025 15:12
@fogti
Copy link
Contributor

fogti commented Oct 30, 2025

Appears to work on linux now 🎉

Copy link
Contributor

@fogti fogti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from fixing the MacOS / Darwin part, this looks good now.

@n0toose
Copy link
Member Author

n0toose commented Nov 1, 2025

Apart from fixing the MacOS / Darwin part, this looks good now.

The test-kernels are also a bit of a problem. It would make sense to compile an older version of the kernel to test whether the I/O port-based hypercalls still work in those cases, right?

(P.S. I'm aware of the suggestion regarding that exit still)

@n0toose
Copy link
Member Author

n0toose commented Nov 1, 2025

We also aren't making the paging conditional - there are some corner cases (particularly when disabling ASLR) where this breaks, I think. So we're not quite done yet.

@n0toose n0toose force-pushed the uhyve_if_v2-mmiowrite branch from 3b25ec9 to 7287905 Compare November 7, 2025 16:08
@n0toose
Copy link
Member Author

n0toose commented Nov 7, 2025

Okay, now that the "abuse the macOS CI because I don't have a machine" strat worked, I should probably fix the mess I made trying to frantically rebase this, check whether I wiped some work during rebasing accidentally, squash and continue.

@n0toose n0toose force-pushed the uhyve_if_v2-mmiowrite branch from b4da38a to 2c77b78 Compare November 14, 2025 14:20
@n0toose n0toose marked this pull request as ready for review November 14, 2025 15:54
@n0toose n0toose changed the title Uhyve Interface V2 + MmioWrite-based hypercalls Introduce uhyve-interface v2 and MmioWrite-based hypercalls on x86_64 Nov 14, 2025
n0toose

This comment was marked as resolved.

Copy link
Contributor

@fogti fogti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, a few weirdnesses remain.

if let Ok(hypercall_port) = HypercallAddress::try_from(addr as u64) {
Some(match hypercall_port {
HypercallAddress::FileClose => {
let sysclose = unsafe { mem.get_ref_mut::<CloseParams>(data).unwrap() };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we sometimes have to explicitly denote the parameter type (e.g. ::<CloseParams> and sometimes not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this was answered yet...

n0toose added a commit to n0toose/uhyve that referenced this pull request Nov 29, 2025
This globally enforces a suggestion by Ellen in:
hermit-os#1145

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
n0toose added a commit to n0toose/uhyve that referenced this pull request Nov 29, 2025
This globally enforces a suggestion by Ellen in:
hermit-os#1145

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
n0toose added a commit to n0toose/uhyve that referenced this pull request Nov 29, 2025
This is based on a suggestion by Ellen:
hermit-os#1145 (comment)

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
if bytes_read >= 0 {
bytes_read as i64
} else {
-1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use some errno number here?

src/vm.rs Outdated
use std::{
env, fmt, fs, io,
num::NonZeroU32,
num::{NonZero, NonZeroU32},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably get rid of the NonZeroU32, too.

/// Number of bytes to read into the buffer.
pub len: usize,
pub len: u64,
/// Number of bytes read on success. `-1` on failure.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about -EFAULT?

n0toose added a commit to n0toose/uhyve that referenced this pull request Nov 29, 2025
This is based on a suggestion by Ellen:
hermit-os#1145 (comment)

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Dec 1, 2025
This globally enforces a suggestion by Ellen in:
#1145

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Dec 1, 2025
This is based on a suggestion by Ellen:
#1145 (comment)

Helped-by: Ellen Emilia Anna Zscheile <[email protected]>
@n0toose n0toose force-pushed the uhyve_if_v2-mmiowrite branch from a1aa479 to 175d06f Compare December 1, 2025 22:52
jounathaen and others added 4 commits December 2, 2025 00:16
Co-authored-by: Panagiotis "Ivory" Vasilopoulos <[email protected]>
- bump uhyve-interface to 0.2.0
- perform virtaddr -> physaddr conversions in hermit for read, write.
- use adjust serial_port based on version of uhyve-interface used
- Exit hypercalls should encode the exit code instead of a pointer to
  the integer. ExitArgs has been removed.
- v2: add v2 support in src/stats.rs, futureproof
- v2: use u64, i64 instead of usize, isize
- v2 (x86_64): allocate page for MmioExits

uhyve-interface (v2) should now use MmioWrite to invoke hypercalls,
so as to allow for using pointers to 64-bit addresses (ports
restrict us to 32-bit). This restriction should not apply for
serial writes, although it also remains possible for the kernel
to print out messages.

Co-authored-by: Ellen Emilia Anna Zscheile <[email protected]>
Co-authored-by: Jonathan Klimt <[email protected]>
@n0toose n0toose force-pushed the uhyve_if_v2-mmiowrite branch from 175d06f to 954e7e1 Compare December 1, 2025 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants