Слияние кода завершено, страница обновится автоматически
// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//! # MMIO
//!
//! This mod is used for create MMIO device.
//!
//! ## Design
//!
//! This module offers support for:
//! 1. DeviceType to identify NET,BLK,SERIAL...
//! 2. MMIO device structure.
//! 3. MMIO device trait.
//!
//! ## Platform Support
//!
//! - `x86_64`
//! - `aarch64`
use kvm_ioctls::VmFd;
use std::sync::{Arc, Mutex};
mod bus;
mod virtio_mmio;
pub use self::bus::Bus;
pub use self::virtio_mmio::VirtioMmioDevice;
use super::DeviceOps;
use address_space::{AddressSpace, GuestAddress, Region, RegionIoEventFd, RegionOps};
use error_chain::bail;
use machine_manager::config::{BootSource, ConfigCheck, Param};
pub mod errors {
error_chain! {
links {
AddressSpace(address_space::errors::Error, address_space::errors::ErrorKind);
Virtio(crate::virtio::errors::Error, crate::virtio::errors::ErrorKind);
}
errors {
MmioRegister(offset: u64) {
display("Unsupported mmio register, 0x{:x}", offset)
}
DeviceStatus(status: u32) {
display("Invalid device status 0x{:x}", status)
}
}
}
}
use self::errors::{Result, ResultExt};
/// The different type of MMIO Device.
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum DeviceType {
NET,
BLK,
SERIAL,
BALLOON,
#[cfg(target_arch = "aarch64")]
RTC,
OTHER,
CONSOLE,
}
/// The requirement of address space and irq number by MMIO device.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct DeviceResource {
/// Address space start address.
pub addr: u64,
/// Address space size.
pub size: u64,
/// Interrupt irq number.
pub irq: u32,
/// MMIO device type.
pub dev_type: DeviceType,
}
/// MmioDevice structure which used to register into system address space.
#[derive(Clone)]
pub struct MmioDevice {
/// MmioDeviceOps used to be invoked in function realize().
device: Arc<Mutex<dyn MmioDeviceOps>>,
/// RegionOps used to be registered into system address space.
region_ops: RegionOps,
/// The DeviceResource required by this MMIO device.
resource: Arc<DeviceResource>,
}
impl MmioDevice {
pub fn new<T: 'static + MmioDeviceOps>(
device: Arc<Mutex<T>>,
res: DeviceResource,
) -> MmioDevice {
let device_clone = device.clone();
let read_ops = move |data: &mut [u8], addr: GuestAddress, offset: u64| -> bool {
let mut device_locked = device_clone.lock().unwrap();
device_locked.read(data, addr, offset)
};
let device_clone = device.clone();
let write_ops = move |data: &[u8], addr: GuestAddress, offset: u64| -> bool {
let mut device_locked = device_clone.lock().unwrap();
device_locked.write(data, addr, offset)
};
let region_ops = RegionOps {
read: Arc::new(read_ops),
write: Arc::new(write_ops),
};
MmioDevice {
device,
region_ops,
resource: Arc::new(res),
}
}
/// Realize this MMIO device for VM.
///
/// # Arguments
///
/// * `vm_fd` - The file descriptor of VM.
/// * `bs` - The boot source of VM.
/// * `sys_mem` - The guest memory to device constructs over.
pub fn realize(
&self,
vm_fd: &VmFd,
bs: &Arc<Mutex<BootSource>>,
sys_mem: &Arc<AddressSpace>,
#[cfg(target_arch = "x86_64")] sys_io: Arc<AddressSpace>,
) -> Result<()> {
let dev_type = self.resource.dev_type;
self.device
.lock()
.unwrap()
.realize(vm_fd, *self.resource)
.chain_err(|| format!("Failed to realize device {:?}", dev_type))?;
let region = Region::init_io_region(self.resource.size, self.region_ops.clone());
region.set_ioeventfds(&self.device.lock().unwrap().ioeventfds());
match dev_type {
DeviceType::SERIAL if cfg!(target_arch = "x86_64") => {
#[cfg(target_arch = "x86_64")]
sys_io
.root()
.add_subregion(region, self.resource.addr)
.chain_err(|| {
format!(
"Failed to add subregion for io space, type {:?}, addr: 0x{:X}",
dev_type, self.resource.addr,
)
})?;
}
_ => {
sys_mem
.root()
.add_subregion(region, self.resource.addr)
.chain_err(|| {
format!(
"Failed to add subregion for mem space, type {:?}, addr: 0x{:X}",
dev_type, self.resource.addr,
)
})?;
}
}
// add to kernel cmdline
let cmdline = &mut bs.lock().unwrap().kernel_cmdline;
if let DeviceType::SERIAL = self.resource.dev_type {
#[cfg(target_arch = "aarch64")]
cmdline.push(Param {
param_type: "earlycon".to_string(),
value: format!("uart,mmio,0x{:08x}", self.resource.addr),
});
} else {
#[cfg(target_arch = "x86_64")]
cmdline.push(Param {
param_type: "virtio_mmio.device".to_string(),
value: format!(
"{}@0x{:08x}:{}",
self.resource.size, self.resource.addr, self.resource.irq
),
});
}
Ok(())
}
/// Get the resource requirement of MMIO device.
#[cfg(target_arch = "aarch64")]
pub fn get_resource(&self) -> DeviceResource {
*self.resource
}
/// Update the low level config of MMIO device.
///
/// # Arguments
///
/// * `file_path` - For Block device is image path; For Net device is tap path.
pub fn update_config(&self, dev_config: Option<Arc<dyn ConfigCheck>>) -> Result<()> {
self.device.lock().unwrap().update_config(dev_config)
}
}
/// Trait for MMIO device.
pub trait MmioDeviceOps: Send + DeviceOps {
/// Realize this MMIO device for VM.
fn realize(&mut self, vm_fd: &VmFd, resource: DeviceResource) -> Result<()>;
/// Get the resource requirement of MMIO device.
fn get_type(&self) -> DeviceType;
/// Update the low level config of MMIO device.
fn update_config(&mut self, _dev_config: Option<Arc<dyn ConfigCheck>>) -> Result<()> {
bail!("Unsupported to update configuration");
}
/// Get IoEventFds of MMIO device.
fn ioeventfds(&self) -> Vec<RegionIoEventFd> {
Vec::new()
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )