Skip to content

Commit 7036a3e

Browse files
committed
Prepare the ACPI tables for generation
Combine all ACPI tables into the format expected by firmware(OVMF) by using fw_cfg's table-loader commands for address patching and checksum computation. Signed-off-by: Amey Narkhede <ameynarkhede03@gmail.com>
1 parent 4eedc0e commit 7036a3e

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

lib/propolis/src/firmware/acpi/tables.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use zerocopy::{Immutable, IntoBytes};
1313

1414
pub const ACPI_TABLE_HEADER_SIZE: usize = 36;
1515
const ACPI_TABLE_LENGTH_OFFSET: usize = 4;
16+
pub const ACPI_TABLE_CHECKSUM_OFF: usize = 9;
1617

1718
#[derive(Copy, Clone, IntoBytes, Immutable)]
1819
#[repr(C, packed)]

lib/propolis/src/hw/qemu/fwcfg.rs

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,241 @@ pub mod formats {
14771477
pub const ACPI_RSDP_FWCFG_NAME: &str = "etc/acpi/rsdp";
14781478

14791479
pub use crate::firmware::acpi::{Dsdt, Facs, Fadt, Hpet, Madt, Mcfg, Rsdt, Rsdp, Xsdt};
1480+
use crate::firmware::acpi::tables::{
1481+
ACPI_PROCESSOR_ALL, ACPI_TABLE_CHECKSUM_OFF, FADT_OFF_DSDT32,
1482+
FADT_OFF_DSDT64, FADT_OFF_FACS32, GSI_SCI, GSI_TIMER, ISA_BUS,
1483+
ISA_IRQ_SCI, ISA_IRQ_TIMER, LINT1, MADT_INT_FLAGS_DEFAULT,
1484+
MADT_INT_LEVEL_ACTIVE_HIGH, MADT_LAPIC_ENABLED, RSDP_CHECKSUM_OFFSET,
1485+
RSDP_EXT_CHECKSUM_OFFSET, RSDP_SIZE, RSDP_V1_SIZE, RSDP_XSDT_ADDR_OFFSET,
1486+
};
1487+
1488+
use std::mem::size_of;
1489+
1490+
pub struct AcpiConfig {
1491+
pub num_cpus: u8,
1492+
pub local_apic_addr: u32,
1493+
pub io_apic_id: u8,
1494+
pub io_apic_addr: u32,
1495+
pub pcie_ecam_base: u64,
1496+
pub pcie_ecam_size: u64,
1497+
pub pcie_bus_start: u8,
1498+
pub pcie_bus_end: u8,
1499+
pub pcie_mmio32_base: u64,
1500+
pub pcie_mmio32_limit: u64,
1501+
pub pcie_mmio64_base: u64,
1502+
pub pcie_mmio64_limit: u64,
1503+
}
1504+
1505+
impl Default for AcpiConfig {
1506+
fn default() -> Self {
1507+
Self {
1508+
num_cpus: 1,
1509+
local_apic_addr: 0xfee0_0000,
1510+
io_apic_id: 0,
1511+
io_apic_addr: 0xfec0_0000,
1512+
pcie_ecam_base: 0xe000_0000,
1513+
pcie_ecam_size: 0x1000_0000,
1514+
pcie_bus_start: 0,
1515+
pcie_bus_end: 255,
1516+
pcie_mmio32_base: 0xc000_0000,
1517+
pcie_mmio32_limit: 0xfbff_ffff,
1518+
pcie_mmio64_base: 0x1_0000_0000,
1519+
pcie_mmio64_limit: 0xf_ffff_ffff,
1520+
}
1521+
}
1522+
}
1523+
1524+
pub struct AcpiTables {
1525+
pub tables: Vec<u8>,
1526+
pub rsdp: Vec<u8>,
1527+
pub loader: Vec<u8>,
1528+
}
1529+
1530+
pub fn build_acpi_tables(
1531+
config: &AcpiConfig,
1532+
generators: &[&dyn crate::firmware::acpi::DsdtGenerator],
1533+
) -> AcpiTables {
1534+
use crate::firmware::acpi::{build_dsdt_aml, DsdtConfig, PcieConfig};
1535+
1536+
let mut tables = Vec::new();
1537+
let mut loader = TableLoader::new();
1538+
1539+
let dsdt_config = DsdtConfig {
1540+
pcie: Some(PcieConfig {
1541+
ecam_base: config.pcie_ecam_base,
1542+
ecam_size: config.pcie_ecam_size,
1543+
bus_start: config.pcie_bus_start,
1544+
bus_end: config.pcie_bus_end,
1545+
mmio32_base: config.pcie_mmio32_base,
1546+
mmio32_limit: config.pcie_mmio32_limit,
1547+
mmio64_base: config.pcie_mmio64_base,
1548+
mmio64_limit: config.pcie_mmio64_limit,
1549+
}),
1550+
};
1551+
let aml = build_dsdt_aml(&dsdt_config, generators);
1552+
let mut dsdt = Dsdt::new();
1553+
dsdt.append_aml(&aml);
1554+
let dsdt_offset = tables.len();
1555+
tables.extend_from_slice(&dsdt.finish());
1556+
1557+
let fadt = Fadt::new();
1558+
let fadt_offset = tables.len();
1559+
tables.extend_from_slice(&fadt.finish());
1560+
1561+
let mut madt = Madt::new(config.local_apic_addr);
1562+
for i in 0..config.num_cpus {
1563+
madt.add_local_apic(i, i, MADT_LAPIC_ENABLED);
1564+
}
1565+
madt.add_io_apic(config.io_apic_id, config.io_apic_addr, 0);
1566+
madt.add_int_src_override(ISA_BUS, ISA_IRQ_TIMER, GSI_TIMER, 0);
1567+
madt.add_int_src_override(
1568+
ISA_BUS,
1569+
ISA_IRQ_SCI,
1570+
GSI_SCI,
1571+
MADT_INT_LEVEL_ACTIVE_HIGH,
1572+
);
1573+
madt.add_lapic_nmi(ACPI_PROCESSOR_ALL, MADT_INT_FLAGS_DEFAULT, LINT1);
1574+
let madt_offset = tables.len();
1575+
tables.extend_from_slice(&madt.finish());
1576+
1577+
let mut mcfg = Mcfg::new();
1578+
mcfg.add_allocation(
1579+
config.pcie_ecam_base,
1580+
0,
1581+
config.pcie_bus_start,
1582+
config.pcie_bus_end,
1583+
);
1584+
let mcfg_offset = tables.len();
1585+
tables.extend_from_slice(&mcfg.finish());
1586+
1587+
let hpet = Hpet::new();
1588+
let hpet_offset = tables.len();
1589+
tables.extend_from_slice(&hpet.finish());
1590+
1591+
let mut xsdt = Xsdt::new();
1592+
let xsdt_fadt_off = xsdt.add_entry();
1593+
let xsdt_madt_off = xsdt.add_entry();
1594+
let xsdt_mcfg_off = xsdt.add_entry();
1595+
let xsdt_hpet_off = xsdt.add_entry();
1596+
let xsdt_offset = tables.len();
1597+
tables.extend_from_slice(&xsdt.finish());
1598+
1599+
let facs = Facs::new();
1600+
let facs_offset = tables.len();
1601+
tables.extend_from_slice(&facs.finish());
1602+
1603+
let rsdp_data = Rsdp::new().finish();
1604+
1605+
tables[fadt_offset + FADT_OFF_FACS32
1606+
..fadt_offset + FADT_OFF_FACS32 + size_of::<u32>()]
1607+
.copy_from_slice(&(facs_offset as u32).to_le_bytes());
1608+
1609+
tables[fadt_offset + FADT_OFF_DSDT32
1610+
..fadt_offset + FADT_OFF_DSDT32 + size_of::<u32>()]
1611+
.copy_from_slice(&(dsdt_offset as u32).to_le_bytes());
1612+
tables[fadt_offset + FADT_OFF_DSDT64
1613+
..fadt_offset + FADT_OFF_DSDT64 + size_of::<u64>()]
1614+
.copy_from_slice(&(dsdt_offset as u64).to_le_bytes());
1615+
1616+
let xsdt_entries = [
1617+
(xsdt_fadt_off, fadt_offset),
1618+
(xsdt_madt_off, madt_offset),
1619+
(xsdt_mcfg_off, mcfg_offset),
1620+
(xsdt_hpet_off, hpet_offset),
1621+
];
1622+
for (entry_off, table_offset) in xsdt_entries {
1623+
let off = xsdt_offset + entry_off as usize;
1624+
tables[off..off + size_of::<u64>()]
1625+
.copy_from_slice(&(table_offset as u64).to_le_bytes());
1626+
}
1627+
1628+
loader
1629+
.add_allocate(ACPI_TABLES_FWCFG_NAME, 64, AllocZone::High)
1630+
.unwrap();
1631+
loader.add_allocate(ACPI_RSDP_FWCFG_NAME, 16, AllocZone::FSeg).unwrap();
1632+
1633+
let table_pointers: &[(u32, u8)] = &[
1634+
(
1635+
fadt_offset as u32 + FADT_OFF_FACS32 as u32,
1636+
size_of::<u32>() as u8,
1637+
),
1638+
(
1639+
fadt_offset as u32 + FADT_OFF_DSDT32 as u32,
1640+
size_of::<u32>() as u8,
1641+
),
1642+
(
1643+
fadt_offset as u32 + FADT_OFF_DSDT64 as u32,
1644+
size_of::<u64>() as u8,
1645+
),
1646+
(xsdt_offset as u32 + xsdt_fadt_off, size_of::<u64>() as u8),
1647+
(xsdt_offset as u32 + xsdt_madt_off, size_of::<u64>() as u8),
1648+
(xsdt_offset as u32 + xsdt_mcfg_off, size_of::<u64>() as u8),
1649+
(xsdt_offset as u32 + xsdt_hpet_off, size_of::<u64>() as u8),
1650+
];
1651+
for &(offset, size) in table_pointers {
1652+
loader
1653+
.add_pointer(
1654+
ACPI_TABLES_FWCFG_NAME,
1655+
ACPI_TABLES_FWCFG_NAME,
1656+
offset,
1657+
size,
1658+
)
1659+
.unwrap();
1660+
}
1661+
1662+
loader
1663+
.add_pointer(
1664+
ACPI_RSDP_FWCFG_NAME,
1665+
ACPI_TABLES_FWCFG_NAME,
1666+
RSDP_XSDT_ADDR_OFFSET as u32,
1667+
size_of::<u64>() as u8,
1668+
)
1669+
.unwrap();
1670+
1671+
let table_offsets = [
1672+
dsdt_offset,
1673+
fadt_offset,
1674+
madt_offset,
1675+
mcfg_offset,
1676+
hpet_offset,
1677+
xsdt_offset,
1678+
facs_offset,
1679+
];
1680+
for pair in table_offsets.windows(2) {
1681+
let (start, end) = (pair[0] as u32, pair[1] as u32);
1682+
loader
1683+
.add_checksum(
1684+
ACPI_TABLES_FWCFG_NAME,
1685+
start + ACPI_TABLE_CHECKSUM_OFF as u32,
1686+
start,
1687+
end - start,
1688+
)
1689+
.unwrap();
1690+
}
1691+
1692+
let rsdp_checksums = [
1693+
(RSDP_CHECKSUM_OFFSET, RSDP_V1_SIZE),
1694+
(RSDP_EXT_CHECKSUM_OFFSET, RSDP_SIZE),
1695+
];
1696+
for (checksum_off, length) in rsdp_checksums {
1697+
loader
1698+
.add_checksum(
1699+
ACPI_RSDP_FWCFG_NAME,
1700+
checksum_off as u32,
1701+
0,
1702+
length as u32,
1703+
)
1704+
.unwrap();
1705+
}
1706+
1707+
let loader_entry = loader.finish();
1708+
let loader_bytes = match loader_entry {
1709+
super::Entry::Bytes(b) => b,
1710+
_ => unreachable!(),
1711+
};
1712+
1713+
AcpiTables { tables, rsdp: rsdp_data, loader: loader_bytes }
1714+
}
14801715

14811716
#[cfg(test)]
14821717
mod test_table_loader {

0 commit comments

Comments
 (0)