-
Notifications
You must be signed in to change notification settings - Fork 565
Add support for userspace IOAPIC #57
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
Conversation
|
I know clippy is not happy, I'll fix it tomorrow... |
|
Just fixed |
7540e9b to
2d221c4
Compare
|
@sameo @rbradford PR ready for review. I've added a test too! |
|
FYI, depends on rust-vmm/kvm#51 |
ed69207 to
7fb542d
Compare
70be2f1 to
8acb396
Compare
chao-p
left a comment
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.
If you pulled this from crosvm, could you indicate which commit you used?
Oh yes thanks for reminding me :) |
|
@chao-p comments addressed, please take another look. |
devices/src/ioapic.rs
Outdated
|
|
||
| type Result<T> = result::Result<T, Error>; | ||
|
|
||
| pub type IoapicInterrupt = Box<Fn(MsiMessage) -> result::Result<(), Error> + Send>; |
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.
Could we define a trait for that one instead?
pub trait IoapicInterrupt : Send {
fn deliver_msi(message: MsiMessage) -> Result<()>
}And then have struct Ioapic use that trait.
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.
Actually, why do we need this to be dynamic? When will we need anything but what's defined in
4b2d4fe#diff-a375fb00f71d40c3e15532f95f8f8933R426 , i.e. an MSI based interrupt injection through KVM? Is this to not add VmFd dependency on the IOAPIC implementation?
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.
As you mentioned, the reason for an abstraction here (callback or trait) is to prevent the IOAPIC code from being aware about the VmFd, which is KVM specific.
| // 11: Destination Mode - R/W | ||
| // 10-8: Delivery Mode - R/W | ||
| // 7-0: Interrupt Vector - R/W | ||
| pub type RedirectionTableEntry = u64; |
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.
Wouldn't it be more idiomatic to have a pub struct RedirectionTableEntry(u64) and then implement all the functions below as accessors?
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 thought about it, but then it's complicated to access the RedirectionTableEntry everywhere in the code, as you need to cast it into a u64 every single time you want to use it.
482671f to
7957beb
Compare
|
@sameo PR updated as discussed. The IOAPIC now takes a |
sameo
left a comment
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.
Besides the DeviceInterrupt callback that I'd like to see changed into a trait, this looks good to me.
devices/src/lib.rs
Outdated
| IoError(io::Error), | ||
| } | ||
|
|
||
| pub type DeviceInterrupt = Box<Fn() -> result::Result<(), std::io::Error> + Send>; |
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.
Could we please have that one as a trait and simply let the serial driver implement it?
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.
Yes I can try this, but to bring some clarification, this needs to go the other way around. The serial is a simple consumer of an object that needs to implement the DeviceInterrupt trait. And we need two distincts structures (UserIoapicIrq and KernelIoapicIrq for instance) which implement this trait. And one last point, this trait would only require a method deliver_interrupt() to be implemented.
Is this correct?
| .map_err(DeviceManagerError::Irq)?; | ||
|
|
||
| Box::new(move |_p: InterruptParameters| irqfd.write(1)) as InterruptDelivery | ||
| }; |
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.
Just a longer term comment: We have DeviceInterrupt and InterruptDelivery callbacks, for essentially doing the same thing: Delivering an interrupt to the guest. I think we should be looking at converging those 2 into one single trait.
This would make the VMM code clearer and easier to follow.
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.
Agreed. To be specific, I'm looking for something more generic Event (or EventChannel) trait and implementations, just need some abstract around Linux-specific EventFd. It's not only limited to host-to-guest event, but also guest-to-host event, and even inter-communication events between vmm and vhost-user-backend, etc.
trait Event {
pub notify(value)
}
struct IrqEvent {
eventfd: Option<EvendFd>;
}
impl Event for IrqEvent {
pub new(eventfd: EventFd) {
}
pub notify(value: Option) {
eventfd.write(1);
}
}Your latest version is very close to this and only the naming could be more generic.
This commit anticipate the future need from having support for both in kernel and userspace IOAPIC. The way to signal an interrupt from the serial device will vary depending on the use case, but this should be independent from the serial implementation itself. That's why this patch provides a generic trait for the serial device to call from, so that it can trigger interrupts independently from the IOAPIC type chosen (in kernel vs userspace). Signed-off-by: Sebastien Boeuf <[email protected]>
The goal for cloud-hypervisor is to keep the host safe. With this in mind, we want to emulate as much as possible in userspace instead of in kernel directly. The IOAPIC is a good candidate to move from kernel to userspace, which is why this commit introduces a userspace implementation of the IOAPIC 82093AA based on the documentation: https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf This code is inspired from the files devices/src/ioapic.rs and devices/src/split_irqchip_common.rs from the crosvm codebase. The reference version used being 6c1e23eee3065b3f3d6fc4fb992ac9884dbabf68. Signed-off-by: Sebastien Boeuf <[email protected]>
The previous commit introduced a userspace implementation of an IOAPIC and this commits aims to plumb it into the cloud-hypervisor VMM. Here is the list of new things brought by this patch: - Update the rust-vmm/kvm-ioctls dependency to benefit from latest patches including the support for split irqchip, and the vector being returned when a VM exit is caused by an EOI. - Enable the split irqchip (which means no IOAPIC or PIC is emulated in kernel). This is done conditionally based on the support of the TSC_DEADLINE_TIMER from both KVM and the underlying CPU. The dependency on TSC_DEADLINE_TIMER is related to KVM which does not support creating the in kernel PIT if it has a split irqchip. - Rely on callbacks to handle the following use cases: - in kernel IOAPIC + serial IRQ (pin based) - in kernel IOAPIC + virtio-pci MSI-X - in kernel IOAPIC + virtio-pci IRQ (pin based) - userspace IOAPIC + serial IRQ (pin based) - userspace IOAPIC + virtio-pci MSI-X - userspace IOAPIC + virtio-pci IRQ (pin based) Fixes cloud-hypervisor#13 Signed-off-by: Sebastien Boeuf <[email protected]>
Based on the newly added code, we expect the split irqchip to be used. This means we should not see any "timer" or "cascade" components attached to the IOAPIC since our userspace IOAPIC does not advertise those. Signed-off-by: Sebastien Boeuf <[email protected]>
|
@sameo PR updated. The callback has been removed and replaced by a trait :) |
sameo
left a comment
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'm ok merging that one as is. There's an ongoing discussion about how to make the interrupt delivery mechanism more generic, but I think this should be part of a separate PR.
If @chao-p is fine with it, we can merge.
yes, we can merge this. |
This pull request implements a userspace IOAPIC and plumbs
it into the cloud-hypervisor VMM to allow getting rid of the in
kernel emulation provided by
KVM_CREATE_IRQCHIP.It allows for what is called a "split" irqchip, which means that
only the local APIC is emulated in kernel.
Fixes #13