pci_emul.h revision 270159
112891Swpaul/*- 212891Swpaul * Copyright (c) 2011 NetApp, Inc. 312891Swpaul * All rights reserved. 412891Swpaul * 512891Swpaul * Redistribution and use in source and binary forms, with or without 612891Swpaul * modification, are permitted provided that the following conditions 712891Swpaul * are met: 812891Swpaul * 1. Redistributions of source code must retain the above copyright 912891Swpaul * notice, this list of conditions and the following disclaimer. 1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1112891Swpaul * notice, this list of conditions and the following disclaimer in the 1212891Swpaul * documentation and/or other materials provided with the distribution. 1312891Swpaul * 1412891Swpaul * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 1512891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1612891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1712891Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 1812891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1912891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2012891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2112891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2212891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2312891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2412891Swpaul * SUCH DAMAGE. 2512891Swpaul * 2612891Swpaul * $FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.h 270159 2014-08-19 01:20:24Z grehan $ 2712891Swpaul */ 2812891Swpaul 2912891Swpaul#ifndef _PCI_EMUL_H_ 3012891Swpaul#define _PCI_EMUL_H_ 3112891Swpaul 3212891Swpaul#include <sys/types.h> 3312891Swpaul#include <sys/queue.h> 34114601Sobrien#include <sys/kernel.h> 35114601Sobrien#include <sys/_pthreadtypes.h> 3630827Scharnier 3720818Swpaul#include <dev/pci/pcireg.h> 3812891Swpaul 3930827Scharnier#include <assert.h> 4030827Scharnier 4112891Swpaul#define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */ 4212891Swpaul 4312891Swpaulstruct vmctx; 4412891Swpaulstruct pci_devinst; 4512891Swpaulstruct memory_region; 4612891Swpaul 4712891Swpaulstruct pci_devemu { 4812997Swpaul char *pe_emu; /* Name of device emulation */ 4912891Swpaul 5012891Swpaul /* instance creation */ 5112891Swpaul int (*pe_init)(struct vmctx *, struct pci_devinst *, 5228042Swpaul char *opts); 5328042Swpaul 5428042Swpaul /* ACPI DSDT enumeration */ 5528042Swpaul void (*pe_write_dsdt)(struct pci_devinst *); 5628042Swpaul 5790298Sdes /* config space read/write callbacks */ 5890298Sdes int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu, 5946186Swpaul struct pci_devinst *pi, int offset, 6046186Swpaul int bytes, uint32_t val); 6146186Swpaul int (*pe_cfgread)(struct vmctx *ctx, int vcpu, 6246186Swpaul struct pci_devinst *pi, int offset, 6346186Swpaul int bytes, uint32_t *retval); 6446186Swpaul 6546186Swpaul /* BAR read/write callbacks */ 6646186Swpaul void (*pe_barwrite)(struct vmctx *ctx, int vcpu, 6746186Swpaul struct pci_devinst *pi, int baridx, 6846186Swpaul uint64_t offset, int size, uint64_t value); 6914262Swpaul uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu, 7014262Swpaul struct pci_devinst *pi, int baridx, 7114262Swpaul uint64_t offset, int size); 7214262Swpaul}; 7312891Swpaul#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x); 7412891Swpaul 7512891Swpaulenum pcibar_type { 7612891Swpaul PCIBAR_NONE, 7712891Swpaul PCIBAR_IO, 7812891Swpaul PCIBAR_MEM32, 7919161Swpaul PCIBAR_MEM64, 8019161Swpaul PCIBAR_MEMHI64 8119161Swpaul}; 8212891Swpaul 8319161Swpaulstruct pcibar { 8412891Swpaul enum pcibar_type type; /* io or memory */ 8512891Swpaul uint64_t size; 8612891Swpaul uint64_t addr; 8712891Swpaul}; 8812891Swpaul 8912891Swpaul#define PI_NAMESZ 40 9012891Swpaul 9112891Swpaulstruct msix_table_entry { 9212891Swpaul uint64_t addr; 9312891Swpaul uint32_t msg_data; 9412891Swpaul uint32_t vector_control; 9512891Swpaul} __packed; 9619161Swpaul 9719161Swpaul/* 9819161Swpaul * In case the structure is modified to hold extra information, use a define 9912891Swpaul * for the size that should be emulated. 10019161Swpaul */ 10112891Swpaul#define MSIX_TABLE_ENTRY_SIZE 16 10212891Swpaul#define MAX_MSIX_TABLE_ENTRIES 2048 10312891Swpaul#define PBA_SIZE(msgnum) (roundup2((msgnum), 64) / 8) 10412891Swpaul 10512891Swpaulenum lintr_stat { 10612891Swpaul IDLE, 10712891Swpaul ASSERTED, 10812891Swpaul PENDING 10912891Swpaul}; 11012891Swpaul 11112891Swpaulstruct pci_devinst { 11212891Swpaul struct pci_devemu *pi_d; 11312891Swpaul struct vmctx *pi_vmctx; 11412891Swpaul uint8_t pi_bus, pi_slot, pi_func; 11512891Swpaul char pi_name[PI_NAMESZ]; 11612891Swpaul int pi_bar_getsize; 11712891Swpaul int pi_prevcap; 11819161Swpaul int pi_capend; 11919161Swpaul 12019161Swpaul struct { 12112891Swpaul int8_t pin; 12219161Swpaul enum lintr_stat state; 12312891Swpaul int pirq_pin; 12412891Swpaul int ioapic_irq; 12512891Swpaul pthread_mutex_t lock; 12612891Swpaul } pi_lintr; 12712891Swpaul 12812891Swpaul struct { 12912891Swpaul int enabled; 13012891Swpaul uint64_t addr; 13112891Swpaul uint64_t msg_data; 13212891Swpaul int maxmsgnum; 13312891Swpaul } pi_msi; 13412891Swpaul 13512891Swpaul struct { 13612891Swpaul int enabled; 13712891Swpaul int table_bar; 13814304Swpaul int pba_bar; 13914304Swpaul uint32_t table_offset; 14019161Swpaul int table_count; 14119161Swpaul uint32_t pba_offset; 14219161Swpaul int pba_size; 14319161Swpaul int function_mask; 14412891Swpaul struct msix_table_entry *table; /* allocated at runtime */ 14519161Swpaul } pi_msix; 14612891Swpaul 14712891Swpaul void *pi_arg; /* devemu-private data */ 14812891Swpaul 14912891Swpaul u_char pi_cfgdata[PCI_REGMAX + 1]; 15012891Swpaul struct pcibar pi_bar[PCI_BARMAX + 1]; 15112891Swpaul}; 15212891Swpaul 15312891Swpaulstruct msicap { 15412891Swpaul uint8_t capid; 15533250Swpaul uint8_t nextptr; 15620818Swpaul uint16_t msgctrl; 15720818Swpaul uint32_t addrlo; 15812891Swpaul uint32_t addrhi; 15912891Swpaul uint16_t msgdata; 16020818Swpaul} __packed; 16120818Swpaul 16212891Swpaulstruct msixcap { 16312891Swpaul uint8_t capid; 16412891Swpaul uint8_t nextptr; 16512891Swpaul uint16_t msgctrl; 16619161Swpaul uint32_t table_info; /* bar index and offset within it */ 167159461Smaxim uint32_t pba_info; /* bar index and offset within it */ 16819161Swpaul} __packed; 169159461Smaxim 17019161Swpaulstruct pciecap { 171145792Sume uint8_t capid; 172145793Sume uint8_t nextptr; 17319161Swpaul uint16_t pcie_capabilities; 17427589Swpaul 17590297Sdes uint32_t dev_capabilities; /* all devices */ 17620818Swpaul uint16_t dev_control; 17727589Swpaul uint16_t dev_status; 17827589Swpaul 17912891Swpaul uint32_t link_capabilities; /* devices with links */ 18012891Swpaul uint16_t link_control; 18130827Scharnier uint16_t link_status; 18212891Swpaul 18312891Swpaul uint32_t slot_capabilities; /* ports with slots */ 184145792Sume uint16_t slot_control; 185145792Sume uint16_t slot_status; 18612891Swpaul 187145792Sume uint16_t root_control; /* root ports */ 188145792Sume uint16_t root_capabilities; 189145792Sume uint32_t root_status; 190145792Sume 191145792Sume uint32_t dev_capabilities2; /* all devices */ 192145792Sume uint16_t dev_control2; 193145792Sume uint16_t dev_status2; 194145792Sume 19512891Swpaul uint32_t link_capabilities2; /* devices with links */ 19620818Swpaul uint16_t link_control2; 19720818Swpaul uint16_t link_status2; 19812891Swpaul 19912891Swpaul uint32_t slot_capabilities2; /* ports with slots */ 20012891Swpaul uint16_t slot_control2; 20112891Swpaul uint16_t slot_status2; 20212891Swpaul} __packed; 20312891Swpaul 20412891Swpaultypedef void (*pci_lintr_cb)(int b, int s, int pin, int pirq_pin, 20512891Swpaul int ioapic_irq, void *arg); 20612891Swpaul 20712891Swpaulint init_pci(struct vmctx *ctx); 20814304Swpaulvoid msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 20914304Swpaul int bytes, uint32_t val); 21019161Swpaulvoid msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 21119161Swpaul int bytes, uint32_t val); 21219161Swpaulvoid pci_callback(void); 21319161Swpaulint pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, 21412891Swpaul enum pcibar_type type, uint64_t size); 21519161Swpaulint pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, 21612891Swpaul uint64_t hostbase, enum pcibar_type type, uint64_t size); 21712891Swpaulint pci_emul_add_msicap(struct pci_devinst *pi, int msgnum); 21812891Swpaulint pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type); 21912891Swpaulvoid pci_generate_msi(struct pci_devinst *pi, int msgnum); 22012891Swpaulvoid pci_generate_msix(struct pci_devinst *pi, int msgnum); 22112891Swpaulvoid pci_lintr_assert(struct pci_devinst *pi); 22212891Swpaulvoid pci_lintr_deassert(struct pci_devinst *pi); 22312891Swpaulvoid pci_lintr_request(struct pci_devinst *pi); 22412891Swpaulint pci_msi_enabled(struct pci_devinst *pi); 22533250Swpaulint pci_msix_enabled(struct pci_devinst *pi); 22612891Swpaulint pci_msix_table_bar(struct pci_devinst *pi); 22712891Swpaulint pci_msix_pba_bar(struct pci_devinst *pi); 22812891Swpaulint pci_msi_msgnum(struct pci_devinst *pi); 22912891Swpaulint pci_parse_slot(char *opt); 23020818Swpaulvoid pci_populate_msicap(struct msicap *cap, int msgs, int nextptr); 23112891Swpaulint pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum); 23212891Swpaulint pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size, 23312891Swpaul uint64_t value); 23412891Swpauluint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size); 23512891Swpaulint pci_count_lintr(int bus); 23612891Swpaulvoid pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg); 23712891Swpaulvoid pci_write_dsdt(void); 23812891Swpauluint64_t pci_ecfg_base(void); 23912891Swpaulint pci_bus_configured(int bus); 24014304Swpaul 24114304Swpaulstatic __inline void 24215426Swpaulpci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val) 24319161Swpaul{ 24419161Swpaul assert(offset <= PCI_REGMAX); 24519161Swpaul *(uint8_t *)(pi->pi_cfgdata + offset) = val; 24612891Swpaul} 24719161Swpaul 24812891Swpaulstatic __inline void 24912891Swpaulpci_set_cfgdata16(struct pci_devinst *pi, int offset, uint16_t val) 25012891Swpaul{ 25112891Swpaul assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 25212891Swpaul *(uint16_t *)(pi->pi_cfgdata + offset) = val; 25312891Swpaul} 25412891Swpaul 25512891Swpaulstatic __inline void 25612891Swpaulpci_set_cfgdata32(struct pci_devinst *pi, int offset, uint32_t val) 25720818Swpaul{ 25812891Swpaul assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 25912891Swpaul *(uint32_t *)(pi->pi_cfgdata + offset) = val; 26012891Swpaul} 26112891Swpaul 26220818Swpaulstatic __inline uint8_t 26320818Swpaulpci_get_cfgdata8(struct pci_devinst *pi, int offset) 26412891Swpaul{ 26520818Swpaul assert(offset <= PCI_REGMAX); 26620818Swpaul return (*(uint8_t *)(pi->pi_cfgdata + offset)); 26712891Swpaul} 26812891Swpaul 26912891Swpaulstatic __inline uint16_t 27090298Sdespci_get_cfgdata16(struct pci_devinst *pi, int offset) 27190298Sdes{ 27290298Sdes assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 27312997Swpaul return (*(uint16_t *)(pi->pi_cfgdata + offset)); 27412997Swpaul} 27512997Swpaul 27612997Swpaulstatic __inline uint32_t 27712997Swpaulpci_get_cfgdata32(struct pci_devinst *pi, int offset) 27813375Swpaul{ 27912997Swpaul assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 28013375Swpaul return (*(uint32_t *)(pi->pi_cfgdata + offset)); 28112997Swpaul} 28212997Swpaul 28312997Swpaul#endif /* _PCI_EMUL_H_ */ 28419131Swpaul