1*bf21cd93STycho Nightingale /*- 2*bf21cd93STycho Nightingale * Copyright (c) 2011 NetApp, Inc. 3*bf21cd93STycho Nightingale * All rights reserved. 4*bf21cd93STycho Nightingale * 5*bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without 6*bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions 7*bf21cd93STycho Nightingale * are met: 8*bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright 9*bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer. 10*bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright 11*bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the 12*bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution. 13*bf21cd93STycho Nightingale * 14*bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15*bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18*bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*bf21cd93STycho Nightingale * SUCH DAMAGE. 25*bf21cd93STycho Nightingale * 26*bf21cd93STycho Nightingale * $FreeBSD: head/usr.sbin/bhyve/pci_emul.c 269700 2014-08-08 03:49:01Z neel $ 27*bf21cd93STycho Nightingale */ 28*bf21cd93STycho Nightingale /* 29*bf21cd93STycho Nightingale * This file and its contents are supplied under the terms of the 30*bf21cd93STycho Nightingale * Common Development and Distribution License ("CDDL"), version 1.0. 31*bf21cd93STycho Nightingale * You may only use this file in accordance with the terms of version 32*bf21cd93STycho Nightingale * 1.0 of the CDDL. 33*bf21cd93STycho Nightingale * 34*bf21cd93STycho Nightingale * A full copy of the text of the CDDL should have accompanied this 35*bf21cd93STycho Nightingale * source. A copy of the CDDL is also available via the Internet at 36*bf21cd93STycho Nightingale * http://www.illumos.org/license/CDDL. 37*bf21cd93STycho Nightingale * 38*bf21cd93STycho Nightingale * Copyright 2014 Pluribus Networks Inc. 39*bf21cd93STycho Nightingale */ 40*bf21cd93STycho Nightingale 41*bf21cd93STycho Nightingale #include <sys/cdefs.h> 42*bf21cd93STycho Nightingale __FBSDID("$FreeBSD: head/usr.sbin/bhyve/pci_emul.c 269700 2014-08-08 03:49:01Z neel $"); 43*bf21cd93STycho Nightingale 44*bf21cd93STycho Nightingale #include <sys/param.h> 45*bf21cd93STycho Nightingale #include <sys/linker_set.h> 46*bf21cd93STycho Nightingale #include <sys/errno.h> 47*bf21cd93STycho Nightingale 48*bf21cd93STycho Nightingale #include <ctype.h> 49*bf21cd93STycho Nightingale #include <pthread.h> 50*bf21cd93STycho Nightingale #include <stdio.h> 51*bf21cd93STycho Nightingale #include <stdlib.h> 52*bf21cd93STycho Nightingale #include <string.h> 53*bf21cd93STycho Nightingale #include <strings.h> 54*bf21cd93STycho Nightingale #include <assert.h> 55*bf21cd93STycho Nightingale #include <stdbool.h> 56*bf21cd93STycho Nightingale 57*bf21cd93STycho Nightingale #include <machine/vmm.h> 58*bf21cd93STycho Nightingale #include <vmmapi.h> 59*bf21cd93STycho Nightingale 60*bf21cd93STycho Nightingale #include "acpi.h" 61*bf21cd93STycho Nightingale #include "bhyverun.h" 62*bf21cd93STycho Nightingale #include "inout.h" 63*bf21cd93STycho Nightingale #include "ioapic.h" 64*bf21cd93STycho Nightingale #include "mem.h" 65*bf21cd93STycho Nightingale #include "pci_emul.h" 66*bf21cd93STycho Nightingale #include "pci_irq.h" 67*bf21cd93STycho Nightingale #include "pci_lpc.h" 68*bf21cd93STycho Nightingale 69*bf21cd93STycho Nightingale #define CONF1_ADDR_PORT 0x0cf8 70*bf21cd93STycho Nightingale #define CONF1_DATA_PORT 0x0cfc 71*bf21cd93STycho Nightingale 72*bf21cd93STycho Nightingale #define CONF1_ENABLE 0x80000000ul 73*bf21cd93STycho Nightingale 74*bf21cd93STycho Nightingale #define CFGWRITE(pi,off,val,b) \ 75*bf21cd93STycho Nightingale do { \ 76*bf21cd93STycho Nightingale if ((b) == 1) { \ 77*bf21cd93STycho Nightingale pci_set_cfgdata8((pi),(off),(val)); \ 78*bf21cd93STycho Nightingale } else if ((b) == 2) { \ 79*bf21cd93STycho Nightingale pci_set_cfgdata16((pi),(off),(val)); \ 80*bf21cd93STycho Nightingale } else { \ 81*bf21cd93STycho Nightingale pci_set_cfgdata32((pi),(off),(val)); \ 82*bf21cd93STycho Nightingale } \ 83*bf21cd93STycho Nightingale } while (0) 84*bf21cd93STycho Nightingale 85*bf21cd93STycho Nightingale #define MAXBUSES (PCI_BUSMAX + 1) 86*bf21cd93STycho Nightingale #define MAXSLOTS (PCI_SLOTMAX + 1) 87*bf21cd93STycho Nightingale #define MAXFUNCS (PCI_FUNCMAX + 1) 88*bf21cd93STycho Nightingale 89*bf21cd93STycho Nightingale struct funcinfo { 90*bf21cd93STycho Nightingale char *fi_name; 91*bf21cd93STycho Nightingale char *fi_param; 92*bf21cd93STycho Nightingale struct pci_devinst *fi_devi; 93*bf21cd93STycho Nightingale }; 94*bf21cd93STycho Nightingale 95*bf21cd93STycho Nightingale struct intxinfo { 96*bf21cd93STycho Nightingale int ii_count; 97*bf21cd93STycho Nightingale int ii_pirq_pin; 98*bf21cd93STycho Nightingale int ii_ioapic_irq; 99*bf21cd93STycho Nightingale }; 100*bf21cd93STycho Nightingale 101*bf21cd93STycho Nightingale struct slotinfo { 102*bf21cd93STycho Nightingale struct intxinfo si_intpins[4]; 103*bf21cd93STycho Nightingale struct funcinfo si_funcs[MAXFUNCS]; 104*bf21cd93STycho Nightingale }; 105*bf21cd93STycho Nightingale 106*bf21cd93STycho Nightingale struct businfo { 107*bf21cd93STycho Nightingale uint16_t iobase, iolimit; /* I/O window */ 108*bf21cd93STycho Nightingale uint32_t membase32, memlimit32; /* mmio window below 4GB */ 109*bf21cd93STycho Nightingale uint64_t membase64, memlimit64; /* mmio window above 4GB */ 110*bf21cd93STycho Nightingale struct slotinfo slotinfo[MAXSLOTS]; 111*bf21cd93STycho Nightingale }; 112*bf21cd93STycho Nightingale 113*bf21cd93STycho Nightingale static struct businfo *pci_businfo[MAXBUSES]; 114*bf21cd93STycho Nightingale 115*bf21cd93STycho Nightingale SET_DECLARE(pci_devemu_set, struct pci_devemu); 116*bf21cd93STycho Nightingale 117*bf21cd93STycho Nightingale static uint64_t pci_emul_iobase; 118*bf21cd93STycho Nightingale static uint64_t pci_emul_membase32; 119*bf21cd93STycho Nightingale static uint64_t pci_emul_membase64; 120*bf21cd93STycho Nightingale 121*bf21cd93STycho Nightingale #define PCI_EMUL_IOBASE 0x2000 122*bf21cd93STycho Nightingale #define PCI_EMUL_IOLIMIT 0x10000 123*bf21cd93STycho Nightingale 124*bf21cd93STycho Nightingale #define PCI_EMUL_ECFG_BASE 0xE0000000 /* 3.5GB */ 125*bf21cd93STycho Nightingale #define PCI_EMUL_ECFG_SIZE (MAXBUSES * 1024 * 1024) /* 1MB per bus */ 126*bf21cd93STycho Nightingale SYSRES_MEM(PCI_EMUL_ECFG_BASE, PCI_EMUL_ECFG_SIZE); 127*bf21cd93STycho Nightingale 128*bf21cd93STycho Nightingale #define PCI_EMUL_MEMLIMIT32 PCI_EMUL_ECFG_BASE 129*bf21cd93STycho Nightingale 130*bf21cd93STycho Nightingale #define PCI_EMUL_MEMBASE64 0xD000000000UL 131*bf21cd93STycho Nightingale #define PCI_EMUL_MEMLIMIT64 0xFD00000000UL 132*bf21cd93STycho Nightingale 133*bf21cd93STycho Nightingale static struct pci_devemu *pci_emul_finddev(char *name); 134*bf21cd93STycho Nightingale static void pci_lintr_route(struct pci_devinst *pi); 135*bf21cd93STycho Nightingale static void pci_lintr_update(struct pci_devinst *pi); 136*bf21cd93STycho Nightingale static void pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, 137*bf21cd93STycho Nightingale int func, int coff, int bytes, uint32_t *val); 138*bf21cd93STycho Nightingale 139*bf21cd93STycho Nightingale /* 140*bf21cd93STycho Nightingale * I/O access 141*bf21cd93STycho Nightingale */ 142*bf21cd93STycho Nightingale 143*bf21cd93STycho Nightingale /* 144*bf21cd93STycho Nightingale * Slot options are in the form: 145*bf21cd93STycho Nightingale * 146*bf21cd93STycho Nightingale * <bus>:<slot>:<func>,<emul>[,<config>] 147*bf21cd93STycho Nightingale * <slot>[:<func>],<emul>[,<config>] 148*bf21cd93STycho Nightingale * 149*bf21cd93STycho Nightingale * slot is 0..31 150*bf21cd93STycho Nightingale * func is 0..7 151*bf21cd93STycho Nightingale * emul is a string describing the type of PCI device e.g. virtio-net 152*bf21cd93STycho Nightingale * config is an optional string, depending on the device, that can be 153*bf21cd93STycho Nightingale * used for configuration. 154*bf21cd93STycho Nightingale * Examples are: 155*bf21cd93STycho Nightingale * 1,virtio-net,tap0 156*bf21cd93STycho Nightingale * 3:0,dummy 157*bf21cd93STycho Nightingale */ 158*bf21cd93STycho Nightingale static void 159*bf21cd93STycho Nightingale pci_parse_slot_usage(char *aopt) 160*bf21cd93STycho Nightingale { 161*bf21cd93STycho Nightingale 162*bf21cd93STycho Nightingale fprintf(stderr, "Invalid PCI slot info field \"%s\"\n", aopt); 163*bf21cd93STycho Nightingale } 164*bf21cd93STycho Nightingale 165*bf21cd93STycho Nightingale int 166*bf21cd93STycho Nightingale pci_parse_slot(char *opt) 167*bf21cd93STycho Nightingale { 168*bf21cd93STycho Nightingale struct businfo *bi; 169*bf21cd93STycho Nightingale struct slotinfo *si; 170*bf21cd93STycho Nightingale char *emul, *config, *str, *cp; 171*bf21cd93STycho Nightingale int error, bnum, snum, fnum; 172*bf21cd93STycho Nightingale 173*bf21cd93STycho Nightingale error = -1; 174*bf21cd93STycho Nightingale str = strdup(opt); 175*bf21cd93STycho Nightingale 176*bf21cd93STycho Nightingale emul = config = NULL; 177*bf21cd93STycho Nightingale if ((cp = strchr(str, ',')) != NULL) { 178*bf21cd93STycho Nightingale *cp = '\0'; 179*bf21cd93STycho Nightingale emul = cp + 1; 180*bf21cd93STycho Nightingale if ((cp = strchr(emul, ',')) != NULL) { 181*bf21cd93STycho Nightingale *cp = '\0'; 182*bf21cd93STycho Nightingale config = cp + 1; 183*bf21cd93STycho Nightingale } 184*bf21cd93STycho Nightingale } else { 185*bf21cd93STycho Nightingale pci_parse_slot_usage(opt); 186*bf21cd93STycho Nightingale goto done; 187*bf21cd93STycho Nightingale } 188*bf21cd93STycho Nightingale 189*bf21cd93STycho Nightingale /* <bus>:<slot>:<func> */ 190*bf21cd93STycho Nightingale if (sscanf(str, "%d:%d:%d", &bnum, &snum, &fnum) != 3) { 191*bf21cd93STycho Nightingale bnum = 0; 192*bf21cd93STycho Nightingale /* <slot>:<func> */ 193*bf21cd93STycho Nightingale if (sscanf(str, "%d:%d", &snum, &fnum) != 2) { 194*bf21cd93STycho Nightingale fnum = 0; 195*bf21cd93STycho Nightingale /* <slot> */ 196*bf21cd93STycho Nightingale if (sscanf(str, "%d", &snum) != 1) { 197*bf21cd93STycho Nightingale snum = -1; 198*bf21cd93STycho Nightingale } 199*bf21cd93STycho Nightingale } 200*bf21cd93STycho Nightingale } 201*bf21cd93STycho Nightingale 202*bf21cd93STycho Nightingale if (bnum < 0 || bnum >= MAXBUSES || snum < 0 || snum >= MAXSLOTS || 203*bf21cd93STycho Nightingale fnum < 0 || fnum >= MAXFUNCS) { 204*bf21cd93STycho Nightingale pci_parse_slot_usage(opt); 205*bf21cd93STycho Nightingale goto done; 206*bf21cd93STycho Nightingale } 207*bf21cd93STycho Nightingale 208*bf21cd93STycho Nightingale if (pci_businfo[bnum] == NULL) 209*bf21cd93STycho Nightingale pci_businfo[bnum] = calloc(1, sizeof(struct businfo)); 210*bf21cd93STycho Nightingale 211*bf21cd93STycho Nightingale bi = pci_businfo[bnum]; 212*bf21cd93STycho Nightingale si = &bi->slotinfo[snum]; 213*bf21cd93STycho Nightingale 214*bf21cd93STycho Nightingale if (si->si_funcs[fnum].fi_name != NULL) { 215*bf21cd93STycho Nightingale fprintf(stderr, "pci slot %d:%d already occupied!\n", 216*bf21cd93STycho Nightingale snum, fnum); 217*bf21cd93STycho Nightingale goto done; 218*bf21cd93STycho Nightingale } 219*bf21cd93STycho Nightingale 220*bf21cd93STycho Nightingale if (pci_emul_finddev(emul) == NULL) { 221*bf21cd93STycho Nightingale fprintf(stderr, "pci slot %d:%d: unknown device \"%s\"\n", 222*bf21cd93STycho Nightingale snum, fnum, emul); 223*bf21cd93STycho Nightingale goto done; 224*bf21cd93STycho Nightingale } 225*bf21cd93STycho Nightingale 226*bf21cd93STycho Nightingale error = 0; 227*bf21cd93STycho Nightingale si->si_funcs[fnum].fi_name = emul; 228*bf21cd93STycho Nightingale si->si_funcs[fnum].fi_param = config; 229*bf21cd93STycho Nightingale 230*bf21cd93STycho Nightingale done: 231*bf21cd93STycho Nightingale if (error) 232*bf21cd93STycho Nightingale free(str); 233*bf21cd93STycho Nightingale 234*bf21cd93STycho Nightingale return (error); 235*bf21cd93STycho Nightingale } 236*bf21cd93STycho Nightingale 237*bf21cd93STycho Nightingale static int 238*bf21cd93STycho Nightingale pci_valid_pba_offset(struct pci_devinst *pi, uint64_t offset) 239*bf21cd93STycho Nightingale { 240*bf21cd93STycho Nightingale 241*bf21cd93STycho Nightingale if (offset < pi->pi_msix.pba_offset) 242*bf21cd93STycho Nightingale return (0); 243*bf21cd93STycho Nightingale 244*bf21cd93STycho Nightingale if (offset >= pi->pi_msix.pba_offset + pi->pi_msix.pba_size) { 245*bf21cd93STycho Nightingale return (0); 246*bf21cd93STycho Nightingale } 247*bf21cd93STycho Nightingale 248*bf21cd93STycho Nightingale return (1); 249*bf21cd93STycho Nightingale } 250*bf21cd93STycho Nightingale 251*bf21cd93STycho Nightingale int 252*bf21cd93STycho Nightingale pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size, 253*bf21cd93STycho Nightingale uint64_t value) 254*bf21cd93STycho Nightingale { 255*bf21cd93STycho Nightingale int msix_entry_offset; 256*bf21cd93STycho Nightingale int tab_index; 257*bf21cd93STycho Nightingale char *dest; 258*bf21cd93STycho Nightingale 259*bf21cd93STycho Nightingale /* support only 4 or 8 byte writes */ 260*bf21cd93STycho Nightingale if (size != 4 && size != 8) 261*bf21cd93STycho Nightingale return (-1); 262*bf21cd93STycho Nightingale 263*bf21cd93STycho Nightingale /* 264*bf21cd93STycho Nightingale * Return if table index is beyond what device supports 265*bf21cd93STycho Nightingale */ 266*bf21cd93STycho Nightingale tab_index = offset / MSIX_TABLE_ENTRY_SIZE; 267*bf21cd93STycho Nightingale if (tab_index >= pi->pi_msix.table_count) 268*bf21cd93STycho Nightingale return (-1); 269*bf21cd93STycho Nightingale 270*bf21cd93STycho Nightingale msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; 271*bf21cd93STycho Nightingale 272*bf21cd93STycho Nightingale /* support only aligned writes */ 273*bf21cd93STycho Nightingale if ((msix_entry_offset % size) != 0) 274*bf21cd93STycho Nightingale return (-1); 275*bf21cd93STycho Nightingale 276*bf21cd93STycho Nightingale dest = (char *)(pi->pi_msix.table + tab_index); 277*bf21cd93STycho Nightingale dest += msix_entry_offset; 278*bf21cd93STycho Nightingale 279*bf21cd93STycho Nightingale if (size == 4) 280*bf21cd93STycho Nightingale *((uint32_t *)dest) = value; 281*bf21cd93STycho Nightingale else 282*bf21cd93STycho Nightingale *((uint64_t *)dest) = value; 283*bf21cd93STycho Nightingale 284*bf21cd93STycho Nightingale return (0); 285*bf21cd93STycho Nightingale } 286*bf21cd93STycho Nightingale 287*bf21cd93STycho Nightingale uint64_t 288*bf21cd93STycho Nightingale pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size) 289*bf21cd93STycho Nightingale { 290*bf21cd93STycho Nightingale char *dest; 291*bf21cd93STycho Nightingale int msix_entry_offset; 292*bf21cd93STycho Nightingale int tab_index; 293*bf21cd93STycho Nightingale uint64_t retval = ~0; 294*bf21cd93STycho Nightingale 295*bf21cd93STycho Nightingale /* 296*bf21cd93STycho Nightingale * The PCI standard only allows 4 and 8 byte accesses to the MSI-X 297*bf21cd93STycho Nightingale * table but we also allow 1 byte access to accomodate reads from 298*bf21cd93STycho Nightingale * ddb. 299*bf21cd93STycho Nightingale */ 300*bf21cd93STycho Nightingale if (size != 1 && size != 4 && size != 8) 301*bf21cd93STycho Nightingale return (retval); 302*bf21cd93STycho Nightingale 303*bf21cd93STycho Nightingale msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; 304*bf21cd93STycho Nightingale 305*bf21cd93STycho Nightingale /* support only aligned reads */ 306*bf21cd93STycho Nightingale if ((msix_entry_offset % size) != 0) { 307*bf21cd93STycho Nightingale return (retval); 308*bf21cd93STycho Nightingale } 309*bf21cd93STycho Nightingale 310*bf21cd93STycho Nightingale tab_index = offset / MSIX_TABLE_ENTRY_SIZE; 311*bf21cd93STycho Nightingale 312*bf21cd93STycho Nightingale if (tab_index < pi->pi_msix.table_count) { 313*bf21cd93STycho Nightingale /* valid MSI-X Table access */ 314*bf21cd93STycho Nightingale dest = (char *)(pi->pi_msix.table + tab_index); 315*bf21cd93STycho Nightingale dest += msix_entry_offset; 316*bf21cd93STycho Nightingale 317*bf21cd93STycho Nightingale if (size == 1) 318*bf21cd93STycho Nightingale retval = *((uint8_t *)dest); 319*bf21cd93STycho Nightingale else if (size == 4) 320*bf21cd93STycho Nightingale retval = *((uint32_t *)dest); 321*bf21cd93STycho Nightingale else 322*bf21cd93STycho Nightingale retval = *((uint64_t *)dest); 323*bf21cd93STycho Nightingale } else if (pci_valid_pba_offset(pi, offset)) { 324*bf21cd93STycho Nightingale /* return 0 for PBA access */ 325*bf21cd93STycho Nightingale retval = 0; 326*bf21cd93STycho Nightingale } 327*bf21cd93STycho Nightingale 328*bf21cd93STycho Nightingale return (retval); 329*bf21cd93STycho Nightingale } 330*bf21cd93STycho Nightingale 331*bf21cd93STycho Nightingale int 332*bf21cd93STycho Nightingale pci_msix_table_bar(struct pci_devinst *pi) 333*bf21cd93STycho Nightingale { 334*bf21cd93STycho Nightingale 335*bf21cd93STycho Nightingale if (pi->pi_msix.table != NULL) 336*bf21cd93STycho Nightingale return (pi->pi_msix.table_bar); 337*bf21cd93STycho Nightingale else 338*bf21cd93STycho Nightingale return (-1); 339*bf21cd93STycho Nightingale } 340*bf21cd93STycho Nightingale 341*bf21cd93STycho Nightingale int 342*bf21cd93STycho Nightingale pci_msix_pba_bar(struct pci_devinst *pi) 343*bf21cd93STycho Nightingale { 344*bf21cd93STycho Nightingale 345*bf21cd93STycho Nightingale if (pi->pi_msix.table != NULL) 346*bf21cd93STycho Nightingale return (pi->pi_msix.pba_bar); 347*bf21cd93STycho Nightingale else 348*bf21cd93STycho Nightingale return (-1); 349*bf21cd93STycho Nightingale } 350*bf21cd93STycho Nightingale 351*bf21cd93STycho Nightingale static int 352*bf21cd93STycho Nightingale pci_emul_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 353*bf21cd93STycho Nightingale uint32_t *eax, void *arg) 354*bf21cd93STycho Nightingale { 355*bf21cd93STycho Nightingale struct pci_devinst *pdi = arg; 356*bf21cd93STycho Nightingale struct pci_devemu *pe = pdi->pi_d; 357*bf21cd93STycho Nightingale uint64_t offset; 358*bf21cd93STycho Nightingale int i; 359*bf21cd93STycho Nightingale 360*bf21cd93STycho Nightingale for (i = 0; i <= PCI_BARMAX; i++) { 361*bf21cd93STycho Nightingale if (pdi->pi_bar[i].type == PCIBAR_IO && 362*bf21cd93STycho Nightingale port >= pdi->pi_bar[i].addr && 363*bf21cd93STycho Nightingale port + bytes <= pdi->pi_bar[i].addr + pdi->pi_bar[i].size) { 364*bf21cd93STycho Nightingale offset = port - pdi->pi_bar[i].addr; 365*bf21cd93STycho Nightingale if (in) 366*bf21cd93STycho Nightingale *eax = (*pe->pe_barread)(ctx, vcpu, pdi, i, 367*bf21cd93STycho Nightingale offset, bytes); 368*bf21cd93STycho Nightingale else 369*bf21cd93STycho Nightingale (*pe->pe_barwrite)(ctx, vcpu, pdi, i, offset, 370*bf21cd93STycho Nightingale bytes, *eax); 371*bf21cd93STycho Nightingale return (0); 372*bf21cd93STycho Nightingale } 373*bf21cd93STycho Nightingale } 374*bf21cd93STycho Nightingale return (-1); 375*bf21cd93STycho Nightingale } 376*bf21cd93STycho Nightingale 377*bf21cd93STycho Nightingale static int 378*bf21cd93STycho Nightingale pci_emul_mem_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, 379*bf21cd93STycho Nightingale int size, uint64_t *val, void *arg1, long arg2) 380*bf21cd93STycho Nightingale { 381*bf21cd93STycho Nightingale struct pci_devinst *pdi = arg1; 382*bf21cd93STycho Nightingale struct pci_devemu *pe = pdi->pi_d; 383*bf21cd93STycho Nightingale uint64_t offset; 384*bf21cd93STycho Nightingale int bidx = (int) arg2; 385*bf21cd93STycho Nightingale 386*bf21cd93STycho Nightingale assert(bidx <= PCI_BARMAX); 387*bf21cd93STycho Nightingale assert(pdi->pi_bar[bidx].type == PCIBAR_MEM32 || 388*bf21cd93STycho Nightingale pdi->pi_bar[bidx].type == PCIBAR_MEM64); 389*bf21cd93STycho Nightingale assert(addr >= pdi->pi_bar[bidx].addr && 390*bf21cd93STycho Nightingale addr + size <= pdi->pi_bar[bidx].addr + pdi->pi_bar[bidx].size); 391*bf21cd93STycho Nightingale 392*bf21cd93STycho Nightingale offset = addr - pdi->pi_bar[bidx].addr; 393*bf21cd93STycho Nightingale 394*bf21cd93STycho Nightingale if (dir == MEM_F_WRITE) { 395*bf21cd93STycho Nightingale if (size == 8) { 396*bf21cd93STycho Nightingale (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, 397*bf21cd93STycho Nightingale 4, *val & 0xffffffff); 398*bf21cd93STycho Nightingale (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset + 4, 399*bf21cd93STycho Nightingale 4, *val >> 32); 400*bf21cd93STycho Nightingale } else { 401*bf21cd93STycho Nightingale (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, 402*bf21cd93STycho Nightingale size, *val); 403*bf21cd93STycho Nightingale } 404*bf21cd93STycho Nightingale } else { 405*bf21cd93STycho Nightingale if (size == 8) { 406*bf21cd93STycho Nightingale *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, 407*bf21cd93STycho Nightingale offset, 4); 408*bf21cd93STycho Nightingale *val |= (*pe->pe_barread)(ctx, vcpu, pdi, bidx, 409*bf21cd93STycho Nightingale offset + 4, 4) << 32; 410*bf21cd93STycho Nightingale } else { 411*bf21cd93STycho Nightingale *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, 412*bf21cd93STycho Nightingale offset, size); 413*bf21cd93STycho Nightingale } 414*bf21cd93STycho Nightingale } 415*bf21cd93STycho Nightingale 416*bf21cd93STycho Nightingale return (0); 417*bf21cd93STycho Nightingale } 418*bf21cd93STycho Nightingale 419*bf21cd93STycho Nightingale 420*bf21cd93STycho Nightingale static int 421*bf21cd93STycho Nightingale pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size, 422*bf21cd93STycho Nightingale uint64_t *addr) 423*bf21cd93STycho Nightingale { 424*bf21cd93STycho Nightingale uint64_t base; 425*bf21cd93STycho Nightingale 426*bf21cd93STycho Nightingale assert((size & (size - 1)) == 0); /* must be a power of 2 */ 427*bf21cd93STycho Nightingale 428*bf21cd93STycho Nightingale base = roundup2(*baseptr, size); 429*bf21cd93STycho Nightingale 430*bf21cd93STycho Nightingale if (base + size <= limit) { 431*bf21cd93STycho Nightingale *addr = base; 432*bf21cd93STycho Nightingale *baseptr = base + size; 433*bf21cd93STycho Nightingale return (0); 434*bf21cd93STycho Nightingale } else 435*bf21cd93STycho Nightingale return (-1); 436*bf21cd93STycho Nightingale } 437*bf21cd93STycho Nightingale 438*bf21cd93STycho Nightingale int 439*bf21cd93STycho Nightingale pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type, 440*bf21cd93STycho Nightingale uint64_t size) 441*bf21cd93STycho Nightingale { 442*bf21cd93STycho Nightingale 443*bf21cd93STycho Nightingale return (pci_emul_alloc_pbar(pdi, idx, 0, type, size)); 444*bf21cd93STycho Nightingale } 445*bf21cd93STycho Nightingale 446*bf21cd93STycho Nightingale /* 447*bf21cd93STycho Nightingale * Register (or unregister) the MMIO or I/O region associated with the BAR 448*bf21cd93STycho Nightingale * register 'idx' of an emulated pci device. 449*bf21cd93STycho Nightingale */ 450*bf21cd93STycho Nightingale static void 451*bf21cd93STycho Nightingale modify_bar_registration(struct pci_devinst *pi, int idx, int registration) 452*bf21cd93STycho Nightingale { 453*bf21cd93STycho Nightingale int error; 454*bf21cd93STycho Nightingale struct inout_port iop; 455*bf21cd93STycho Nightingale struct mem_range mr; 456*bf21cd93STycho Nightingale 457*bf21cd93STycho Nightingale switch (pi->pi_bar[idx].type) { 458*bf21cd93STycho Nightingale case PCIBAR_IO: 459*bf21cd93STycho Nightingale bzero(&iop, sizeof(struct inout_port)); 460*bf21cd93STycho Nightingale iop.name = pi->pi_name; 461*bf21cd93STycho Nightingale iop.port = pi->pi_bar[idx].addr; 462*bf21cd93STycho Nightingale iop.size = pi->pi_bar[idx].size; 463*bf21cd93STycho Nightingale if (registration) { 464*bf21cd93STycho Nightingale iop.flags = IOPORT_F_INOUT; 465*bf21cd93STycho Nightingale iop.handler = pci_emul_io_handler; 466*bf21cd93STycho Nightingale iop.arg = pi; 467*bf21cd93STycho Nightingale error = register_inout(&iop); 468*bf21cd93STycho Nightingale } else 469*bf21cd93STycho Nightingale error = unregister_inout(&iop); 470*bf21cd93STycho Nightingale break; 471*bf21cd93STycho Nightingale case PCIBAR_MEM32: 472*bf21cd93STycho Nightingale case PCIBAR_MEM64: 473*bf21cd93STycho Nightingale bzero(&mr, sizeof(struct mem_range)); 474*bf21cd93STycho Nightingale mr.name = pi->pi_name; 475*bf21cd93STycho Nightingale mr.base = pi->pi_bar[idx].addr; 476*bf21cd93STycho Nightingale mr.size = pi->pi_bar[idx].size; 477*bf21cd93STycho Nightingale if (registration) { 478*bf21cd93STycho Nightingale mr.flags = MEM_F_RW; 479*bf21cd93STycho Nightingale mr.handler = pci_emul_mem_handler; 480*bf21cd93STycho Nightingale mr.arg1 = pi; 481*bf21cd93STycho Nightingale mr.arg2 = idx; 482*bf21cd93STycho Nightingale error = register_mem(&mr); 483*bf21cd93STycho Nightingale } else 484*bf21cd93STycho Nightingale error = unregister_mem(&mr); 485*bf21cd93STycho Nightingale break; 486*bf21cd93STycho Nightingale default: 487*bf21cd93STycho Nightingale error = EINVAL; 488*bf21cd93STycho Nightingale break; 489*bf21cd93STycho Nightingale } 490*bf21cd93STycho Nightingale assert(error == 0); 491*bf21cd93STycho Nightingale } 492*bf21cd93STycho Nightingale 493*bf21cd93STycho Nightingale static void 494*bf21cd93STycho Nightingale unregister_bar(struct pci_devinst *pi, int idx) 495*bf21cd93STycho Nightingale { 496*bf21cd93STycho Nightingale 497*bf21cd93STycho Nightingale modify_bar_registration(pi, idx, 0); 498*bf21cd93STycho Nightingale } 499*bf21cd93STycho Nightingale 500*bf21cd93STycho Nightingale static void 501*bf21cd93STycho Nightingale register_bar(struct pci_devinst *pi, int idx) 502*bf21cd93STycho Nightingale { 503*bf21cd93STycho Nightingale 504*bf21cd93STycho Nightingale modify_bar_registration(pi, idx, 1); 505*bf21cd93STycho Nightingale } 506*bf21cd93STycho Nightingale 507*bf21cd93STycho Nightingale /* Are we decoding i/o port accesses for the emulated pci device? */ 508*bf21cd93STycho Nightingale static int 509*bf21cd93STycho Nightingale porten(struct pci_devinst *pi) 510*bf21cd93STycho Nightingale { 511*bf21cd93STycho Nightingale uint16_t cmd; 512*bf21cd93STycho Nightingale 513*bf21cd93STycho Nightingale cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); 514*bf21cd93STycho Nightingale 515*bf21cd93STycho Nightingale return (cmd & PCIM_CMD_PORTEN); 516*bf21cd93STycho Nightingale } 517*bf21cd93STycho Nightingale 518*bf21cd93STycho Nightingale /* Are we decoding memory accesses for the emulated pci device? */ 519*bf21cd93STycho Nightingale static int 520*bf21cd93STycho Nightingale memen(struct pci_devinst *pi) 521*bf21cd93STycho Nightingale { 522*bf21cd93STycho Nightingale uint16_t cmd; 523*bf21cd93STycho Nightingale 524*bf21cd93STycho Nightingale cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); 525*bf21cd93STycho Nightingale 526*bf21cd93STycho Nightingale return (cmd & PCIM_CMD_MEMEN); 527*bf21cd93STycho Nightingale } 528*bf21cd93STycho Nightingale 529*bf21cd93STycho Nightingale /* 530*bf21cd93STycho Nightingale * Update the MMIO or I/O address that is decoded by the BAR register. 531*bf21cd93STycho Nightingale * 532*bf21cd93STycho Nightingale * If the pci device has enabled the address space decoding then intercept 533*bf21cd93STycho Nightingale * the address range decoded by the BAR register. 534*bf21cd93STycho Nightingale */ 535*bf21cd93STycho Nightingale static void 536*bf21cd93STycho Nightingale update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type) 537*bf21cd93STycho Nightingale { 538*bf21cd93STycho Nightingale int decode; 539*bf21cd93STycho Nightingale 540*bf21cd93STycho Nightingale if (pi->pi_bar[idx].type == PCIBAR_IO) 541*bf21cd93STycho Nightingale decode = porten(pi); 542*bf21cd93STycho Nightingale else 543*bf21cd93STycho Nightingale decode = memen(pi); 544*bf21cd93STycho Nightingale 545*bf21cd93STycho Nightingale if (decode) 546*bf21cd93STycho Nightingale unregister_bar(pi, idx); 547*bf21cd93STycho Nightingale 548*bf21cd93STycho Nightingale switch (type) { 549*bf21cd93STycho Nightingale case PCIBAR_IO: 550*bf21cd93STycho Nightingale case PCIBAR_MEM32: 551*bf21cd93STycho Nightingale pi->pi_bar[idx].addr = addr; 552*bf21cd93STycho Nightingale break; 553*bf21cd93STycho Nightingale case PCIBAR_MEM64: 554*bf21cd93STycho Nightingale pi->pi_bar[idx].addr &= ~0xffffffffUL; 555*bf21cd93STycho Nightingale pi->pi_bar[idx].addr |= addr; 556*bf21cd93STycho Nightingale break; 557*bf21cd93STycho Nightingale case PCIBAR_MEMHI64: 558*bf21cd93STycho Nightingale pi->pi_bar[idx].addr &= 0xffffffff; 559*bf21cd93STycho Nightingale pi->pi_bar[idx].addr |= addr; 560*bf21cd93STycho Nightingale break; 561*bf21cd93STycho Nightingale default: 562*bf21cd93STycho Nightingale assert(0); 563*bf21cd93STycho Nightingale } 564*bf21cd93STycho Nightingale 565*bf21cd93STycho Nightingale if (decode) 566*bf21cd93STycho Nightingale register_bar(pi, idx); 567*bf21cd93STycho Nightingale } 568*bf21cd93STycho Nightingale 569*bf21cd93STycho Nightingale int 570*bf21cd93STycho Nightingale pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, 571*bf21cd93STycho Nightingale enum pcibar_type type, uint64_t size) 572*bf21cd93STycho Nightingale { 573*bf21cd93STycho Nightingale int error; 574*bf21cd93STycho Nightingale uint64_t *baseptr, limit, addr, mask, lobits, bar; 575*bf21cd93STycho Nightingale 576*bf21cd93STycho Nightingale assert(idx >= 0 && idx <= PCI_BARMAX); 577*bf21cd93STycho Nightingale 578*bf21cd93STycho Nightingale if ((size & (size - 1)) != 0) 579*bf21cd93STycho Nightingale size = 1UL << flsl(size); /* round up to a power of 2 */ 580*bf21cd93STycho Nightingale 581*bf21cd93STycho Nightingale /* Enforce minimum BAR sizes required by the PCI standard */ 582*bf21cd93STycho Nightingale if (type == PCIBAR_IO) { 583*bf21cd93STycho Nightingale if (size < 4) 584*bf21cd93STycho Nightingale size = 4; 585*bf21cd93STycho Nightingale } else { 586*bf21cd93STycho Nightingale if (size < 16) 587*bf21cd93STycho Nightingale size = 16; 588*bf21cd93STycho Nightingale } 589*bf21cd93STycho Nightingale 590*bf21cd93STycho Nightingale switch (type) { 591*bf21cd93STycho Nightingale case PCIBAR_NONE: 592*bf21cd93STycho Nightingale baseptr = NULL; 593*bf21cd93STycho Nightingale addr = mask = lobits = 0; 594*bf21cd93STycho Nightingale break; 595*bf21cd93STycho Nightingale case PCIBAR_IO: 596*bf21cd93STycho Nightingale baseptr = &pci_emul_iobase; 597*bf21cd93STycho Nightingale limit = PCI_EMUL_IOLIMIT; 598*bf21cd93STycho Nightingale mask = PCIM_BAR_IO_BASE; 599*bf21cd93STycho Nightingale lobits = PCIM_BAR_IO_SPACE; 600*bf21cd93STycho Nightingale break; 601*bf21cd93STycho Nightingale case PCIBAR_MEM64: 602*bf21cd93STycho Nightingale /* 603*bf21cd93STycho Nightingale * XXX 604*bf21cd93STycho Nightingale * Some drivers do not work well if the 64-bit BAR is allocated 605*bf21cd93STycho Nightingale * above 4GB. Allow for this by allocating small requests under 606*bf21cd93STycho Nightingale * 4GB unless then allocation size is larger than some arbitrary 607*bf21cd93STycho Nightingale * number (32MB currently). 608*bf21cd93STycho Nightingale */ 609*bf21cd93STycho Nightingale if (size > 32 * 1024 * 1024) { 610*bf21cd93STycho Nightingale /* 611*bf21cd93STycho Nightingale * XXX special case for device requiring peer-peer DMA 612*bf21cd93STycho Nightingale */ 613*bf21cd93STycho Nightingale if (size == 0x100000000UL) 614*bf21cd93STycho Nightingale baseptr = &hostbase; 615*bf21cd93STycho Nightingale else 616*bf21cd93STycho Nightingale baseptr = &pci_emul_membase64; 617*bf21cd93STycho Nightingale limit = PCI_EMUL_MEMLIMIT64; 618*bf21cd93STycho Nightingale mask = PCIM_BAR_MEM_BASE; 619*bf21cd93STycho Nightingale lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | 620*bf21cd93STycho Nightingale PCIM_BAR_MEM_PREFETCH; 621*bf21cd93STycho Nightingale break; 622*bf21cd93STycho Nightingale } else { 623*bf21cd93STycho Nightingale baseptr = &pci_emul_membase32; 624*bf21cd93STycho Nightingale limit = PCI_EMUL_MEMLIMIT32; 625*bf21cd93STycho Nightingale mask = PCIM_BAR_MEM_BASE; 626*bf21cd93STycho Nightingale lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64; 627*bf21cd93STycho Nightingale } 628*bf21cd93STycho Nightingale break; 629*bf21cd93STycho Nightingale case PCIBAR_MEM32: 630*bf21cd93STycho Nightingale baseptr = &pci_emul_membase32; 631*bf21cd93STycho Nightingale limit = PCI_EMUL_MEMLIMIT32; 632*bf21cd93STycho Nightingale mask = PCIM_BAR_MEM_BASE; 633*bf21cd93STycho Nightingale lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; 634*bf21cd93STycho Nightingale break; 635*bf21cd93STycho Nightingale default: 636*bf21cd93STycho Nightingale printf("pci_emul_alloc_base: invalid bar type %d\n", type); 637*bf21cd93STycho Nightingale assert(0); 638*bf21cd93STycho Nightingale } 639*bf21cd93STycho Nightingale 640*bf21cd93STycho Nightingale if (baseptr != NULL) { 641*bf21cd93STycho Nightingale error = pci_emul_alloc_resource(baseptr, limit, size, &addr); 642*bf21cd93STycho Nightingale if (error != 0) 643*bf21cd93STycho Nightingale return (error); 644*bf21cd93STycho Nightingale } 645*bf21cd93STycho Nightingale 646*bf21cd93STycho Nightingale pdi->pi_bar[idx].type = type; 647*bf21cd93STycho Nightingale pdi->pi_bar[idx].addr = addr; 648*bf21cd93STycho Nightingale pdi->pi_bar[idx].size = size; 649*bf21cd93STycho Nightingale 650*bf21cd93STycho Nightingale /* Initialize the BAR register in config space */ 651*bf21cd93STycho Nightingale bar = (addr & mask) | lobits; 652*bf21cd93STycho Nightingale pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); 653*bf21cd93STycho Nightingale 654*bf21cd93STycho Nightingale if (type == PCIBAR_MEM64) { 655*bf21cd93STycho Nightingale assert(idx + 1 <= PCI_BARMAX); 656*bf21cd93STycho Nightingale pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64; 657*bf21cd93STycho Nightingale pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); 658*bf21cd93STycho Nightingale } 659*bf21cd93STycho Nightingale 660*bf21cd93STycho Nightingale register_bar(pdi, idx); 661*bf21cd93STycho Nightingale 662*bf21cd93STycho Nightingale return (0); 663*bf21cd93STycho Nightingale } 664*bf21cd93STycho Nightingale 665*bf21cd93STycho Nightingale #define CAP_START_OFFSET 0x40 666*bf21cd93STycho Nightingale static int 667*bf21cd93STycho Nightingale pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) 668*bf21cd93STycho Nightingale { 669*bf21cd93STycho Nightingale int i, capoff, reallen; 670*bf21cd93STycho Nightingale uint16_t sts; 671*bf21cd93STycho Nightingale 672*bf21cd93STycho Nightingale assert(caplen > 0); 673*bf21cd93STycho Nightingale 674*bf21cd93STycho Nightingale reallen = roundup2(caplen, 4); /* dword aligned */ 675*bf21cd93STycho Nightingale 676*bf21cd93STycho Nightingale sts = pci_get_cfgdata16(pi, PCIR_STATUS); 677*bf21cd93STycho Nightingale if ((sts & PCIM_STATUS_CAPPRESENT) == 0) 678*bf21cd93STycho Nightingale capoff = CAP_START_OFFSET; 679*bf21cd93STycho Nightingale else 680*bf21cd93STycho Nightingale capoff = pi->pi_capend + 1; 681*bf21cd93STycho Nightingale 682*bf21cd93STycho Nightingale /* Check if we have enough space */ 683*bf21cd93STycho Nightingale if (capoff + reallen > PCI_REGMAX + 1) 684*bf21cd93STycho Nightingale return (-1); 685*bf21cd93STycho Nightingale 686*bf21cd93STycho Nightingale /* Set the previous capability pointer */ 687*bf21cd93STycho Nightingale if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { 688*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); 689*bf21cd93STycho Nightingale pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); 690*bf21cd93STycho Nightingale } else 691*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, pi->pi_prevcap + 1, capoff); 692*bf21cd93STycho Nightingale 693*bf21cd93STycho Nightingale /* Copy the capability */ 694*bf21cd93STycho Nightingale for (i = 0; i < caplen; i++) 695*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, capoff + i, capdata[i]); 696*bf21cd93STycho Nightingale 697*bf21cd93STycho Nightingale /* Set the next capability pointer */ 698*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, capoff + 1, 0); 699*bf21cd93STycho Nightingale 700*bf21cd93STycho Nightingale pi->pi_prevcap = capoff; 701*bf21cd93STycho Nightingale pi->pi_capend = capoff + reallen - 1; 702*bf21cd93STycho Nightingale return (0); 703*bf21cd93STycho Nightingale } 704*bf21cd93STycho Nightingale 705*bf21cd93STycho Nightingale static struct pci_devemu * 706*bf21cd93STycho Nightingale pci_emul_finddev(char *name) 707*bf21cd93STycho Nightingale { 708*bf21cd93STycho Nightingale struct pci_devemu **pdpp, *pdp; 709*bf21cd93STycho Nightingale 710*bf21cd93STycho Nightingale SET_FOREACH(pdpp, pci_devemu_set) { 711*bf21cd93STycho Nightingale pdp = *pdpp; 712*bf21cd93STycho Nightingale if (!strcmp(pdp->pe_emu, name)) { 713*bf21cd93STycho Nightingale return (pdp); 714*bf21cd93STycho Nightingale } 715*bf21cd93STycho Nightingale } 716*bf21cd93STycho Nightingale 717*bf21cd93STycho Nightingale return (NULL); 718*bf21cd93STycho Nightingale } 719*bf21cd93STycho Nightingale 720*bf21cd93STycho Nightingale static int 721*bf21cd93STycho Nightingale pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot, 722*bf21cd93STycho Nightingale int func, struct funcinfo *fi) 723*bf21cd93STycho Nightingale { 724*bf21cd93STycho Nightingale struct pci_devinst *pdi; 725*bf21cd93STycho Nightingale int err; 726*bf21cd93STycho Nightingale 727*bf21cd93STycho Nightingale pdi = calloc(1, sizeof(struct pci_devinst)); 728*bf21cd93STycho Nightingale 729*bf21cd93STycho Nightingale pdi->pi_vmctx = ctx; 730*bf21cd93STycho Nightingale pdi->pi_bus = bus; 731*bf21cd93STycho Nightingale pdi->pi_slot = slot; 732*bf21cd93STycho Nightingale pdi->pi_func = func; 733*bf21cd93STycho Nightingale pthread_mutex_init(&pdi->pi_lintr.lock, NULL); 734*bf21cd93STycho Nightingale pdi->pi_lintr.pin = 0; 735*bf21cd93STycho Nightingale pdi->pi_lintr.state = IDLE; 736*bf21cd93STycho Nightingale pdi->pi_lintr.pirq_pin = 0; 737*bf21cd93STycho Nightingale pdi->pi_lintr.ioapic_irq = 0; 738*bf21cd93STycho Nightingale pdi->pi_d = pde; 739*bf21cd93STycho Nightingale snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); 740*bf21cd93STycho Nightingale 741*bf21cd93STycho Nightingale /* Disable legacy interrupts */ 742*bf21cd93STycho Nightingale pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); 743*bf21cd93STycho Nightingale pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); 744*bf21cd93STycho Nightingale 745*bf21cd93STycho Nightingale pci_set_cfgdata8(pdi, PCIR_COMMAND, 746*bf21cd93STycho Nightingale PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 747*bf21cd93STycho Nightingale 748*bf21cd93STycho Nightingale err = (*pde->pe_init)(ctx, pdi, fi->fi_param); 749*bf21cd93STycho Nightingale if (err == 0) 750*bf21cd93STycho Nightingale fi->fi_devi = pdi; 751*bf21cd93STycho Nightingale else 752*bf21cd93STycho Nightingale free(pdi); 753*bf21cd93STycho Nightingale 754*bf21cd93STycho Nightingale return (err); 755*bf21cd93STycho Nightingale } 756*bf21cd93STycho Nightingale 757*bf21cd93STycho Nightingale void 758*bf21cd93STycho Nightingale pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr) 759*bf21cd93STycho Nightingale { 760*bf21cd93STycho Nightingale int mmc; 761*bf21cd93STycho Nightingale 762*bf21cd93STycho Nightingale CTASSERT(sizeof(struct msicap) == 14); 763*bf21cd93STycho Nightingale 764*bf21cd93STycho Nightingale /* Number of msi messages must be a power of 2 between 1 and 32 */ 765*bf21cd93STycho Nightingale assert((msgnum & (msgnum - 1)) == 0 && msgnum >= 1 && msgnum <= 32); 766*bf21cd93STycho Nightingale mmc = ffs(msgnum) - 1; 767*bf21cd93STycho Nightingale 768*bf21cd93STycho Nightingale bzero(msicap, sizeof(struct msicap)); 769*bf21cd93STycho Nightingale msicap->capid = PCIY_MSI; 770*bf21cd93STycho Nightingale msicap->nextptr = nextptr; 771*bf21cd93STycho Nightingale msicap->msgctrl = PCIM_MSICTRL_64BIT | (mmc << 1); 772*bf21cd93STycho Nightingale } 773*bf21cd93STycho Nightingale 774*bf21cd93STycho Nightingale int 775*bf21cd93STycho Nightingale pci_emul_add_msicap(struct pci_devinst *pi, int msgnum) 776*bf21cd93STycho Nightingale { 777*bf21cd93STycho Nightingale struct msicap msicap; 778*bf21cd93STycho Nightingale 779*bf21cd93STycho Nightingale pci_populate_msicap(&msicap, msgnum, 0); 780*bf21cd93STycho Nightingale 781*bf21cd93STycho Nightingale return (pci_emul_add_capability(pi, (u_char *)&msicap, sizeof(msicap))); 782*bf21cd93STycho Nightingale } 783*bf21cd93STycho Nightingale 784*bf21cd93STycho Nightingale static void 785*bf21cd93STycho Nightingale pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum, 786*bf21cd93STycho Nightingale uint32_t msix_tab_size) 787*bf21cd93STycho Nightingale { 788*bf21cd93STycho Nightingale CTASSERT(sizeof(struct msixcap) == 12); 789*bf21cd93STycho Nightingale 790*bf21cd93STycho Nightingale assert(msix_tab_size % 4096 == 0); 791*bf21cd93STycho Nightingale 792*bf21cd93STycho Nightingale bzero(msixcap, sizeof(struct msixcap)); 793*bf21cd93STycho Nightingale msixcap->capid = PCIY_MSIX; 794*bf21cd93STycho Nightingale 795*bf21cd93STycho Nightingale /* 796*bf21cd93STycho Nightingale * Message Control Register, all fields set to 797*bf21cd93STycho Nightingale * zero except for the Table Size. 798*bf21cd93STycho Nightingale * Note: Table size N is encoded as N-1 799*bf21cd93STycho Nightingale */ 800*bf21cd93STycho Nightingale msixcap->msgctrl = msgnum - 1; 801*bf21cd93STycho Nightingale 802*bf21cd93STycho Nightingale /* 803*bf21cd93STycho Nightingale * MSI-X BAR setup: 804*bf21cd93STycho Nightingale * - MSI-X table start at offset 0 805*bf21cd93STycho Nightingale * - PBA table starts at a 4K aligned offset after the MSI-X table 806*bf21cd93STycho Nightingale */ 807*bf21cd93STycho Nightingale msixcap->table_info = barnum & PCIM_MSIX_BIR_MASK; 808*bf21cd93STycho Nightingale msixcap->pba_info = msix_tab_size | (barnum & PCIM_MSIX_BIR_MASK); 809*bf21cd93STycho Nightingale } 810*bf21cd93STycho Nightingale 811*bf21cd93STycho Nightingale static void 812*bf21cd93STycho Nightingale pci_msix_table_init(struct pci_devinst *pi, int table_entries) 813*bf21cd93STycho Nightingale { 814*bf21cd93STycho Nightingale int i, table_size; 815*bf21cd93STycho Nightingale 816*bf21cd93STycho Nightingale assert(table_entries > 0); 817*bf21cd93STycho Nightingale assert(table_entries <= MAX_MSIX_TABLE_ENTRIES); 818*bf21cd93STycho Nightingale 819*bf21cd93STycho Nightingale table_size = table_entries * MSIX_TABLE_ENTRY_SIZE; 820*bf21cd93STycho Nightingale pi->pi_msix.table = calloc(1, table_size); 821*bf21cd93STycho Nightingale 822*bf21cd93STycho Nightingale /* set mask bit of vector control register */ 823*bf21cd93STycho Nightingale for (i = 0; i < table_entries; i++) 824*bf21cd93STycho Nightingale pi->pi_msix.table[i].vector_control |= PCIM_MSIX_VCTRL_MASK; 825*bf21cd93STycho Nightingale } 826*bf21cd93STycho Nightingale 827*bf21cd93STycho Nightingale int 828*bf21cd93STycho Nightingale pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum) 829*bf21cd93STycho Nightingale { 830*bf21cd93STycho Nightingale uint32_t tab_size; 831*bf21cd93STycho Nightingale struct msixcap msixcap; 832*bf21cd93STycho Nightingale 833*bf21cd93STycho Nightingale assert(msgnum >= 1 && msgnum <= MAX_MSIX_TABLE_ENTRIES); 834*bf21cd93STycho Nightingale assert(barnum >= 0 && barnum <= PCIR_MAX_BAR_0); 835*bf21cd93STycho Nightingale 836*bf21cd93STycho Nightingale tab_size = msgnum * MSIX_TABLE_ENTRY_SIZE; 837*bf21cd93STycho Nightingale 838*bf21cd93STycho Nightingale /* Align table size to nearest 4K */ 839*bf21cd93STycho Nightingale tab_size = roundup2(tab_size, 4096); 840*bf21cd93STycho Nightingale 841*bf21cd93STycho Nightingale pi->pi_msix.table_bar = barnum; 842*bf21cd93STycho Nightingale pi->pi_msix.pba_bar = barnum; 843*bf21cd93STycho Nightingale pi->pi_msix.table_offset = 0; 844*bf21cd93STycho Nightingale pi->pi_msix.table_count = msgnum; 845*bf21cd93STycho Nightingale pi->pi_msix.pba_offset = tab_size; 846*bf21cd93STycho Nightingale pi->pi_msix.pba_size = PBA_SIZE(msgnum); 847*bf21cd93STycho Nightingale 848*bf21cd93STycho Nightingale pci_msix_table_init(pi, msgnum); 849*bf21cd93STycho Nightingale 850*bf21cd93STycho Nightingale pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size); 851*bf21cd93STycho Nightingale 852*bf21cd93STycho Nightingale /* allocate memory for MSI-X Table and PBA */ 853*bf21cd93STycho Nightingale pci_emul_alloc_bar(pi, barnum, PCIBAR_MEM32, 854*bf21cd93STycho Nightingale tab_size + pi->pi_msix.pba_size); 855*bf21cd93STycho Nightingale 856*bf21cd93STycho Nightingale return (pci_emul_add_capability(pi, (u_char *)&msixcap, 857*bf21cd93STycho Nightingale sizeof(msixcap))); 858*bf21cd93STycho Nightingale } 859*bf21cd93STycho Nightingale 860*bf21cd93STycho Nightingale void 861*bf21cd93STycho Nightingale msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 862*bf21cd93STycho Nightingale int bytes, uint32_t val) 863*bf21cd93STycho Nightingale { 864*bf21cd93STycho Nightingale uint16_t msgctrl, rwmask; 865*bf21cd93STycho Nightingale int off, table_bar; 866*bf21cd93STycho Nightingale 867*bf21cd93STycho Nightingale off = offset - capoff; 868*bf21cd93STycho Nightingale table_bar = pi->pi_msix.table_bar; 869*bf21cd93STycho Nightingale /* Message Control Register */ 870*bf21cd93STycho Nightingale if (off == 2 && bytes == 2) { 871*bf21cd93STycho Nightingale rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK; 872*bf21cd93STycho Nightingale msgctrl = pci_get_cfgdata16(pi, offset); 873*bf21cd93STycho Nightingale msgctrl &= ~rwmask; 874*bf21cd93STycho Nightingale msgctrl |= val & rwmask; 875*bf21cd93STycho Nightingale val = msgctrl; 876*bf21cd93STycho Nightingale 877*bf21cd93STycho Nightingale pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE; 878*bf21cd93STycho Nightingale pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK; 879*bf21cd93STycho Nightingale pci_lintr_update(pi); 880*bf21cd93STycho Nightingale } 881*bf21cd93STycho Nightingale 882*bf21cd93STycho Nightingale CFGWRITE(pi, offset, val, bytes); 883*bf21cd93STycho Nightingale } 884*bf21cd93STycho Nightingale 885*bf21cd93STycho Nightingale void 886*bf21cd93STycho Nightingale msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 887*bf21cd93STycho Nightingale int bytes, uint32_t val) 888*bf21cd93STycho Nightingale { 889*bf21cd93STycho Nightingale uint16_t msgctrl, rwmask, msgdata, mme; 890*bf21cd93STycho Nightingale uint32_t addrlo; 891*bf21cd93STycho Nightingale 892*bf21cd93STycho Nightingale /* 893*bf21cd93STycho Nightingale * If guest is writing to the message control register make sure 894*bf21cd93STycho Nightingale * we do not overwrite read-only fields. 895*bf21cd93STycho Nightingale */ 896*bf21cd93STycho Nightingale if ((offset - capoff) == 2 && bytes == 2) { 897*bf21cd93STycho Nightingale rwmask = PCIM_MSICTRL_MME_MASK | PCIM_MSICTRL_MSI_ENABLE; 898*bf21cd93STycho Nightingale msgctrl = pci_get_cfgdata16(pi, offset); 899*bf21cd93STycho Nightingale msgctrl &= ~rwmask; 900*bf21cd93STycho Nightingale msgctrl |= val & rwmask; 901*bf21cd93STycho Nightingale val = msgctrl; 902*bf21cd93STycho Nightingale 903*bf21cd93STycho Nightingale addrlo = pci_get_cfgdata32(pi, capoff + 4); 904*bf21cd93STycho Nightingale if (msgctrl & PCIM_MSICTRL_64BIT) 905*bf21cd93STycho Nightingale msgdata = pci_get_cfgdata16(pi, capoff + 12); 906*bf21cd93STycho Nightingale else 907*bf21cd93STycho Nightingale msgdata = pci_get_cfgdata16(pi, capoff + 8); 908*bf21cd93STycho Nightingale 909*bf21cd93STycho Nightingale mme = msgctrl & PCIM_MSICTRL_MME_MASK; 910*bf21cd93STycho Nightingale pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0; 911*bf21cd93STycho Nightingale if (pi->pi_msi.enabled) { 912*bf21cd93STycho Nightingale pi->pi_msi.addr = addrlo; 913*bf21cd93STycho Nightingale pi->pi_msi.msg_data = msgdata; 914*bf21cd93STycho Nightingale pi->pi_msi.maxmsgnum = 1 << (mme >> 4); 915*bf21cd93STycho Nightingale } else { 916*bf21cd93STycho Nightingale pi->pi_msi.maxmsgnum = 0; 917*bf21cd93STycho Nightingale } 918*bf21cd93STycho Nightingale pci_lintr_update(pi); 919*bf21cd93STycho Nightingale } 920*bf21cd93STycho Nightingale 921*bf21cd93STycho Nightingale CFGWRITE(pi, offset, val, bytes); 922*bf21cd93STycho Nightingale } 923*bf21cd93STycho Nightingale 924*bf21cd93STycho Nightingale void 925*bf21cd93STycho Nightingale pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 926*bf21cd93STycho Nightingale int bytes, uint32_t val) 927*bf21cd93STycho Nightingale { 928*bf21cd93STycho Nightingale 929*bf21cd93STycho Nightingale /* XXX don't write to the readonly parts */ 930*bf21cd93STycho Nightingale CFGWRITE(pi, offset, val, bytes); 931*bf21cd93STycho Nightingale } 932*bf21cd93STycho Nightingale 933*bf21cd93STycho Nightingale #define PCIECAP_VERSION 0x2 934*bf21cd93STycho Nightingale int 935*bf21cd93STycho Nightingale pci_emul_add_pciecap(struct pci_devinst *pi, int type) 936*bf21cd93STycho Nightingale { 937*bf21cd93STycho Nightingale int err; 938*bf21cd93STycho Nightingale struct pciecap pciecap; 939*bf21cd93STycho Nightingale 940*bf21cd93STycho Nightingale CTASSERT(sizeof(struct pciecap) == 60); 941*bf21cd93STycho Nightingale 942*bf21cd93STycho Nightingale if (type != PCIEM_TYPE_ROOT_PORT) 943*bf21cd93STycho Nightingale return (-1); 944*bf21cd93STycho Nightingale 945*bf21cd93STycho Nightingale bzero(&pciecap, sizeof(pciecap)); 946*bf21cd93STycho Nightingale 947*bf21cd93STycho Nightingale pciecap.capid = PCIY_EXPRESS; 948*bf21cd93STycho Nightingale pciecap.pcie_capabilities = PCIECAP_VERSION | PCIEM_TYPE_ROOT_PORT; 949*bf21cd93STycho Nightingale pciecap.link_capabilities = 0x411; /* gen1, x1 */ 950*bf21cd93STycho Nightingale pciecap.link_status = 0x11; /* gen1, x1 */ 951*bf21cd93STycho Nightingale 952*bf21cd93STycho Nightingale err = pci_emul_add_capability(pi, (u_char *)&pciecap, sizeof(pciecap)); 953*bf21cd93STycho Nightingale return (err); 954*bf21cd93STycho Nightingale } 955*bf21cd93STycho Nightingale 956*bf21cd93STycho Nightingale /* 957*bf21cd93STycho Nightingale * This function assumes that 'coff' is in the capabilities region of the 958*bf21cd93STycho Nightingale * config space. 959*bf21cd93STycho Nightingale */ 960*bf21cd93STycho Nightingale static void 961*bf21cd93STycho Nightingale pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val) 962*bf21cd93STycho Nightingale { 963*bf21cd93STycho Nightingale int capid; 964*bf21cd93STycho Nightingale uint8_t capoff, nextoff; 965*bf21cd93STycho Nightingale 966*bf21cd93STycho Nightingale /* Do not allow un-aligned writes */ 967*bf21cd93STycho Nightingale if ((offset & (bytes - 1)) != 0) 968*bf21cd93STycho Nightingale return; 969*bf21cd93STycho Nightingale 970*bf21cd93STycho Nightingale /* Find the capability that we want to update */ 971*bf21cd93STycho Nightingale capoff = CAP_START_OFFSET; 972*bf21cd93STycho Nightingale while (1) { 973*bf21cd93STycho Nightingale nextoff = pci_get_cfgdata8(pi, capoff + 1); 974*bf21cd93STycho Nightingale if (nextoff == 0) 975*bf21cd93STycho Nightingale break; 976*bf21cd93STycho Nightingale if (offset >= capoff && offset < nextoff) 977*bf21cd93STycho Nightingale break; 978*bf21cd93STycho Nightingale 979*bf21cd93STycho Nightingale capoff = nextoff; 980*bf21cd93STycho Nightingale } 981*bf21cd93STycho Nightingale assert(offset >= capoff); 982*bf21cd93STycho Nightingale 983*bf21cd93STycho Nightingale /* 984*bf21cd93STycho Nightingale * Capability ID and Next Capability Pointer are readonly. 985*bf21cd93STycho Nightingale * However, some o/s's do 4-byte writes that include these. 986*bf21cd93STycho Nightingale * For this case, trim the write back to 2 bytes and adjust 987*bf21cd93STycho Nightingale * the data. 988*bf21cd93STycho Nightingale */ 989*bf21cd93STycho Nightingale if (offset == capoff || offset == capoff + 1) { 990*bf21cd93STycho Nightingale if (offset == capoff && bytes == 4) { 991*bf21cd93STycho Nightingale bytes = 2; 992*bf21cd93STycho Nightingale offset += 2; 993*bf21cd93STycho Nightingale val >>= 16; 994*bf21cd93STycho Nightingale } else 995*bf21cd93STycho Nightingale return; 996*bf21cd93STycho Nightingale } 997*bf21cd93STycho Nightingale 998*bf21cd93STycho Nightingale capid = pci_get_cfgdata8(pi, capoff); 999*bf21cd93STycho Nightingale switch (capid) { 1000*bf21cd93STycho Nightingale case PCIY_MSI: 1001*bf21cd93STycho Nightingale msicap_cfgwrite(pi, capoff, offset, bytes, val); 1002*bf21cd93STycho Nightingale break; 1003*bf21cd93STycho Nightingale case PCIY_MSIX: 1004*bf21cd93STycho Nightingale msixcap_cfgwrite(pi, capoff, offset, bytes, val); 1005*bf21cd93STycho Nightingale break; 1006*bf21cd93STycho Nightingale case PCIY_EXPRESS: 1007*bf21cd93STycho Nightingale pciecap_cfgwrite(pi, capoff, offset, bytes, val); 1008*bf21cd93STycho Nightingale break; 1009*bf21cd93STycho Nightingale default: 1010*bf21cd93STycho Nightingale break; 1011*bf21cd93STycho Nightingale } 1012*bf21cd93STycho Nightingale } 1013*bf21cd93STycho Nightingale 1014*bf21cd93STycho Nightingale static int 1015*bf21cd93STycho Nightingale pci_emul_iscap(struct pci_devinst *pi, int offset) 1016*bf21cd93STycho Nightingale { 1017*bf21cd93STycho Nightingale uint16_t sts; 1018*bf21cd93STycho Nightingale 1019*bf21cd93STycho Nightingale sts = pci_get_cfgdata16(pi, PCIR_STATUS); 1020*bf21cd93STycho Nightingale if ((sts & PCIM_STATUS_CAPPRESENT) != 0) { 1021*bf21cd93STycho Nightingale if (offset >= CAP_START_OFFSET && offset <= pi->pi_capend) 1022*bf21cd93STycho Nightingale return (1); 1023*bf21cd93STycho Nightingale } 1024*bf21cd93STycho Nightingale return (0); 1025*bf21cd93STycho Nightingale } 1026*bf21cd93STycho Nightingale 1027*bf21cd93STycho Nightingale static int 1028*bf21cd93STycho Nightingale pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, 1029*bf21cd93STycho Nightingale int size, uint64_t *val, void *arg1, long arg2) 1030*bf21cd93STycho Nightingale { 1031*bf21cd93STycho Nightingale /* 1032*bf21cd93STycho Nightingale * Ignore writes; return 0xff's for reads. The mem read code 1033*bf21cd93STycho Nightingale * will take care of truncating to the correct size. 1034*bf21cd93STycho Nightingale */ 1035*bf21cd93STycho Nightingale if (dir == MEM_F_READ) { 1036*bf21cd93STycho Nightingale *val = 0xffffffffffffffff; 1037*bf21cd93STycho Nightingale } 1038*bf21cd93STycho Nightingale 1039*bf21cd93STycho Nightingale return (0); 1040*bf21cd93STycho Nightingale } 1041*bf21cd93STycho Nightingale 1042*bf21cd93STycho Nightingale static int 1043*bf21cd93STycho Nightingale pci_emul_ecfg_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, 1044*bf21cd93STycho Nightingale int bytes, uint64_t *val, void *arg1, long arg2) 1045*bf21cd93STycho Nightingale { 1046*bf21cd93STycho Nightingale int bus, slot, func, coff, in; 1047*bf21cd93STycho Nightingale 1048*bf21cd93STycho Nightingale coff = addr & 0xfff; 1049*bf21cd93STycho Nightingale func = (addr >> 12) & 0x7; 1050*bf21cd93STycho Nightingale slot = (addr >> 15) & 0x1f; 1051*bf21cd93STycho Nightingale bus = (addr >> 20) & 0xff; 1052*bf21cd93STycho Nightingale in = (dir == MEM_F_READ); 1053*bf21cd93STycho Nightingale if (in) 1054*bf21cd93STycho Nightingale *val = ~0UL; 1055*bf21cd93STycho Nightingale pci_cfgrw(ctx, vcpu, in, bus, slot, func, coff, bytes, (uint32_t *)val); 1056*bf21cd93STycho Nightingale return (0); 1057*bf21cd93STycho Nightingale } 1058*bf21cd93STycho Nightingale 1059*bf21cd93STycho Nightingale uint64_t 1060*bf21cd93STycho Nightingale pci_ecfg_base(void) 1061*bf21cd93STycho Nightingale { 1062*bf21cd93STycho Nightingale 1063*bf21cd93STycho Nightingale return (PCI_EMUL_ECFG_BASE); 1064*bf21cd93STycho Nightingale } 1065*bf21cd93STycho Nightingale 1066*bf21cd93STycho Nightingale #define BUSIO_ROUNDUP 32 1067*bf21cd93STycho Nightingale #define BUSMEM_ROUNDUP (1024 * 1024) 1068*bf21cd93STycho Nightingale 1069*bf21cd93STycho Nightingale int 1070*bf21cd93STycho Nightingale init_pci(struct vmctx *ctx) 1071*bf21cd93STycho Nightingale { 1072*bf21cd93STycho Nightingale struct mem_range mr; 1073*bf21cd93STycho Nightingale struct pci_devemu *pde; 1074*bf21cd93STycho Nightingale struct businfo *bi; 1075*bf21cd93STycho Nightingale struct slotinfo *si; 1076*bf21cd93STycho Nightingale struct funcinfo *fi; 1077*bf21cd93STycho Nightingale size_t lowmem; 1078*bf21cd93STycho Nightingale int bus, slot, func; 1079*bf21cd93STycho Nightingale int error; 1080*bf21cd93STycho Nightingale 1081*bf21cd93STycho Nightingale pci_emul_iobase = PCI_EMUL_IOBASE; 1082*bf21cd93STycho Nightingale pci_emul_membase32 = vm_get_lowmem_limit(ctx); 1083*bf21cd93STycho Nightingale pci_emul_membase64 = PCI_EMUL_MEMBASE64; 1084*bf21cd93STycho Nightingale 1085*bf21cd93STycho Nightingale for (bus = 0; bus < MAXBUSES; bus++) { 1086*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) == NULL) 1087*bf21cd93STycho Nightingale continue; 1088*bf21cd93STycho Nightingale /* 1089*bf21cd93STycho Nightingale * Keep track of the i/o and memory resources allocated to 1090*bf21cd93STycho Nightingale * this bus. 1091*bf21cd93STycho Nightingale */ 1092*bf21cd93STycho Nightingale bi->iobase = pci_emul_iobase; 1093*bf21cd93STycho Nightingale bi->membase32 = pci_emul_membase32; 1094*bf21cd93STycho Nightingale bi->membase64 = pci_emul_membase64; 1095*bf21cd93STycho Nightingale 1096*bf21cd93STycho Nightingale for (slot = 0; slot < MAXSLOTS; slot++) { 1097*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1098*bf21cd93STycho Nightingale for (func = 0; func < MAXFUNCS; func++) { 1099*bf21cd93STycho Nightingale fi = &si->si_funcs[func]; 1100*bf21cd93STycho Nightingale if (fi->fi_name == NULL) 1101*bf21cd93STycho Nightingale continue; 1102*bf21cd93STycho Nightingale pde = pci_emul_finddev(fi->fi_name); 1103*bf21cd93STycho Nightingale assert(pde != NULL); 1104*bf21cd93STycho Nightingale error = pci_emul_init(ctx, pde, bus, slot, 1105*bf21cd93STycho Nightingale func, fi); 1106*bf21cd93STycho Nightingale if (error) 1107*bf21cd93STycho Nightingale return (error); 1108*bf21cd93STycho Nightingale } 1109*bf21cd93STycho Nightingale } 1110*bf21cd93STycho Nightingale 1111*bf21cd93STycho Nightingale /* 1112*bf21cd93STycho Nightingale * Add some slop to the I/O and memory resources decoded by 1113*bf21cd93STycho Nightingale * this bus to give a guest some flexibility if it wants to 1114*bf21cd93STycho Nightingale * reprogram the BARs. 1115*bf21cd93STycho Nightingale */ 1116*bf21cd93STycho Nightingale pci_emul_iobase += BUSIO_ROUNDUP; 1117*bf21cd93STycho Nightingale pci_emul_iobase = roundup2(pci_emul_iobase, BUSIO_ROUNDUP); 1118*bf21cd93STycho Nightingale bi->iolimit = pci_emul_iobase; 1119*bf21cd93STycho Nightingale 1120*bf21cd93STycho Nightingale pci_emul_membase32 += BUSMEM_ROUNDUP; 1121*bf21cd93STycho Nightingale pci_emul_membase32 = roundup2(pci_emul_membase32, 1122*bf21cd93STycho Nightingale BUSMEM_ROUNDUP); 1123*bf21cd93STycho Nightingale bi->memlimit32 = pci_emul_membase32; 1124*bf21cd93STycho Nightingale 1125*bf21cd93STycho Nightingale pci_emul_membase64 += BUSMEM_ROUNDUP; 1126*bf21cd93STycho Nightingale pci_emul_membase64 = roundup2(pci_emul_membase64, 1127*bf21cd93STycho Nightingale BUSMEM_ROUNDUP); 1128*bf21cd93STycho Nightingale bi->memlimit64 = pci_emul_membase64; 1129*bf21cd93STycho Nightingale } 1130*bf21cd93STycho Nightingale 1131*bf21cd93STycho Nightingale /* 1132*bf21cd93STycho Nightingale * PCI backends are initialized before routing INTx interrupts 1133*bf21cd93STycho Nightingale * so that LPC devices are able to reserve ISA IRQs before 1134*bf21cd93STycho Nightingale * routing PIRQ pins. 1135*bf21cd93STycho Nightingale */ 1136*bf21cd93STycho Nightingale for (bus = 0; bus < MAXBUSES; bus++) { 1137*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) == NULL) 1138*bf21cd93STycho Nightingale continue; 1139*bf21cd93STycho Nightingale 1140*bf21cd93STycho Nightingale for (slot = 0; slot < MAXSLOTS; slot++) { 1141*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1142*bf21cd93STycho Nightingale for (func = 0; func < MAXFUNCS; func++) { 1143*bf21cd93STycho Nightingale fi = &si->si_funcs[func]; 1144*bf21cd93STycho Nightingale if (fi->fi_devi == NULL) 1145*bf21cd93STycho Nightingale continue; 1146*bf21cd93STycho Nightingale pci_lintr_route(fi->fi_devi); 1147*bf21cd93STycho Nightingale } 1148*bf21cd93STycho Nightingale } 1149*bf21cd93STycho Nightingale } 1150*bf21cd93STycho Nightingale lpc_pirq_routed(); 1151*bf21cd93STycho Nightingale 1152*bf21cd93STycho Nightingale /* 1153*bf21cd93STycho Nightingale * The guest physical memory map looks like the following: 1154*bf21cd93STycho Nightingale * [0, lowmem) guest system memory 1155*bf21cd93STycho Nightingale * [lowmem, lowmem_limit) memory hole (may be absent) 1156*bf21cd93STycho Nightingale * [lowmem_limit, 0xE0000000) PCI hole (32-bit BAR allocation) 1157*bf21cd93STycho Nightingale * [0xE0000000, 0xF0000000) PCI extended config window 1158*bf21cd93STycho Nightingale * [0xF0000000, 4GB) LAPIC, IOAPIC, HPET, firmware 1159*bf21cd93STycho Nightingale * [4GB, 4GB + highmem) 1160*bf21cd93STycho Nightingale */ 1161*bf21cd93STycho Nightingale 1162*bf21cd93STycho Nightingale /* 1163*bf21cd93STycho Nightingale * Accesses to memory addresses that are not allocated to system 1164*bf21cd93STycho Nightingale * memory or PCI devices return 0xff's. 1165*bf21cd93STycho Nightingale */ 1166*bf21cd93STycho Nightingale lowmem = vm_get_lowmem_size(ctx); 1167*bf21cd93STycho Nightingale bzero(&mr, sizeof(struct mem_range)); 1168*bf21cd93STycho Nightingale mr.name = "PCI hole"; 1169*bf21cd93STycho Nightingale mr.flags = MEM_F_RW | MEM_F_IMMUTABLE; 1170*bf21cd93STycho Nightingale mr.base = lowmem; 1171*bf21cd93STycho Nightingale mr.size = (4ULL * 1024 * 1024 * 1024) - lowmem; 1172*bf21cd93STycho Nightingale mr.handler = pci_emul_fallback_handler; 1173*bf21cd93STycho Nightingale error = register_mem_fallback(&mr); 1174*bf21cd93STycho Nightingale assert(error == 0); 1175*bf21cd93STycho Nightingale 1176*bf21cd93STycho Nightingale /* PCI extended config space */ 1177*bf21cd93STycho Nightingale bzero(&mr, sizeof(struct mem_range)); 1178*bf21cd93STycho Nightingale mr.name = "PCI ECFG"; 1179*bf21cd93STycho Nightingale mr.flags = MEM_F_RW | MEM_F_IMMUTABLE; 1180*bf21cd93STycho Nightingale mr.base = PCI_EMUL_ECFG_BASE; 1181*bf21cd93STycho Nightingale mr.size = PCI_EMUL_ECFG_SIZE; 1182*bf21cd93STycho Nightingale mr.handler = pci_emul_ecfg_handler; 1183*bf21cd93STycho Nightingale error = register_mem(&mr); 1184*bf21cd93STycho Nightingale assert(error == 0); 1185*bf21cd93STycho Nightingale 1186*bf21cd93STycho Nightingale return (0); 1187*bf21cd93STycho Nightingale } 1188*bf21cd93STycho Nightingale 1189*bf21cd93STycho Nightingale #ifdef __FreeBSD__ 1190*bf21cd93STycho Nightingale static void 1191*bf21cd93STycho Nightingale pci_apic_prt_entry(int bus, int slot, int pin, int pirq_pin, int ioapic_irq, 1192*bf21cd93STycho Nightingale void *arg) 1193*bf21cd93STycho Nightingale { 1194*bf21cd93STycho Nightingale 1195*bf21cd93STycho Nightingale dsdt_line(" Package ()"); 1196*bf21cd93STycho Nightingale dsdt_line(" {"); 1197*bf21cd93STycho Nightingale dsdt_line(" 0x%X,", slot << 16 | 0xffff); 1198*bf21cd93STycho Nightingale dsdt_line(" 0x%02X,", pin - 1); 1199*bf21cd93STycho Nightingale dsdt_line(" Zero,"); 1200*bf21cd93STycho Nightingale dsdt_line(" 0x%X", ioapic_irq); 1201*bf21cd93STycho Nightingale dsdt_line(" },"); 1202*bf21cd93STycho Nightingale } 1203*bf21cd93STycho Nightingale 1204*bf21cd93STycho Nightingale static void 1205*bf21cd93STycho Nightingale pci_pirq_prt_entry(int bus, int slot, int pin, int pirq_pin, int ioapic_irq, 1206*bf21cd93STycho Nightingale void *arg) 1207*bf21cd93STycho Nightingale { 1208*bf21cd93STycho Nightingale char *name; 1209*bf21cd93STycho Nightingale 1210*bf21cd93STycho Nightingale name = lpc_pirq_name(pirq_pin); 1211*bf21cd93STycho Nightingale if (name == NULL) 1212*bf21cd93STycho Nightingale return; 1213*bf21cd93STycho Nightingale dsdt_line(" Package ()"); 1214*bf21cd93STycho Nightingale dsdt_line(" {"); 1215*bf21cd93STycho Nightingale dsdt_line(" 0x%X,", slot << 16 | 0xffff); 1216*bf21cd93STycho Nightingale dsdt_line(" 0x%02X,", pin - 1); 1217*bf21cd93STycho Nightingale dsdt_line(" %s,", name); 1218*bf21cd93STycho Nightingale dsdt_line(" 0x00"); 1219*bf21cd93STycho Nightingale dsdt_line(" },"); 1220*bf21cd93STycho Nightingale free(name); 1221*bf21cd93STycho Nightingale } 1222*bf21cd93STycho Nightingale 1223*bf21cd93STycho Nightingale /* 1224*bf21cd93STycho Nightingale * A bhyve virtual machine has a flat PCI hierarchy with a root port 1225*bf21cd93STycho Nightingale * corresponding to each PCI bus. 1226*bf21cd93STycho Nightingale */ 1227*bf21cd93STycho Nightingale static void 1228*bf21cd93STycho Nightingale pci_bus_write_dsdt(int bus) 1229*bf21cd93STycho Nightingale { 1230*bf21cd93STycho Nightingale struct businfo *bi; 1231*bf21cd93STycho Nightingale struct slotinfo *si; 1232*bf21cd93STycho Nightingale struct pci_devinst *pi; 1233*bf21cd93STycho Nightingale int count, func, slot; 1234*bf21cd93STycho Nightingale 1235*bf21cd93STycho Nightingale /* 1236*bf21cd93STycho Nightingale * If there are no devices on this 'bus' then just return. 1237*bf21cd93STycho Nightingale */ 1238*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) == NULL) { 1239*bf21cd93STycho Nightingale /* 1240*bf21cd93STycho Nightingale * Bus 0 is special because it decodes the I/O ports used 1241*bf21cd93STycho Nightingale * for PCI config space access even if there are no devices 1242*bf21cd93STycho Nightingale * on it. 1243*bf21cd93STycho Nightingale */ 1244*bf21cd93STycho Nightingale if (bus != 0) 1245*bf21cd93STycho Nightingale return; 1246*bf21cd93STycho Nightingale } 1247*bf21cd93STycho Nightingale 1248*bf21cd93STycho Nightingale dsdt_line(" Device (PC%02X)", bus); 1249*bf21cd93STycho Nightingale dsdt_line(" {"); 1250*bf21cd93STycho Nightingale dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))"); 1251*bf21cd93STycho Nightingale dsdt_line(" Name (_ADR, Zero)"); 1252*bf21cd93STycho Nightingale 1253*bf21cd93STycho Nightingale dsdt_line(" Method (_BBN, 0, NotSerialized)"); 1254*bf21cd93STycho Nightingale dsdt_line(" {"); 1255*bf21cd93STycho Nightingale dsdt_line(" Return (0x%08X)", bus); 1256*bf21cd93STycho Nightingale dsdt_line(" }"); 1257*bf21cd93STycho Nightingale dsdt_line(" Name (_CRS, ResourceTemplate ()"); 1258*bf21cd93STycho Nightingale dsdt_line(" {"); 1259*bf21cd93STycho Nightingale dsdt_line(" WordBusNumber (ResourceProducer, MinFixed, " 1260*bf21cd93STycho Nightingale "MaxFixed, PosDecode,"); 1261*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Granularity"); 1262*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Range Minimum", bus); 1263*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Range Maximum", bus); 1264*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Translation Offset"); 1265*bf21cd93STycho Nightingale dsdt_line(" 0x0001, // Length"); 1266*bf21cd93STycho Nightingale dsdt_line(" ,, )"); 1267*bf21cd93STycho Nightingale 1268*bf21cd93STycho Nightingale if (bus == 0) { 1269*bf21cd93STycho Nightingale dsdt_indent(3); 1270*bf21cd93STycho Nightingale dsdt_fixed_ioport(0xCF8, 8); 1271*bf21cd93STycho Nightingale dsdt_unindent(3); 1272*bf21cd93STycho Nightingale 1273*bf21cd93STycho Nightingale dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " 1274*bf21cd93STycho Nightingale "PosDecode, EntireRange,"); 1275*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Granularity"); 1276*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Range Minimum"); 1277*bf21cd93STycho Nightingale dsdt_line(" 0x0CF7, // Range Maximum"); 1278*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Translation Offset"); 1279*bf21cd93STycho Nightingale dsdt_line(" 0x0CF8, // Length"); 1280*bf21cd93STycho Nightingale dsdt_line(" ,, , TypeStatic)"); 1281*bf21cd93STycho Nightingale 1282*bf21cd93STycho Nightingale dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " 1283*bf21cd93STycho Nightingale "PosDecode, EntireRange,"); 1284*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Granularity"); 1285*bf21cd93STycho Nightingale dsdt_line(" 0x0D00, // Range Minimum"); 1286*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Range Maximum", 1287*bf21cd93STycho Nightingale PCI_EMUL_IOBASE - 1); 1288*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Translation Offset"); 1289*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Length", 1290*bf21cd93STycho Nightingale PCI_EMUL_IOBASE - 0x0D00); 1291*bf21cd93STycho Nightingale dsdt_line(" ,, , TypeStatic)"); 1292*bf21cd93STycho Nightingale 1293*bf21cd93STycho Nightingale if (bi == NULL) { 1294*bf21cd93STycho Nightingale dsdt_line(" })"); 1295*bf21cd93STycho Nightingale goto done; 1296*bf21cd93STycho Nightingale } 1297*bf21cd93STycho Nightingale } 1298*bf21cd93STycho Nightingale assert(bi != NULL); 1299*bf21cd93STycho Nightingale 1300*bf21cd93STycho Nightingale /* i/o window */ 1301*bf21cd93STycho Nightingale dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " 1302*bf21cd93STycho Nightingale "PosDecode, EntireRange,"); 1303*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Granularity"); 1304*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Range Minimum", bi->iobase); 1305*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Range Maximum", 1306*bf21cd93STycho Nightingale bi->iolimit - 1); 1307*bf21cd93STycho Nightingale dsdt_line(" 0x0000, // Translation Offset"); 1308*bf21cd93STycho Nightingale dsdt_line(" 0x%04X, // Length", 1309*bf21cd93STycho Nightingale bi->iolimit - bi->iobase); 1310*bf21cd93STycho Nightingale dsdt_line(" ,, , TypeStatic)"); 1311*bf21cd93STycho Nightingale 1312*bf21cd93STycho Nightingale /* mmio window (32-bit) */ 1313*bf21cd93STycho Nightingale dsdt_line(" DWordMemory (ResourceProducer, PosDecode, " 1314*bf21cd93STycho Nightingale "MinFixed, MaxFixed, NonCacheable, ReadWrite,"); 1315*bf21cd93STycho Nightingale dsdt_line(" 0x00000000, // Granularity"); 1316*bf21cd93STycho Nightingale dsdt_line(" 0x%08X, // Range Minimum\n", bi->membase32); 1317*bf21cd93STycho Nightingale dsdt_line(" 0x%08X, // Range Maximum\n", 1318*bf21cd93STycho Nightingale bi->memlimit32 - 1); 1319*bf21cd93STycho Nightingale dsdt_line(" 0x00000000, // Translation Offset"); 1320*bf21cd93STycho Nightingale dsdt_line(" 0x%08X, // Length\n", 1321*bf21cd93STycho Nightingale bi->memlimit32 - bi->membase32); 1322*bf21cd93STycho Nightingale dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); 1323*bf21cd93STycho Nightingale 1324*bf21cd93STycho Nightingale /* mmio window (64-bit) */ 1325*bf21cd93STycho Nightingale dsdt_line(" QWordMemory (ResourceProducer, PosDecode, " 1326*bf21cd93STycho Nightingale "MinFixed, MaxFixed, NonCacheable, ReadWrite,"); 1327*bf21cd93STycho Nightingale dsdt_line(" 0x0000000000000000, // Granularity"); 1328*bf21cd93STycho Nightingale dsdt_line(" 0x%016lX, // Range Minimum\n", bi->membase64); 1329*bf21cd93STycho Nightingale dsdt_line(" 0x%016lX, // Range Maximum\n", 1330*bf21cd93STycho Nightingale bi->memlimit64 - 1); 1331*bf21cd93STycho Nightingale dsdt_line(" 0x0000000000000000, // Translation Offset"); 1332*bf21cd93STycho Nightingale dsdt_line(" 0x%016lX, // Length\n", 1333*bf21cd93STycho Nightingale bi->memlimit64 - bi->membase64); 1334*bf21cd93STycho Nightingale dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); 1335*bf21cd93STycho Nightingale dsdt_line(" })"); 1336*bf21cd93STycho Nightingale 1337*bf21cd93STycho Nightingale count = pci_count_lintr(bus); 1338*bf21cd93STycho Nightingale if (count != 0) { 1339*bf21cd93STycho Nightingale dsdt_indent(2); 1340*bf21cd93STycho Nightingale dsdt_line("Name (PPRT, Package ()"); 1341*bf21cd93STycho Nightingale dsdt_line("{"); 1342*bf21cd93STycho Nightingale pci_walk_lintr(bus, pci_pirq_prt_entry, NULL); 1343*bf21cd93STycho Nightingale dsdt_line("})"); 1344*bf21cd93STycho Nightingale dsdt_line("Name (APRT, Package ()"); 1345*bf21cd93STycho Nightingale dsdt_line("{"); 1346*bf21cd93STycho Nightingale pci_walk_lintr(bus, pci_apic_prt_entry, NULL); 1347*bf21cd93STycho Nightingale dsdt_line("})"); 1348*bf21cd93STycho Nightingale dsdt_line("Method (_PRT, 0, NotSerialized)"); 1349*bf21cd93STycho Nightingale dsdt_line("{"); 1350*bf21cd93STycho Nightingale dsdt_line(" If (PICM)"); 1351*bf21cd93STycho Nightingale dsdt_line(" {"); 1352*bf21cd93STycho Nightingale dsdt_line(" Return (APRT)"); 1353*bf21cd93STycho Nightingale dsdt_line(" }"); 1354*bf21cd93STycho Nightingale dsdt_line(" Else"); 1355*bf21cd93STycho Nightingale dsdt_line(" {"); 1356*bf21cd93STycho Nightingale dsdt_line(" Return (PPRT)"); 1357*bf21cd93STycho Nightingale dsdt_line(" }"); 1358*bf21cd93STycho Nightingale dsdt_line("}"); 1359*bf21cd93STycho Nightingale dsdt_unindent(2); 1360*bf21cd93STycho Nightingale } 1361*bf21cd93STycho Nightingale 1362*bf21cd93STycho Nightingale dsdt_indent(2); 1363*bf21cd93STycho Nightingale for (slot = 0; slot < MAXSLOTS; slot++) { 1364*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1365*bf21cd93STycho Nightingale for (func = 0; func < MAXFUNCS; func++) { 1366*bf21cd93STycho Nightingale pi = si->si_funcs[func].fi_devi; 1367*bf21cd93STycho Nightingale if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL) 1368*bf21cd93STycho Nightingale pi->pi_d->pe_write_dsdt(pi); 1369*bf21cd93STycho Nightingale } 1370*bf21cd93STycho Nightingale } 1371*bf21cd93STycho Nightingale dsdt_unindent(2); 1372*bf21cd93STycho Nightingale done: 1373*bf21cd93STycho Nightingale dsdt_line(" }"); 1374*bf21cd93STycho Nightingale } 1375*bf21cd93STycho Nightingale 1376*bf21cd93STycho Nightingale void 1377*bf21cd93STycho Nightingale pci_write_dsdt(void) 1378*bf21cd93STycho Nightingale { 1379*bf21cd93STycho Nightingale int bus; 1380*bf21cd93STycho Nightingale 1381*bf21cd93STycho Nightingale dsdt_indent(1); 1382*bf21cd93STycho Nightingale dsdt_line("Name (PICM, 0x00)"); 1383*bf21cd93STycho Nightingale dsdt_line("Method (_PIC, 1, NotSerialized)"); 1384*bf21cd93STycho Nightingale dsdt_line("{"); 1385*bf21cd93STycho Nightingale dsdt_line(" Store (Arg0, PICM)"); 1386*bf21cd93STycho Nightingale dsdt_line("}"); 1387*bf21cd93STycho Nightingale dsdt_line(""); 1388*bf21cd93STycho Nightingale dsdt_line("Scope (_SB)"); 1389*bf21cd93STycho Nightingale dsdt_line("{"); 1390*bf21cd93STycho Nightingale for (bus = 0; bus < MAXBUSES; bus++) 1391*bf21cd93STycho Nightingale pci_bus_write_dsdt(bus); 1392*bf21cd93STycho Nightingale dsdt_line("}"); 1393*bf21cd93STycho Nightingale dsdt_unindent(1); 1394*bf21cd93STycho Nightingale } 1395*bf21cd93STycho Nightingale #endif 1396*bf21cd93STycho Nightingale 1397*bf21cd93STycho Nightingale int 1398*bf21cd93STycho Nightingale pci_bus_configured(int bus) 1399*bf21cd93STycho Nightingale { 1400*bf21cd93STycho Nightingale assert(bus >= 0 && bus < MAXBUSES); 1401*bf21cd93STycho Nightingale return (pci_businfo[bus] != NULL); 1402*bf21cd93STycho Nightingale } 1403*bf21cd93STycho Nightingale 1404*bf21cd93STycho Nightingale int 1405*bf21cd93STycho Nightingale pci_msi_enabled(struct pci_devinst *pi) 1406*bf21cd93STycho Nightingale { 1407*bf21cd93STycho Nightingale return (pi->pi_msi.enabled); 1408*bf21cd93STycho Nightingale } 1409*bf21cd93STycho Nightingale 1410*bf21cd93STycho Nightingale int 1411*bf21cd93STycho Nightingale pci_msi_maxmsgnum(struct pci_devinst *pi) 1412*bf21cd93STycho Nightingale { 1413*bf21cd93STycho Nightingale if (pi->pi_msi.enabled) 1414*bf21cd93STycho Nightingale return (pi->pi_msi.maxmsgnum); 1415*bf21cd93STycho Nightingale else 1416*bf21cd93STycho Nightingale return (0); 1417*bf21cd93STycho Nightingale } 1418*bf21cd93STycho Nightingale 1419*bf21cd93STycho Nightingale int 1420*bf21cd93STycho Nightingale pci_msix_enabled(struct pci_devinst *pi) 1421*bf21cd93STycho Nightingale { 1422*bf21cd93STycho Nightingale 1423*bf21cd93STycho Nightingale return (pi->pi_msix.enabled && !pi->pi_msi.enabled); 1424*bf21cd93STycho Nightingale } 1425*bf21cd93STycho Nightingale 1426*bf21cd93STycho Nightingale void 1427*bf21cd93STycho Nightingale pci_generate_msix(struct pci_devinst *pi, int index) 1428*bf21cd93STycho Nightingale { 1429*bf21cd93STycho Nightingale struct msix_table_entry *mte; 1430*bf21cd93STycho Nightingale 1431*bf21cd93STycho Nightingale if (!pci_msix_enabled(pi)) 1432*bf21cd93STycho Nightingale return; 1433*bf21cd93STycho Nightingale 1434*bf21cd93STycho Nightingale if (pi->pi_msix.function_mask) 1435*bf21cd93STycho Nightingale return; 1436*bf21cd93STycho Nightingale 1437*bf21cd93STycho Nightingale if (index >= pi->pi_msix.table_count) 1438*bf21cd93STycho Nightingale return; 1439*bf21cd93STycho Nightingale 1440*bf21cd93STycho Nightingale mte = &pi->pi_msix.table[index]; 1441*bf21cd93STycho Nightingale if ((mte->vector_control & PCIM_MSIX_VCTRL_MASK) == 0) { 1442*bf21cd93STycho Nightingale /* XXX Set PBA bit if interrupt is disabled */ 1443*bf21cd93STycho Nightingale vm_lapic_msi(pi->pi_vmctx, mte->addr, mte->msg_data); 1444*bf21cd93STycho Nightingale } 1445*bf21cd93STycho Nightingale } 1446*bf21cd93STycho Nightingale 1447*bf21cd93STycho Nightingale void 1448*bf21cd93STycho Nightingale pci_generate_msi(struct pci_devinst *pi, int index) 1449*bf21cd93STycho Nightingale { 1450*bf21cd93STycho Nightingale 1451*bf21cd93STycho Nightingale if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) { 1452*bf21cd93STycho Nightingale vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr, 1453*bf21cd93STycho Nightingale pi->pi_msi.msg_data + index); 1454*bf21cd93STycho Nightingale } 1455*bf21cd93STycho Nightingale } 1456*bf21cd93STycho Nightingale 1457*bf21cd93STycho Nightingale static bool 1458*bf21cd93STycho Nightingale pci_lintr_permitted(struct pci_devinst *pi) 1459*bf21cd93STycho Nightingale { 1460*bf21cd93STycho Nightingale uint16_t cmd; 1461*bf21cd93STycho Nightingale 1462*bf21cd93STycho Nightingale cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); 1463*bf21cd93STycho Nightingale return (!(pi->pi_msi.enabled || pi->pi_msix.enabled || 1464*bf21cd93STycho Nightingale (cmd & PCIM_CMD_INTxDIS))); 1465*bf21cd93STycho Nightingale } 1466*bf21cd93STycho Nightingale 1467*bf21cd93STycho Nightingale void 1468*bf21cd93STycho Nightingale pci_lintr_request(struct pci_devinst *pi) 1469*bf21cd93STycho Nightingale { 1470*bf21cd93STycho Nightingale struct businfo *bi; 1471*bf21cd93STycho Nightingale struct slotinfo *si; 1472*bf21cd93STycho Nightingale int bestpin, bestcount, pin; 1473*bf21cd93STycho Nightingale 1474*bf21cd93STycho Nightingale bi = pci_businfo[pi->pi_bus]; 1475*bf21cd93STycho Nightingale assert(bi != NULL); 1476*bf21cd93STycho Nightingale 1477*bf21cd93STycho Nightingale /* 1478*bf21cd93STycho Nightingale * Just allocate a pin from our slot. The pin will be 1479*bf21cd93STycho Nightingale * assigned IRQs later when interrupts are routed. 1480*bf21cd93STycho Nightingale */ 1481*bf21cd93STycho Nightingale si = &bi->slotinfo[pi->pi_slot]; 1482*bf21cd93STycho Nightingale bestpin = 0; 1483*bf21cd93STycho Nightingale bestcount = si->si_intpins[0].ii_count; 1484*bf21cd93STycho Nightingale for (pin = 1; pin < 4; pin++) { 1485*bf21cd93STycho Nightingale if (si->si_intpins[pin].ii_count < bestcount) { 1486*bf21cd93STycho Nightingale bestpin = pin; 1487*bf21cd93STycho Nightingale bestcount = si->si_intpins[pin].ii_count; 1488*bf21cd93STycho Nightingale } 1489*bf21cd93STycho Nightingale } 1490*bf21cd93STycho Nightingale 1491*bf21cd93STycho Nightingale si->si_intpins[bestpin].ii_count++; 1492*bf21cd93STycho Nightingale pi->pi_lintr.pin = bestpin + 1; 1493*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, PCIR_INTPIN, bestpin + 1); 1494*bf21cd93STycho Nightingale } 1495*bf21cd93STycho Nightingale 1496*bf21cd93STycho Nightingale static void 1497*bf21cd93STycho Nightingale pci_lintr_route(struct pci_devinst *pi) 1498*bf21cd93STycho Nightingale { 1499*bf21cd93STycho Nightingale struct businfo *bi; 1500*bf21cd93STycho Nightingale struct intxinfo *ii; 1501*bf21cd93STycho Nightingale 1502*bf21cd93STycho Nightingale if (pi->pi_lintr.pin == 0) 1503*bf21cd93STycho Nightingale return; 1504*bf21cd93STycho Nightingale 1505*bf21cd93STycho Nightingale bi = pci_businfo[pi->pi_bus]; 1506*bf21cd93STycho Nightingale assert(bi != NULL); 1507*bf21cd93STycho Nightingale ii = &bi->slotinfo[pi->pi_slot].si_intpins[pi->pi_lintr.pin - 1]; 1508*bf21cd93STycho Nightingale 1509*bf21cd93STycho Nightingale /* 1510*bf21cd93STycho Nightingale * Attempt to allocate an I/O APIC pin for this intpin if one 1511*bf21cd93STycho Nightingale * is not yet assigned. 1512*bf21cd93STycho Nightingale */ 1513*bf21cd93STycho Nightingale if (ii->ii_ioapic_irq == 0) 1514*bf21cd93STycho Nightingale ii->ii_ioapic_irq = ioapic_pci_alloc_irq(); 1515*bf21cd93STycho Nightingale assert(ii->ii_ioapic_irq > 0); 1516*bf21cd93STycho Nightingale 1517*bf21cd93STycho Nightingale /* 1518*bf21cd93STycho Nightingale * Attempt to allocate a PIRQ pin for this intpin if one is 1519*bf21cd93STycho Nightingale * not yet assigned. 1520*bf21cd93STycho Nightingale */ 1521*bf21cd93STycho Nightingale if (ii->ii_pirq_pin == 0) 1522*bf21cd93STycho Nightingale ii->ii_pirq_pin = pirq_alloc_pin(pi->pi_vmctx); 1523*bf21cd93STycho Nightingale assert(ii->ii_pirq_pin > 0); 1524*bf21cd93STycho Nightingale 1525*bf21cd93STycho Nightingale pi->pi_lintr.ioapic_irq = ii->ii_ioapic_irq; 1526*bf21cd93STycho Nightingale pi->pi_lintr.pirq_pin = ii->ii_pirq_pin; 1527*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, PCIR_INTLINE, pirq_irq(ii->ii_pirq_pin)); 1528*bf21cd93STycho Nightingale } 1529*bf21cd93STycho Nightingale 1530*bf21cd93STycho Nightingale void 1531*bf21cd93STycho Nightingale pci_lintr_assert(struct pci_devinst *pi) 1532*bf21cd93STycho Nightingale { 1533*bf21cd93STycho Nightingale 1534*bf21cd93STycho Nightingale assert(pi->pi_lintr.pin > 0); 1535*bf21cd93STycho Nightingale 1536*bf21cd93STycho Nightingale pthread_mutex_lock(&pi->pi_lintr.lock); 1537*bf21cd93STycho Nightingale if (pi->pi_lintr.state == IDLE) { 1538*bf21cd93STycho Nightingale if (pci_lintr_permitted(pi)) { 1539*bf21cd93STycho Nightingale pi->pi_lintr.state = ASSERTED; 1540*bf21cd93STycho Nightingale pci_irq_assert(pi); 1541*bf21cd93STycho Nightingale } else 1542*bf21cd93STycho Nightingale pi->pi_lintr.state = PENDING; 1543*bf21cd93STycho Nightingale } 1544*bf21cd93STycho Nightingale pthread_mutex_unlock(&pi->pi_lintr.lock); 1545*bf21cd93STycho Nightingale } 1546*bf21cd93STycho Nightingale 1547*bf21cd93STycho Nightingale void 1548*bf21cd93STycho Nightingale pci_lintr_deassert(struct pci_devinst *pi) 1549*bf21cd93STycho Nightingale { 1550*bf21cd93STycho Nightingale 1551*bf21cd93STycho Nightingale assert(pi->pi_lintr.pin > 0); 1552*bf21cd93STycho Nightingale 1553*bf21cd93STycho Nightingale pthread_mutex_lock(&pi->pi_lintr.lock); 1554*bf21cd93STycho Nightingale if (pi->pi_lintr.state == ASSERTED) { 1555*bf21cd93STycho Nightingale pi->pi_lintr.state = IDLE; 1556*bf21cd93STycho Nightingale pci_irq_deassert(pi); 1557*bf21cd93STycho Nightingale } else if (pi->pi_lintr.state == PENDING) 1558*bf21cd93STycho Nightingale pi->pi_lintr.state = IDLE; 1559*bf21cd93STycho Nightingale pthread_mutex_unlock(&pi->pi_lintr.lock); 1560*bf21cd93STycho Nightingale } 1561*bf21cd93STycho Nightingale 1562*bf21cd93STycho Nightingale static void 1563*bf21cd93STycho Nightingale pci_lintr_update(struct pci_devinst *pi) 1564*bf21cd93STycho Nightingale { 1565*bf21cd93STycho Nightingale 1566*bf21cd93STycho Nightingale pthread_mutex_lock(&pi->pi_lintr.lock); 1567*bf21cd93STycho Nightingale if (pi->pi_lintr.state == ASSERTED && !pci_lintr_permitted(pi)) { 1568*bf21cd93STycho Nightingale pci_irq_deassert(pi); 1569*bf21cd93STycho Nightingale pi->pi_lintr.state = PENDING; 1570*bf21cd93STycho Nightingale } else if (pi->pi_lintr.state == PENDING && pci_lintr_permitted(pi)) { 1571*bf21cd93STycho Nightingale pi->pi_lintr.state = ASSERTED; 1572*bf21cd93STycho Nightingale pci_irq_assert(pi); 1573*bf21cd93STycho Nightingale } 1574*bf21cd93STycho Nightingale pthread_mutex_unlock(&pi->pi_lintr.lock); 1575*bf21cd93STycho Nightingale } 1576*bf21cd93STycho Nightingale 1577*bf21cd93STycho Nightingale int 1578*bf21cd93STycho Nightingale pci_count_lintr(int bus) 1579*bf21cd93STycho Nightingale { 1580*bf21cd93STycho Nightingale int count, slot, pin; 1581*bf21cd93STycho Nightingale struct slotinfo *slotinfo; 1582*bf21cd93STycho Nightingale 1583*bf21cd93STycho Nightingale count = 0; 1584*bf21cd93STycho Nightingale if (pci_businfo[bus] != NULL) { 1585*bf21cd93STycho Nightingale for (slot = 0; slot < MAXSLOTS; slot++) { 1586*bf21cd93STycho Nightingale slotinfo = &pci_businfo[bus]->slotinfo[slot]; 1587*bf21cd93STycho Nightingale for (pin = 0; pin < 4; pin++) { 1588*bf21cd93STycho Nightingale if (slotinfo->si_intpins[pin].ii_count != 0) 1589*bf21cd93STycho Nightingale count++; 1590*bf21cd93STycho Nightingale } 1591*bf21cd93STycho Nightingale } 1592*bf21cd93STycho Nightingale } 1593*bf21cd93STycho Nightingale return (count); 1594*bf21cd93STycho Nightingale } 1595*bf21cd93STycho Nightingale 1596*bf21cd93STycho Nightingale void 1597*bf21cd93STycho Nightingale pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg) 1598*bf21cd93STycho Nightingale { 1599*bf21cd93STycho Nightingale struct businfo *bi; 1600*bf21cd93STycho Nightingale struct slotinfo *si; 1601*bf21cd93STycho Nightingale struct intxinfo *ii; 1602*bf21cd93STycho Nightingale int slot, pin; 1603*bf21cd93STycho Nightingale 1604*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) == NULL) 1605*bf21cd93STycho Nightingale return; 1606*bf21cd93STycho Nightingale 1607*bf21cd93STycho Nightingale for (slot = 0; slot < MAXSLOTS; slot++) { 1608*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1609*bf21cd93STycho Nightingale for (pin = 0; pin < 4; pin++) { 1610*bf21cd93STycho Nightingale ii = &si->si_intpins[pin]; 1611*bf21cd93STycho Nightingale if (ii->ii_count != 0) 1612*bf21cd93STycho Nightingale cb(bus, slot, pin + 1, ii->ii_pirq_pin, 1613*bf21cd93STycho Nightingale ii->ii_ioapic_irq, arg); 1614*bf21cd93STycho Nightingale } 1615*bf21cd93STycho Nightingale } 1616*bf21cd93STycho Nightingale } 1617*bf21cd93STycho Nightingale 1618*bf21cd93STycho Nightingale /* 1619*bf21cd93STycho Nightingale * Return 1 if the emulated device in 'slot' is a multi-function device. 1620*bf21cd93STycho Nightingale * Return 0 otherwise. 1621*bf21cd93STycho Nightingale */ 1622*bf21cd93STycho Nightingale static int 1623*bf21cd93STycho Nightingale pci_emul_is_mfdev(int bus, int slot) 1624*bf21cd93STycho Nightingale { 1625*bf21cd93STycho Nightingale struct businfo *bi; 1626*bf21cd93STycho Nightingale struct slotinfo *si; 1627*bf21cd93STycho Nightingale int f, numfuncs; 1628*bf21cd93STycho Nightingale 1629*bf21cd93STycho Nightingale numfuncs = 0; 1630*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) != NULL) { 1631*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1632*bf21cd93STycho Nightingale for (f = 0; f < MAXFUNCS; f++) { 1633*bf21cd93STycho Nightingale if (si->si_funcs[f].fi_devi != NULL) { 1634*bf21cd93STycho Nightingale numfuncs++; 1635*bf21cd93STycho Nightingale } 1636*bf21cd93STycho Nightingale } 1637*bf21cd93STycho Nightingale } 1638*bf21cd93STycho Nightingale return (numfuncs > 1); 1639*bf21cd93STycho Nightingale } 1640*bf21cd93STycho Nightingale 1641*bf21cd93STycho Nightingale /* 1642*bf21cd93STycho Nightingale * Ensure that the PCIM_MFDEV bit is properly set (or unset) depending on 1643*bf21cd93STycho Nightingale * whether or not is a multi-function being emulated in the pci 'slot'. 1644*bf21cd93STycho Nightingale */ 1645*bf21cd93STycho Nightingale static void 1646*bf21cd93STycho Nightingale pci_emul_hdrtype_fixup(int bus, int slot, int off, int bytes, uint32_t *rv) 1647*bf21cd93STycho Nightingale { 1648*bf21cd93STycho Nightingale int mfdev; 1649*bf21cd93STycho Nightingale 1650*bf21cd93STycho Nightingale if (off <= PCIR_HDRTYPE && off + bytes > PCIR_HDRTYPE) { 1651*bf21cd93STycho Nightingale mfdev = pci_emul_is_mfdev(bus, slot); 1652*bf21cd93STycho Nightingale switch (bytes) { 1653*bf21cd93STycho Nightingale case 1: 1654*bf21cd93STycho Nightingale case 2: 1655*bf21cd93STycho Nightingale *rv &= ~PCIM_MFDEV; 1656*bf21cd93STycho Nightingale if (mfdev) { 1657*bf21cd93STycho Nightingale *rv |= PCIM_MFDEV; 1658*bf21cd93STycho Nightingale } 1659*bf21cd93STycho Nightingale break; 1660*bf21cd93STycho Nightingale case 4: 1661*bf21cd93STycho Nightingale *rv &= ~(PCIM_MFDEV << 16); 1662*bf21cd93STycho Nightingale if (mfdev) { 1663*bf21cd93STycho Nightingale *rv |= (PCIM_MFDEV << 16); 1664*bf21cd93STycho Nightingale } 1665*bf21cd93STycho Nightingale break; 1666*bf21cd93STycho Nightingale } 1667*bf21cd93STycho Nightingale } 1668*bf21cd93STycho Nightingale } 1669*bf21cd93STycho Nightingale 1670*bf21cd93STycho Nightingale static uint32_t 1671*bf21cd93STycho Nightingale bits_changed(uint32_t old, uint32_t new, uint32_t mask) 1672*bf21cd93STycho Nightingale { 1673*bf21cd93STycho Nightingale 1674*bf21cd93STycho Nightingale return ((old ^ new) & mask); 1675*bf21cd93STycho Nightingale } 1676*bf21cd93STycho Nightingale 1677*bf21cd93STycho Nightingale static void 1678*bf21cd93STycho Nightingale pci_emul_cmdwrite(struct pci_devinst *pi, uint32_t new, int bytes) 1679*bf21cd93STycho Nightingale { 1680*bf21cd93STycho Nightingale int i; 1681*bf21cd93STycho Nightingale uint16_t old; 1682*bf21cd93STycho Nightingale 1683*bf21cd93STycho Nightingale /* 1684*bf21cd93STycho Nightingale * The command register is at an offset of 4 bytes and thus the 1685*bf21cd93STycho Nightingale * guest could write 1, 2 or 4 bytes starting at this offset. 1686*bf21cd93STycho Nightingale */ 1687*bf21cd93STycho Nightingale 1688*bf21cd93STycho Nightingale old = pci_get_cfgdata16(pi, PCIR_COMMAND); /* stash old value */ 1689*bf21cd93STycho Nightingale CFGWRITE(pi, PCIR_COMMAND, new, bytes); /* update config */ 1690*bf21cd93STycho Nightingale new = pci_get_cfgdata16(pi, PCIR_COMMAND); /* get updated value */ 1691*bf21cd93STycho Nightingale 1692*bf21cd93STycho Nightingale /* 1693*bf21cd93STycho Nightingale * If the MMIO or I/O address space decoding has changed then 1694*bf21cd93STycho Nightingale * register/unregister all BARs that decode that address space. 1695*bf21cd93STycho Nightingale */ 1696*bf21cd93STycho Nightingale for (i = 0; i <= PCI_BARMAX; i++) { 1697*bf21cd93STycho Nightingale switch (pi->pi_bar[i].type) { 1698*bf21cd93STycho Nightingale case PCIBAR_NONE: 1699*bf21cd93STycho Nightingale case PCIBAR_MEMHI64: 1700*bf21cd93STycho Nightingale break; 1701*bf21cd93STycho Nightingale case PCIBAR_IO: 1702*bf21cd93STycho Nightingale /* I/O address space decoding changed? */ 1703*bf21cd93STycho Nightingale if (bits_changed(old, new, PCIM_CMD_PORTEN)) { 1704*bf21cd93STycho Nightingale if (porten(pi)) 1705*bf21cd93STycho Nightingale register_bar(pi, i); 1706*bf21cd93STycho Nightingale else 1707*bf21cd93STycho Nightingale unregister_bar(pi, i); 1708*bf21cd93STycho Nightingale } 1709*bf21cd93STycho Nightingale break; 1710*bf21cd93STycho Nightingale case PCIBAR_MEM32: 1711*bf21cd93STycho Nightingale case PCIBAR_MEM64: 1712*bf21cd93STycho Nightingale /* MMIO address space decoding changed? */ 1713*bf21cd93STycho Nightingale if (bits_changed(old, new, PCIM_CMD_MEMEN)) { 1714*bf21cd93STycho Nightingale if (memen(pi)) 1715*bf21cd93STycho Nightingale register_bar(pi, i); 1716*bf21cd93STycho Nightingale else 1717*bf21cd93STycho Nightingale unregister_bar(pi, i); 1718*bf21cd93STycho Nightingale } 1719*bf21cd93STycho Nightingale break; 1720*bf21cd93STycho Nightingale default: 1721*bf21cd93STycho Nightingale assert(0); 1722*bf21cd93STycho Nightingale } 1723*bf21cd93STycho Nightingale } 1724*bf21cd93STycho Nightingale 1725*bf21cd93STycho Nightingale /* 1726*bf21cd93STycho Nightingale * If INTx has been unmasked and is pending, assert the 1727*bf21cd93STycho Nightingale * interrupt. 1728*bf21cd93STycho Nightingale */ 1729*bf21cd93STycho Nightingale pci_lintr_update(pi); 1730*bf21cd93STycho Nightingale } 1731*bf21cd93STycho Nightingale 1732*bf21cd93STycho Nightingale static void 1733*bf21cd93STycho Nightingale pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, 1734*bf21cd93STycho Nightingale int coff, int bytes, uint32_t *eax) 1735*bf21cd93STycho Nightingale { 1736*bf21cd93STycho Nightingale struct businfo *bi; 1737*bf21cd93STycho Nightingale struct slotinfo *si; 1738*bf21cd93STycho Nightingale struct pci_devinst *pi; 1739*bf21cd93STycho Nightingale struct pci_devemu *pe; 1740*bf21cd93STycho Nightingale int idx, needcfg; 1741*bf21cd93STycho Nightingale uint64_t addr, bar, mask; 1742*bf21cd93STycho Nightingale 1743*bf21cd93STycho Nightingale if ((bi = pci_businfo[bus]) != NULL) { 1744*bf21cd93STycho Nightingale si = &bi->slotinfo[slot]; 1745*bf21cd93STycho Nightingale pi = si->si_funcs[func].fi_devi; 1746*bf21cd93STycho Nightingale } else 1747*bf21cd93STycho Nightingale pi = NULL; 1748*bf21cd93STycho Nightingale 1749*bf21cd93STycho Nightingale /* 1750*bf21cd93STycho Nightingale * Just return if there is no device at this slot:func or if the 1751*bf21cd93STycho Nightingale * the guest is doing an un-aligned access. 1752*bf21cd93STycho Nightingale */ 1753*bf21cd93STycho Nightingale if (pi == NULL || (bytes != 1 && bytes != 2 && bytes != 4) || 1754*bf21cd93STycho Nightingale (coff & (bytes - 1)) != 0) { 1755*bf21cd93STycho Nightingale if (in) 1756*bf21cd93STycho Nightingale *eax = 0xffffffff; 1757*bf21cd93STycho Nightingale return; 1758*bf21cd93STycho Nightingale } 1759*bf21cd93STycho Nightingale 1760*bf21cd93STycho Nightingale /* 1761*bf21cd93STycho Nightingale * Ignore all writes beyond the standard config space and return all 1762*bf21cd93STycho Nightingale * ones on reads. 1763*bf21cd93STycho Nightingale */ 1764*bf21cd93STycho Nightingale if (coff >= PCI_REGMAX + 1) { 1765*bf21cd93STycho Nightingale if (in) { 1766*bf21cd93STycho Nightingale *eax = 0xffffffff; 1767*bf21cd93STycho Nightingale /* 1768*bf21cd93STycho Nightingale * Extended capabilities begin at offset 256 in config 1769*bf21cd93STycho Nightingale * space. Absence of extended capabilities is signaled 1770*bf21cd93STycho Nightingale * with all 0s in the extended capability header at 1771*bf21cd93STycho Nightingale * offset 256. 1772*bf21cd93STycho Nightingale */ 1773*bf21cd93STycho Nightingale if (coff <= PCI_REGMAX + 4) 1774*bf21cd93STycho Nightingale *eax = 0x00000000; 1775*bf21cd93STycho Nightingale } 1776*bf21cd93STycho Nightingale return; 1777*bf21cd93STycho Nightingale } 1778*bf21cd93STycho Nightingale 1779*bf21cd93STycho Nightingale pe = pi->pi_d; 1780*bf21cd93STycho Nightingale 1781*bf21cd93STycho Nightingale /* 1782*bf21cd93STycho Nightingale * Config read 1783*bf21cd93STycho Nightingale */ 1784*bf21cd93STycho Nightingale if (in) { 1785*bf21cd93STycho Nightingale /* Let the device emulation override the default handler */ 1786*bf21cd93STycho Nightingale if (pe->pe_cfgread != NULL) { 1787*bf21cd93STycho Nightingale needcfg = pe->pe_cfgread(ctx, vcpu, pi, coff, bytes, 1788*bf21cd93STycho Nightingale eax); 1789*bf21cd93STycho Nightingale } else { 1790*bf21cd93STycho Nightingale needcfg = 1; 1791*bf21cd93STycho Nightingale } 1792*bf21cd93STycho Nightingale 1793*bf21cd93STycho Nightingale if (needcfg) { 1794*bf21cd93STycho Nightingale if (bytes == 1) 1795*bf21cd93STycho Nightingale *eax = pci_get_cfgdata8(pi, coff); 1796*bf21cd93STycho Nightingale else if (bytes == 2) 1797*bf21cd93STycho Nightingale *eax = pci_get_cfgdata16(pi, coff); 1798*bf21cd93STycho Nightingale else 1799*bf21cd93STycho Nightingale *eax = pci_get_cfgdata32(pi, coff); 1800*bf21cd93STycho Nightingale } 1801*bf21cd93STycho Nightingale 1802*bf21cd93STycho Nightingale pci_emul_hdrtype_fixup(bus, slot, coff, bytes, eax); 1803*bf21cd93STycho Nightingale } else { 1804*bf21cd93STycho Nightingale /* Let the device emulation override the default handler */ 1805*bf21cd93STycho Nightingale if (pe->pe_cfgwrite != NULL && 1806*bf21cd93STycho Nightingale (*pe->pe_cfgwrite)(ctx, vcpu, pi, coff, bytes, *eax) == 0) 1807*bf21cd93STycho Nightingale return; 1808*bf21cd93STycho Nightingale 1809*bf21cd93STycho Nightingale /* 1810*bf21cd93STycho Nightingale * Special handling for write to BAR registers 1811*bf21cd93STycho Nightingale */ 1812*bf21cd93STycho Nightingale if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) { 1813*bf21cd93STycho Nightingale /* 1814*bf21cd93STycho Nightingale * Ignore writes to BAR registers that are not 1815*bf21cd93STycho Nightingale * 4-byte aligned. 1816*bf21cd93STycho Nightingale */ 1817*bf21cd93STycho Nightingale if (bytes != 4 || (coff & 0x3) != 0) 1818*bf21cd93STycho Nightingale return; 1819*bf21cd93STycho Nightingale idx = (coff - PCIR_BAR(0)) / 4; 1820*bf21cd93STycho Nightingale mask = ~(pi->pi_bar[idx].size - 1); 1821*bf21cd93STycho Nightingale switch (pi->pi_bar[idx].type) { 1822*bf21cd93STycho Nightingale case PCIBAR_NONE: 1823*bf21cd93STycho Nightingale pi->pi_bar[idx].addr = bar = 0; 1824*bf21cd93STycho Nightingale break; 1825*bf21cd93STycho Nightingale case PCIBAR_IO: 1826*bf21cd93STycho Nightingale addr = *eax & mask; 1827*bf21cd93STycho Nightingale addr &= 0xffff; 1828*bf21cd93STycho Nightingale bar = addr | PCIM_BAR_IO_SPACE; 1829*bf21cd93STycho Nightingale /* 1830*bf21cd93STycho Nightingale * Register the new BAR value for interception 1831*bf21cd93STycho Nightingale */ 1832*bf21cd93STycho Nightingale if (addr != pi->pi_bar[idx].addr) { 1833*bf21cd93STycho Nightingale update_bar_address(pi, addr, idx, 1834*bf21cd93STycho Nightingale PCIBAR_IO); 1835*bf21cd93STycho Nightingale } 1836*bf21cd93STycho Nightingale break; 1837*bf21cd93STycho Nightingale case PCIBAR_MEM32: 1838*bf21cd93STycho Nightingale addr = bar = *eax & mask; 1839*bf21cd93STycho Nightingale bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; 1840*bf21cd93STycho Nightingale if (addr != pi->pi_bar[idx].addr) { 1841*bf21cd93STycho Nightingale update_bar_address(pi, addr, idx, 1842*bf21cd93STycho Nightingale PCIBAR_MEM32); 1843*bf21cd93STycho Nightingale } 1844*bf21cd93STycho Nightingale break; 1845*bf21cd93STycho Nightingale case PCIBAR_MEM64: 1846*bf21cd93STycho Nightingale addr = bar = *eax & mask; 1847*bf21cd93STycho Nightingale bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | 1848*bf21cd93STycho Nightingale PCIM_BAR_MEM_PREFETCH; 1849*bf21cd93STycho Nightingale if (addr != (uint32_t)pi->pi_bar[idx].addr) { 1850*bf21cd93STycho Nightingale update_bar_address(pi, addr, idx, 1851*bf21cd93STycho Nightingale PCIBAR_MEM64); 1852*bf21cd93STycho Nightingale } 1853*bf21cd93STycho Nightingale break; 1854*bf21cd93STycho Nightingale case PCIBAR_MEMHI64: 1855*bf21cd93STycho Nightingale mask = ~(pi->pi_bar[idx - 1].size - 1); 1856*bf21cd93STycho Nightingale addr = ((uint64_t)*eax << 32) & mask; 1857*bf21cd93STycho Nightingale bar = addr >> 32; 1858*bf21cd93STycho Nightingale if (bar != pi->pi_bar[idx - 1].addr >> 32) { 1859*bf21cd93STycho Nightingale update_bar_address(pi, addr, idx - 1, 1860*bf21cd93STycho Nightingale PCIBAR_MEMHI64); 1861*bf21cd93STycho Nightingale } 1862*bf21cd93STycho Nightingale break; 1863*bf21cd93STycho Nightingale default: 1864*bf21cd93STycho Nightingale assert(0); 1865*bf21cd93STycho Nightingale } 1866*bf21cd93STycho Nightingale pci_set_cfgdata32(pi, coff, bar); 1867*bf21cd93STycho Nightingale 1868*bf21cd93STycho Nightingale } else if (pci_emul_iscap(pi, coff)) { 1869*bf21cd93STycho Nightingale pci_emul_capwrite(pi, coff, bytes, *eax); 1870*bf21cd93STycho Nightingale } else if (coff == PCIR_COMMAND) { 1871*bf21cd93STycho Nightingale pci_emul_cmdwrite(pi, *eax, bytes); 1872*bf21cd93STycho Nightingale } else { 1873*bf21cd93STycho Nightingale CFGWRITE(pi, coff, *eax, bytes); 1874*bf21cd93STycho Nightingale } 1875*bf21cd93STycho Nightingale } 1876*bf21cd93STycho Nightingale } 1877*bf21cd93STycho Nightingale 1878*bf21cd93STycho Nightingale static int cfgenable, cfgbus, cfgslot, cfgfunc, cfgoff; 1879*bf21cd93STycho Nightingale 1880*bf21cd93STycho Nightingale static int 1881*bf21cd93STycho Nightingale pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 1882*bf21cd93STycho Nightingale uint32_t *eax, void *arg) 1883*bf21cd93STycho Nightingale { 1884*bf21cd93STycho Nightingale uint32_t x; 1885*bf21cd93STycho Nightingale 1886*bf21cd93STycho Nightingale if (bytes != 4) { 1887*bf21cd93STycho Nightingale if (in) 1888*bf21cd93STycho Nightingale *eax = (bytes == 2) ? 0xffff : 0xff; 1889*bf21cd93STycho Nightingale return (0); 1890*bf21cd93STycho Nightingale } 1891*bf21cd93STycho Nightingale 1892*bf21cd93STycho Nightingale if (in) { 1893*bf21cd93STycho Nightingale x = (cfgbus << 16) | (cfgslot << 11) | (cfgfunc << 8) | cfgoff; 1894*bf21cd93STycho Nightingale if (cfgenable) 1895*bf21cd93STycho Nightingale x |= CONF1_ENABLE; 1896*bf21cd93STycho Nightingale *eax = x; 1897*bf21cd93STycho Nightingale } else { 1898*bf21cd93STycho Nightingale x = *eax; 1899*bf21cd93STycho Nightingale cfgenable = (x & CONF1_ENABLE) == CONF1_ENABLE; 1900*bf21cd93STycho Nightingale cfgoff = x & PCI_REGMAX; 1901*bf21cd93STycho Nightingale cfgfunc = (x >> 8) & PCI_FUNCMAX; 1902*bf21cd93STycho Nightingale cfgslot = (x >> 11) & PCI_SLOTMAX; 1903*bf21cd93STycho Nightingale cfgbus = (x >> 16) & PCI_BUSMAX; 1904*bf21cd93STycho Nightingale } 1905*bf21cd93STycho Nightingale 1906*bf21cd93STycho Nightingale return (0); 1907*bf21cd93STycho Nightingale } 1908*bf21cd93STycho Nightingale INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_INOUT, pci_emul_cfgaddr); 1909*bf21cd93STycho Nightingale 1910*bf21cd93STycho Nightingale static int 1911*bf21cd93STycho Nightingale pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 1912*bf21cd93STycho Nightingale uint32_t *eax, void *arg) 1913*bf21cd93STycho Nightingale { 1914*bf21cd93STycho Nightingale int coff; 1915*bf21cd93STycho Nightingale 1916*bf21cd93STycho Nightingale assert(bytes == 1 || bytes == 2 || bytes == 4); 1917*bf21cd93STycho Nightingale 1918*bf21cd93STycho Nightingale coff = cfgoff + (port - CONF1_DATA_PORT); 1919*bf21cd93STycho Nightingale if (cfgenable) { 1920*bf21cd93STycho Nightingale pci_cfgrw(ctx, vcpu, in, cfgbus, cfgslot, cfgfunc, coff, bytes, 1921*bf21cd93STycho Nightingale eax); 1922*bf21cd93STycho Nightingale } else { 1923*bf21cd93STycho Nightingale /* Ignore accesses to cfgdata if not enabled by cfgaddr */ 1924*bf21cd93STycho Nightingale if (in) 1925*bf21cd93STycho Nightingale *eax = 0xffffffff; 1926*bf21cd93STycho Nightingale } 1927*bf21cd93STycho Nightingale return (0); 1928*bf21cd93STycho Nightingale } 1929*bf21cd93STycho Nightingale 1930*bf21cd93STycho Nightingale INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+0, IOPORT_F_INOUT, pci_emul_cfgdata); 1931*bf21cd93STycho Nightingale INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+1, IOPORT_F_INOUT, pci_emul_cfgdata); 1932*bf21cd93STycho Nightingale INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+2, IOPORT_F_INOUT, pci_emul_cfgdata); 1933*bf21cd93STycho Nightingale INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+3, IOPORT_F_INOUT, pci_emul_cfgdata); 1934*bf21cd93STycho Nightingale 1935*bf21cd93STycho Nightingale #define PCI_EMUL_TEST 1936*bf21cd93STycho Nightingale #ifdef PCI_EMUL_TEST 1937*bf21cd93STycho Nightingale /* 1938*bf21cd93STycho Nightingale * Define a dummy test device 1939*bf21cd93STycho Nightingale */ 1940*bf21cd93STycho Nightingale #define DIOSZ 8 1941*bf21cd93STycho Nightingale #define DMEMSZ 4096 1942*bf21cd93STycho Nightingale struct pci_emul_dsoftc { 1943*bf21cd93STycho Nightingale uint8_t ioregs[DIOSZ]; 1944*bf21cd93STycho Nightingale uint8_t memregs[DMEMSZ]; 1945*bf21cd93STycho Nightingale }; 1946*bf21cd93STycho Nightingale 1947*bf21cd93STycho Nightingale #define PCI_EMUL_MSI_MSGS 4 1948*bf21cd93STycho Nightingale #define PCI_EMUL_MSIX_MSGS 16 1949*bf21cd93STycho Nightingale 1950*bf21cd93STycho Nightingale static int 1951*bf21cd93STycho Nightingale pci_emul_dinit(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 1952*bf21cd93STycho Nightingale { 1953*bf21cd93STycho Nightingale int error; 1954*bf21cd93STycho Nightingale struct pci_emul_dsoftc *sc; 1955*bf21cd93STycho Nightingale 1956*bf21cd93STycho Nightingale sc = calloc(1, sizeof(struct pci_emul_dsoftc)); 1957*bf21cd93STycho Nightingale 1958*bf21cd93STycho Nightingale pi->pi_arg = sc; 1959*bf21cd93STycho Nightingale 1960*bf21cd93STycho Nightingale pci_set_cfgdata16(pi, PCIR_DEVICE, 0x0001); 1961*bf21cd93STycho Nightingale pci_set_cfgdata16(pi, PCIR_VENDOR, 0x10DD); 1962*bf21cd93STycho Nightingale pci_set_cfgdata8(pi, PCIR_CLASS, 0x02); 1963*bf21cd93STycho Nightingale 1964*bf21cd93STycho Nightingale error = pci_emul_add_msicap(pi, PCI_EMUL_MSI_MSGS); 1965*bf21cd93STycho Nightingale assert(error == 0); 1966*bf21cd93STycho Nightingale 1967*bf21cd93STycho Nightingale error = pci_emul_alloc_bar(pi, 0, PCIBAR_IO, DIOSZ); 1968*bf21cd93STycho Nightingale assert(error == 0); 1969*bf21cd93STycho Nightingale 1970*bf21cd93STycho Nightingale error = pci_emul_alloc_bar(pi, 1, PCIBAR_MEM32, DMEMSZ); 1971*bf21cd93STycho Nightingale assert(error == 0); 1972*bf21cd93STycho Nightingale 1973*bf21cd93STycho Nightingale return (0); 1974*bf21cd93STycho Nightingale } 1975*bf21cd93STycho Nightingale 1976*bf21cd93STycho Nightingale static void 1977*bf21cd93STycho Nightingale pci_emul_diow(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, 1978*bf21cd93STycho Nightingale uint64_t offset, int size, uint64_t value) 1979*bf21cd93STycho Nightingale { 1980*bf21cd93STycho Nightingale int i; 1981*bf21cd93STycho Nightingale struct pci_emul_dsoftc *sc = pi->pi_arg; 1982*bf21cd93STycho Nightingale 1983*bf21cd93STycho Nightingale if (baridx == 0) { 1984*bf21cd93STycho Nightingale if (offset + size > DIOSZ) { 1985*bf21cd93STycho Nightingale printf("diow: iow too large, offset %ld size %d\n", 1986*bf21cd93STycho Nightingale offset, size); 1987*bf21cd93STycho Nightingale return; 1988*bf21cd93STycho Nightingale } 1989*bf21cd93STycho Nightingale 1990*bf21cd93STycho Nightingale if (size == 1) { 1991*bf21cd93STycho Nightingale sc->ioregs[offset] = value & 0xff; 1992*bf21cd93STycho Nightingale } else if (size == 2) { 1993*bf21cd93STycho Nightingale *(uint16_t *)&sc->ioregs[offset] = value & 0xffff; 1994*bf21cd93STycho Nightingale } else if (size == 4) { 1995*bf21cd93STycho Nightingale *(uint32_t *)&sc->ioregs[offset] = value; 1996*bf21cd93STycho Nightingale } else { 1997*bf21cd93STycho Nightingale printf("diow: iow unknown size %d\n", size); 1998*bf21cd93STycho Nightingale } 1999*bf21cd93STycho Nightingale 2000*bf21cd93STycho Nightingale /* 2001*bf21cd93STycho Nightingale * Special magic value to generate an interrupt 2002*bf21cd93STycho Nightingale */ 2003*bf21cd93STycho Nightingale if (offset == 4 && size == 4 && pci_msi_enabled(pi)) 2004*bf21cd93STycho Nightingale pci_generate_msi(pi, value % pci_msi_maxmsgnum(pi)); 2005*bf21cd93STycho Nightingale 2006*bf21cd93STycho Nightingale if (value == 0xabcdef) { 2007*bf21cd93STycho Nightingale for (i = 0; i < pci_msi_maxmsgnum(pi); i++) 2008*bf21cd93STycho Nightingale pci_generate_msi(pi, i); 2009*bf21cd93STycho Nightingale } 2010*bf21cd93STycho Nightingale } 2011*bf21cd93STycho Nightingale 2012*bf21cd93STycho Nightingale if (baridx == 1) { 2013*bf21cd93STycho Nightingale if (offset + size > DMEMSZ) { 2014*bf21cd93STycho Nightingale printf("diow: memw too large, offset %ld size %d\n", 2015*bf21cd93STycho Nightingale offset, size); 2016*bf21cd93STycho Nightingale return; 2017*bf21cd93STycho Nightingale } 2018*bf21cd93STycho Nightingale 2019*bf21cd93STycho Nightingale if (size == 1) { 2020*bf21cd93STycho Nightingale sc->memregs[offset] = value; 2021*bf21cd93STycho Nightingale } else if (size == 2) { 2022*bf21cd93STycho Nightingale *(uint16_t *)&sc->memregs[offset] = value; 2023*bf21cd93STycho Nightingale } else if (size == 4) { 2024*bf21cd93STycho Nightingale *(uint32_t *)&sc->memregs[offset] = value; 2025*bf21cd93STycho Nightingale } else if (size == 8) { 2026*bf21cd93STycho Nightingale *(uint64_t *)&sc->memregs[offset] = value; 2027*bf21cd93STycho Nightingale } else { 2028*bf21cd93STycho Nightingale printf("diow: memw unknown size %d\n", size); 2029*bf21cd93STycho Nightingale } 2030*bf21cd93STycho Nightingale 2031*bf21cd93STycho Nightingale /* 2032*bf21cd93STycho Nightingale * magic interrupt ?? 2033*bf21cd93STycho Nightingale */ 2034*bf21cd93STycho Nightingale } 2035*bf21cd93STycho Nightingale 2036*bf21cd93STycho Nightingale if (baridx > 1) { 2037*bf21cd93STycho Nightingale printf("diow: unknown bar idx %d\n", baridx); 2038*bf21cd93STycho Nightingale } 2039*bf21cd93STycho Nightingale } 2040*bf21cd93STycho Nightingale 2041*bf21cd93STycho Nightingale static uint64_t 2042*bf21cd93STycho Nightingale pci_emul_dior(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, 2043*bf21cd93STycho Nightingale uint64_t offset, int size) 2044*bf21cd93STycho Nightingale { 2045*bf21cd93STycho Nightingale struct pci_emul_dsoftc *sc = pi->pi_arg; 2046*bf21cd93STycho Nightingale uint32_t value; 2047*bf21cd93STycho Nightingale 2048*bf21cd93STycho Nightingale if (baridx == 0) { 2049*bf21cd93STycho Nightingale if (offset + size > DIOSZ) { 2050*bf21cd93STycho Nightingale printf("dior: ior too large, offset %ld size %d\n", 2051*bf21cd93STycho Nightingale offset, size); 2052*bf21cd93STycho Nightingale return (0); 2053*bf21cd93STycho Nightingale } 2054*bf21cd93STycho Nightingale 2055*bf21cd93STycho Nightingale if (size == 1) { 2056*bf21cd93STycho Nightingale value = sc->ioregs[offset]; 2057*bf21cd93STycho Nightingale } else if (size == 2) { 2058*bf21cd93STycho Nightingale value = *(uint16_t *) &sc->ioregs[offset]; 2059*bf21cd93STycho Nightingale } else if (size == 4) { 2060*bf21cd93STycho Nightingale value = *(uint32_t *) &sc->ioregs[offset]; 2061*bf21cd93STycho Nightingale } else { 2062*bf21cd93STycho Nightingale printf("dior: ior unknown size %d\n", size); 2063*bf21cd93STycho Nightingale } 2064*bf21cd93STycho Nightingale } 2065*bf21cd93STycho Nightingale 2066*bf21cd93STycho Nightingale if (baridx == 1) { 2067*bf21cd93STycho Nightingale if (offset + size > DMEMSZ) { 2068*bf21cd93STycho Nightingale printf("dior: memr too large, offset %ld size %d\n", 2069*bf21cd93STycho Nightingale offset, size); 2070*bf21cd93STycho Nightingale return (0); 2071*bf21cd93STycho Nightingale } 2072*bf21cd93STycho Nightingale 2073*bf21cd93STycho Nightingale if (size == 1) { 2074*bf21cd93STycho Nightingale value = sc->memregs[offset]; 2075*bf21cd93STycho Nightingale } else if (size == 2) { 2076*bf21cd93STycho Nightingale value = *(uint16_t *) &sc->memregs[offset]; 2077*bf21cd93STycho Nightingale } else if (size == 4) { 2078*bf21cd93STycho Nightingale value = *(uint32_t *) &sc->memregs[offset]; 2079*bf21cd93STycho Nightingale } else if (size == 8) { 2080*bf21cd93STycho Nightingale value = *(uint64_t *) &sc->memregs[offset]; 2081*bf21cd93STycho Nightingale } else { 2082*bf21cd93STycho Nightingale printf("dior: ior unknown size %d\n", size); 2083*bf21cd93STycho Nightingale } 2084*bf21cd93STycho Nightingale } 2085*bf21cd93STycho Nightingale 2086*bf21cd93STycho Nightingale 2087*bf21cd93STycho Nightingale if (baridx > 1) { 2088*bf21cd93STycho Nightingale printf("dior: unknown bar idx %d\n", baridx); 2089*bf21cd93STycho Nightingale return (0); 2090*bf21cd93STycho Nightingale } 2091*bf21cd93STycho Nightingale 2092*bf21cd93STycho Nightingale return (value); 2093*bf21cd93STycho Nightingale } 2094*bf21cd93STycho Nightingale 2095*bf21cd93STycho Nightingale struct pci_devemu pci_dummy = { 2096*bf21cd93STycho Nightingale .pe_emu = "dummy", 2097*bf21cd93STycho Nightingale .pe_init = pci_emul_dinit, 2098*bf21cd93STycho Nightingale .pe_barwrite = pci_emul_diow, 2099*bf21cd93STycho Nightingale .pe_barread = pci_emul_dior 2100*bf21cd93STycho Nightingale }; 2101*bf21cd93STycho Nightingale PCI_EMUL_SET(pci_dummy); 2102*bf21cd93STycho Nightingale 2103*bf21cd93STycho Nightingale #endif /* PCI_EMUL_TEST */ 2104