Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145532721
D28277.1778136537.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D28277.1778136537.diff
View Options
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -92,6 +92,7 @@
enum pcibar_type type; /* io or memory */
uint64_t size;
uint64_t addr;
+ uint8_t lobits;
};
#define PI_NAMESZ 40
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -544,8 +544,9 @@
* the address range decoded by the BAR register.
*/
static void
-update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type)
+update_bar_address(struct pci_devinst *pi, int idx, uint32_t val)
{
+ int update_idx = idx;
int decode;
if (pi->pi_bar[idx].type == PCIBAR_IO)
@@ -553,28 +554,103 @@
else
decode = memen(pi);
- if (decode)
- unregister_bar(pi, idx);
-
- switch (type) {
+ switch (pi->pi_bar[idx].type) {
+ case PCIBAR_MEMHI64:
+ --update_idx;
case PCIBAR_IO:
case PCIBAR_MEM32:
- pi->pi_bar[idx].addr = addr;
- break;
case PCIBAR_MEM64:
- pi->pi_bar[idx].addr &= ~0xffffffffUL;
- pi->pi_bar[idx].addr |= addr;
+ {
+ struct pcibar *bar = &pi->pi_bar[update_idx];
+
+ if (decode && (bar->addr != 0))
+ unregister_bar(pi, update_idx);
+
+ if (val == ~0U) {
+ /* guest wants to read size of BAR */
+ pci_set_cfgdata32(pi, PCIR_BAR(idx), ~0U);
+ bar->addr = 0;
+ break;
+ }
+
+ /* guest sets address of BAR */
+ uint64_t mask;
+ uint32_t bar_val;
+ mask = ~(bar->size - 1UL);
+ if (pi->pi_bar[idx].type == PCIBAR_MEMHI64)
+ mask >>= 32UL;
+ bar_val = val & mask;
+ bar_val |= pi->pi_bar[idx].lobits;
+ pci_set_cfgdata32(pi, PCIR_BAR(idx), bar_val);
+
+ /* Only register BAR if it contains a valid address */
+ uint32_t lo, hi;
+ lo = pci_get_cfgdata32(pi, PCIR_BAR(update_idx));
+ hi = 0;
+ if (bar->type == PCIBAR_MEM64)
+ hi = pci_get_cfgdata32(pi, PCIR_BAR(update_idx + 1));
+ if (lo == ~0U || hi == ~0U) {
+ bar->addr = 0;
+ break;
+ }
+
+ if (bar->type == PCIBAR_IO)
+ lo &= PCIM_BAR_IO_BASE;
+ else
+ lo &= PCIM_BAR_MEM_BASE;
+ bar->addr = (uint64_t)lo | ((uint64_t)hi << 32UL);
+ if (decode)
+ register_bar(pi, update_idx);
+
break;
- case PCIBAR_MEMHI64:
- pi->pi_bar[idx].addr &= 0xffffffff;
- pi->pi_bar[idx].addr |= addr;
+ }
+ case PCIBAR_NONE:
break;
default:
assert(0);
}
+}
+
+static uint32_t
+read_bar_value(struct pci_devinst *pi, int coff, int bytes)
+{
+ uint8_t idx;
+ idx = (coff - PCIR_BAR(0)) / 4;
+ assert(idx <= PCI_BARMAX);
- if (decode)
- register_bar(pi, idx);
+ uint8_t update_idx = idx;
+ uint64_t val;
+
+ if (pi->pi_bar[idx].type == PCIBAR_MEMHI64)
+ --update_idx;
+
+ val = pci_get_cfgdata32(pi, PCIR_BAR(idx));
+
+ /* return size of BAR */
+ if (val == ~0U) {
+ val = ~(pi->pi_bar[update_idx].size - 1);
+ val |= pi->pi_bar[update_idx].lobits;
+ if (pi->pi_bar[idx].type == PCIBAR_MEMHI64)
+ val >>= 32;
+ }
+
+ switch (bytes) {
+ case 1:
+ val = (val >> (8 * (coff & 0x03))) & 0xFF;
+ break;
+ case 2:
+ assert((coff & 0x01) == 0);
+ val = (val >> (8 * (coff & 0x02))) & 0xFFFF;
+ break;
+ case 4:
+ assert((coff & 0x03) == 0);
+ val = (uint32_t)val;
+ break;
+ default:
+ assert(0);
+ }
+
+ return val;
}
int
@@ -654,6 +730,13 @@
pdi->pi_bar[idx].type = type;
pdi->pi_bar[idx].addr = addr;
pdi->pi_bar[idx].size = size;
+ /* passthru devices are using same lobits as physical device
+ * they set this property
+ */
+ if (pdi->pi_bar[idx].lobits != 0)
+ lobits = pdi->pi_bar[idx].lobits;
+ else
+ pdi->pi_bar[idx].lobits = lobits;
/* Initialize the BAR register in config space */
bar = (addr & mask) | lobits;
@@ -1780,7 +1863,6 @@
struct pci_devinst *pi;
struct pci_devemu *pe;
int idx, needcfg;
- uint64_t addr, bar, mask;
if ((bi = pci_businfo[bus]) != NULL) {
si = &bi->slotinfo[slot];
@@ -1832,8 +1914,13 @@
needcfg = 1;
}
- if (needcfg)
- *eax = CFGREAD(pi, coff, bytes);
+ if (needcfg) {
+ if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) {
+ *eax = read_bar_value(pi, coff, bytes);
+ } else {
+ *eax = CFGREAD(pi, coff, bytes);
+ }
+ }
pci_emul_hdrtype_fixup(bus, slot, coff, bytes, eax);
} else {
@@ -1852,55 +1939,10 @@
*/
if (bytes != 4 || (coff & 0x3) != 0)
return;
+
idx = (coff - PCIR_BAR(0)) / 4;
- mask = ~(pi->pi_bar[idx].size - 1);
- switch (pi->pi_bar[idx].type) {
- case PCIBAR_NONE:
- pi->pi_bar[idx].addr = bar = 0;
- break;
- case PCIBAR_IO:
- addr = *eax & mask;
- addr &= 0xffff;
- bar = addr | PCIM_BAR_IO_SPACE;
- /*
- * Register the new BAR value for interception
- */
- if (addr != pi->pi_bar[idx].addr) {
- update_bar_address(pi, addr, idx,
- PCIBAR_IO);
- }
- break;
- case PCIBAR_MEM32:
- addr = bar = *eax & mask;
- bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
- if (addr != pi->pi_bar[idx].addr) {
- update_bar_address(pi, addr, idx,
- PCIBAR_MEM32);
- }
- break;
- case PCIBAR_MEM64:
- addr = bar = *eax & mask;
- bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
- PCIM_BAR_MEM_PREFETCH;
- if (addr != (uint32_t)pi->pi_bar[idx].addr) {
- update_bar_address(pi, addr, idx,
- PCIBAR_MEM64);
- }
- break;
- case PCIBAR_MEMHI64:
- mask = ~(pi->pi_bar[idx - 1].size - 1);
- addr = ((uint64_t)*eax << 32) & mask;
- bar = addr >> 32;
- if (bar != pi->pi_bar[idx - 1].addr >> 32) {
- update_bar_address(pi, addr, idx - 1,
- PCIBAR_MEMHI64);
- }
- break;
- default:
- assert(0);
- }
- pci_set_cfgdata32(pi, coff, bar);
-
+
+ update_bar_address(pi, idx, *eax);
} else if (pci_emul_iscap(pi, coff)) {
pci_emul_capwrite(pi, coff, bytes, *eax, 0, 0);
} else if (coff >= PCIR_COMMAND && coff < PCIR_REVID) {
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -582,6 +582,16 @@
sc->psc_bar[i].size = size;
sc->psc_bar[i].addr = base;
+ /* Use same lobits as physical bar */
+ uint8_t lobits = read_config(&sc->psc_sel, PCIR_BAR(i), 0x01);
+ if (bartype == PCIBAR_MEM32 || bartype == PCIBAR_MEM64) {
+ lobits &= ~PCIM_BAR_MEM_BASE;
+ } else {
+ lobits &= ~PCIM_BAR_IO_BASE;
+ }
+ sc->psc_bar[i].lobits = lobits;
+ pi->pi_bar[i].lobits = lobits;
+
/* Allocate the BAR in the guest I/O or MMIO space */
error = pci_emul_alloc_bar(pi, i, bartype, size);
if (error)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, May 7, 6:48 AM (7 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28583392
Default Alt Text
D28277.1778136537.diff (6 KB)
Attached To
Mode
D28277: bhyve: rework BAR emulation
Attached
Detach File
Event Timeline
Log In to Comment