-
Notifications
You must be signed in to change notification settings - Fork 1.9k
WIP: Refactor device managers, preparing for PCIe devices #5174
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
base: feature/pcie
Are you sure you want to change the base?
WIP: Refactor device managers, preparing for PCIe devices #5174
Conversation
503fa5d
to
a7ec377
Compare
903e15a
to
564c7c0
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/pcie #5174 +/- ##
================================================
- Coverage 82.93% 82.88% -0.05%
================================================
Files 251 253 +2
Lines 27069 27169 +100
================================================
+ Hits 22450 22520 +70
- Misses 4619 4649 +30
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
ffb9ed0
to
f84229f
Compare
Bring in the vm-device crate from CloudHypervisor. We will be using it for adding PCIe support. Signed-off-by: Babis Chalios <[email protected]>
We use `SerialDevice` with Stdin as the input source. Encode this in the type so that we don't spill the generic all over the place. Signed-off-by: Babis Chalios <[email protected]> Co-authored-by: Egor Lazarchuk <[email protected]> Signed-off-by: Egor Lazarchuk <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
Use the vm_device::Bus bus for all MMIO devices. This mainly to prepare for using it for PCIe devices. Also, sepate VirtIO devices from other MMIO devices inside the MMIODeviceManager struct. This makes iterating over VirtIO devices since we don't need to access two data structures as to get a reference to a VirtIO device any more. Signed-off-by: Babis Chalios <[email protected]>
We were always constructing RTCDevice using a set of metrics that were defined in the RTC module itself. Don't leak the metrics to other modules. Instead, create a new() function that always constructs it the correct way. Signed-off-by: Babis Chalios <[email protected]>
Use the vm_device::Bus bus for PortIO devices on x86. PCIe devices will use this as well. Signed-off-by: Babis Chalios <[email protected]>
PCIe spec mandates that software can access the configuration space of PCIe devices both via MMIO and Port IO accesses. As a result, PCIe devices will need to register to both buses (on x86). Change the organization of devices, so that MMIO and PIO device managers do not own the buses. Instead, introduce a DeviceManager object which holds the buses, the resource allocator and includes also all types of device managers (at the moment MMIO, PIO and ACPI). Signed-off-by: Babis Chalios <[email protected]>
match &self.serial { | ||
Some(device) => { |
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 can be an assert, as the serial is registered right before this call. Otherwise maybe just remove this function and to the addition inline in the attach_legacy_devices_aarch64
? (like we do for block devices)
balloon.process_virtio_queues(); | ||
} | ||
let _: Result<(), MmioError> = self.for_each_virtio_device(|virtio_type, id, device| { | ||
let mmio_transport_locked = device.inner.lock().expect("Poisoned locked"); |
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.
s/locked/lock/
impl MmioTransport { | ||
pub fn bus_read(&mut self, offset: u64, data: &mut [u8]) { | ||
impl vm_device::BusDevice for MmioTransport { | ||
fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) { |
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 see that the base
arg is never used, so maybe it is worth removing it from a trait definition?
And same question about Option<Arc<Barrier>>
return type in write
function.
src/vmm/src/builder.rs
Outdated
let i8042 = Arc::new(Mutex::new(I8042Device::new( | ||
reset_evt, | ||
EventFd::new(libc::EFD_NONBLOCK).map_err(VmmError::EventFd)?, | ||
))); |
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.
note: the I8042Device::new
can be simplified by moving EventFd
creation inside and asserting on 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.
What are the gaps between the rust-vmm vm-devices
create and this one? Is there any possibility of upstreaming these changes to the crate?
src/vmm/src/builder.rs
Outdated
}))); | ||
let serial = Arc::new(Mutex::new(BusDevice::Serial( | ||
SerialDevice::new(Some(std::io::stdin()), SerialOut::Stdout(std::io::stdout())) | ||
.map_err(VmmError::EventFd)?, |
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.
nit: can this fail only due to EventFd
?
device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, | ||
virtio_devices: Vec<&MMIODeviceInfo>, | ||
rtc: Option<&MMIODeviceInfo>, | ||
serial: Option<&MMIODeviceInfo>, |
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.
can this be simplified by passing the DeviceManager
as we do in ACPI?
src/vmm/src/builder.rs
Outdated
@@ -615,7 +615,11 @@ fn attach_legacy_devices_aarch64( | |||
if cmdline_contains_console { | |||
// Make stdout non-blocking. | |||
set_stdout_nonblocking(); | |||
let serial = setup_serial_device(event_manager)?; |
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 didn't follow why we're inlining the function here for arm but not for x86. Also, this could be moved to the earlier commit.
#[cfg(target_arch = "x86_64")] | ||
pub(crate) dsdt_data: Vec<u8>, |
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.
any reason to leave this in in ARM?
let _: Result<(), MmioError> = self.for_each_virtio_device(|virtio_type, id, device| { | ||
let mmio_transport_locked = device.inner.lock().expect("Poisoned locked"); | ||
let mut virtio = mmio_transport_locked.locked_device(); | ||
match *virtio_type { |
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.
unrelated to the scope of this PR, but I'm wondering if the "kick" can become a trait function that we call on every device, rather than having this combination of downcast and device-specific logic.
self.bus | ||
.insert(device.clone(), device_info.addr, device_info.len)?; |
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.
does the "register" function no longer actually register the device with the bus?
let boot_timer = Arc::new(Mutex::new(BootTimer::new(request_ts))); | ||
|
||
self.mmio_devices | ||
.register_mmio_boot_timer(&mut self.resource_allocator, boot_timer)?; |
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.
does this not get registered with the Bus?
Ok(serial) | ||
} | ||
|
||
#[cfg_attr(target_arch = "aarch64", allow(unused))] |
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.
nit: why allow(unused)
?
Changes
Group all device managers in a single top-level device manager, which now becomes the owner of the MMIO and Port IO buses along with the resource allocator. Also, it gets rid of the our
Bus
implementation in favour of thevm-device
one from Cloud Hypervisor.Reason
PCIe devices also need to be registered to the MMIO and Port IO buses. So, it makes more sense to keep the buses outside of MMIO and PortIO device managers.
Regarding switching to using
vm_devices::Bus
, PCIe implementation is using it and it was quite simpler to switch our own implementation to the upstream type rather than the other way around.License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md
.PR Checklist
tools/devtool checkstyle
to verify that the PR passes theautomated style checks.
how they are solving the problem in a clear and encompassing way.
in the PR.
CHANGELOG.md
.Runbook for Firecracker API changes.
integration tests.
TODO
.rust-vmm
.