Deleted Added
sdiff udiff text old ( 248477 ) new ( 249321 )
full compact
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.sbin/bhyve/pci_emul.c 248477 2013-03-18 22:38:30Z neel $
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/usr.sbin/bhyve/pci_emul.c 248477 2013-03-18 22:38:30Z neel $");
31
32#include <sys/param.h>
33#include <sys/linker_set.h>
34
35#include <ctype.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <strings.h>
40#include <assert.h>
41
42#include <machine/vmm.h>
43#include <vmmapi.h>
44
45#include "bhyverun.h"
46#include "inout.h"
47#include "mem.h"
48#include "mptbl.h"

--- 299 unchanged lines hidden (view full) ---

348int
349pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type,
350 uint64_t size)
351{
352
353 return (pci_emul_alloc_pbar(pdi, idx, 0, type, size));
354}
355
356int
357pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
358 enum pcibar_type type, uint64_t size)
359{
360 int i, error;
361 uint64_t *baseptr, limit, addr, mask, lobits, bar;
362 struct inout_port iop;
363 struct mem_range memp;
364
365 assert(idx >= 0 && idx <= PCI_BARMAX);
366
367 if ((size & (size - 1)) != 0)
368 size = 1UL << flsl(size); /* round up to a power of 2 */
369
370 switch (type) {
371 case PCIBAR_NONE:
372 baseptr = NULL;
373 addr = mask = lobits = 0;
374 break;
375 case PCIBAR_IO:
376 if (hostbase &&
377 pci_slotinfo[pdi->pi_slot][pdi->pi_func].si_legacy) {

--- 60 unchanged lines hidden (view full) ---

438 pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar);
439
440 if (type == PCIBAR_MEM64) {
441 assert(idx + 1 <= PCI_BARMAX);
442 pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64;
443 pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32);
444 }
445
446 /* add a handler to intercept accesses to the I/O bar */
447 if (type == PCIBAR_IO) {
448 iop.name = pdi->pi_name;
449 iop.flags = IOPORT_F_INOUT;
450 iop.handler = pci_emul_io_handler;
451 iop.arg = pdi;
452
453 for (i = 0; i < size; i++) {
454 iop.port = addr + i;
455 register_inout(&iop);
456 }
457 } else if (type == PCIBAR_MEM32 || type == PCIBAR_MEM64) {
458 /* add memory bar intercept handler */
459 memp.name = pdi->pi_name;
460 memp.flags = MEM_F_RW;
461 memp.base = addr;
462 memp.size = size;
463 memp.handler = pci_emul_mem_handler;
464 memp.arg1 = pdi;
465 memp.arg2 = idx;
466
467 error = register_mem(&memp);
468 assert(error == 0);
469 }
470
471 return (0);
472}
473
474#define CAP_START_OFFSET 0x40
475static int
476pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen)
477{
478 int i, capoff, capid, reallen;

--- 617 unchanged lines hidden (view full) ---

1096 cfgfunc = (x >> 8) & PCI_FUNCMAX;
1097 cfgslot = (x >> 11) & PCI_SLOTMAX;
1098 cfgbus = (x >> 16) & PCI_BUSMAX;
1099
1100 return (0);
1101}
1102INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_OUT, pci_emul_cfgaddr);
1103
1104static int
1105pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
1106 uint32_t *eax, void *arg)
1107{
1108 struct pci_devinst *pi;
1109 struct pci_devemu *pe;
1110 int coff, idx, needcfg;
1111 uint64_t mask, bar;
1112
1113 assert(bytes == 1 || bytes == 2 || bytes == 4);
1114
1115 if (cfgbus == 0)
1116 pi = pci_slotinfo[cfgslot][cfgfunc].si_devi;
1117 else
1118 pi = NULL;
1119

--- 50 unchanged lines hidden (view full) ---

1170 if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) {
1171 /*
1172 * Ignore writes to BAR registers that are not
1173 * 4-byte aligned.
1174 */
1175 if (bytes != 4 || (coff & 0x3) != 0)
1176 return (0);
1177 idx = (coff - PCIR_BAR(0)) / 4;
1178 switch (pi->pi_bar[idx].type) {
1179 case PCIBAR_NONE:
1180 bar = 0;
1181 break;
1182 case PCIBAR_IO:
1183 mask = ~(pi->pi_bar[idx].size - 1);
1184 mask &= PCIM_BAR_IO_BASE;
1185 bar = (*eax & mask) | PCIM_BAR_IO_SPACE;
1186 break;
1187 case PCIBAR_MEM32:
1188 mask = ~(pi->pi_bar[idx].size - 1);
1189 mask &= PCIM_BAR_MEM_BASE;
1190 bar = *eax & mask;
1191 bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
1192 break;
1193 case PCIBAR_MEM64:
1194 mask = ~(pi->pi_bar[idx].size - 1);
1195 mask &= PCIM_BAR_MEM_BASE;
1196 bar = *eax & mask;
1197 bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
1198 PCIM_BAR_MEM_PREFETCH;
1199 break;
1200 case PCIBAR_MEMHI64:
1201 mask = ~(pi->pi_bar[idx - 1].size - 1);
1202 mask &= PCIM_BAR_MEM_BASE;
1203 bar = ((uint64_t)*eax << 32) & mask;
1204 bar = bar >> 32;
1205 break;
1206 default:
1207 assert(0);
1208 }
1209 pci_set_cfgdata32(pi, coff, bar);
1210
1211 } else if (pci_emul_iscap(pi, coff)) {
1212 pci_emul_capwrite(pi, coff, bytes, *eax);
1213 } else {
1214 CFGWRITE(pi, coff, *eax, bytes);
1215 }
1216 }
1217
1218 return (0);
1219}
1220

--- 188 unchanged lines hidden ---