1bf21cd93STycho Nightingale /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 4bf21cd93STycho Nightingale * Copyright (c) 2011 NetApp, Inc. 5bf21cd93STycho Nightingale * All rights reserved. 6bf21cd93STycho Nightingale * 7bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without 8bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions 9bf21cd93STycho Nightingale * are met: 10bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright 11bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer. 12bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright 13bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the 14bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution. 15bf21cd93STycho Nightingale * 16bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26bf21cd93STycho Nightingale * SUCH DAMAGE. 27bf21cd93STycho Nightingale * 284c87aefeSPatrick Mooney * $FreeBSD$ 29bf21cd93STycho Nightingale */ 30b22a70abSPatrick Mooney /* 31b22a70abSPatrick Mooney * Copyright 2018 Joyent, Inc. 32b22a70abSPatrick Mooney */ 33bf21cd93STycho Nightingale 34bf21cd93STycho Nightingale #ifndef _PCI_EMUL_H_ 35bf21cd93STycho Nightingale #define _PCI_EMUL_H_ 36bf21cd93STycho Nightingale 37bf21cd93STycho Nightingale #include <sys/types.h> 38bf21cd93STycho Nightingale #include <sys/queue.h> 39bf21cd93STycho Nightingale #include <sys/kernel.h> 40*2b948146SAndy Fiddaman #include <sys/nv.h> 41bf21cd93STycho Nightingale #include <sys/_pthreadtypes.h> 42bf21cd93STycho Nightingale 43bf21cd93STycho Nightingale #include <dev/pci/pcireg.h> 44bf21cd93STycho Nightingale 45bf21cd93STycho Nightingale #include <assert.h> 46bf21cd93STycho Nightingale 47bf21cd93STycho Nightingale #define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */ 48bf21cd93STycho Nightingale 49bf21cd93STycho Nightingale struct vmctx; 50bf21cd93STycho Nightingale struct pci_devinst; 51bf21cd93STycho Nightingale struct memory_region; 52bf21cd93STycho Nightingale 53bf21cd93STycho Nightingale struct pci_devemu { 54bf21cd93STycho Nightingale char *pe_emu; /* Name of device emulation */ 55bf21cd93STycho Nightingale 56bf21cd93STycho Nightingale /* instance creation */ 57bf21cd93STycho Nightingale int (*pe_init)(struct vmctx *, struct pci_devinst *, 58*2b948146SAndy Fiddaman nvlist_t *); 59*2b948146SAndy Fiddaman int (*pe_legacy_config)(nvlist_t *, const char *); 60*2b948146SAndy Fiddaman const char *pe_alias; 61bf21cd93STycho Nightingale 62bf21cd93STycho Nightingale /* ACPI DSDT enumeration */ 63bf21cd93STycho Nightingale void (*pe_write_dsdt)(struct pci_devinst *); 64bf21cd93STycho Nightingale 65bf21cd93STycho Nightingale /* config space read/write callbacks */ 66bf21cd93STycho Nightingale int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu, 67bf21cd93STycho Nightingale struct pci_devinst *pi, int offset, 68bf21cd93STycho Nightingale int bytes, uint32_t val); 69bf21cd93STycho Nightingale int (*pe_cfgread)(struct vmctx *ctx, int vcpu, 70bf21cd93STycho Nightingale struct pci_devinst *pi, int offset, 71bf21cd93STycho Nightingale int bytes, uint32_t *retval); 72bf21cd93STycho Nightingale 73bf21cd93STycho Nightingale /* BAR read/write callbacks */ 74bf21cd93STycho Nightingale void (*pe_barwrite)(struct vmctx *ctx, int vcpu, 75bf21cd93STycho Nightingale struct pci_devinst *pi, int baridx, 76bf21cd93STycho Nightingale uint64_t offset, int size, uint64_t value); 77bf21cd93STycho Nightingale uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu, 78bf21cd93STycho Nightingale struct pci_devinst *pi, int baridx, 79bf21cd93STycho Nightingale uint64_t offset, int size); 80b22a70abSPatrick Mooney 81*2b948146SAndy Fiddaman void (*pe_baraddr)(struct vmctx *ctx, struct pci_devinst *pi, 82*2b948146SAndy Fiddaman int baridx, int enabled, uint64_t address); 83b22a70abSPatrick Mooney #ifndef __FreeBSD__ 84b22a70abSPatrick Mooney void (*pe_lintrupdate)(struct pci_devinst *pi); 85b22a70abSPatrick Mooney #endif /* __FreeBSD__ */ 86bf21cd93STycho Nightingale }; 87*2b948146SAndy Fiddaman 88bf21cd93STycho Nightingale #define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x); 89bf21cd93STycho Nightingale 90bf21cd93STycho Nightingale enum pcibar_type { 91bf21cd93STycho Nightingale PCIBAR_NONE, 92bf21cd93STycho Nightingale PCIBAR_IO, 93bf21cd93STycho Nightingale PCIBAR_MEM32, 94bf21cd93STycho Nightingale PCIBAR_MEM64, 95bf21cd93STycho Nightingale PCIBAR_MEMHI64 96bf21cd93STycho Nightingale }; 97bf21cd93STycho Nightingale 98bf21cd93STycho Nightingale struct pcibar { 99bf21cd93STycho Nightingale enum pcibar_type type; /* io or memory */ 100bf21cd93STycho Nightingale uint64_t size; 101bf21cd93STycho Nightingale uint64_t addr; 102bf21cd93STycho Nightingale }; 103bf21cd93STycho Nightingale 104bf21cd93STycho Nightingale #define PI_NAMESZ 40 105bf21cd93STycho Nightingale 106bf21cd93STycho Nightingale struct msix_table_entry { 107bf21cd93STycho Nightingale uint64_t addr; 108bf21cd93STycho Nightingale uint32_t msg_data; 109bf21cd93STycho Nightingale uint32_t vector_control; 110bf21cd93STycho Nightingale } __packed; 111bf21cd93STycho Nightingale 112bf21cd93STycho Nightingale /* 113bf21cd93STycho Nightingale * In case the structure is modified to hold extra information, use a define 114bf21cd93STycho Nightingale * for the size that should be emulated. 115bf21cd93STycho Nightingale */ 116bf21cd93STycho Nightingale #define MSIX_TABLE_ENTRY_SIZE 16 117bf21cd93STycho Nightingale #define MAX_MSIX_TABLE_ENTRIES 2048 118bf21cd93STycho Nightingale #define PBA_SIZE(msgnum) (roundup2((msgnum), 64) / 8) 119bf21cd93STycho Nightingale 120bf21cd93STycho Nightingale enum lintr_stat { 121bf21cd93STycho Nightingale IDLE, 122bf21cd93STycho Nightingale ASSERTED, 123bf21cd93STycho Nightingale PENDING 124bf21cd93STycho Nightingale }; 125bf21cd93STycho Nightingale 126bf21cd93STycho Nightingale struct pci_devinst { 127bf21cd93STycho Nightingale struct pci_devemu *pi_d; 128bf21cd93STycho Nightingale struct vmctx *pi_vmctx; 129bf21cd93STycho Nightingale uint8_t pi_bus, pi_slot, pi_func; 130bf21cd93STycho Nightingale char pi_name[PI_NAMESZ]; 131bf21cd93STycho Nightingale int pi_bar_getsize; 132bf21cd93STycho Nightingale int pi_prevcap; 133bf21cd93STycho Nightingale int pi_capend; 134bf21cd93STycho Nightingale 135bf21cd93STycho Nightingale struct { 136bf21cd93STycho Nightingale int8_t pin; 137bf21cd93STycho Nightingale enum lintr_stat state; 138bf21cd93STycho Nightingale int pirq_pin; 139bf21cd93STycho Nightingale int ioapic_irq; 140bf21cd93STycho Nightingale pthread_mutex_t lock; 141bf21cd93STycho Nightingale } pi_lintr; 142bf21cd93STycho Nightingale 143bf21cd93STycho Nightingale struct { 144bf21cd93STycho Nightingale int enabled; 145bf21cd93STycho Nightingale uint64_t addr; 146bf21cd93STycho Nightingale uint64_t msg_data; 147bf21cd93STycho Nightingale int maxmsgnum; 148bf21cd93STycho Nightingale } pi_msi; 149bf21cd93STycho Nightingale 150bf21cd93STycho Nightingale struct { 151bf21cd93STycho Nightingale int enabled; 152bf21cd93STycho Nightingale int table_bar; 153bf21cd93STycho Nightingale int pba_bar; 154bf21cd93STycho Nightingale uint32_t table_offset; 155bf21cd93STycho Nightingale int table_count; 156bf21cd93STycho Nightingale uint32_t pba_offset; 157bf21cd93STycho Nightingale int pba_size; 158bf21cd93STycho Nightingale int function_mask; 159bf21cd93STycho Nightingale struct msix_table_entry *table; /* allocated at runtime */ 1604c87aefeSPatrick Mooney void *pba_page; 1614c87aefeSPatrick Mooney int pba_page_offset; 162bf21cd93STycho Nightingale } pi_msix; 163bf21cd93STycho Nightingale 164bf21cd93STycho Nightingale void *pi_arg; /* devemu-private data */ 165bf21cd93STycho Nightingale 166bf21cd93STycho Nightingale u_char pi_cfgdata[PCI_REGMAX + 1]; 167bf21cd93STycho Nightingale struct pcibar pi_bar[PCI_BARMAX + 1]; 168bf21cd93STycho Nightingale }; 169bf21cd93STycho Nightingale 170bf21cd93STycho Nightingale struct msicap { 171bf21cd93STycho Nightingale uint8_t capid; 172bf21cd93STycho Nightingale uint8_t nextptr; 173bf21cd93STycho Nightingale uint16_t msgctrl; 174bf21cd93STycho Nightingale uint32_t addrlo; 175bf21cd93STycho Nightingale uint32_t addrhi; 176bf21cd93STycho Nightingale uint16_t msgdata; 177bf21cd93STycho Nightingale } __packed; 1784c87aefeSPatrick Mooney static_assert(sizeof(struct msicap) == 14, "compile-time assertion failed"); 179bf21cd93STycho Nightingale 180bf21cd93STycho Nightingale struct msixcap { 181bf21cd93STycho Nightingale uint8_t capid; 182bf21cd93STycho Nightingale uint8_t nextptr; 183bf21cd93STycho Nightingale uint16_t msgctrl; 184bf21cd93STycho Nightingale uint32_t table_info; /* bar index and offset within it */ 185bf21cd93STycho Nightingale uint32_t pba_info; /* bar index and offset within it */ 186bf21cd93STycho Nightingale } __packed; 1874c87aefeSPatrick Mooney static_assert(sizeof(struct msixcap) == 12, "compile-time assertion failed"); 188bf21cd93STycho Nightingale 189bf21cd93STycho Nightingale struct pciecap { 190bf21cd93STycho Nightingale uint8_t capid; 191bf21cd93STycho Nightingale uint8_t nextptr; 192bf21cd93STycho Nightingale uint16_t pcie_capabilities; 193bf21cd93STycho Nightingale 194bf21cd93STycho Nightingale uint32_t dev_capabilities; /* all devices */ 195bf21cd93STycho Nightingale uint16_t dev_control; 196bf21cd93STycho Nightingale uint16_t dev_status; 197bf21cd93STycho Nightingale 198bf21cd93STycho Nightingale uint32_t link_capabilities; /* devices with links */ 199bf21cd93STycho Nightingale uint16_t link_control; 200bf21cd93STycho Nightingale uint16_t link_status; 201bf21cd93STycho Nightingale 202bf21cd93STycho Nightingale uint32_t slot_capabilities; /* ports with slots */ 203bf21cd93STycho Nightingale uint16_t slot_control; 204bf21cd93STycho Nightingale uint16_t slot_status; 205bf21cd93STycho Nightingale 206bf21cd93STycho Nightingale uint16_t root_control; /* root ports */ 207bf21cd93STycho Nightingale uint16_t root_capabilities; 208bf21cd93STycho Nightingale uint32_t root_status; 209bf21cd93STycho Nightingale 210bf21cd93STycho Nightingale uint32_t dev_capabilities2; /* all devices */ 211bf21cd93STycho Nightingale uint16_t dev_control2; 212bf21cd93STycho Nightingale uint16_t dev_status2; 213bf21cd93STycho Nightingale 214bf21cd93STycho Nightingale uint32_t link_capabilities2; /* devices with links */ 215bf21cd93STycho Nightingale uint16_t link_control2; 216bf21cd93STycho Nightingale uint16_t link_status2; 217bf21cd93STycho Nightingale 218bf21cd93STycho Nightingale uint32_t slot_capabilities2; /* ports with slots */ 219bf21cd93STycho Nightingale uint16_t slot_control2; 220bf21cd93STycho Nightingale uint16_t slot_status2; 221bf21cd93STycho Nightingale } __packed; 2224c87aefeSPatrick Mooney static_assert(sizeof(struct pciecap) == 60, "compile-time assertion failed"); 223bf21cd93STycho Nightingale 224bf21cd93STycho Nightingale typedef void (*pci_lintr_cb)(int b, int s, int pin, int pirq_pin, 225bf21cd93STycho Nightingale int ioapic_irq, void *arg); 226bf21cd93STycho Nightingale 227bf21cd93STycho Nightingale int init_pci(struct vmctx *ctx); 228bf21cd93STycho Nightingale void pci_callback(void); 229bf21cd93STycho Nightingale int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, 230bf21cd93STycho Nightingale enum pcibar_type type, uint64_t size); 231bf21cd93STycho Nightingale int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum); 232bf21cd93STycho Nightingale int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type); 233154972afSPatrick Mooney void pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, 234154972afSPatrick Mooney uint32_t val, uint8_t capoff, int capid); 23584659b24SMichael Zeller void pci_emul_cmd_changed(struct pci_devinst *pi, uint16_t old); 236bf21cd93STycho Nightingale void pci_generate_msi(struct pci_devinst *pi, int msgnum); 237bf21cd93STycho Nightingale void pci_generate_msix(struct pci_devinst *pi, int msgnum); 238bf21cd93STycho Nightingale void pci_lintr_assert(struct pci_devinst *pi); 239bf21cd93STycho Nightingale void pci_lintr_deassert(struct pci_devinst *pi); 240bf21cd93STycho Nightingale void pci_lintr_request(struct pci_devinst *pi); 241bf21cd93STycho Nightingale int pci_msi_enabled(struct pci_devinst *pi); 242bf21cd93STycho Nightingale int pci_msix_enabled(struct pci_devinst *pi); 243bf21cd93STycho Nightingale int pci_msix_table_bar(struct pci_devinst *pi); 244bf21cd93STycho Nightingale int pci_msix_pba_bar(struct pci_devinst *pi); 2454c87aefeSPatrick Mooney int pci_msi_maxmsgnum(struct pci_devinst *pi); 246*2b948146SAndy Fiddaman int pci_parse_legacy_config(nvlist_t *nvl, const char *opt); 247bf21cd93STycho Nightingale int pci_parse_slot(char *opt); 2484c87aefeSPatrick Mooney void pci_print_supported_devices(); 249bf21cd93STycho Nightingale void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr); 250bf21cd93STycho Nightingale int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum); 251bf21cd93STycho Nightingale int pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size, 252bf21cd93STycho Nightingale uint64_t value); 253bf21cd93STycho Nightingale uint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size); 254bf21cd93STycho Nightingale int pci_count_lintr(int bus); 255bf21cd93STycho Nightingale void pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg); 256bf21cd93STycho Nightingale void pci_write_dsdt(void); 257bf21cd93STycho Nightingale uint64_t pci_ecfg_base(void); 258bf21cd93STycho Nightingale int pci_bus_configured(int bus); 259bf21cd93STycho Nightingale 260bf21cd93STycho Nightingale static __inline void 261bf21cd93STycho Nightingale pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val) 262bf21cd93STycho Nightingale { 263bf21cd93STycho Nightingale assert(offset <= PCI_REGMAX); 264bf21cd93STycho Nightingale *(uint8_t *)(pi->pi_cfgdata + offset) = val; 265bf21cd93STycho Nightingale } 266bf21cd93STycho Nightingale 267bf21cd93STycho Nightingale static __inline void 268bf21cd93STycho Nightingale pci_set_cfgdata16(struct pci_devinst *pi, int offset, uint16_t val) 269bf21cd93STycho Nightingale { 270bf21cd93STycho Nightingale assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 271bf21cd93STycho Nightingale *(uint16_t *)(pi->pi_cfgdata + offset) = val; 272bf21cd93STycho Nightingale } 273bf21cd93STycho Nightingale 274bf21cd93STycho Nightingale static __inline void 275bf21cd93STycho Nightingale pci_set_cfgdata32(struct pci_devinst *pi, int offset, uint32_t val) 276bf21cd93STycho Nightingale { 277bf21cd93STycho Nightingale assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 278bf21cd93STycho Nightingale *(uint32_t *)(pi->pi_cfgdata + offset) = val; 279bf21cd93STycho Nightingale } 280bf21cd93STycho Nightingale 281bf21cd93STycho Nightingale static __inline uint8_t 282bf21cd93STycho Nightingale pci_get_cfgdata8(struct pci_devinst *pi, int offset) 283bf21cd93STycho Nightingale { 284bf21cd93STycho Nightingale assert(offset <= PCI_REGMAX); 285bf21cd93STycho Nightingale return (*(uint8_t *)(pi->pi_cfgdata + offset)); 286bf21cd93STycho Nightingale } 287bf21cd93STycho Nightingale 288bf21cd93STycho Nightingale static __inline uint16_t 289bf21cd93STycho Nightingale pci_get_cfgdata16(struct pci_devinst *pi, int offset) 290bf21cd93STycho Nightingale { 291bf21cd93STycho Nightingale assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 292bf21cd93STycho Nightingale return (*(uint16_t *)(pi->pi_cfgdata + offset)); 293bf21cd93STycho Nightingale } 294bf21cd93STycho Nightingale 295bf21cd93STycho Nightingale static __inline uint32_t 296bf21cd93STycho Nightingale pci_get_cfgdata32(struct pci_devinst *pi, int offset) 297bf21cd93STycho Nightingale { 298bf21cd93STycho Nightingale assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 299bf21cd93STycho Nightingale return (*(uint32_t *)(pi->pi_cfgdata + offset)); 300bf21cd93STycho Nightingale } 301bf21cd93STycho Nightingale 302bf21cd93STycho Nightingale #endif /* _PCI_EMUL_H_ */ 303