Deleted Added
full compact
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 ---