mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Use virtio-blk to support booting from disk image
After the virtio-blk device support has been introduced in the
previous commit, the vmm need to rely on this new device to boot
from disk images instead of initrd built into the kernel.
In order to achieve the proper support of virtio-blk, this commit
had to handle a few things:
- Register an ioevent fd for each virtqueue. This important to be
notified from the virtio driver that something has been written
on the queue.
- Fix the retrieval of 64bits BAR address. This is needed to provide
the right address which need to be registered as the notification
address from the virtio driver.
- Fix the write_bar and read_bar functions. They were both assuming
to be provided with an address, from which they were trying to
find the associated offset. But the reality is that the offset is
directly provided by the Bus layer.
- Register a new virtio-blk device as a virtio-pci device from the
vm.rs code. When the VM is started, it expects a block device to
be created, using this block device as the VM rootfs.
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
committed by
Samuel Ortiz
parent
65f96e408f
commit
b67e0b3dad
@@ -17,11 +17,13 @@ use std::fmt;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
mod block;
|
||||
mod device;
|
||||
mod queue;
|
||||
|
||||
pub mod transport;
|
||||
|
||||
pub use self::block::*;
|
||||
pub use self::device::*;
|
||||
pub use self::queue::*;
|
||||
|
||||
@@ -123,4 +125,7 @@ pub enum Error {
|
||||
event: DeviceEventT,
|
||||
},
|
||||
IoError(io::Error),
|
||||
EpollCreateFd(io::Error),
|
||||
EpollCtl(io::Error),
|
||||
EpollWait(io::Error),
|
||||
}
|
||||
|
||||
@@ -218,6 +218,18 @@ impl VirtioPciDevice {
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the list of queue events that must be triggered whenever the VM writes to
|
||||
/// `virtio::NOTIFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the
|
||||
/// value being written equals the index of the event in this list.
|
||||
pub fn queue_evts(&self) -> &[EventFd] {
|
||||
self.queue_evts.as_slice()
|
||||
}
|
||||
|
||||
/// Gets the event this device uses to interrupt the VM when the used queue is changed.
|
||||
pub fn interrupt_evt(&self) -> Option<&EventFd> {
|
||||
self.interrupt_evt.as_ref()
|
||||
}
|
||||
|
||||
fn is_driver_ready(&self) -> bool {
|
||||
let ready_bits =
|
||||
(DEVICE_ACKNOWLEDGE | DEVICE_DRIVER | DEVICE_DRIVER_OK | DEVICE_FEATURES_OK) as u8;
|
||||
@@ -305,6 +317,24 @@ impl PciDevice for VirtioPciDevice {
|
||||
&mut self.configuration
|
||||
}
|
||||
|
||||
fn ioeventfds(&self) -> Vec<(&EventFd, u64, u64)> {
|
||||
let bar0 = self
|
||||
.configuration
|
||||
.get_bar64_addr(self.settings_bar as usize);
|
||||
let notify_base = bar0 + NOTIFICATION_BAR_OFFSET;
|
||||
self.queue_evts()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, event)| {
|
||||
(
|
||||
event,
|
||||
notify_base + i as u64 * u64::from(NOTIFY_OFF_MULTIPLIER),
|
||||
i as u64,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn allocate_bars(
|
||||
&mut self,
|
||||
allocator: &mut SystemAllocator,
|
||||
@@ -326,8 +356,9 @@ impl PciDevice for VirtioPciDevice {
|
||||
})? as u8;
|
||||
|
||||
println!(
|
||||
"VIRTIO PCI BAR starts at 0x{:x}",
|
||||
virtio_pci_bar_addr.raw_value()
|
||||
"VIRTIO PCI BAR starts at 0x{:x}, size 0x{:x}",
|
||||
virtio_pci_bar_addr.raw_value(),
|
||||
CAPABILITY_BAR_SIZE
|
||||
);
|
||||
ranges.push((virtio_pci_bar_addr, CAPABILITY_BAR_SIZE));
|
||||
|
||||
@@ -349,10 +380,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
Ok(ranges)
|
||||
}
|
||||
|
||||
fn read_bar(&mut self, addr: u64, data: &mut [u8]) {
|
||||
// The driver is only allowed to do aligned, properly sized access.
|
||||
let bar0 = u64::from(self.configuration.get_bar_addr(self.settings_bar as usize));
|
||||
let offset = addr - bar0;
|
||||
fn read_bar(&mut self, offset: u64, data: &mut [u8]) {
|
||||
match offset {
|
||||
o if o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => self.common_config.read(
|
||||
o - COMMON_CONFIG_BAR_OFFSET,
|
||||
@@ -380,9 +408,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_bar(&mut self, addr: u64, data: &[u8]) {
|
||||
let bar0 = u64::from(self.configuration.get_bar_addr(self.settings_bar as usize));
|
||||
let offset = addr - bar0;
|
||||
fn write_bar(&mut self, offset: u64, data: &[u8]) {
|
||||
match offset {
|
||||
o if o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => self.common_config.write(
|
||||
o - COMMON_CONFIG_BAR_OFFSET,
|
||||
|
||||
Reference in New Issue
Block a user