Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions bin/propolis-server/src/lib/initializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ impl MachineInitializer<'_> {
}
}),
));
let sci_pin = Arc::new(i440fx::LNKPin::new());

let chipset_hb = i440fx::I440FxHostBridge::create(
pci_topology,
Expand All @@ -350,8 +351,10 @@ impl MachineInitializer<'_> {
enable_pcie: i440fx.enable_pcie,
},
);
let chipset_lpc =
i440fx::Piix3Lpc::create(self.machine.hdl.clone());
let chipset_lpc = i440fx::Piix3Lpc::create(
self.machine.hdl.clone(),
sci_pin.clone(),
);

let chipset_pm = i440fx::Piix3PM::create(
self.machine.hdl.clone(),
Expand Down
11 changes: 6 additions & 5 deletions bin/propolis-standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use propolis::chardev::{BlockingSource, Sink, Source, UDSock};
use propolis::common::{DeviceMetadataMap, GB, MB};
use propolis::enlightenment::{bhyve, hyperv, Enlightenment};
use propolis::firmware::{acpi, smbios};
use propolis::hw::chipset::{i440fx, Chipset};
use propolis::hw::chipset::{i440fx, i440fx::LNKPin, Chipset};
use propolis::hw::ps2::ctrl::PS2Ctrl;
use propolis::hw::qemu::fwcfg;
use propolis::hw::uart::{LpcUart, LpcUartMetadata};
Expand Down Expand Up @@ -740,7 +740,7 @@ impl Instance {
}
}

fn generate_pins(&self) -> (Arc<FuncPin>, Arc<FuncPin>) {
fn generate_pins(&self) -> (Arc<FuncPin>, Arc<FuncPin>, Arc<LNKPin>) {
let power_eq = self.0.eq.clone();
let power_pin =
propolis::intr_pins::FuncPin::new(Box::new(move |rising| {
Expand All @@ -761,7 +761,7 @@ impl Instance {
);
}
}));
(Arc::new(power_pin), Arc::new(reset_pin))
(Arc::new(power_pin), Arc::new(reset_pin), Arc::new(LNKPin::new()))
}

fn lock(&self) -> Option<MutexGuard<'_, InstState>> {
Expand Down Expand Up @@ -1214,7 +1214,7 @@ fn setup_instance(
guard.inventory.register_instance(vcpu, &vcpu.id.to_string())
}

let (power_pin, reset_pin) = inst.generate_pins();
let (power_pin, reset_pin, sci_pin) = inst.generate_pins();
let pci_topo =
propolis::hw::pci::topology::Builder::new().finish(machine)?.topology;

Expand All @@ -1226,7 +1226,8 @@ fn setup_instance(
..Default::default()
},
);
let chipset_lpc = i440fx::Piix3Lpc::create(machine.hdl.clone());
let chipset_lpc =
i440fx::Piix3Lpc::create(machine.hdl.clone(), sci_pin.clone());
let chipset_pm = i440fx::Piix3PM::create(
machine.hdl.clone(),
chipset_hb.power_pin(),
Expand Down
22 changes: 22 additions & 0 deletions lib/propolis/src/firmware/acpi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
//!
//! <https://github.com/oxidecomputer/edk2/tree/propolis/edk2-stable202105/OvmfPkg/AcpiTables>

use std::sync::Arc;

use serde::{Deserialize, Serialize};

use crate::hw::chipset::i440fx;
use crate::intr_pins::{IntrPin, OrGate};

pub mod aml;
pub mod dsdt;
Expand Down Expand Up @@ -89,3 +92,22 @@ const LOCAL_APIC_LEN: u32 = 0x10_0000;
// information.
const GPE0_BLK_ADDR: u16 = 0xafe0;
const GPE0_BLK_LEN: u8 = 4;

pub struct Acpi {
// The SCI state can be driven by multiple inputs that OR'ed to determine
// if an interrupt should happen, so model it as an OrGate and hand out new
// inputs for components that connect to the SCI pin.
//
// Refer to Fig. 4.3 of the ACPI spec. v6.6 for more information.
sci_gate: Arc<OrGate>,
}

impl Acpi {
pub fn create(sci_pin: Arc<dyn IntrPin>) -> Arc<Self> {
Arc::new(Self { sci_gate: OrGate::new(sci_pin) })
}

pub fn sci_pin(&self) -> Arc<dyn IntrPin> {
self.sci_gate.new_input()
}
}
23 changes: 9 additions & 14 deletions lib/propolis/src/hw/chipset/i440fx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ pub const DEFAULT_HB_BDF: Bdf = Bdf::new_unchecked(0, 0, 0);
pub const DEFAULT_LPC_BDF: Bdf = Bdf::new_unchecked(0, 1, 0);
pub const DEFAULT_PM_BDF: Bdf = Bdf::new_unchecked(0, 1, 3);

struct LNKPin {
pub struct LNKPin {
inner: Mutex<LNKPinInner>,
}
struct LNKPinInner {
asserted: bool,
pin: Option<LegacyPin>,
}
impl LNKPin {
fn new() -> Self {
pub fn new() -> Self {
Self { inner: Mutex::new(LNKPinInner { asserted: false, pin: None }) }
}
fn reassign(&self, new_pin: Option<LegacyPin>) {
Expand Down Expand Up @@ -100,17 +100,11 @@ impl IntrPin for LNKPin {

struct IrqConfig {
pic: Arc<LegacyPIC>,

lnk_pins: [Arc<LNKPin>; 4],

#[allow(unused)]
// XXX: wire up SCI notifications
sci_pin: Arc<LNKPin>,
Comment on lines -106 to -108

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I was working on the ACPI GPE registers I realized that it would make more sense to move the SCI pin and OrGate to an ACPI-related struct. This struct is going to hold ACPI state, so I think it makes sense that it also controls who connects to the SCI pin.

The struct is not being used in this PR, but here's a preview of how it will look like: c9fd6b7. Other components that an input to the SCI can call acpi.sci_pin().

}
impl IrqConfig {
fn create(hdl: Arc<VmmHdl>) -> Arc<Self> {
fn create(hdl: Arc<VmmHdl>, sci_pin: Arc<LNKPin>) -> Arc<Self> {
let pic = LegacyPIC::new(hdl);
let sci_pin = Arc::new(LNKPin::new());
sci_pin.reassign(pic.pin_handle(SCI_IRQ));
Arc::new(Self {
pic,
Expand All @@ -120,7 +114,6 @@ impl IrqConfig {
Arc::new(LNKPin::new()),
Arc::new(LNKPin::new()),
],
sci_pin,
})
}
fn set_lnk_route(&self, idx: usize, irq: Option<u8>) {
Expand Down Expand Up @@ -357,7 +350,7 @@ pub struct Piix3Lpc {
post_code: AtomicU8,
}
impl Piix3Lpc {
pub fn create(hdl: Arc<VmmHdl>) -> Arc<Self> {
pub fn create(hdl: Arc<VmmHdl>, sci_pin: Arc<LNKPin>) -> Arc<Self> {
let pci_state = pci::Builder::new(pci::Ident {
vendor_id: VENDOR_INTEL,
device_id: PIIX3_ISA_DEV_ID,
Expand All @@ -370,7 +363,7 @@ impl Piix3Lpc {
.add_custom_cfg(PIR_OFFSET as u8, PIR_LEN as u8)
.finish();

let irq_config = IrqConfig::create(hdl.clone());
let irq_config = IrqConfig::create(hdl.clone(), sci_pin);

Arc::new(Self {
pci_state,
Expand Down Expand Up @@ -1161,8 +1154,9 @@ mod test {
fn lpc_pci_cfg_read() {
let hdl = Arc::new(VmmHdl::new_test(0).unwrap());
let scaffold = Scaffold::new();
let sci_pin = Arc::new(LNKPin::new());

let lpc = Piix3Lpc::create(hdl);
let lpc = Piix3Lpc::create(hdl, sci_pin);
let _bus = setup_attach(&scaffold, lpc.clone());

cfg_read(lpc.as_ref() as &dyn Endpoint);
Expand All @@ -1172,8 +1166,9 @@ mod test {
fn lpc_pci_cfg_write() {
let hdl = Arc::new(VmmHdl::new_test(0).unwrap());
let scaffold = Scaffold::new();
let sci_pin = Arc::new(LNKPin::new());

let lpc = Piix3Lpc::create(hdl);
let lpc = Piix3Lpc::create(hdl, sci_pin);
let _bus = setup_attach(&scaffold, lpc.clone());

cfg_write(lpc.as_ref() as &dyn Endpoint);
Expand Down
Loading
Loading