Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_emul.c
Show First 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
uint16_t cmd; | uint16_t cmd; | ||||
cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); | cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); | ||||
return (cmd & PCIM_CMD_MEMEN); | return (cmd & PCIM_CMD_MEMEN); | ||||
} | } | ||||
/* Is the registration actually just all 'f's? */ | |||||
static bool | |||||
addr_is_probe(uint64_t addr, uint64_t size, int type) | |||||
{ | |||||
switch (type) { | |||||
case PCIBAR_IO: | |||||
return (addr + size - 1 == 0xffffUL); | |||||
case PCIBAR_MEM32: | |||||
case PCIBAR_MEM64: | |||||
return ((addr & 0xffffffffUL) + size - 1 == 0xffffffffUL); | |||||
case PCIBAR_MEMHI64: | |||||
return ((addr >> 32) + size - 1 == 0xffffffffUL); | |||||
default: | |||||
assert(0); | |||||
} | |||||
} | |||||
/* | /* | ||||
* Update the MMIO or I/O address that is decoded by the BAR register. | * Update the MMIO or I/O address that is decoded by the BAR register. | ||||
* | * | ||||
* If the pci device has enabled the address space decoding then intercept | * If the pci device has enabled the address space decoding then intercept | ||||
* the address range decoded by the BAR register. | * the address range decoded by the BAR register. | ||||
* | |||||
* However, do not intercept the address if we are writing all '1's to the | |||||
* BAR register, since that is an attempt to probe the capabilities of | |||||
* the device. | |||||
*/ | */ | ||||
static void | static void | ||||
update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type) | update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type) | ||||
{ | { | ||||
int decode; | int decode; | ||||
uint64_t size; | |||||
size = pi->pi_bar[idx].size; | |||||
if (pi->pi_bar[idx].type == PCIBAR_IO) | if (pi->pi_bar[idx].type == PCIBAR_IO) | ||||
decode = porten(pi); | decode = porten(pi); | ||||
else | else | ||||
decode = memen(pi); | decode = memen(pi); | ||||
if (decode) | if (decode && !addr_is_probe(pi->pi_bar[idx].addr, size, type)) | ||||
unregister_bar(pi, idx); | unregister_bar(pi, idx); | ||||
switch (type) { | switch (type) { | ||||
case PCIBAR_IO: | case PCIBAR_IO: | ||||
case PCIBAR_MEM32: | case PCIBAR_MEM32: | ||||
pi->pi_bar[idx].addr = addr; | pi->pi_bar[idx].addr = addr; | ||||
break; | break; | ||||
case PCIBAR_MEM64: | case PCIBAR_MEM64: | ||||
pi->pi_bar[idx].addr &= ~0xffffffffUL; | pi->pi_bar[idx].addr &= ~0xffffffffUL; | ||||
pi->pi_bar[idx].addr |= addr; | pi->pi_bar[idx].addr |= addr; | ||||
break; | break; | ||||
case PCIBAR_MEMHI64: | case PCIBAR_MEMHI64: | ||||
pi->pi_bar[idx].addr &= 0xffffffff; | pi->pi_bar[idx].addr &= 0xffffffffUL; | ||||
pi->pi_bar[idx].addr |= addr; | pi->pi_bar[idx].addr |= addr; | ||||
break; | break; | ||||
default: | default: | ||||
assert(0); | assert(0); | ||||
} | } | ||||
if (decode) | if (decode && !addr_is_probe(pi->pi_bar[idx].addr, size, type)) | ||||
register_bar(pi, idx); | register_bar(pi, idx); | ||||
} | } | ||||
int | int | ||||
pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type, | pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type, | ||||
uint64_t size) | uint64_t size) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 1,791 Lines • Show Last 20 Lines |