-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Big refactor #527
Big refactor #527
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #527 +/- ##
==========================================
+ Coverage 65.97% 68.19% +2.22%
==========================================
Files 17 20 +3
Lines 2110 2305 +195
==========================================
+ Hits 1392 1572 +180
- Misses 718 733 +15 ☔ View full report in Codecov by Sentry. |
56e55af
to
70891d0
Compare
I think, the reason this fails is the |
70891d0
to
1482a34
Compare
dd58f24
to
d55f4b8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks good overall. :)
I have a few comments though, it's a big PR after all. :D
benches/vm/mod.rs
Outdated
#[cfg(target_os = "linux")] | ||
let mut vm = UhyveVm::<KvmCpu>::new(path, params).expect("Unable to create VM"); | ||
#[cfg(target_os = "macos")] | ||
let mut vm = UhyveVm::<XhyveCpu>::new(path, params).expect("Unable to create VM"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, we should not force users to specify a Vcpu
implementation, since that makes code unnecessarily verbose. Essentially, we should move these cfg
s into the library somehow, making default usage easier.
I think a default type would be easiest. Something like:
#[cfg(target_os = "linux")]
pub type Vcpu = KvmCpu;
#[cfg(target_os = "macos")]
pub type Vcpu = XhyveCpu;
pub struct UhyveVm<T = Vcpu> {}
That would avoid exploding configurations into users of the library when there is only one option per target anyway. This also allows explicitly setting the type parameter, should that change in the future, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interestingly, this is not necessarily always required. See src/bin/uhyve.rs
. As there is only one implementation for VirtualCpuType
present for each architecture, Rust apparently picks that one.
I'm not quite sure if the verbosity is really a problem. As for our use cases, the virtualization backend does matter, it might make sense if the user should be forced to think about it. I'm still undecided, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The benchmarks you picked here are probably a pretty good example of where it should be kept explicit. If one day the default changes, you wouldn't want a surprising change in the benchmark performance just because it uses a different backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason explicit types are only required here is that run
is only implemented for the concrete type:
impl<VCpuType: VirtualCPU> UhyveVm<VCpuType> {
pub fn new();
}
impl UhyveVm<KvmCpu> {
pub fn run();
}
So whenever UhyveVm::<T>::run()
is called, T
is coerced to KvmCpu
(or whatever the concrete type is), since on that platform no other implementor of VirtualCPU
exists.
Consistency could be achieved either
- by making the signature of
UhyveVm::<T>::run()
independent ofKvmCpu
, forcing the user to explicitly supplyT
every time - or by providing the type hint for
UhyveVm
.
I strongly support the latter, since I see the added verbosity as pure boilerplate code.
Regarding benchmarks: Changes in benchmark performance should not be expected to be reflected in public API types. Changes in performance can happen through any changes in the library. This should be first and foremost the responsibility of the changelog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, this still boils down to a personal preference. I completely see why you favor this, but I, personally, don't like to be implicit on such an important design aspect here.
Consistency could be achieved either
- by making the signature of UhyveVm::::run() independent of KvmCpu, forcing the user to explicitly supply T every time
I thought about this before, and this would be a nice approach. The only problem here is run
with a debugger attached, which is on first sight not that trivial to make it part of the VirtualCPU
trait.
I'm all open to improving that part, but I'd suggest doing that, once other debugger interfaces (e.g., whatever MacOS uses) get implemented.
Regarding benchmarks: Changes in benchmark performance should not be expected to be reflected in public API types. Changes in performance can happen through any changes in the library. This should be first and foremost the responsibility of the changelog.
I totally agree when talking about smaller changes in performance due to implementation changes. But a change in the virtualization backend just because the default has changed can easily change the performance by orders of magnitude. This is not just an implementation detail for a library user, but a relevant choice when using UhyveVM
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Box<T, A = GlobalAlloc>
, HashMap<K, V, S = RandomState>
and LazyCell<T, F = fn() -> T>
all provide sensible defaults to avoid repeating yourself. Unnecessary cfg's
should really be avoided. Something like having a cross-platform AccelVcpu
and EmulatedVcpu
or similar in the future and a default would at least get rid of that.
I really cannot see how this would be an improvement for anyone. I can only see this making everyone's life more difficult (maintainers and users of the library). While I am strongly against this, the behavior and current use should at the very least be consistent and not change on whether rustc
can infer T
through run
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is resolved now, right?
c4718e6
to
6afda9e
Compare
6afda9e
to
2329720
Compare
45701a8
to
70f2796
Compare
Fixes #382 Breaks the whole ARM code
…Memory trait and guest_vm fn
- Added index functionality for MmapMemory - Added memory host_address and read functions with test - MmapMemory: Added slice access comfort fns - Use GuestPhysAddr in MmapMemory - changed mmap memory host addr to ptr type
Vcpu contains an Arc to the VM to access any non-cpu related information
…eads never to finish
…calls. Note: I did not increase the interface version, as there are no kernels out there that have used the incorrect type and uhyve has always treated it the way it is now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yaaay! 🥳
This is a big refactor around the former
VirtualCPU
andUhyveCPU
traits.Fixes #382
UhyveVM
, which is generic overVirtualCPU
implementations that provide the platform specific virtualization code.MmapMemory
.MmapMemory
provides more abstractions.arch
modules.GuestVirtAddr
andGuestPhysAddr
instead ofusize
/u64
where applicable.Note, the aarch64 code was not touched and is probably completely broken after this PR. But I think it already was before.