Skip to content

Commit df687fe

Browse files
committed
pci: add support for ACPI MCFG table
So that we can declare which memory region is used by PCIe devices for MMCONFIG. Signed-off-by: Babis Chalios <[email protected]>
1 parent c27dd13 commit df687fe

File tree

3 files changed

+105
-5
lines changed

3 files changed

+105
-5
lines changed

src/acpi-tables/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ pub mod aml;
1010
pub mod dsdt;
1111
pub mod fadt;
1212
pub mod madt;
13+
pub mod mcfg;
1314
pub mod rsdp;
1415
pub mod xsdt;
1516

1617
pub use aml::Aml;
1718
pub use dsdt::Dsdt;
1819
pub use fadt::Fadt;
1920
pub use madt::Madt;
21+
pub use mcfg::Mcfg;
2022
pub use rsdp::Rsdp;
2123
pub use xsdt::Xsdt;
2224
use zerocopy::little_endian::{U32, U64};
@@ -89,7 +91,7 @@ pub struct SdtHeader {
8991
pub oem_table_id: [u8; 8],
9092
pub oem_revision: U32,
9193
pub creator_id: [u8; 4],
92-
pub creator_revison: U32,
94+
pub creator_revision: U32,
9395
}
9496

9597
impl SdtHeader {
@@ -110,7 +112,7 @@ impl SdtHeader {
110112
oem_table_id,
111113
oem_revision: U32::new(oem_revision),
112114
creator_id: FC_ACPI_CREATOR_ID,
113-
creator_revison: U32::new(FC_ACPI_CREATOR_REVISION),
115+
creator_revision: U32::new(FC_ACPI_CREATOR_REVISION),
114116
}
115117
}
116118
}

src/acpi-tables/src/mcfg.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright © 2019 Intel Corporation
2+
// Copyright © 2023 Rivos, Inc.
3+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
7+
use std::mem::size_of;
8+
9+
use vm_memory::{Bytes, GuestAddress, GuestMemory};
10+
use zerocopy::{Immutable, IntoBytes};
11+
12+
use crate::{Result, Sdt, SdtHeader, checksum};
13+
14+
#[allow(dead_code)]
15+
#[repr(C, packed)]
16+
#[derive(Default, Debug, IntoBytes, Clone, Copy, Immutable)]
17+
struct PciRangeEntry {
18+
pub base_address: u64,
19+
pub segment: u16,
20+
pub start: u8,
21+
pub end: u8,
22+
_reserved: u32,
23+
}
24+
25+
#[allow(dead_code)]
26+
#[repr(C, packed)]
27+
#[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)]
28+
pub struct Mcfg {
29+
header: SdtHeader,
30+
_reserved: u64,
31+
pci_range_entry: PciRangeEntry,
32+
}
33+
34+
impl Mcfg {
35+
pub fn new(
36+
oem_id: [u8; 6],
37+
oem_table_id: [u8; 8],
38+
oem_revision: u32,
39+
pci_mmio_config_addr: u64,
40+
) -> Self {
41+
let header = SdtHeader::new(
42+
*b"MCFG",
43+
size_of::<Mcfg>().try_into().unwrap(),
44+
1,
45+
oem_id,
46+
oem_table_id,
47+
oem_revision,
48+
);
49+
50+
let mut mcfg = Mcfg {
51+
header,
52+
pci_range_entry: PciRangeEntry {
53+
base_address: pci_mmio_config_addr,
54+
segment: 0,
55+
start: 0,
56+
end: 0,
57+
..Default::default()
58+
},
59+
..Default::default()
60+
};
61+
62+
mcfg.header.checksum = checksum(&[mcfg.as_bytes()]);
63+
64+
mcfg
65+
}
66+
}
67+
68+
impl Sdt for Mcfg {
69+
fn len(&self) -> usize {
70+
self.as_bytes().len()
71+
}
72+
73+
fn write_to_guest<M: GuestMemory>(&mut self, mem: &M, address: GuestAddress) -> Result<()> {
74+
mem.write_slice(self.as_bytes(), address)?;
75+
Ok(())
76+
}
77+
}

src/vmm/src/acpi/mod.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use acpi_tables::fadt::{FADT_F_HW_REDUCED_ACPI, FADT_F_PWR_BUTTON, FADT_F_SLP_BUTTON};
5-
use acpi_tables::{Aml, Dsdt, Fadt, Madt, Rsdp, Sdt, Xsdt, aml};
5+
use acpi_tables::{Aml, Dsdt, Fadt, Madt, Mcfg, Rsdp, Sdt, Xsdt, aml};
66
use log::{debug, error};
77
use vm_allocator::AllocPolicy;
88

99
use crate::Vcpu;
1010
use crate::acpi::x86_64::{
1111
apic_addr, rsdp_addr, setup_arch_dsdt, setup_arch_fadt, setup_interrupt_controllers,
1212
};
13+
use crate::arch::x86_64::layout;
1314
use crate::device_manager::DeviceManager;
1415
use crate::device_manager::resources::ResourceAllocator;
1516
use crate::vstate::memory::{GuestAddress, GuestMemoryMmap};
@@ -145,16 +146,27 @@ impl AcpiTableWriter<'_> {
145146
resource_allocator: &ResourceAllocator,
146147
fadt_addr: u64,
147148
madt_addr: u64,
149+
mcfg_addr: u64,
148150
) -> Result<u64, AcpiError> {
149151
let mut xsdt = Xsdt::new(
150152
OEM_ID,
151153
*b"FCMVXSDT",
152154
OEM_REVISION,
153-
vec![fadt_addr, madt_addr],
155+
vec![fadt_addr, madt_addr, mcfg_addr],
154156
);
155157
self.write_acpi_table(resource_allocator, &mut xsdt)
156158
}
157159

160+
/// Build the MCFG table for the guest.
161+
fn build_mcfg(
162+
&mut self,
163+
resource_allocator: &ResourceAllocator,
164+
pci_mmio_config_addr: u64,
165+
) -> Result<u64, AcpiError> {
166+
let mut mcfg = Mcfg::new(OEM_ID, *b"FCMVMCFG", OEM_REVISION, pci_mmio_config_addr);
167+
self.write_acpi_table(resource_allocator, &mut mcfg)
168+
}
169+
158170
/// Build the RSDP pointer for the guest.
159171
///
160172
/// This will build the RSDP pointer which points to the XSDT table and write it in guest
@@ -191,7 +203,16 @@ pub(crate) fn create_acpi_tables(
191203
&device_manager.resource_allocator,
192204
vcpus.len().try_into().unwrap(),
193205
)?;
194-
let xsdt_addr = writer.build_xsdt(&device_manager.resource_allocator, fadt_addr, madt_addr)?;
206+
let mcfg_addr = writer.build_mcfg(
207+
&device_manager.resource_allocator,
208+
layout::PCI_MMCONFIG_START,
209+
)?;
210+
let xsdt_addr = writer.build_xsdt(
211+
&device_manager.resource_allocator,
212+
fadt_addr,
213+
madt_addr,
214+
mcfg_addr,
215+
)?;
195216
writer.build_rsdp(xsdt_addr)
196217
}
197218

0 commit comments

Comments
 (0)