vmm: Add acpi table for fw_cfg device
This allows the fw_cfg device to be recognized by the guest linux kernel. This becomes more relavnt in the following cl where I add the option to load files into the guest via fw_cfg. The Linux kernel already has a fw_cfg driver that will automatically load these files under /sys when CONFIG_FW_CFG_SYSFS is enabled in the kernel config For arm we must add fw_cfg to the devices tree Signed-off-by: Alex Orozco <alexorozco@google.com>
This commit is contained in:
parent
edee53ac1a
commit
971f552e09
6 changed files with 69 additions and 5 deletions
|
|
@ -6,6 +6,7 @@ version = "0.1.0"
|
|||
|
||||
[features]
|
||||
default = []
|
||||
fw_cfg = []
|
||||
kvm = ["hypervisor/kvm"]
|
||||
sev_snp = []
|
||||
tdx = []
|
||||
|
|
|
|||
|
|
@ -850,6 +850,21 @@ fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/devicetree/bindings/arm/fw-cfg.txt
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
fn create_fw_cfg_node<T: DeviceInfoForFdt + Clone + Debug>(
|
||||
fdt: &mut FdtWriter,
|
||||
dev_info: &T,
|
||||
) -> FdtWriterResult<()> {
|
||||
// FwCfg node
|
||||
let fw_cfg_node = fdt.begin_node(&format!("fw-cfg@{:x}", dev_info.addr()))?;
|
||||
fdt.property("compatible", b"qemu,fw-cfg-mmio\0")?;
|
||||
fdt.property_array_u64("reg", &[dev_info.addr(), dev_info.length()])?;
|
||||
fdt.end_node(fw_cfg_node)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||
fdt: &mut FdtWriter,
|
||||
dev_info: &HashMap<(DeviceType, String), T, S>,
|
||||
|
|
@ -865,6 +880,8 @@ fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Buil
|
|||
DeviceType::Virtio(_) => {
|
||||
ordered_virtio_device.push(info);
|
||||
}
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
DeviceType::FwCfg => create_fw_cfg_node(fdt, info)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ pub enum DeviceType {
|
|||
/// Device Type: GPIO.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
Gpio,
|
||||
/// Device Type: fw_cfg.
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
FwCfg,
|
||||
}
|
||||
|
||||
/// Default (smallest) memory page size for the supported architectures.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,6 @@ arch = { path = "../arch" }
|
|||
|
||||
[features]
|
||||
default = []
|
||||
fw_cfg = ["bitfield-struct", "linux-loader", "zerocopy"]
|
||||
fw_cfg = ["arch/fw_cfg", "bitfield-struct", "linux-loader", "zerocopy"]
|
||||
kvm = ["arch/kvm"]
|
||||
pvmemcontrol = []
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ const FW_CFG_KNOWN_ITEMS: usize = 0x20;
|
|||
|
||||
pub const FW_CFG_FILE_FIRST: u16 = 0x20;
|
||||
pub const FW_CFG_DMA_SIGNATURE: [u8; 8] = *b"QEMU CFG";
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/qemu_fw_cfg.h
|
||||
pub const FW_CFG_ACPI_ID: &str = "QEMU0002";
|
||||
// Reserved (must be enabled)
|
||||
const FW_CFG_F_RESERVED: u8 = 1 << 0;
|
||||
// DMA Toggle Bit (enabled by default)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ use devices::gic;
|
|||
use devices::interrupt_controller::InterruptController;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use devices::ioapic;
|
||||
#[cfg(all(feature = "fw_cfg", target_arch = "x86_64"))]
|
||||
use devices::legacy::fw_cfg::FW_CFG_ACPI_ID;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use devices::legacy::Pl011;
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
|
||||
|
|
@ -1495,11 +1497,29 @@ impl DeviceManager {
|
|||
// default address for fw_cfg on arm via mmio
|
||||
// https://github.com/torvalds/linux/blob/master/drivers/firmware/qemu_fw_cfg.c#L27
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
self.address_manager
|
||||
.mmio_bus
|
||||
.insert(fw_cfg.clone(), PORT_FW_CFG_BASE, PORT_FW_CFG_WIDTH)
|
||||
.map_err(DeviceManagerError::ErrorAddingFwCfgToBus)?;
|
||||
{
|
||||
self.address_manager
|
||||
.mmio_bus
|
||||
.insert(fw_cfg.clone(), PORT_FW_CFG_BASE, PORT_FW_CFG_WIDTH)
|
||||
.map_err(DeviceManagerError::ErrorAddingFwCfgToBus)?;
|
||||
|
||||
let fw_cfg_irq = self
|
||||
.address_manager
|
||||
.allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate_irq()
|
||||
.unwrap();
|
||||
|
||||
self.id_to_dev_info.insert(
|
||||
(DeviceType::FwCfg, "fw-cfg".to_string()),
|
||||
MmioDeviceInfo {
|
||||
addr: PORT_FW_CFG_BASE,
|
||||
len: PORT_FW_CFG_WIDTH,
|
||||
irq: fw_cfg_irq,
|
||||
},
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -5003,6 +5023,27 @@ impl Aml for DeviceManager {
|
|||
)
|
||||
.to_aml_bytes(sink);
|
||||
|
||||
#[cfg(all(feature = "fw_cfg", target_arch = "x86_64"))]
|
||||
if self.fw_cfg.is_some() {
|
||||
aml::Device::new(
|
||||
"_SB_.FWCF".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &FW_CFG_ACPI_ID.to_string()),
|
||||
&aml::Name::new("_STA".into(), &0xB_usize),
|
||||
&aml::Name::new(
|
||||
"_CRS".into(),
|
||||
&aml::ResourceTemplate::new(vec![&aml::IO::new(
|
||||
PORT_FW_CFG_BASE as u16,
|
||||
PORT_FW_CFG_BASE as u16,
|
||||
0x01,
|
||||
PORT_FW_CFG_WIDTH as u8,
|
||||
)]),
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
}
|
||||
|
||||
// Serial device
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let serial_irq = 4;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue