Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_passthru.c
Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | struct { | ||||||||||||
int capoff; | int capoff; | ||||||||||||
int msgctrl; | int msgctrl; | ||||||||||||
int emulated; | int emulated; | ||||||||||||
} psc_msi; | } psc_msi; | ||||||||||||
struct { | struct { | ||||||||||||
int capoff; | int capoff; | ||||||||||||
} psc_msix; | } psc_msix; | ||||||||||||
struct pcisel psc_sel; | struct pcisel psc_sel; | ||||||||||||
cfgread_handler psc_pcir_rhandler[PCI_REGMAX + 1]; | |||||||||||||
cfgwrite_handler psc_pcir_whandler[PCI_REGMAX + 1]; | |||||||||||||
}; | }; | ||||||||||||
static int | static int | ||||||||||||
msi_caplen(int msgctrl) | msi_caplen(int msgctrl) | ||||||||||||
{ | { | ||||||||||||
int len; | int len; | ||||||||||||
len = 10; /* minimum length of msi capability */ | len = 10; /* minimum length of msi capability */ | ||||||||||||
▲ Show 20 Lines • Show All 534 Lines • ▼ Show 20 Lines | if (pci_msix_table_bar(pi) >= 0) { | ||||||||||||
} | } | ||||||||||||
} | } | ||||||||||||
error = 0; /* success */ | error = 0; /* success */ | ||||||||||||
done: | done: | ||||||||||||
return (error); | return (error); | ||||||||||||
} | } | ||||||||||||
int | |||||||||||||
set_pcir_handler(struct passthru_softc *sc, int reg, int len, | |||||||||||||
cfgread_handler rhandler, cfgwrite_handler whandler) | |||||||||||||
{ | |||||||||||||
if (reg > PCI_REGMAX || reg + len > PCI_REGMAX + 1) | |||||||||||||
return (-1); | |||||||||||||
for (int i = reg; i < reg + len; ++i) { | |||||||||||||
assert(sc->psc_pcir_rhandler[i] == NULL || rhandler == NULL); | |||||||||||||
assert(sc->psc_pcir_whandler[i] == NULL || whandler == NULL); | |||||||||||||
sc->psc_pcir_rhandler[i] = rhandler; | |||||||||||||
sc->psc_pcir_whandler[i] = whandler; | |||||||||||||
} | |||||||||||||
markjUnsubmitted Not Done Inline Actions
markj: | |||||||||||||
return (0); | |||||||||||||
} | |||||||||||||
static int | static int | ||||||||||||
passthru_legacy_config(nvlist_t *nvl, const char *opts) | passthru_legacy_config(nvlist_t *nvl, const char *opts) | ||||||||||||
{ | { | ||||||||||||
const char *cp; | const char *cp; | ||||||||||||
char *tofree; | char *tofree; | ||||||||||||
char value[16]; | char value[16]; | ||||||||||||
int bus, slot, func; | int bus, slot, func; | ||||||||||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | if ((error = passthru_init_rom(sc, | ||||||||||||
goto done; | goto done; | ||||||||||||
error = 0; /* success */ | error = 0; /* success */ | ||||||||||||
done: | done: | ||||||||||||
if (error) { | if (error) { | ||||||||||||
free(sc); | free(sc); | ||||||||||||
vm_unassign_pptdev(pi->pi_vmctx, bus, slot, func); | vm_unassign_pptdev(pi->pi_vmctx, bus, slot, func); | ||||||||||||
} | } | ||||||||||||
return (error); | return (error); | ||||||||||||
Not Done Inline ActionsAlternately, can cfgread/write just call cfgread/write_default if no handler is installed? That might be a bit simpler and easier to follow. markj: Alternately, can cfgread/write just call cfgread/write_default if no handler is installed? That… | |||||||||||||
Not Done Inline ActionsBut now this call isn't needed, right? And set_pcir_handler() can assert that a handler is not already set? markj: But now this call isn't needed, right? And set_pcir_handler() can assert that a handler is not… | |||||||||||||
} | } | ||||||||||||
static int | static int | ||||||||||||
bar_access(int coff) | bar_access(int coff) | ||||||||||||
{ | { | ||||||||||||
if ((coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) || | if ((coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) || | ||||||||||||
coff == PCIR_BIOS) | coff == PCIR_BIOS) | ||||||||||||
return (1); | return (1); | ||||||||||||
Show All 23 Lines | msixcap_access(struct passthru_softc *sc, int coff) | ||||||||||||
if (sc->psc_msix.capoff == 0) | if (sc->psc_msix.capoff == 0) | ||||||||||||
return (0); | return (0); | ||||||||||||
return (coff >= sc->psc_msix.capoff && | return (coff >= sc->psc_msix.capoff && | ||||||||||||
coff < sc->psc_msix.capoff + MSIX_CAPLEN); | coff < sc->psc_msix.capoff + MSIX_CAPLEN); | ||||||||||||
} | } | ||||||||||||
static int | static int | ||||||||||||
passthru_cfgread(struct pci_devinst *pi, int coff, int bytes, uint32_t *rv) | passthru_cfgread_default(struct passthru_softc *sc, | ||||||||||||
struct pci_devinst *pi __unused, int coff, int bytes, uint32_t *rv) | |||||||||||||
{ | { | ||||||||||||
struct passthru_softc *sc; | |||||||||||||
sc = pi->pi_arg; | |||||||||||||
/* | /* | ||||||||||||
* PCI BARs and MSI capability is emulated. | * PCI BARs and MSI capability is emulated. | ||||||||||||
*/ | */ | ||||||||||||
if (bar_access(coff) || msicap_access(sc, coff) || | if (bar_access(coff) || msicap_access(sc, coff) || | ||||||||||||
msixcap_access(sc, coff)) | msixcap_access(sc, coff)) | ||||||||||||
return (-1); | return (-1); | ||||||||||||
#ifdef LEGACY_SUPPORT | #ifdef LEGACY_SUPPORT | ||||||||||||
Show All 22 Lines | #endif | ||||||||||||
/* Everything else just read from the device's config space */ | /* Everything else just read from the device's config space */ | ||||||||||||
*rv = read_config(&sc->psc_sel, coff, bytes); | *rv = read_config(&sc->psc_sel, coff, bytes); | ||||||||||||
return (0); | return (0); | ||||||||||||
} | } | ||||||||||||
static int | static int | ||||||||||||
passthru_cfgwrite(struct pci_devinst *pi, int coff, int bytes, uint32_t val) | passthru_cfgread(struct pci_devinst *pi, int coff, int bytes, uint32_t *rv) | ||||||||||||
{ | { | ||||||||||||
int error, msix_table_entries, i; | |||||||||||||
struct passthru_softc *sc; | struct passthru_softc *sc; | ||||||||||||
uint16_t cmd_old; | |||||||||||||
sc = pi->pi_arg; | sc = pi->pi_arg; | ||||||||||||
if (sc->psc_pcir_rhandler[coff] != NULL) | |||||||||||||
return (sc->psc_pcir_rhandler[coff](sc, pi, coff, bytes, rv)); | |||||||||||||
return (passthru_cfgread_default(sc, pi, coff, bytes, rv)); | |||||||||||||
} | |||||||||||||
static int | |||||||||||||
passthru_cfgwrite_default(struct passthru_softc *sc, struct pci_devinst *pi, | |||||||||||||
int coff, int bytes, uint32_t val) | |||||||||||||
{ | |||||||||||||
int error, msix_table_entries, i; | |||||||||||||
uint16_t cmd_old; | |||||||||||||
/* | /* | ||||||||||||
* PCI BARs are emulated | * PCI BARs are emulated | ||||||||||||
*/ | */ | ||||||||||||
if (bar_access(coff)) | if (bar_access(coff)) | ||||||||||||
return (-1); | return (-1); | ||||||||||||
/* | /* | ||||||||||||
* MSI capability is emulated | * MSI capability is emulated | ||||||||||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | if (coff == PCIR_COMMAND) { | ||||||||||||
if (bytes == 1) | if (bytes == 1) | ||||||||||||
pci_set_cfgdata8(pi, PCIR_COMMAND, val); | pci_set_cfgdata8(pi, PCIR_COMMAND, val); | ||||||||||||
else if (bytes == 2) | else if (bytes == 2) | ||||||||||||
pci_set_cfgdata16(pi, PCIR_COMMAND, val); | pci_set_cfgdata16(pi, PCIR_COMMAND, val); | ||||||||||||
pci_emul_cmd_changed(pi, cmd_old); | pci_emul_cmd_changed(pi, cmd_old); | ||||||||||||
} | } | ||||||||||||
return (0); | return (0); | ||||||||||||
} | |||||||||||||
static int | |||||||||||||
passthru_cfgwrite(struct pci_devinst *pi, int coff, int bytes, uint32_t val) | |||||||||||||
{ | |||||||||||||
struct passthru_softc *sc; | |||||||||||||
sc = pi->pi_arg; | |||||||||||||
if (sc->psc_pcir_whandler[coff] != NULL) | |||||||||||||
return (sc->psc_pcir_whandler[coff](sc, pi, coff, bytes, val)); | |||||||||||||
return (passthru_cfgwrite_default(sc, pi, coff, bytes, val)); | |||||||||||||
} | } | ||||||||||||
static void | static void | ||||||||||||
passthru_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size, | passthru_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size, | ||||||||||||
uint64_t value) | uint64_t value) | ||||||||||||
{ | { | ||||||||||||
struct passthru_softc *sc; | struct passthru_softc *sc; | ||||||||||||
struct pci_bar_ioreq pio; | struct pci_bar_ioreq pio; | ||||||||||||
▲ Show 20 Lines • Show All 184 Lines • Show Last 20 Lines |