Page MenuHomeFreeBSD

D58892.diff
No OneTemporary

D58892.diff

Index: usr.sbin/bhyve/pci_passthru.c
===================================================================
--- usr.sbin/bhyve/pci_passthru.c
+++ usr.sbin/bhyve/pci_passthru.c
@@ -101,6 +101,11 @@
struct {
int capoff;
} psc_msix;
+ struct {
+ int capoff;
+ uint16_t pmcsr;
+ uint16_t reset_pmcsr;
+ } psc_pm;
struct {
int capoff;
uint16_t devctl;
@@ -332,6 +337,8 @@
capptr += 4;
msixcap_ptr += 4;
}
+ } else if (cap == PCIY_PMG) {
+ sc->psc_pm.capoff = ptr;
} else if (cap == PCIY_EXPRESS) {
sc->psc_pcie.capoff = ptr;
}
@@ -339,6 +346,13 @@
1);
}
}
+ if (sc->psc_pm.capoff != 0) {
+ sc->psc_pm.pmcsr = passthru_read_config(&sel,
+ sc->psc_pm.capoff + PCIR_POWER_STATUS, 2);
+ /* The physical function remains in its host-owned power state. */
+ sc->psc_pm.pmcsr |= PCIM_PSTAT_NOSOFTRESET;
+ sc->psc_pm.reset_pmcsr = sc->psc_pm.pmcsr;
+ }
if (sc->psc_pcie.capoff != 0) {
sc->psc_pcie.devctl = passthru_read_config(&sel,
sc->psc_pcie.capoff + PCIER_DEVICE_CTL, 2);
@@ -1122,6 +1136,8 @@
#define PASSTHRU_DEVCTL_NO_WRITE PCIEM_CTL_PHANTHOM_FUNCS
#define PASSTHRU_DEVCTL2_VIRT (PCIEM_CTL2_COMP_TIMO_VAL | \
PCIEM_CTL2_COMP_TIMO_DISABLE)
+#define PASSTHRU_PMCSR_VIRT (PCIM_PSTAT_DMASK | \
+ PCIM_PSTAT_NOSOFTRESET)
static uint32_t
passthru_cfg_field_mask(int coff, int bytes, int fieldoff, uint16_t mask)
@@ -1227,6 +1243,8 @@
(sc->psc_pcie.reset_devctl & ~PCIEM_CTL_MAX_PAYLOAD) | guest_mps;
if (sc->psc_pcie.has_devctl2)
sc->psc_pcie.devctl2 = sc->psc_pcie.reset_devctl2;
+ if (sc->psc_pm.capoff != 0)
+ sc->psc_pm.pmcsr = sc->psc_pm.reset_pmcsr;
}
static int
@@ -1301,22 +1319,30 @@
/* Everything else just read from the device's config space. */
*rv = passthru_read_config(&sc->psc_sel, coff, bytes);
+ /* The physical Vendor ID, not virtual capability fields, reports removal. */
+ if (sc->psc_pm.capoff != 0) {
+ uint32_t mask;
+ int pmcsr;
+
+ pmcsr = sc->psc_pm.capoff + PCIR_POWER_STATUS;
+ mask = passthru_cfg_field_mask(coff, bytes, pmcsr,
+ PASSTHRU_PMCSR_VIRT);
+ if (mask != 0)
+ *rv = (*rv & ~mask) |
+ (passthru_cfg_field_value(coff, bytes, pmcsr,
+ sc->psc_pm.pmcsr) & mask);
+ }
if (sc->psc_pcie.capoff != 0) {
uint32_t mask;
- uint16_t physical_devctl;
int devctl;
devctl = sc->psc_pcie.capoff + PCIER_DEVICE_CTL;
mask = passthru_cfg_field_mask(coff, bytes, devctl,
PASSTHRU_DEVCTL_VIRT);
- if (mask != 0) {
- physical_devctl = passthru_read_config(&sc->psc_sel,
- devctl, 2);
- if (physical_devctl != 0xffff)
- *rv = (*rv & ~mask) |
- (passthru_cfg_field_value(coff, bytes,
- devctl, sc->psc_pcie.devctl) & mask);
- }
+ if (mask != 0)
+ *rv = (*rv & ~mask) |
+ (passthru_cfg_field_value(coff, bytes, devctl,
+ sc->psc_pcie.devctl) & mask);
if (sc->psc_pcie.has_devctl2) {
devctl = sc->psc_pcie.capoff + PCIER_DEVICE_CTL2;
mask = passthru_cfg_field_mask(coff, bytes, devctl,
@@ -1357,8 +1383,8 @@
int coff, int bytes, uint32_t val)
{
uint32_t flr_mask, host_mask, transport_mask;
- uint16_t physical_devctl;
- int devctl, devctl2, host_mps, guest_mrrs;
+ uint16_t physical_devctl, physical_pmcsr;
+ int devctl, devctl2, host_mps, guest_mrrs, pmcsr;
int error, msix_table_entries, i;
uint16_t cmd_old;
@@ -1403,6 +1429,33 @@
return (0);
}
+ /*
+ * A physical D3hot-to-D0 transition may reset the function and clear
+ * Command behind bhyve's emulated copy. Keep the physical D-state
+ * host-owned, emulate the guest D-state, and advertise No_Soft_Reset so
+ * the guest does not rely on this cycle as a function reset.
+ */
+ pmcsr = sc->psc_pm.capoff + PCIR_POWER_STATUS;
+ if (sc->psc_pm.capoff != 0 && coff < pmcsr + 2 &&
+ coff + bytes > pmcsr) {
+ physical_pmcsr = passthru_read_config(&sc->psc_sel, pmcsr, 2);
+ if (physical_pmcsr == 0xffff) {
+ warnx("configuration space unavailable for passthru "
+ "device %d/%d/%d", sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func);
+ return (0);
+ }
+ passthru_cfg_update_field(coff, bytes, val, pmcsr,
+ PCIM_PSTAT_DMASK, &sc->psc_pm.pmcsr);
+ host_mask = passthru_cfg_field_mask(coff, bytes, pmcsr,
+ PASSTHRU_PMCSR_VIRT);
+ val = (val & ~host_mask) |
+ (passthru_cfg_field_value(coff, bytes, pmcsr,
+ physical_pmcsr) & host_mask);
+ passthru_write_config(&sc->psc_sel, coff, bytes, val);
+ return (0);
+ }
+
/*
* A direct FLR would clear physical Command while the guest sees its
* emulated copy remain enabled. Route FLR through ppt so it restores

File Metadata

Mime Type
text/plain
Expires
Wed, Aug 19, 6:44 PM (2 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36916832
Default Alt Text
D58892.diff (4 KB)

Event Timeline