pci_emul.c (267341) | pci_emul.c (267393) |
---|---|
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.c 267341 2014-06-10 21:20:37Z jhb $ | 26 * $FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.c 267393 2014-06-12 13:13:15Z jhb $ |
27 */ 28 29#include <sys/cdefs.h> | 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.c 267341 2014-06-10 21:20:37Z jhb $"); | 30__FBSDID("$FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.c 267393 2014-06-12 13:13:15Z jhb $"); |
31 32#include <sys/param.h> 33#include <sys/linker_set.h> 34#include <sys/errno.h> 35 36#include <ctype.h> | 31 32#include <sys/param.h> 33#include <sys/linker_set.h> 34#include <sys/errno.h> 35 36#include <ctype.h> |
37#include <pthread.h> |
|
37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <strings.h> 41#include <assert.h> 42#include <stdbool.h> 43 44#include <machine/vmm.h> 45#include <vmmapi.h> 46 47#include "acpi.h" 48#include "bhyverun.h" 49#include "inout.h" | 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <strings.h> 42#include <assert.h> 43#include <stdbool.h> 44 45#include <machine/vmm.h> 46#include <vmmapi.h> 47 48#include "acpi.h" 49#include "bhyverun.h" 50#include "inout.h" |
50#include "legacy_irq.h" | 51#include "ioapic.h" |
51#include "mem.h" 52#include "pci_emul.h" 53#include "pci_lpc.h" 54 55#define CONF1_ADDR_PORT 0x0cf8 56#define CONF1_DATA_PORT 0x0cfc 57 58#define CONF1_ENABLE 0x80000000ul --- 7 unchanged lines hidden (view full) --- 66 } else { \ 67 pci_set_cfgdata32((pi),(off),(val)); \ 68 } \ 69} while (0) 70 71#define MAXSLOTS (PCI_SLOTMAX + 1) 72#define MAXFUNCS (PCI_FUNCMAX + 1) 73 | 52#include "mem.h" 53#include "pci_emul.h" 54#include "pci_lpc.h" 55 56#define CONF1_ADDR_PORT 0x0cf8 57#define CONF1_DATA_PORT 0x0cfc 58 59#define CONF1_ENABLE 0x80000000ul --- 7 unchanged lines hidden (view full) --- 67 } else { \ 68 pci_set_cfgdata32((pi),(off),(val)); \ 69 } \ 70} while (0) 71 72#define MAXSLOTS (PCI_SLOTMAX + 1) 73#define MAXFUNCS (PCI_FUNCMAX + 1) 74 |
74static struct slotinfo { 75 char *si_name; 76 char *si_param; 77 struct pci_devinst *si_devi; 78} pci_slotinfo[MAXSLOTS][MAXFUNCS]; | 75struct funcinfo { 76 char *fi_name; 77 char *fi_param; 78 struct pci_devinst *fi_devi; 79}; |
79 | 80 |
81struct intxinfo { 82 int ii_count; 83 int ii_ioapic_irq; 84}; 85 86struct slotinfo { 87 struct intxinfo si_intpins[4]; 88 struct funcinfo si_funcs[MAXFUNCS]; 89} pci_slotinfo[MAXSLOTS]; 90 |
|
80SET_DECLARE(pci_devemu_set, struct pci_devemu); 81 82static uint64_t pci_emul_iobase; 83static uint64_t pci_emul_membase32; 84static uint64_t pci_emul_membase64; 85 86#define PCI_EMUL_IOBASE 0x2000 87#define PCI_EMUL_IOLIMIT 0x10000 88 89#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */ 90 91#define PCI_EMUL_MEMBASE64 0xD000000000UL 92#define PCI_EMUL_MEMLIMIT64 0xFD00000000UL 93 94static struct pci_devemu *pci_emul_finddev(char *name); | 91SET_DECLARE(pci_devemu_set, struct pci_devemu); 92 93static uint64_t pci_emul_iobase; 94static uint64_t pci_emul_membase32; 95static uint64_t pci_emul_membase64; 96 97#define PCI_EMUL_IOBASE 0x2000 98#define PCI_EMUL_IOLIMIT 0x10000 99 100#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */ 101 102#define PCI_EMUL_MEMBASE64 0xD000000000UL 103#define PCI_EMUL_MEMLIMIT64 0xFD00000000UL 104 105static struct pci_devemu *pci_emul_finddev(char *name); |
106static void pci_lintr_update(struct pci_devinst *pi); |
|
95 96static int pci_emul_devices; 97static struct mem_range pci_mem_hole; 98 99/* 100 * I/O access 101 */ 102 --- 46 unchanged lines hidden (view full) --- 149 snum = atoi(slot); 150 fnum = func ? atoi(func) : 0; 151 152 if (snum < 0 || snum >= MAXSLOTS || fnum < 0 || fnum >= MAXFUNCS) { 153 pci_parse_slot_usage(opt); 154 goto done; 155 } 156 | 107 108static int pci_emul_devices; 109static struct mem_range pci_mem_hole; 110 111/* 112 * I/O access 113 */ 114 --- 46 unchanged lines hidden (view full) --- 161 snum = atoi(slot); 162 fnum = func ? atoi(func) : 0; 163 164 if (snum < 0 || snum >= MAXSLOTS || fnum < 0 || fnum >= MAXFUNCS) { 165 pci_parse_slot_usage(opt); 166 goto done; 167 } 168 |
157 if (pci_slotinfo[snum][fnum].si_name != NULL) { | 169 if (pci_slotinfo[snum].si_funcs[fnum].fi_name != NULL) { |
158 fprintf(stderr, "pci slot %d:%d already occupied!\n", 159 snum, fnum); 160 goto done; 161 } 162 163 if (pci_emul_finddev(emul) == NULL) { 164 fprintf(stderr, "pci slot %d:%d: unknown device \"%s\"\n", 165 snum, fnum, emul); 166 goto done; 167 } 168 169 error = 0; | 170 fprintf(stderr, "pci slot %d:%d already occupied!\n", 171 snum, fnum); 172 goto done; 173 } 174 175 if (pci_emul_finddev(emul) == NULL) { 176 fprintf(stderr, "pci slot %d:%d: unknown device \"%s\"\n", 177 snum, fnum, emul); 178 goto done; 179 } 180 181 error = 0; |
170 pci_slotinfo[snum][fnum].si_name = emul; 171 pci_slotinfo[snum][fnum].si_param = config; | 182 pci_slotinfo[snum].si_funcs[fnum].fi_name = emul; 183 pci_slotinfo[snum].si_funcs[fnum].fi_param = config; |
172 173done: 174 if (error) 175 free(cpy); 176 177 return (error); 178} 179 --- 481 unchanged lines hidden (view full) --- 661 662 pdi = malloc(sizeof(struct pci_devinst)); 663 bzero(pdi, sizeof(*pdi)); 664 665 pdi->pi_vmctx = ctx; 666 pdi->pi_bus = 0; 667 pdi->pi_slot = slot; 668 pdi->pi_func = func; | 184 185done: 186 if (error) 187 free(cpy); 188 189 return (error); 190} 191 --- 481 unchanged lines hidden (view full) --- 673 674 pdi = malloc(sizeof(struct pci_devinst)); 675 bzero(pdi, sizeof(*pdi)); 676 677 pdi->pi_vmctx = ctx; 678 pdi->pi_bus = 0; 679 pdi->pi_slot = slot; 680 pdi->pi_func = func; |
669 pdi->pi_lintr_pin = -1; | 681 pthread_mutex_init(&pdi->pi_lintr.lock, NULL); 682 pdi->pi_lintr.pin = 0; 683 pdi->pi_lintr.state = IDLE; 684 pdi->pi_lintr.ioapic_irq = 0; |
670 pdi->pi_d = pde; 671 snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); 672 673 /* Disable legacy interrupts */ 674 pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); 675 pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); 676 677 pci_set_cfgdata8(pdi, PCIR_COMMAND, 678 PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 679 680 err = (*pde->pe_init)(ctx, pdi, params); 681 if (err != 0) { 682 free(pdi); 683 } else { 684 pci_emul_devices++; | 685 pdi->pi_d = pde; 686 snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); 687 688 /* Disable legacy interrupts */ 689 pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); 690 pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); 691 692 pci_set_cfgdata8(pdi, PCIR_COMMAND, 693 PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 694 695 err = (*pde->pe_init)(ctx, pdi, params); 696 if (err != 0) { 697 free(pdi); 698 } else { 699 pci_emul_devices++; |
685 pci_slotinfo[slot][func].si_devi = pdi; | 700 pci_slotinfo[slot].si_funcs[func].fi_devi = pdi; |
686 } 687 688 return (err); 689} 690 691void 692pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr) 693{ --- 117 unchanged lines hidden (view full) --- 811 rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK; 812 msgctrl = pci_get_cfgdata16(pi, offset); 813 msgctrl &= ~rwmask; 814 msgctrl |= val & rwmask; 815 val = msgctrl; 816 817 pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE; 818 pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK; | 701 } 702 703 return (err); 704} 705 706void 707pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr) 708{ --- 117 unchanged lines hidden (view full) --- 826 rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK; 827 msgctrl = pci_get_cfgdata16(pi, offset); 828 msgctrl &= ~rwmask; 829 msgctrl |= val & rwmask; 830 val = msgctrl; 831 832 pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE; 833 pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK; |
834 pci_lintr_update(pi); |
|
819 } 820 821 CFGWRITE(pi, offset, val, bytes); 822} 823 824void 825msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 826 int bytes, uint32_t val) --- 22 unchanged lines hidden (view full) --- 849 pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0; 850 if (pi->pi_msi.enabled) { 851 pi->pi_msi.addr = addrlo; 852 pi->pi_msi.msg_data = msgdata; 853 pi->pi_msi.maxmsgnum = 1 << (mme >> 4); 854 } else { 855 pi->pi_msi.maxmsgnum = 0; 856 } | 835 } 836 837 CFGWRITE(pi, offset, val, bytes); 838} 839 840void 841msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 842 int bytes, uint32_t val) --- 22 unchanged lines hidden (view full) --- 865 pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0; 866 if (pi->pi_msi.enabled) { 867 pi->pi_msi.addr = addrlo; 868 pi->pi_msi.msg_data = msgdata; 869 pi->pi_msi.maxmsgnum = 1 << (mme >> 4); 870 } else { 871 pi->pi_msi.maxmsgnum = 0; 872 } |
873 pci_lintr_update(pi); |
|
857 } 858 859 CFGWRITE(pi, offset, val, bytes); 860} 861 862void 863pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 864 int bytes, uint32_t val) --- 123 unchanged lines hidden (view full) --- 988 989 return (0); 990} 991 992int 993init_pci(struct vmctx *ctx) 994{ 995 struct pci_devemu *pde; | 874 } 875 876 CFGWRITE(pi, offset, val, bytes); 877} 878 879void 880pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 881 int bytes, uint32_t val) --- 123 unchanged lines hidden (view full) --- 1005 1006 return (0); 1007} 1008 1009int 1010init_pci(struct vmctx *ctx) 1011{ 1012 struct pci_devemu *pde; |
996 struct slotinfo *si; | 1013 struct funcinfo *fi; |
997 size_t lowmem; 998 int slot, func; 999 int error; 1000 1001 pci_emul_iobase = PCI_EMUL_IOBASE; 1002 pci_emul_membase32 = vm_get_lowmem_limit(ctx); 1003 pci_emul_membase64 = PCI_EMUL_MEMBASE64; 1004 1005 for (slot = 0; slot < MAXSLOTS; slot++) { 1006 for (func = 0; func < MAXFUNCS; func++) { | 1014 size_t lowmem; 1015 int slot, func; 1016 int error; 1017 1018 pci_emul_iobase = PCI_EMUL_IOBASE; 1019 pci_emul_membase32 = vm_get_lowmem_limit(ctx); 1020 pci_emul_membase64 = PCI_EMUL_MEMBASE64; 1021 1022 for (slot = 0; slot < MAXSLOTS; slot++) { 1023 for (func = 0; func < MAXFUNCS; func++) { |
1007 si = &pci_slotinfo[slot][func]; 1008 if (si->si_name != NULL) { 1009 pde = pci_emul_finddev(si->si_name); | 1024 fi = &pci_slotinfo[slot].si_funcs[func]; 1025 if (fi->fi_name != NULL) { 1026 pde = pci_emul_finddev(fi->fi_name); |
1010 assert(pde != NULL); 1011 error = pci_emul_init(ctx, pde, slot, func, | 1027 assert(pde != NULL); 1028 error = pci_emul_init(ctx, pde, slot, func, |
1012 si->si_param); | 1029 fi->fi_param); |
1013 if (error) 1014 return (error); 1015 } 1016 } 1017 } 1018 1019 /* 1020 * The guest physical memory map looks like the following: --- 16 unchanged lines hidden (view full) --- 1037 pci_mem_hole.handler = pci_emul_fallback_handler; 1038 1039 error = register_mem_fallback(&pci_mem_hole); 1040 assert(error == 0); 1041 1042 return (0); 1043} 1044 | 1030 if (error) 1031 return (error); 1032 } 1033 } 1034 } 1035 1036 /* 1037 * The guest physical memory map looks like the following: --- 16 unchanged lines hidden (view full) --- 1054 pci_mem_hole.handler = pci_emul_fallback_handler; 1055 1056 error = register_mem_fallback(&pci_mem_hole); 1057 assert(error == 0); 1058 1059 return (0); 1060} 1061 |
1062static void 1063pci_prt_entry(int slot, int pin, int ioapic_irq, void *arg) 1064{ 1065 int *count; 1066 1067 count = arg; 1068 dsdt_line(" Package (0x04)"); 1069 dsdt_line(" {"); 1070 dsdt_line(" 0x%X,", slot << 16 | 0xffff); 1071 dsdt_line(" 0x%02X,", pin - 1); 1072 dsdt_line(" Zero,"); 1073 dsdt_line(" 0x%X", ioapic_irq); 1074 dsdt_line(" }%s", *count == 1 ? "" : ","); 1075 (*count)--; 1076} 1077 |
|
1045void 1046pci_write_dsdt(void) 1047{ 1048 struct pci_devinst *pi; | 1078void 1079pci_write_dsdt(void) 1080{ 1081 struct pci_devinst *pi; |
1049 int slot, func; | 1082 int count, slot, func; |
1050 1051 dsdt_indent(1); 1052 dsdt_line("Scope (_SB)"); 1053 dsdt_line("{"); 1054 dsdt_line(" Device (PCI0)"); 1055 dsdt_line(" {"); 1056 dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))"); 1057 dsdt_line(" Name (_ADR, Zero)"); --- 44 unchanged lines hidden (view full) --- 1102 PCI_EMUL_MEMBASE64); 1103 dsdt_line(" 0x%016lX, // Range Maximum\n", 1104 PCI_EMUL_MEMLIMIT64 - 1); 1105 dsdt_line(" 0x0000000000000000, // Translation Offset"); 1106 dsdt_line(" 0x%016lX, // Length\n", 1107 PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64); 1108 dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); 1109 dsdt_line(" })"); | 1083 1084 dsdt_indent(1); 1085 dsdt_line("Scope (_SB)"); 1086 dsdt_line("{"); 1087 dsdt_line(" Device (PCI0)"); 1088 dsdt_line(" {"); 1089 dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))"); 1090 dsdt_line(" Name (_ADR, Zero)"); --- 44 unchanged lines hidden (view full) --- 1135 PCI_EMUL_MEMBASE64); 1136 dsdt_line(" 0x%016lX, // Range Maximum\n", 1137 PCI_EMUL_MEMLIMIT64 - 1); 1138 dsdt_line(" 0x0000000000000000, // Translation Offset"); 1139 dsdt_line(" 0x%016lX, // Length\n", 1140 PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64); 1141 dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); 1142 dsdt_line(" })"); |
1143 count = pci_count_lintr(); 1144 if (count != 0) { 1145 dsdt_indent(2); 1146 dsdt_line("Name (_PRT, Package (0x%02X)", count); 1147 dsdt_line("{"); 1148 pci_walk_lintr(pci_prt_entry, &count); 1149 dsdt_line("})"); 1150 dsdt_unindent(2); 1151 } |
|
1110 1111 dsdt_indent(2); 1112 for (slot = 0; slot < MAXSLOTS; slot++) { 1113 for (func = 0; func < MAXFUNCS; func++) { | 1152 1153 dsdt_indent(2); 1154 for (slot = 0; slot < MAXSLOTS; slot++) { 1155 for (func = 0; func < MAXFUNCS; func++) { |
1114 pi = pci_slotinfo[slot][func].si_devi; | 1156 pi = pci_slotinfo[slot].si_funcs[func].fi_devi; |
1115 if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL) 1116 pi->pi_d->pe_write_dsdt(pi); 1117 } 1118 } 1119 dsdt_unindent(2); 1120 1121 dsdt_line(" }"); 1122 dsdt_line("}"); --- 48 unchanged lines hidden (view full) --- 1171{ 1172 1173 if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) { 1174 vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr, 1175 pi->pi_msi.msg_data + index); 1176 } 1177} 1178 | 1157 if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL) 1158 pi->pi_d->pe_write_dsdt(pi); 1159 } 1160 } 1161 dsdt_unindent(2); 1162 1163 dsdt_line(" }"); 1164 dsdt_line("}"); --- 48 unchanged lines hidden (view full) --- 1213{ 1214 1215 if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) { 1216 vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr, 1217 pi->pi_msi.msg_data + index); 1218 } 1219} 1220 |
1221static bool 1222pci_lintr_permitted(struct pci_devinst *pi) 1223{ 1224 uint16_t cmd; 1225 1226 cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); 1227 return (!(pi->pi_msi.enabled || pi->pi_msix.enabled || 1228 (cmd & PCIM_CMD_INTxDIS))); 1229} 1230 |
|
1179int | 1231int |
1180pci_lintr_request(struct pci_devinst *pi, int req) | 1232pci_lintr_request(struct pci_devinst *pi) |
1181{ | 1233{ |
1182 int irq; | 1234 struct slotinfo *si; 1235 int bestpin, bestcount, irq, pin; |
1183 | 1236 |
1184 irq = legacy_irq_alloc(req); 1185 if (irq < 0) 1186 return (-1); | 1237 /* 1238 * First, allocate a pin from our slot. 1239 */ 1240 si = &pci_slotinfo[pi->pi_slot]; 1241 bestpin = 0; 1242 bestcount = si->si_intpins[0].ii_count; 1243 for (pin = 1; pin < 4; pin++) { 1244 if (si->si_intpins[pin].ii_count < bestcount) { 1245 bestpin = pin; 1246 bestcount = si->si_intpins[pin].ii_count; 1247 } 1248 } |
1187 | 1249 |
1188 pi->pi_lintr_pin = irq; | 1250 /* 1251 * Attempt to allocate an I/O APIC pin for this intpin. If 1252 * 8259A support is added we will need a separate field to 1253 * assign the intpin to an input pin on the PCI interrupt 1254 * router. 1255 */ 1256 if (si->si_intpins[bestpin].ii_count == 0) { 1257 irq = ioapic_pci_alloc_irq(); 1258 if (irq < 0) 1259 return (-1); 1260 si->si_intpins[bestpin].ii_ioapic_irq = irq; 1261 } else 1262 irq = si->si_intpins[bestpin].ii_ioapic_irq; 1263 si->si_intpins[bestpin].ii_count++; 1264 1265 pi->pi_lintr.pin = bestpin + 1; 1266 pi->pi_lintr.ioapic_irq = irq; |
1189 pci_set_cfgdata8(pi, PCIR_INTLINE, irq); | 1267 pci_set_cfgdata8(pi, PCIR_INTLINE, irq); |
1190 pci_set_cfgdata8(pi, PCIR_INTPIN, 1); | 1268 pci_set_cfgdata8(pi, PCIR_INTPIN, bestpin + 1); |
1191 return (0); 1192} 1193 1194void 1195pci_lintr_assert(struct pci_devinst *pi) 1196{ 1197 | 1269 return (0); 1270} 1271 1272void 1273pci_lintr_assert(struct pci_devinst *pi) 1274{ 1275 |
1198 assert(pi->pi_lintr_pin >= 0); | 1276 assert(pi->pi_lintr.pin > 0); |
1199 | 1277 |
1200 if (pi->pi_lintr_state == 0) { 1201 pi->pi_lintr_state = 1; 1202 vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr_pin); | 1278 pthread_mutex_lock(&pi->pi_lintr.lock); 1279 if (pi->pi_lintr.state == IDLE) { 1280 if (pci_lintr_permitted(pi)) { 1281 pi->pi_lintr.state = ASSERTED; 1282 vm_ioapic_assert_irq(pi->pi_vmctx, 1283 pi->pi_lintr.ioapic_irq); 1284 } else 1285 pi->pi_lintr.state = PENDING; |
1203 } | 1286 } |
1287 pthread_mutex_unlock(&pi->pi_lintr.lock); |
|
1204} 1205 1206void 1207pci_lintr_deassert(struct pci_devinst *pi) 1208{ 1209 | 1288} 1289 1290void 1291pci_lintr_deassert(struct pci_devinst *pi) 1292{ 1293 |
1210 assert(pi->pi_lintr_pin >= 0); | 1294 assert(pi->pi_lintr.pin > 0); |
1211 | 1295 |
1212 if (pi->pi_lintr_state == 1) { 1213 pi->pi_lintr_state = 0; 1214 vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr_pin); | 1296 pthread_mutex_lock(&pi->pi_lintr.lock); 1297 if (pi->pi_lintr.state == ASSERTED) { 1298 pi->pi_lintr.state = IDLE; 1299 vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq); 1300 } else if (pi->pi_lintr.state == PENDING) 1301 pi->pi_lintr.state = IDLE; 1302 pthread_mutex_unlock(&pi->pi_lintr.lock); 1303} 1304 1305static void 1306pci_lintr_update(struct pci_devinst *pi) 1307{ 1308 1309 pthread_mutex_lock(&pi->pi_lintr.lock); 1310 if (pi->pi_lintr.state == ASSERTED && !pci_lintr_permitted(pi)) { 1311 vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq); 1312 pi->pi_lintr.state = PENDING; 1313 } else if (pi->pi_lintr.state == PENDING && pci_lintr_permitted(pi)) { 1314 pi->pi_lintr.state = ASSERTED; 1315 vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq); |
1215 } | 1316 } |
1317 pthread_mutex_unlock(&pi->pi_lintr.lock); |
|
1216} 1217 | 1318} 1319 |
1320int 1321pci_count_lintr(void) 1322{ 1323 int count, slot, pin; 1324 1325 count = 0; 1326 for (slot = 0; slot < MAXSLOTS; slot++) { 1327 for (pin = 0; pin < 4; pin++) { 1328 if (pci_slotinfo[slot].si_intpins[pin].ii_count != 0) 1329 count++; 1330 } 1331 } 1332 return (count); 1333} 1334 1335void 1336pci_walk_lintr(pci_lintr_cb cb, void *arg) 1337{ 1338 struct intxinfo *ii; 1339 int slot, pin; 1340 1341 for (slot = 0; slot < MAXSLOTS; slot++) { 1342 for (pin = 0; pin < 4; pin++) { 1343 ii = &pci_slotinfo[slot].si_intpins[pin]; 1344 if (ii->ii_count != 0) 1345 cb(slot, pin + 1, ii->ii_ioapic_irq, arg); 1346 } 1347 } 1348} 1349 |
|
1218/* 1219 * Return 1 if the emulated device in 'slot' is a multi-function device. 1220 * Return 0 otherwise. 1221 */ 1222static int 1223pci_emul_is_mfdev(int slot) 1224{ 1225 int f, numfuncs; 1226 1227 numfuncs = 0; 1228 for (f = 0; f < MAXFUNCS; f++) { | 1350/* 1351 * Return 1 if the emulated device in 'slot' is a multi-function device. 1352 * Return 0 otherwise. 1353 */ 1354static int 1355pci_emul_is_mfdev(int slot) 1356{ 1357 int f, numfuncs; 1358 1359 numfuncs = 0; 1360 for (f = 0; f < MAXFUNCS; f++) { |
1229 if (pci_slotinfo[slot][f].si_devi != NULL) { | 1361 if (pci_slotinfo[slot].si_funcs[f].fi_devi != NULL) { |
1230 numfuncs++; 1231 } 1232 } 1233 return (numfuncs > 1); 1234} 1235 1236/* 1237 * Ensure that the PCIM_MFDEV bit is properly set (or unset) depending on --- 105 unchanged lines hidden (view full) --- 1343 else 1344 unregister_bar(pi, i); 1345 } 1346 break; 1347 default: 1348 assert(0); 1349 } 1350 } | 1362 numfuncs++; 1363 } 1364 } 1365 return (numfuncs > 1); 1366} 1367 1368/* 1369 * Ensure that the PCIM_MFDEV bit is properly set (or unset) depending on --- 105 unchanged lines hidden (view full) --- 1475 else 1476 unregister_bar(pi, i); 1477 } 1478 break; 1479 default: 1480 assert(0); 1481 } 1482 } |
1483 1484 /* 1485 * If INTx has been unmasked and is pending, assert the 1486 * interrupt. 1487 */ 1488 pci_lintr_update(pi); |
|
1351} 1352 1353static int 1354pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 1355 uint32_t *eax, void *arg) 1356{ 1357 struct pci_devinst *pi; 1358 struct pci_devemu *pe; 1359 int coff, idx, needcfg; 1360 uint64_t addr, bar, mask; 1361 1362 assert(bytes == 1 || bytes == 2 || bytes == 4); 1363 1364 if (cfgbus == 0) | 1489} 1490 1491static int 1492pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 1493 uint32_t *eax, void *arg) 1494{ 1495 struct pci_devinst *pi; 1496 struct pci_devemu *pe; 1497 int coff, idx, needcfg; 1498 uint64_t addr, bar, mask; 1499 1500 assert(bytes == 1 || bytes == 2 || bytes == 4); 1501 1502 if (cfgbus == 0) |
1365 pi = pci_slotinfo[cfgslot][cfgfunc].si_devi; | 1503 pi = pci_slotinfo[cfgslot].si_funcs[cfgfunc].fi_devi; |
1366 else 1367 pi = NULL; 1368 1369 coff = cfgoff + (port - CONF1_DATA_PORT); 1370 1371#if 0 1372 printf("pcicfg-%s from 0x%0x of %d bytes (%d/%d/%d)\n\r", 1373 in ? "read" : "write", coff, bytes, cfgbus, cfgslot, cfgfunc); --- 302 unchanged lines hidden --- | 1504 else 1505 pi = NULL; 1506 1507 coff = cfgoff + (port - CONF1_DATA_PORT); 1508 1509#if 0 1510 printf("pcicfg-%s from 0x%0x of %d bytes (%d/%d/%d)\n\r", 1511 in ? "read" : "write", coff, bytes, cfgbus, cfgslot, cfgfunc); --- 302 unchanged lines hidden --- |