VirtualBox

source: vbox/trunk/src/VBox/Devices/Bus/DevPciIch9.cpp@ 71155

Last change on this file since 71155 was 71155, checked in by vboxsync, 7 years ago

Devices/Bus/ICH9: Don't meddle with the IRQ value when traversing bridges if the originating device has MSI/MSI-X enabled. The IRQ has a completely different meaning here (the MSI/MSI-X vector to use) and is not subject to the pin routing for bridges. MSI/MSI-X interrupt handling code paths should really be separated properly to avoid such confusing issues but for a safe backport this is the immediate fix for now

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 147.1 KB
Line 
1/* $Id: DevPciIch9.cpp 71155 2018-02-28 14:56:07Z vboxsync $ */
2/** @file
3 * DevPCI - ICH9 southbridge PCI bus emulation device.
4 *
5 * @remarks We'll be slowly promoting the code in this file to common PCI bus
6 * code. Function without 'static' and using 'devpci' as prefix is
7 * also used by DevPCI.cpp and have a prototype in DevPciInternal.h.
8 *
9 * For the time being the DevPciMerge1.cpp.h file will remain separate,
10 * due to 5.1. We can merge it into this one later in the dev cycle.
11 *
12 * DO NOT use the PDMPciDev* or PCIDev* family of functions in this
13 * file except in the two callbacks for config space access (and the
14 * functions which are used exclusively by that code) and the two
15 * device constructors when setting up the config space for the
16 * bridges. Everything else need extremely careful review. Using
17 * them elsewhere (especially in the init code) causes weird failures
18 * with PCI passthrough, as it would only update the array of
19 * (emulated) config space, but not talk to the actual device (needs
20 * invoking the respective callback).
21 */
22
23/*
24 * Copyright (C) 2010-2017 Oracle Corporation
25 *
26 * This file is part of VirtualBox Open Source Edition (OSE), as
27 * available from http://www.virtualbox.org. This file is free software;
28 * you can redistribute it and/or modify it under the terms of the GNU
29 * General Public License (GPL) as published by the Free Software
30 * Foundation, in version 2 as it comes in the "COPYING" file of the
31 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
32 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
33 */
34
35
36/*********************************************************************************************************************************
37* Header Files *
38*********************************************************************************************************************************/
39#define LOG_GROUP LOG_GROUP_DEV_PCI
40#define PDMPCIDEV_INCLUDE_PRIVATE /* Hack to get pdmpcidevint.h included at the right point. */
41#include <VBox/vmm/pdmpcidev.h>
42
43#include <VBox/msi.h>
44#include <VBox/vmm/pdmdev.h>
45#include <VBox/vmm/mm.h>
46#include <iprt/asm.h>
47#include <iprt/assert.h>
48#include <iprt/string.h>
49#ifdef IN_RING3
50# include <iprt/mem.h>
51# include <iprt/uuid.h>
52#endif
53
54#include "PciInline.h"
55#include "VBoxDD.h"
56#include "MsiCommon.h"
57#include "DevPciInternal.h"
58
59
60/*********************************************************************************************************************************
61* Structures and Typedefs *
62*********************************************************************************************************************************/
63/**
64 * PCI configuration space address.
65 */
66typedef struct
67{
68 uint8_t iBus;
69 uint8_t iDeviceFunc;
70 uint16_t iRegister;
71} PciAddress;
72
73
74/*********************************************************************************************************************************
75* Defined Constants And Macros *
76*********************************************************************************************************************************/
77/** Saved state version of the ICH9 PCI bus device. */
78#define VBOX_ICH9PCI_SAVED_STATE_VERSION VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES
79/** Adds I/O region types and sizes for dealing changes in resource regions. */
80#define VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES 3
81/** This appears to be the first state we need to care about. */
82#define VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI 2
83/** This is apparently not supported or has a grossly incomplete state, juding
84 * from hints in the code. */
85#define VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI 1
86
87/** Invalid PCI region mapping address. */
88#define INVALID_PCI_ADDRESS UINT32_MAX
89
90
91/*********************************************************************************************************************************
92* Internal Functions *
93*********************************************************************************************************************************/
94/* Prototypes */
95static void ich9pciSetIrqInternal(PDEVPCIROOT pPciRoot, uint8_t uDevFn, PPDMPCIDEV pPciDev,
96 int iIrq, int iLevel, uint32_t uTagSrc);
97#ifdef IN_RING3
98static int ich9pciFakePCIBIOS(PPDMDEVINS pDevIns);
99DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PDEVPCIBUS pBus, uint8_t uBus);
100static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus);
101static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, bool fUse64Bit, bool fDryrun);
102#endif
103
104
105// See 7.2.2. PCI Express Enhanced Configuration Mechanism for details of address
106// mapping, we take n=6 approach
107DECLINLINE(void) ich9pciPhysToPciAddr(PDEVPCIROOT pPciRoot, RTGCPHYS GCPhysAddr, PciAddress* pPciAddr)
108{
109 NOREF(pPciRoot);
110 pPciAddr->iBus = (GCPhysAddr >> 20) & ((1<<6) - 1);
111 pPciAddr->iDeviceFunc = (GCPhysAddr >> 12) & ((1<<(5+3)) - 1); // 5 bits - device, 3 bits - function
112 pPciAddr->iRegister = (GCPhysAddr >> 0) & ((1<<(6+4+2)) - 1); // 6 bits - register, 4 bits - extended register, 2 bits -Byte Enable
113}
114
115DECLINLINE(void) ich9pciStateToPciAddr(PDEVPCIROOT pPciRoot, RTGCPHYS addr, PciAddress* pPciAddr)
116{
117 pPciAddr->iBus = (pPciRoot->uConfigReg >> 16) & 0xff;
118 pPciAddr->iDeviceFunc = (pPciRoot->uConfigReg >> 8) & 0xff;
119 pPciAddr->iRegister = (pPciRoot->uConfigReg & 0xfc) | (addr & 3);
120}
121
122PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc)
123{
124 LogFlowFunc(("invoked by %p/%d: iIrq=%d iLevel=%d uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, iIrq, iLevel, uTagSrc));
125 ich9pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PDEVPCIROOT), pPciDev->uDevFn, pPciDev, iIrq, iLevel, uTagSrc);
126}
127
128PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc)
129{
130 /*
131 * The PCI-to-PCI bridge specification defines how the interrupt pins
132 * are routed from the secondary to the primary bus (see chapter 9).
133 * iIrq gives the interrupt pin the pci device asserted.
134 * We change iIrq here according to the spec and call the SetIrq function
135 * of our parent passing the device which asserted the interrupt instead of the device of the bridge.
136 */
137 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
138 PPDMPCIDEV pPciDevBus = pPciDev;
139 int iIrqPinBridge = iIrq;
140 uint8_t uDevFnBridge = 0;
141
142 /* Walk the chain until we reach the host bus. */
143 do
144 {
145 uDevFnBridge = pBus->PciDev.uDevFn;
146 iIrqPinBridge = ((pPciDevBus->uDevFn >> 3) + iIrqPinBridge) & 3;
147
148 /* Get the parent. */
149 pBus = pBus->PciDev.Int.s.CTX_SUFF(pBus);
150 pPciDevBus = &pBus->PciDev;
151 } while (pBus->iBus != 0);
152
153 AssertMsgReturnVoid(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus));
154
155 /*
156 * For MSI/MSI-X enabled devices the iIrq doesn't denote the pin but rather a vector which is completely
157 * orthogonal to the pin based approach. The vector is not subject to the pin based routing with PCI bridges.
158 */
159 int iIrqPinVector = iIrqPinBridge;
160 if ( MsiIsEnabled(pPciDev)
161 || MsixIsEnabled(pPciDev))
162 iIrqPinVector = iIrq;
163 ich9pciSetIrqInternal(DEVPCIBUS_2_DEVPCIROOT(pBus), uDevFnBridge, pPciDev, iIrqPinVector, iLevel, uTagSrc);
164}
165
166
167#ifdef IN_RING3
168
169/**
170 * Port I/O Handler for Fake PCI BIOS trigger OUT operations at 0410h
171 *
172 * @returns VBox status code.
173 *
174 * @param pDevIns ICH9 device instance.
175 * @param pvUser User argument - ignored.
176 * @param uPort Port number used for the OUT operation.
177 * @param u32 The value to output.
178 * @param cb The value size in bytes.
179 */
180DECLCALLBACK(int) ich9pciR3IOPortMagicPCIWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
181{
182 RT_NOREF2(pvUser, uPort);
183 LogFlowFunc(("Port=%#x u32=%#x cb=%d\n", uPort, u32, cb));
184 if (cb == 4)
185 {
186 if (u32 == UINT32_C(19200509)) // Richard Adams
187 {
188 int rc = ich9pciFakePCIBIOS(pDevIns);
189 AssertRC(rc);
190 }
191 }
192
193 return VINF_SUCCESS;
194}
195
196
197/**
198 * Port I/O Handler for Fake PCI BIOS trigger IN operations at 0410h
199 *
200 * @returns VBox status code.
201 *
202 * @param pDevIns ICH9 device instance.
203 * @param pvUser User argument - ignored.
204 * @param uPort Port number used for the IN operation.
205 * @param pu32 Where to store the result.
206 * @param cb Number of bytes read.
207 */
208DECLCALLBACK(int) ich9pciR3IOPortMagicPCIRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
209{
210 RT_NOREF5(pDevIns, pvUser, uPort, pu32, cb);
211 LogFunc(("Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", uPort, cb));
212 return VERR_IOM_IOPORT_UNUSED;
213}
214
215#endif /* IN_RING3 */
216
217
218/**
219 * Port I/O Handler for PCI address OUT operations.
220 *
221 * Emulates writes to Configuration Address Port at 0CF8h for
222 * Configuration Mechanism #1.
223 *
224 * @returns VBox status code.
225 *
226 * @param pDevIns ICH9 device instance.
227 * @param pvUser User argument - ignored.
228 * @param uPort Port number used for the OUT operation.
229 * @param u32 The value to output.
230 * @param cb The value size in bytes.
231 */
232PDMBOTHCBDECL(int) ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
233{
234 LogFlowFunc(("Port=%#x u32=%#x cb=%d\n", uPort, u32, cb));
235 RT_NOREF2(uPort, pvUser);
236 if (cb == 4)
237 {
238 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
239
240 /*
241 * bits [1:0] are hard-wired, read-only and must return zeroes
242 * when read.
243 */
244 u32 &= ~3;
245
246 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_WRITE);
247 pThis->uConfigReg = u32;
248 PCI_UNLOCK(pDevIns);
249 }
250
251 return VINF_SUCCESS;
252}
253
254
255/**
256 * Port I/O Handler for PCI address IN operations.
257 *
258 * Emulates reads from Configuration Address Port at 0CF8h for
259 * Configuration Mechanism #1.
260 *
261 * @returns VBox status code.
262 *
263 * @param pDevIns ICH9 device instance.
264 * @param pvUser User argument - ignored.
265 * @param uPort Port number used for the IN operation.
266 * @param pu32 Where to store the result.
267 * @param cb Number of bytes read.
268 */
269PDMBOTHCBDECL(int) ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
270{
271 RT_NOREF2(uPort, pvUser);
272 if (cb == 4)
273 {
274 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
275
276 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_READ);
277 *pu32 = pThis->uConfigReg;
278 PCI_UNLOCK(pDevIns);
279
280 LogFlowFunc(("Port=%#x cb=%d -> %#x\n", uPort, cb, *pu32));
281 return VINF_SUCCESS;
282 }
283
284 LogFunc(("Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", uPort, cb));
285 return VERR_IOM_IOPORT_UNUSED;
286}
287
288
289/*
290 * Perform configuration space write.
291 */
292static int ich9pciConfigWrite(PDEVPCIROOT pPciRoot, PciAddress* pAddr,
293 uint32_t val, int cb, int rcReschedule)
294{
295 int rc = VINF_SUCCESS;
296#ifdef IN_RING3
297 NOREF(rcReschedule);
298#else
299 RT_NOREF2(val, cb);
300#endif
301
302 if (pAddr->iBus != 0) /* forward to subordinate bus */
303 {
304 if (pPciRoot->PciBus.cBridges)
305 {
306#ifdef IN_RING3 /** @todo do lookup in R0/RC too! r=klaus don't think that it can work, since the config space access callback only works in R3 */
307 PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(&pPciRoot->PciBus, pAddr->iBus);
308 if (pBridgeDevice)
309 {
310 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
311 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->Int.s.CTX_SUFF(pDevIns), pAddr->iBus, pAddr->iDeviceFunc,
312 pAddr->iRegister, val, cb);
313 }
314#else
315 rc = rcReschedule;
316#endif
317 }
318 }
319 else /* forward to directly connected device */
320 {
321 R3PTRTYPE(PDMPCIDEV *) pPciDev = pPciRoot->PciBus.apDevices[pAddr->iDeviceFunc];
322 if (pPciDev)
323 {
324#ifdef IN_RING3
325 rc = VBOXSTRICTRC_TODO(pPciDev->Int.s.pfnConfigWrite(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev,
326 pAddr->iRegister, val, cb));
327#else
328 rc = rcReschedule;
329#endif
330 }
331 }
332
333 Log2Func(("%02x:%02x.%d reg %x(%d) %x %Rrc\n",
334 pAddr->iBus, pAddr->iDeviceFunc >> 3, pAddr->iDeviceFunc & 0x7, pAddr->iRegister, cb, val, rc));
335 return rc;
336}
337
338
339/**
340 * Port I/O Handler for PCI data OUT operations.
341 *
342 * Emulates writes to Configuration Data Port at 0CFCh for
343 * Configuration Mechanism #1.
344 *
345 * @returns VBox status code.
346 *
347 * @param pDevIns ICH9 device instance.
348 * @param pvUser User argument - ignored.
349 * @param uPort Port number used for the OUT operation.
350 * @param u32 The value to output.
351 * @param cb The value size in bytes.
352 */
353PDMBOTHCBDECL(int) ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
354{
355 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
356 LogFlowFunc(("Port=%#x u32=%#x cb=%d (config=%#10x)\n", uPort, u32, cb, pThis->uConfigReg));
357 NOREF(pvUser);
358 int rc = VINF_SUCCESS;
359 if (!(uPort % cb))
360 {
361 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_WRITE);
362
363 do
364 {
365 /* Configuration space mapping enabled? */
366 if (!(pThis->uConfigReg & (1 << 31)))
367 break;
368
369 /* Decode target device from Configuration Address Port */
370 PciAddress aPciAddr;
371 ich9pciStateToPciAddr(pThis, uPort, &aPciAddr);
372
373 /* Perform configuration space write */
374 rc = ich9pciConfigWrite(pThis, &aPciAddr, u32, cb, VINF_IOM_R3_IOPORT_WRITE);
375 } while (0);
376
377 PCI_UNLOCK(pDevIns);
378 }
379 else
380 AssertMsgFailed(("Unaligned write to port %#x u32=%#x cb=%d\n", uPort, u32, cb));
381 return rc;
382}
383
384
385/*
386 * Perform configuration space read.
387 */
388static int ich9pciConfigRead(PDEVPCIROOT pPciRoot, PciAddress* pPciAddr, int cb,
389 uint32_t *pu32, int rcReschedule)
390{
391 int rc = VINF_SUCCESS;
392#ifdef IN_RING3
393 NOREF(rcReschedule);
394#else
395 NOREF(cb);
396#endif
397
398 if (pPciAddr->iBus != 0) /* forward to subordinate bus */
399 {
400 if (pPciRoot->PciBus.cBridges)
401 {
402#ifdef IN_RING3 /** @todo do lookup in R0/RC too! r=klaus don't think that it can work, since the config space access callback only works in R3 */
403 PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(&pPciRoot->PciBus, pPciAddr->iBus);
404 if (pBridgeDevice)
405 {
406 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
407 *pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->Int.s.CTX_SUFF(pDevIns), pPciAddr->iBus,
408 pPciAddr->iDeviceFunc, pPciAddr->iRegister, cb);
409 }
410 else
411 *pu32 = 0xffffffff;
412#else
413 rc = rcReschedule;
414#endif
415 }
416 else
417 *pu32 = 0xffffffff;
418 }
419 else /* forward to directly connected device */
420 {
421 R3PTRTYPE(PDMPCIDEV *) pPciDev = pPciRoot->PciBus.apDevices[pPciAddr->iDeviceFunc];
422 if (pPciDev)
423 {
424#ifdef IN_RING3
425 *pu32 = pPciDev->Int.s.pfnConfigRead(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, pPciAddr->iRegister, cb);
426#else
427 rc = rcReschedule;
428#endif
429 }
430 else
431 *pu32 = 0xffffffff;
432 }
433
434 Log3Func(("%02x:%02x.%d reg %x(%d) gave %x %Rrc\n",
435 pPciAddr->iBus, pPciAddr->iDeviceFunc >> 3, pPciAddr->iDeviceFunc & 0x7, pPciAddr->iRegister, cb, *pu32, rc));
436 return rc;
437}
438
439
440/**
441 * Port I/O Handler for PCI data IN operations.
442 *
443 * Emulates reads from Configuration Data Port at 0CFCh for
444 * Configuration Mechanism #1.
445 *
446 * @returns VBox status code.
447 *
448 * @param pDevIns ICH9 device instance.
449 * @param pvUser User argument - ignored.
450 * @param uPort Port number used for the IN operation.
451 * @param pu32 Where to store the result.
452 * @param cb Number of bytes read.
453 */
454PDMBOTHCBDECL(int) ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
455{
456 NOREF(pvUser);
457 int rc = VINF_SUCCESS;
458 if (!(uPort % cb))
459 {
460 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
461 *pu32 = 0xffffffff;
462
463 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_READ);
464
465 do
466 {
467 /* Configuration space mapping enabled? */
468 if (!(pThis->uConfigReg & (1 << 31)))
469 {
470 rc = VINF_SUCCESS;
471 break;
472 }
473
474 /* Decode target device and configuration space register */
475 PciAddress aPciAddr;
476 ich9pciStateToPciAddr(pThis, uPort, &aPciAddr);
477
478 /* Perform configuration space read */
479 rc = ich9pciConfigRead(pThis, &aPciAddr, cb, pu32, VINF_IOM_R3_IOPORT_READ);
480 } while (0);
481
482 PCI_UNLOCK(pDevIns);
483
484 LogFlowFunc(("Port=%#x cb=%#x (config=%#10x) -> %#x (%Rrc)\n", uPort, cb, *pu32, pThis->uConfigReg, rc));
485 return rc;
486 }
487 AssertMsgFailed(("Unaligned read from port %#x cb=%d\n", uPort, cb));
488 return VERR_IOM_IOPORT_UNUSED;
489}
490
491
492/* Compute mapping of PCI slot and IRQ number to APIC interrupt line */
493DECLINLINE(int) ich9pciSlot2ApicIrq(uint8_t uSlot, int irq_num)
494{
495 return (irq_num + uSlot) & 7;
496}
497
498#ifdef IN_RING3
499
500/* return the global irq number corresponding to a given device irq
501 pin. We could also use the bus number to have a more precise
502 mapping. This is the implementation note described in the PCI spec chapter 2.2.6 */
503DECLINLINE(int) ich9pciSlotGetPirq(uint8_t uBus, uint8_t uDevFn, uint8_t uIrqNum)
504{
505 NOREF(uBus);
506 int iSlotAddend = (uDevFn >> 3) - 1;
507 return (uIrqNum + iSlotAddend) & 3;
508}
509
510/* irqs corresponding to PCI irqs A-D, must match pci_irq_list in pcibios.inc */
511/** @todo r=klaus inconsistent! ich9 doesn't implement PIRQ yet, so both needs to be addressed and tested thoroughly. */
512static const uint8_t aPciIrqs[4] = { 11, 10, 9, 5 };
513
514#endif /* IN_RING3 */
515
516/* Add one more level up request on APIC input line */
517DECLINLINE(void) ich9pciApicLevelUp(PDEVPCIROOT pPciRoot, int irq_num)
518{
519 ASMAtomicIncU32(&pPciRoot->auPciApicIrqLevels[irq_num]);
520}
521
522/* Remove one level up request on APIC input line */
523DECLINLINE(void) ich9pciApicLevelDown(PDEVPCIROOT pPciRoot, int irq_num)
524{
525 ASMAtomicDecU32(&pPciRoot->auPciApicIrqLevels[irq_num]);
526}
527
528static void ich9pciApicSetIrq(PDEVPCIBUS pBus, uint8_t uDevFn, PDMPCIDEV *pPciDev, int irq_num1, int iLevel,
529 uint32_t uTagSrc, int iForcedIrq)
530{
531 /* This is only allowed to be called with a pointer to the root bus. */
532 AssertMsg(pBus->iBus == 0, ("iBus=%u\n", pBus->iBus));
533
534 if (iForcedIrq == -1)
535 {
536 int apic_irq, apic_level;
537 PDEVPCIROOT pPciRoot = DEVPCIBUS_2_DEVPCIROOT(pBus);
538 int irq_num = ich9pciSlot2ApicIrq(uDevFn >> 3, irq_num1);
539
540 if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH)
541 ich9pciApicLevelUp(pPciRoot, irq_num);
542 else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW)
543 ich9pciApicLevelDown(pPciRoot, irq_num);
544
545 apic_irq = irq_num + 0x10;
546 apic_level = pPciRoot->auPciApicIrqLevels[irq_num] != 0;
547 Log3Func(("%s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d uTagSrc=%#x\n",
548 R3STRING(pPciDev->pszNameR3), irq_num1, iLevel, apic_irq, apic_level, irq_num, uTagSrc));
549 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level, uTagSrc);
550
551 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
552 {
553 /*
554 * we raised it few lines above, as PDM_IRQ_LEVEL_FLIP_FLOP has
555 * PDM_IRQ_LEVEL_HIGH bit set
556 */
557 ich9pciApicLevelDown(pPciRoot, irq_num);
558 pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
559 apic_level = pPciRoot->auPciApicIrqLevels[irq_num] != 0;
560 Log3Func(("%s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d uTagSrc=%#x (flop)\n",
561 R3STRING(pPciDev->pszNameR3), irq_num1, iLevel, apic_irq, apic_level, irq_num, uTagSrc));
562 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level, uTagSrc);
563 }
564 } else {
565 Log3Func(("(forced) %s: irq_num1=%d level=%d acpi_irq=%d uTagSrc=%#x\n",
566 R3STRING(pPciDev->pszNameR3), irq_num1, iLevel, iForcedIrq, uTagSrc));
567 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), iForcedIrq, iLevel, uTagSrc);
568 }
569}
570
571static void ich9pciSetIrqInternal(PDEVPCIROOT pPciRoot, uint8_t uDevFn, PPDMPCIDEV pPciDev,
572 int iIrq, int iLevel, uint32_t uTagSrc)
573{
574 /* If MSI or MSI-X is enabled, PCI INTx# signals are disabled regardless of the PCI command
575 * register interrupt bit state.
576 * PCI 3.0 (section 6.8) forbids MSI and MSI-X to be enabled at the same time and makes
577 * that undefined behavior. We check for MSI first, then MSI-X.
578 */
579 if (MsiIsEnabled(pPciDev))
580 {
581 Assert(!MsixIsEnabled(pPciDev)); /* Not allowed -- see note above. */
582 LogFlowFunc(("PCI Dev %p : MSI\n", pPciDev));
583 PPDMDEVINS pDevIns = pPciRoot->PciBus.CTX_SUFF(pDevIns);
584 MsiNotify(pDevIns, pPciRoot->PciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel, uTagSrc);
585 return;
586 }
587
588 if (MsixIsEnabled(pPciDev))
589 {
590 LogFlowFunc(("PCI Dev %p : MSI-X\n", pPciDev));
591 PPDMDEVINS pDevIns = pPciRoot->PciBus.CTX_SUFF(pDevIns);
592 MsixNotify(pDevIns, pPciRoot->PciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel, uTagSrc);
593 return;
594 }
595
596 PDEVPCIBUS pBus = &pPciRoot->PciBus;
597 /* safe, only needs to go to the config space array */
598 const bool fIsAcpiDevice = PDMPciDevGetDeviceId(pPciDev) == 0x7113;
599
600 LogFlowFunc(("PCI Dev %p : IRQ\n", pPciDev));
601 /* Check if the state changed. */
602 if (pPciDev->Int.s.uIrqPinState != iLevel)
603 {
604 pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
605
606 /** @todo r=klaus: implement PIRQ handling (if APIC isn't active). Needed for legacy OSes which don't use the APIC stuff. */
607
608 /* Send interrupt to I/O APIC only now. */
609 if (fIsAcpiDevice)
610 /*
611 * ACPI needs special treatment since SCI is hardwired and
612 * should not be affected by PCI IRQ routing tables at the
613 * same time SCI IRQ is shared in PCI sense hence this
614 * kludge (i.e. we fetch the hardwired value from ACPIs
615 * PCI device configuration space).
616 */
617 /* safe, only needs to go to the config space array */
618 ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, uTagSrc, PDMPciDevGetInterruptLine(pPciDev));
619 else
620 ich9pciApicSetIrq(pBus, uDevFn, pPciDev, iIrq, iLevel, uTagSrc, -1);
621 }
622}
623
624
625/**
626 * Memory mapped I/O Handler for write operations.
627 *
628 * Emulates writes to configuration space.
629 *
630 * @returns VBox status code.
631 *
632 * @param pDevIns The device instance.
633 * @param pvUser User argument.
634 * @param GCPhysAddr Physical address (in GC) where the read starts.
635 * @param pv Where to fetch the result.
636 * @param cb Number of bytes to write.
637 * @remarks Caller enters the device critical section.
638 */
639PDMBOTHCBDECL(int) ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
640{
641 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
642 uint32_t u32 = 0;
643 NOREF(pvUser);
644
645 Log2Func(("%RGp(%d) \n", GCPhysAddr, cb));
646
647 PCI_LOCK(pDevIns, VINF_IOM_R3_MMIO_WRITE);
648
649 /* Decode target device and configuration space register */
650 PciAddress aDest;
651 ich9pciPhysToPciAddr(pPciRoot, GCPhysAddr, &aDest);
652
653 switch (cb)
654 {
655 case 1:
656 u32 = *(uint8_t*)pv;
657 break;
658 case 2:
659 u32 = *(uint16_t*)pv;
660 break;
661 case 4:
662 u32 = *(uint32_t*)pv;
663 break;
664 default:
665 Assert(false);
666 break;
667 }
668
669 /* Perform configuration space write */
670 int rc = ich9pciConfigWrite(pPciRoot, &aDest, u32, cb, VINF_IOM_R3_MMIO_WRITE);
671 PCI_UNLOCK(pDevIns);
672
673 return rc;
674}
675
676
677/**
678 * Memory mapped I/O Handler for read operations.
679 *
680 * Emulates reads from configuration space.
681 *
682 * @returns VBox status code.
683 *
684 * @param pDevIns The device instance.
685 * @param pvUser User argument.
686 * @param GCPhysAddr Physical address (in GC) where the read starts.
687 * @param pv Where to store the result.
688 * @param cb Number of bytes read.
689 * @remarks Caller enters the device critical section.
690 */
691PDMBOTHCBDECL(int) ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
692{
693 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
694 uint32_t rv;
695 NOREF(pvUser);
696
697 LogFlowFunc(("%RGp(%d) \n", GCPhysAddr, cb));
698
699 PCI_LOCK(pDevIns, VINF_IOM_R3_MMIO_READ);
700
701 /* Decode target device and configuration space register */
702 PciAddress aDest;
703 ich9pciPhysToPciAddr(pPciRoot, GCPhysAddr, &aDest);
704
705 /* Perform configuration space read */
706 int rc = ich9pciConfigRead(pPciRoot, &aDest, cb, &rv, VINF_IOM_R3_MMIO_READ);
707
708 if (RT_SUCCESS(rc))
709 {
710 switch (cb)
711 {
712 case 1:
713 *(uint8_t*)pv = (uint8_t)rv;
714 break;
715 case 2:
716 *(uint16_t*)pv = (uint16_t)rv;
717 break;
718 case 4:
719 *(uint32_t*)pv = (uint32_t)rv;
720 break;
721 default:
722 Assert(false);
723 break;
724 }
725 }
726 PCI_UNLOCK(pDevIns);
727
728 return rc;
729}
730
731#ifdef IN_RING3
732
733/*
734 * Include code we share with the other PCI bus implementation.
735 *
736 * Note! No #ifdefs, use instant data booleans/flags/whatever. Goal is to
737 * completely merge these files! File #1 contains code we write, where
738 * as a possible file #2 contains external code if there's any left.
739 */
740# include "DevPciMerge1.cpp.h"
741
742
743DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PDEVPCIBUS pBus, uint8_t uBus)
744{
745 /* Search for a fitting bridge. */
746 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
747 {
748 /*
749 * Examine secondary and subordinate bus number.
750 * If the target bus is in the range we pass the request on to the bridge.
751 */
752 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
753 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
754 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
755 /* safe, only needs to go to the config space array */
756 uint32_t uSecondary = PDMPciDevGetByte(pBridge, VBOX_PCI_SECONDARY_BUS);
757 /* safe, only needs to go to the config space array */
758 uint32_t uSubordinate = PDMPciDevGetByte(pBridge, VBOX_PCI_SUBORDINATE_BUS);
759 Log3Func(("bus %p, bridge %d: %d in %d..%d\n", pBus, iBridge, uBus, uSecondary, uSubordinate));
760 if (uBus >= uSecondary && uBus <= uSubordinate)
761 return pBridge;
762 }
763
764 /* Nothing found. */
765 return NULL;
766}
767
768uint32_t devpciR3GetCfg(PPDMPCIDEV pPciDev, int32_t iRegister, int cb)
769{
770 return pPciDev->Int.s.pfnConfigRead(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, iRegister, cb);
771}
772
773DECLINLINE(uint32_t) devpciGetRegionReg(int iRegion)
774{
775 return iRegion == VBOX_PCI_ROM_SLOT
776 ? VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
777}
778
779void devpciR3SetCfg(PPDMPCIDEV pPciDev, int32_t iRegister, uint32_t u32, int cb)
780{
781 pPciDev->Int.s.pfnConfigWrite(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, iRegister, u32, cb);
782}
783
784
785/* -=-=-=-=-=- PCI Bus Interface Methods (PDMPCIBUSREG) -=-=-=-=-=- */
786
787
788static DECLCALLBACK(int) ich9pciRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
789{
790 NOREF(pDevIns);
791 int rc;
792
793 rc = MsiInit(pPciDev, pMsiReg);
794 if (RT_FAILURE(rc))
795 return rc;
796
797 rc = MsixInit(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), pPciDev, pMsiReg);
798 if (RT_FAILURE(rc))
799 return rc;
800
801 return VINF_SUCCESS;
802}
803
804
805/**
806 * @interface_method_impl{PDMPCIBUSREG,pfnIORegionRegisterR3}
807 */
808DECLCALLBACK(int) devpciR3CommonIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iRegion, RTGCPHYS cbRegion,
809 PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
810{
811 NOREF(pDevIns);
812
813 /*
814 * Validate.
815 */
816 AssertMsgReturn( enmType == (PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_BAR32)
817 || enmType == (PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_BAR32)
818 || enmType == (PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_BAR64)
819 || enmType == (PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_BAR64)
820 || enmType == PCI_ADDRESS_SPACE_IO
821 ,
822 ("Invalid enmType=%#x? Or was this a bitmask after all...\n", enmType),
823 VERR_INVALID_PARAMETER);
824 AssertMsgReturn((unsigned)iRegion < VBOX_PCI_NUM_REGIONS,
825 ("Invalid iRegion=%d VBOX_PCI_NUM_REGIONS=%d\n", iRegion, VBOX_PCI_NUM_REGIONS),
826 VERR_INVALID_PARAMETER);
827 int iLastSet = ASMBitLastSetU64(cbRegion);
828 AssertMsgReturn( iLastSet != 0
829 && RT_BIT_64(iLastSet - 1) == cbRegion,
830 ("Invalid cbRegion=%RGp iLastSet=%#x (not a power of 2 or 0)\n", cbRegion, iLastSet),
831 VERR_INVALID_PARAMETER);
832
833 LogFunc(("%s region %d size %RGp type %x\n", pPciDev->pszNameR3, iRegion, cbRegion, enmType));
834
835 /* Make sure that we haven't marked this region as continuation of 64-bit region. */
836 Assert(pPciDev->Int.s.aIORegions[iRegion].type != 0xff);
837
838 /*
839 * Register the I/O region.
840 */
841 PPCIIOREGION pRegion = &pPciDev->Int.s.aIORegions[iRegion];
842 pRegion->addr = INVALID_PCI_ADDRESS;
843 pRegion->size = cbRegion;
844 pRegion->type = enmType;
845 pRegion->map_func = pfnCallback;
846
847 if ((enmType & PCI_ADDRESS_SPACE_BAR64) != 0)
848 {
849 /* VBOX_PCI_BASE_ADDRESS_5 and VBOX_PCI_ROM_ADDRESS are excluded. */
850 AssertMsgReturn(iRegion < VBOX_PCI_NUM_REGIONS - 2,
851 ("Region %d cannot be 64-bit\n", iRegion),
852 VERR_INVALID_PARAMETER);
853 /* Mark next region as continuation of this one. */
854 pPciDev->Int.s.aIORegions[iRegion + 1].type = 0xff;
855 }
856
857 /* Set type in the PCI config space. */
858 AssertCompile(PCI_ADDRESS_SPACE_MEM == 0);
859 AssertCompile(PCI_ADDRESS_SPACE_IO == 1);
860 AssertCompile(PCI_ADDRESS_SPACE_BAR64 == RT_BIT_32(2));
861 AssertCompile(PCI_ADDRESS_SPACE_MEM_PREFETCH == RT_BIT_32(3));
862 uint32_t u32Value = (uint32_t)enmType & (PCI_ADDRESS_SPACE_IO | PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH);
863 /* safe, only needs to go to the config space array */
864 PDMPciDevSetDWord(pPciDev, devpciGetRegionReg(iRegion), u32Value);
865
866 return VINF_SUCCESS;
867}
868
869
870/**
871 * @interface_method_impl{PDMPCIBUSREG,pfnSetConfigCallbacksR3}
872 */
873DECLCALLBACK(void) devpciR3CommonSetConfigCallbacks(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
874 PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
875 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
876{
877 NOREF(pDevIns);
878
879 if (ppfnReadOld)
880 *ppfnReadOld = pPciDev->Int.s.pfnConfigRead;
881 pPciDev->Int.s.pfnConfigRead = pfnRead;
882
883 if (ppfnWriteOld)
884 *ppfnWriteOld = pPciDev->Int.s.pfnConfigWrite;
885 pPciDev->Int.s.pfnConfigWrite = pfnWrite;
886}
887
888
889static int ich9pciR3CommonSaveExec(PDEVPCIBUS pBus, PSSMHANDLE pSSM)
890{
891 /*
892 * Iterate thru all the devices.
893 */
894 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
895 {
896 PPDMPCIDEV pDev = pBus->apDevices[uDevFn];
897 if (pDev)
898 {
899 /* Device position */
900 SSMR3PutU32(pSSM, uDevFn);
901 /* PCI config registers */
902 SSMR3PutMem(pSSM, pDev->abConfig, sizeof(pDev->abConfig));
903
904 /* Device flags */
905 int rc = SSMR3PutU32(pSSM, pDev->Int.s.fFlags);
906 if (RT_FAILURE(rc))
907 return rc;
908
909 /* IRQ pin state */
910 rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
911 if (RT_FAILURE(rc))
912 return rc;
913
914 /* MSI info */
915 rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapOffset);
916 if (RT_FAILURE(rc))
917 return rc;
918 rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapSize);
919 if (RT_FAILURE(rc))
920 return rc;
921
922 /* MSI-X info */
923 rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapOffset);
924 if (RT_FAILURE(rc))
925 return rc;
926 rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapSize);
927 if (RT_FAILURE(rc))
928 return rc;
929
930 /* Save MSI-X page state */
931 if (pDev->Int.s.u8MsixCapOffset != 0)
932 {
933 Assert(pDev->Int.s.pMsixPageR3 != NULL);
934 SSMR3PutMem(pSSM, pDev->Int.s.pMsixPageR3, 0x1000);
935 if (RT_FAILURE(rc))
936 return rc;
937 }
938
939 /* Save the type an size of all the regions. */
940 for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
941 {
942 SSMR3PutU8(pSSM, pDev->Int.s.aIORegions[iRegion].type);
943 rc = SSMR3PutU64(pSSM, pDev->Int.s.aIORegions[iRegion].size);
944 AssertRCReturn(rc, rc);
945 }
946 }
947 }
948 return SSMR3PutU32(pSSM, UINT32_MAX); /* terminator */
949}
950
951static DECLCALLBACK(int) ich9pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
952{
953 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
954
955 /*
956 * Bus state data.
957 */
958 SSMR3PutU32(pSSM, pThis->uConfigReg);
959
960 /*
961 * Save IRQ states.
962 */
963 for (unsigned i = 0; i < RT_ELEMENTS(pThis->auPciApicIrqLevels); i++)
964 SSMR3PutU32(pSSM, pThis->auPciApicIrqLevels[i]);
965
966 SSMR3PutU32(pSSM, UINT32_MAX); /* separator */
967
968 return ich9pciR3CommonSaveExec(&pThis->PciBus, pSSM);
969}
970
971
972static DECLCALLBACK(int) ich9pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
973{
974 PDEVPCIBUS pThis = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
975 return ich9pciR3CommonSaveExec(pThis, pSSM);
976}
977
978
979static DECLCALLBACK(void) ich9pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t uBus, uint8_t uDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb)
980{
981 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
982
983 LogFlowFunc(("pDevIns=%p uBus=%d uDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, uBus, uDevice, u32Address, u32Value, cb));
984
985 /* If the current bus is not the target bus search for the bus which contains the device. */
986 /* safe, only needs to go to the config space array */
987 if (uBus != PDMPciDevGetByte(&pBus->PciDev, VBOX_PCI_SECONDARY_BUS))
988 {
989 PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(pBus, uBus);
990 if (pBridgeDevice)
991 {
992 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
993 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->Int.s.CTX_SUFF(pDevIns), uBus, uDevice,
994 u32Address, u32Value, cb);
995 }
996 }
997 else
998 {
999 /* This is the target bus, pass the write to the device. */
1000 PPDMPCIDEV pPciDev = pBus->apDevices[uDevice];
1001 if (pPciDev)
1002 {
1003 LogFunc(("%s: addr=%02x val=%08x len=%d\n", pPciDev->pszNameR3, u32Address, u32Value, cb));
1004 /** @todo return rc */
1005 pPciDev->Int.s.pfnConfigWrite(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, u32Address, u32Value, cb);
1006 }
1007 }
1008}
1009
1010static DECLCALLBACK(uint32_t) ich9pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint8_t uBus, uint8_t uDevice, uint32_t u32Address, unsigned cb)
1011{
1012 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
1013 uint32_t u32Value;
1014
1015 LogFlowFunc(("pDevIns=%p uBus=%d uDevice=%d u32Address=%u cb=%d\n", pDevIns, uBus, uDevice, u32Address, cb));
1016
1017 /* If the current bus is not the target bus search for the bus which contains the device. */
1018 /* safe, only needs to go to the config space array */
1019 if (uBus != PDMPciDevGetByte(&pBus->PciDev, VBOX_PCI_SECONDARY_BUS))
1020 {
1021 PPDMPCIDEV pBridgeDevice = ich9pciFindBridge(pBus, uBus);
1022 if (pBridgeDevice)
1023 {
1024 AssertPtr( pBridgeDevice->Int.s.pfnBridgeConfigRead);
1025 u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->Int.s.CTX_SUFF(pDevIns), uBus, uDevice,
1026 u32Address, cb);
1027 }
1028 else
1029 u32Value = 0xffffffff;
1030 }
1031 else
1032 {
1033 /* This is the target bus, pass the read to the device. */
1034 PPDMPCIDEV pPciDev = pBus->apDevices[uDevice];
1035 if (pPciDev)
1036 {
1037 u32Value = pPciDev->Int.s.pfnConfigRead(pPciDev->Int.s.CTX_SUFF(pDevIns), pPciDev, u32Address, cb);
1038 LogFunc(("%s: u32Address=%02x u32Value=%08x cb=%d\n", pPciDev->pszNameR3, u32Address, u32Value, cb));
1039 }
1040 else
1041 u32Value = 0xffffffff;
1042 }
1043
1044 return u32Value;
1045}
1046
1047
1048
1049/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
1050
1051
1052/**
1053 * Common routine for restoring the config registers of a PCI device.
1054 *
1055 * @param pDev The PCI device.
1056 * @param pbSrcConfig The configuration register values to be loaded.
1057 */
1058void devpciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig)
1059{
1060 /*
1061 * This table defines the fields for normal devices and bridge devices, and
1062 * the order in which they need to be restored.
1063 */
1064 static const struct PciField
1065 {
1066 uint8_t off;
1067 uint8_t cb;
1068 uint8_t fWritable;
1069 uint8_t fBridge;
1070 const char *pszName;
1071 } s_aFields[] =
1072 {
1073 /* off,cb,fW,fB, pszName */
1074 { 0x00, 2, 0, 3, "VENDOR_ID" },
1075 { 0x02, 2, 0, 3, "DEVICE_ID" },
1076 { 0x06, 2, 1, 3, "STATUS" },
1077 { 0x08, 1, 0, 3, "REVISION_ID" },
1078 { 0x09, 1, 0, 3, "CLASS_PROG" },
1079 { 0x0a, 1, 0, 3, "CLASS_SUB" },
1080 { 0x0b, 1, 0, 3, "CLASS_BASE" },
1081 { 0x0c, 1, 1, 3, "CACHE_LINE_SIZE" },
1082 { 0x0d, 1, 1, 3, "LATENCY_TIMER" },
1083 { 0x0e, 1, 0, 3, "HEADER_TYPE" },
1084 { 0x0f, 1, 1, 3, "BIST" },
1085 { 0x10, 4, 1, 3, "BASE_ADDRESS_0" },
1086 { 0x14, 4, 1, 3, "BASE_ADDRESS_1" },
1087 { 0x18, 4, 1, 1, "BASE_ADDRESS_2" },
1088 { 0x18, 1, 1, 2, "PRIMARY_BUS" },
1089 { 0x19, 1, 1, 2, "SECONDARY_BUS" },
1090 { 0x1a, 1, 1, 2, "SUBORDINATE_BUS" },
1091 { 0x1b, 1, 1, 2, "SEC_LATENCY_TIMER" },
1092 { 0x1c, 4, 1, 1, "BASE_ADDRESS_3" },
1093 { 0x1c, 1, 1, 2, "IO_BASE" },
1094 { 0x1d, 1, 1, 2, "IO_LIMIT" },
1095 { 0x1e, 2, 1, 2, "SEC_STATUS" },
1096 { 0x20, 4, 1, 1, "BASE_ADDRESS_4" },
1097 { 0x20, 2, 1, 2, "MEMORY_BASE" },
1098 { 0x22, 2, 1, 2, "MEMORY_LIMIT" },
1099 { 0x24, 4, 1, 1, "BASE_ADDRESS_5" },
1100 { 0x24, 2, 1, 2, "PREF_MEMORY_BASE" },
1101 { 0x26, 2, 1, 2, "PREF_MEMORY_LIMIT" },
1102 { 0x28, 4, 0, 1, "CARDBUS_CIS" },
1103 { 0x28, 4, 1, 2, "PREF_BASE_UPPER32" },
1104 { 0x2c, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },
1105 { 0x2c, 4, 1, 2, "PREF_LIMIT_UPPER32" },
1106 { 0x2e, 2, 0, 1, "SUBSYSTEM_ID" },
1107 { 0x30, 4, 1, 1, "ROM_ADDRESS" },
1108 { 0x30, 2, 1, 2, "IO_BASE_UPPER16" },
1109 { 0x32, 2, 1, 2, "IO_LIMIT_UPPER16" },
1110 { 0x34, 4, 0, 3, "CAPABILITY_LIST" },
1111 { 0x38, 4, 1, 1, "RESERVED_38" },
1112 { 0x38, 4, 1, 2, "ROM_ADDRESS_BR" },
1113 { 0x3c, 1, 1, 3, "INTERRUPT_LINE" },
1114 { 0x3d, 1, 0, 3, "INTERRUPT_PIN" },
1115 { 0x3e, 1, 0, 1, "MIN_GNT" },
1116 { 0x3e, 2, 1, 2, "BRIDGE_CONTROL" },
1117 { 0x3f, 1, 0, 1, "MAX_LAT" },
1118 /* The COMMAND register must come last as it requires the *ADDRESS*
1119 registers to be restored before we pretent to change it from 0 to
1120 whatever value the guest assigned it. */
1121 { 0x04, 2, 1, 3, "COMMAND" },
1122 };
1123
1124#ifdef RT_STRICT
1125 /* Check that we've got full register coverage. */
1126 uint32_t bmDevice[0x40 / 32];
1127 uint32_t bmBridge[0x40 / 32];
1128 RT_ZERO(bmDevice);
1129 RT_ZERO(bmBridge);
1130 for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
1131 {
1132 uint8_t off = s_aFields[i].off;
1133 uint8_t cb = s_aFields[i].cb;
1134 uint8_t f = s_aFields[i].fBridge;
1135 while (cb-- > 0)
1136 {
1137 if (f & 1) AssertMsg(!ASMBitTest(bmDevice, off), ("%#x\n", off));
1138 if (f & 2) AssertMsg(!ASMBitTest(bmBridge, off), ("%#x\n", off));
1139 if (f & 1) ASMBitSet(bmDevice, off);
1140 if (f & 2) ASMBitSet(bmBridge, off);
1141 off++;
1142 }
1143 }
1144 for (uint32_t off = 0; off < 0x40; off++)
1145 {
1146 AssertMsg(ASMBitTest(bmDevice, off), ("%#x\n", off));
1147 AssertMsg(ASMBitTest(bmBridge, off), ("%#x\n", off));
1148 }
1149#endif
1150
1151 /*
1152 * Loop thru the fields covering the 64 bytes of standard registers.
1153 */
1154 uint8_t const fBridge = pciDevIsPci2PciBridge(pDev) ? 2 : 1;
1155 Assert(!pciDevIsPassthrough(pDev));
1156 uint8_t *pbDstConfig = &pDev->abConfig[0];
1157
1158 for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
1159 if (s_aFields[i].fBridge & fBridge)
1160 {
1161 uint8_t const off = s_aFields[i].off;
1162 uint8_t const cb = s_aFields[i].cb;
1163 uint32_t u32Src;
1164 uint32_t u32Dst;
1165 switch (cb)
1166 {
1167 case 1:
1168 u32Src = pbSrcConfig[off];
1169 u32Dst = pbDstConfig[off];
1170 break;
1171 case 2:
1172 u32Src = *(uint16_t const *)&pbSrcConfig[off];
1173 u32Dst = *(uint16_t const *)&pbDstConfig[off];
1174 break;
1175 case 4:
1176 u32Src = *(uint32_t const *)&pbSrcConfig[off];
1177 u32Dst = *(uint32_t const *)&pbDstConfig[off];
1178 break;
1179 default:
1180 AssertFailed();
1181 continue;
1182 }
1183
1184 if ( u32Src != u32Dst
1185 || off == VBOX_PCI_COMMAND)
1186 {
1187 if (u32Src != u32Dst)
1188 {
1189 if (!s_aFields[i].fWritable)
1190 LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x - !READ ONLY!\n",
1191 pDev->pszNameR3, pDev->Int.s.CTX_SUFF(pDevIns)->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
1192 else
1193 LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x\n",
1194 pDev->pszNameR3, pDev->Int.s.CTX_SUFF(pDevIns)->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
1195 }
1196 if (off == VBOX_PCI_COMMAND)
1197 /* safe, only needs to go to the config space array */
1198 PDMPciDevSetCommand(pDev, 0); /* For remapping, see pciR3CommonLoadExec/ich9pciR3CommonLoadExec. */
1199 pDev->Int.s.pfnConfigWrite(pDev->Int.s.CTX_SUFF(pDevIns), pDev, off, u32Src, cb);
1200 }
1201 }
1202
1203 /*
1204 * The device dependent registers.
1205 *
1206 * We will not use ConfigWrite here as we have no clue about the size
1207 * of the registers, so the device is responsible for correctly
1208 * restoring functionality governed by these registers.
1209 */
1210 for (uint32_t off = 0x40; off < sizeof(pDev->abConfig); off++)
1211 if (pbDstConfig[off] != pbSrcConfig[off])
1212 {
1213 LogRel(("PCI: %8s/%u: register %02x: %02x -> %02x\n",
1214 pDev->pszNameR3, pDev->Int.s.CTX_SUFF(pDevIns)->iInstance, off, pbDstConfig[off], pbSrcConfig[off])); /** @todo make this Log() later. */
1215 pbDstConfig[off] = pbSrcConfig[off];
1216 }
1217}
1218
1219
1220/**
1221 * @callback_method_impl{FNPCIIOREGIONOLDSETTER}
1222 */
1223static DECLCALLBACK(int) devpciR3CommonRestoreOldSetRegion(PPDMPCIDEV pPciDev, uint32_t iRegion,
1224 RTGCPHYS cbRegion, PCIADDRESSSPACE enmType)
1225{
1226 AssertLogRelReturn(iRegion < RT_ELEMENTS(pPciDev->Int.s.aIORegions), VERR_INVALID_PARAMETER);
1227 pPciDev->Int.s.aIORegions[iRegion].type = enmType;
1228 pPciDev->Int.s.aIORegions[iRegion].size = cbRegion;
1229 return VINF_SUCCESS;
1230}
1231
1232
1233/**
1234 * Checks for and deals with changes in resource sizes and types.
1235 *
1236 * @returns VBox status code.
1237 * @param pSSM The Saved state handle.
1238 * @param pPciDev The PCI device in question.
1239 * @param paIoRegions I/O regions with the size and type fields from
1240 * the saved state.
1241 * @param fNewState Set if this is a new state with I/O region sizes
1242 * and types, clear if old one.
1243 */
1244int devpciR3CommonRestoreRegions(PSSMHANDLE pSSM, PPDMPCIDEV pPciDev, PPCIIOREGION paIoRegions, bool fNewState)
1245{
1246 int rc;
1247 if (fNewState)
1248 {
1249 for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
1250 {
1251 if ( pPciDev->Int.s.aIORegions[iRegion].type != paIoRegions[iRegion].type
1252 || pPciDev->Int.s.aIORegions[iRegion].size != paIoRegions[iRegion].size)
1253 {
1254 AssertLogRelMsgFailed(("PCI: %8s/%u: region #%u size/type load change: %#RGp/%#x -> %#RGp/%#x\n",
1255 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, iRegion,
1256 pPciDev->Int.s.aIORegions[iRegion].size, pPciDev->Int.s.aIORegions[iRegion].type,
1257 paIoRegions[iRegion].size, paIoRegions[iRegion].type));
1258 if (pPciDev->pfnRegionLoadChangeHookR3)
1259 {
1260 rc = pPciDev->pfnRegionLoadChangeHookR3(pPciDev->Int.s.pDevInsR3, pPciDev, iRegion, paIoRegions[iRegion].size,
1261 (PCIADDRESSSPACE)paIoRegions[iRegion].type, NULL /*pfnOldSetter*/);
1262 if (RT_FAILURE(rc))
1263 return SSMR3SetLoadError(pSSM, rc, RT_SRC_POS,
1264 N_("Device %s/%u failed to respond to region #%u size/type changing from %#RGp/%#x to %#RGp/%#x: %Rrc"),
1265 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, iRegion,
1266 pPciDev->Int.s.aIORegions[iRegion].size, pPciDev->Int.s.aIORegions[iRegion].type,
1267 paIoRegions[iRegion].size, paIoRegions[iRegion].type, rc);
1268 }
1269 pPciDev->Int.s.aIORegions[iRegion].type = paIoRegions[iRegion].type;
1270 pPciDev->Int.s.aIORegions[iRegion].size = paIoRegions[iRegion].size;
1271 }
1272 }
1273 }
1274 /* Old saved state without sizes and types. Do a special hook call to give
1275 devices with changes a chance to adjust resources back to old values. */
1276 else if (pPciDev->pfnRegionLoadChangeHookR3)
1277 {
1278 rc = pPciDev->pfnRegionLoadChangeHookR3(pPciDev->Int.s.pDevInsR3, pPciDev, UINT32_MAX, RTGCPHYS_MAX, (PCIADDRESSSPACE)-1,
1279 devpciR3CommonRestoreOldSetRegion);
1280 if (RT_FAILURE(rc))
1281 return SSMR3SetLoadError(pSSM, rc, RT_SRC_POS, N_("Device %s/%u failed to resize its resources: %Rrc"),
1282 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, rc);
1283 }
1284 return VINF_SUCCESS;
1285}
1286
1287
1288/**
1289 * Common worker for ich9pciR3LoadExec and ich9pcibridgeR3LoadExec.
1290 *
1291 * @returns VBox status code.
1292 * @param pBus The bus which data is being loaded.
1293 * @param pSSM The saved state handle.
1294 * @param uVersion The data version.
1295 * @param uPass The pass.
1296 */
1297static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PDEVPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1298{
1299 uint32_t u32;
1300 int rc;
1301
1302 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
1303 if ( uVersion < VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI
1304 || uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
1305 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1306
1307 /*
1308 * Iterate thru all the devices and write 0 to the COMMAND register so
1309 * that all the memory is unmapped before we start restoring the saved
1310 * mapping locations.
1311 *
1312 * The register value is restored afterwards so we can do proper
1313 * LogRels in devpciR3CommonRestoreConfig.
1314 */
1315 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
1316 {
1317 PPDMPCIDEV pDev = pBus->apDevices[uDevFn];
1318 if (pDev)
1319 {
1320 /* safe, only needs to go to the config space array */
1321 uint16_t u16 = PDMPciDevGetCommand(pDev);
1322 pDev->Int.s.pfnConfigWrite(pDev->Int.s.CTX_SUFF(pDevIns), pDev, VBOX_PCI_COMMAND, 0, 2);
1323 /* safe, only needs to go to the config space array */
1324 PDMPciDevSetCommand(pDev, u16);
1325 /* safe, only needs to go to the config space array */
1326 Assert(PDMPciDevGetCommand(pDev) == u16);
1327 }
1328 }
1329
1330 void *pvMsixPage = RTMemTmpAllocZ(0x1000);
1331 AssertReturn(pvMsixPage, VERR_NO_TMP_MEMORY);
1332
1333 /*
1334 * Iterate all the devices.
1335 */
1336 for (uint32_t uDevFn = 0;; uDevFn++)
1337 {
1338 /* index / terminator */
1339 rc = SSMR3GetU32(pSSM, &u32);
1340 if (RT_FAILURE(rc))
1341 break;
1342 if (u32 == (uint32_t)~0)
1343 break;
1344 AssertMsgBreak(u32 < RT_ELEMENTS(pBus->apDevices) && u32 >= uDevFn, ("u32=%#x uDevFn=%#x\n", u32, uDevFn));
1345
1346 /* skip forward to the device checking that no new devices are present. */
1347 PPDMPCIDEV pDev;
1348 for (; uDevFn < u32; uDevFn++)
1349 {
1350 pDev = pBus->apDevices[uDevFn];
1351 if (pDev)
1352 {
1353 /* safe, only needs to go to the config space array */
1354 LogRel(("PCI: New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", uDevFn, pDev->pszNameR3,
1355 PDMPciDevGetVendorId(pDev), PDMPciDevGetDeviceId(pDev)));
1356 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
1357 {
1358 /* safe, only needs to go to the config space array */
1359 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"),
1360 uDevFn, pDev->pszNameR3, PDMPciDevGetVendorId(pDev), PDMPciDevGetDeviceId(pDev));
1361 break;
1362 }
1363 }
1364 }
1365 if (RT_FAILURE(rc))
1366 break;
1367
1368 /* get the data */
1369 PDMPCIDEV DevTmp;
1370 RT_ZERO(DevTmp);
1371 DevTmp.Int.s.fFlags = 0;
1372 DevTmp.Int.s.u8MsiCapOffset = 0;
1373 DevTmp.Int.s.u8MsiCapSize = 0;
1374 DevTmp.Int.s.u8MsixCapOffset = 0;
1375 DevTmp.Int.s.u8MsixCapSize = 0;
1376 DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
1377 SSMR3GetMem(pSSM, DevTmp.abConfig, sizeof(DevTmp.abConfig));
1378
1379 SSMR3GetU32(pSSM, &DevTmp.Int.s.fFlags);
1380 SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
1381 SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapOffset);
1382 SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapSize);
1383 SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapOffset);
1384 rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapSize);
1385 if (RT_FAILURE(rc))
1386 break;
1387
1388 /* Load MSI-X page state */
1389 if (DevTmp.Int.s.u8MsixCapOffset != 0)
1390 {
1391 Assert(pvMsixPage != NULL);
1392 rc = SSMR3GetMem(pSSM, pvMsixPage, 0x1000);
1393 if (RT_FAILURE(rc))
1394 break;
1395 }
1396
1397 /* Load the region types and sizes. */
1398 if (uVersion >= VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES)
1399 {
1400 for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
1401 {
1402 SSMR3GetU8(pSSM, &DevTmp.Int.s.aIORegions[iRegion].type);
1403 rc = SSMR3GetU64(pSSM, &DevTmp.Int.s.aIORegions[iRegion].size);
1404 AssertLogRelRCReturn(rc, rc);
1405 }
1406 }
1407
1408 /*
1409 * Check that it's still around.
1410 */
1411 pDev = pBus->apDevices[uDevFn];
1412 if (!pDev)
1413 {
1414 /* safe, only needs to go to the config space array */
1415 LogRel(("PCI: Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", uDevFn,
1416 PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetDeviceId(&DevTmp)));
1417 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
1418 {
1419 /* safe, only needs to go to the config space array */
1420 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"),
1421 uDevFn, PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetDeviceId(&DevTmp));
1422 break;
1423 }
1424 continue;
1425 }
1426
1427 /* match the vendor id assuming that this will never be changed. */
1428 /* safe, only needs to go to the config space array */
1429 if (PDMPciDevGetVendorId(&DevTmp) != PDMPciDevGetVendorId(pDev))
1430 {
1431 /* safe, only needs to go to the config space array */
1432 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
1433 uDevFn, pDev->pszNameR3, PDMPciDevGetVendorId(&DevTmp), PDMPciDevGetVendorId(pDev));
1434 break;
1435 }
1436
1437 /* commit the loaded device config. */
1438 rc = devpciR3CommonRestoreRegions(pSSM, pDev, DevTmp.Int.s.aIORegions,
1439 uVersion >= VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES);
1440 if (RT_FAILURE(rc))
1441 break;
1442 Assert(!pciDevIsPassthrough(pDev));
1443 devpciR3CommonRestoreConfig(pDev, &DevTmp.abConfig[0]);
1444
1445 pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
1446 pDev->Int.s.u8MsiCapOffset = DevTmp.Int.s.u8MsiCapOffset;
1447 pDev->Int.s.u8MsiCapSize = DevTmp.Int.s.u8MsiCapSize;
1448 pDev->Int.s.u8MsixCapOffset = DevTmp.Int.s.u8MsixCapOffset;
1449 pDev->Int.s.u8MsixCapSize = DevTmp.Int.s.u8MsixCapSize;
1450 if (DevTmp.Int.s.u8MsixCapSize != 0)
1451 {
1452 Assert(pDev->Int.s.pMsixPageR3 != NULL);
1453 Assert(pDev->Int.s.cbMsixRegion != 0);
1454 memcpy(pDev->Int.s.pMsixPageR3, pvMsixPage, pDev->Int.s.cbMsixRegion);
1455 }
1456 }
1457
1458 RTMemTmpFree(pvMsixPage);
1459
1460 return rc;
1461}
1462
1463static DECLCALLBACK(int) ich9pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1464{
1465 PDEVPCIROOT pThis = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
1466 PDEVPCIBUS pBus = &pThis->PciBus;
1467 uint32_t u32;
1468 int rc;
1469
1470 /* We ignore this version as there's no saved state with it anyway */
1471 if (uVersion <= VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI)
1472 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1473 if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
1474 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1475
1476 /*
1477 * Bus state data.
1478 */
1479 SSMR3GetU32(pSSM, &pThis->uConfigReg);
1480
1481 /*
1482 * Load IRQ states.
1483 */
1484 for (unsigned i = 0; i < RT_ELEMENTS(pThis->auPciApicIrqLevels); i++)
1485 SSMR3GetU32(pSSM, (uint32_t*)&pThis->auPciApicIrqLevels[i]);
1486
1487 /* separator */
1488 rc = SSMR3GetU32(pSSM, &u32);
1489 if (RT_FAILURE(rc))
1490 return rc;
1491 if (u32 != (uint32_t)~0)
1492 AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
1493
1494 return ich9pciR3CommonLoadExec(pBus, pSSM, uVersion, uPass);
1495}
1496
1497static DECLCALLBACK(int) ich9pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1498{
1499 PDEVPCIBUS pThis = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
1500 return ich9pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
1501}
1502
1503
1504
1505/* -=-=-=-=-=- Fake PCI BIOS Init -=-=-=-=-=- */
1506
1507
1508void devpciR3BiosInitSetRegionAddress(PDEVPCIBUS pBus, PPDMPCIDEV pPciDev, int iRegion, uint64_t addr)
1509{
1510 NOREF(pBus);
1511 uint32_t uReg = devpciGetRegionReg(iRegion);
1512
1513 /* Read memory type first. */
1514 uint8_t uResourceType = devpciR3GetByte(pPciDev, uReg);
1515 bool f64Bit = (uResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
1516 == PCI_ADDRESS_SPACE_BAR64;
1517
1518 Log(("Set region address: %02x:%02x.%d region %d address=%RX64%s\n",
1519 pBus->iBus, pPciDev->uDevFn >> 3, pPciDev->uDevFn & 7, iRegion, addr, f64Bit ? " (64-bit)" : ""));
1520
1521 /* Write address of the device. */
1522 devpciR3SetDWord(pPciDev, uReg, (uint32_t)addr);
1523 if (f64Bit)
1524 devpciR3SetDWord(pPciDev, uReg + 4, (uint32_t)(addr >> 32));
1525}
1526
1527
1528static void ich9pciBiosInitBridge(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus)
1529{
1530 PPDMPCIDEV pBridge = &pBus->PciDev;
1531 Log(("BIOS init bridge: %02x:%02x.%d\n", pBus->iBus, pBridge->uDevFn >> 3, pBridge->uDevFn & 7));
1532
1533 /*
1534 * The I/O range for the bridge must be aligned to a 4KB boundary.
1535 * This does not change anything really as the access to the device is not going
1536 * through the bridge but we want to be compliant to the spec.
1537 */
1538 if ((pPciRoot->uPciBiosIo % _4K) != 0)
1539 {
1540 pPciRoot->uPciBiosIo = RT_ALIGN_32(pPciRoot->uPciBiosIo, _4K);
1541 LogFunc(("Aligned I/O start address. New address %#x\n", pPciRoot->uPciBiosIo));
1542 }
1543 devpciR3SetByte(pBridge, VBOX_PCI_IO_BASE, (pPciRoot->uPciBiosIo >> 8) & 0xf0);
1544
1545 /* The MMIO range for the bridge must be aligned to a 1MB boundary. */
1546 if ((pPciRoot->uPciBiosMmio % _1M) != 0)
1547 {
1548 pPciRoot->uPciBiosMmio = RT_ALIGN_32(pPciRoot->uPciBiosMmio, _1M);
1549 LogFunc(("Aligned MMIO start address. New address %#x\n", pPciRoot->uPciBiosMmio));
1550 }
1551 devpciR3SetWord(pBridge, VBOX_PCI_MEMORY_BASE, (pPciRoot->uPciBiosMmio >> 16) & UINT32_C(0xffff0));
1552
1553 /* Save values to compare later to. */
1554 uint32_t u32IoAddressBase = pPciRoot->uPciBiosIo;
1555 uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
1556
1557 /* Init all devices behind the bridge (recursing to further buses). */
1558 ich9pciBiosInitAllDevicesOnBus(pPciRoot, pBus);
1559
1560 /*
1561 * Set I/O limit register. If there is no device with I/O space behind the
1562 * bridge we set a lower value than in the base register.
1563 */
1564 if (u32IoAddressBase != pPciRoot->uPciBiosIo)
1565 {
1566 /* Need again alignment to a 4KB boundary. */
1567 pPciRoot->uPciBiosIo = RT_ALIGN_32(pPciRoot->uPciBiosIo, _4K);
1568 devpciR3SetByte(pBridge, VBOX_PCI_IO_LIMIT, ((pPciRoot->uPciBiosIo - 1) >> 8) & 0xf0);
1569 }
1570 else
1571 {
1572 devpciR3SetByte(pBridge, VBOX_PCI_IO_BASE, 0xf0);
1573 devpciR3SetByte(pBridge, VBOX_PCI_IO_LIMIT, 0x00);
1574 }
1575
1576 /* Same with the MMIO limit register but with 1MB boundary here. */
1577 if (u32MMIOAddressBase != pPciRoot->uPciBiosMmio)
1578 {
1579 pPciRoot->uPciBiosMmio = RT_ALIGN_32(pPciRoot->uPciBiosMmio, _1M);
1580 devpciR3SetWord(pBridge, VBOX_PCI_MEMORY_LIMIT, ((pPciRoot->uPciBiosMmio - 1) >> 16) & UINT32_C(0xfff0));
1581 }
1582 else
1583 {
1584 devpciR3SetWord(pBridge, VBOX_PCI_MEMORY_BASE, 0xfff0);
1585 devpciR3SetWord(pBridge, VBOX_PCI_MEMORY_LIMIT, 0x0000);
1586 }
1587
1588 /*
1589 * Set the prefetch base and limit registers. We currently have no device with a prefetchable region
1590 * which may be behind a bridge. That's why it is unconditionally disabled here atm by writing a higher value into
1591 * the base register than in the limit register.
1592 */
1593 devpciR3SetWord(pBridge, VBOX_PCI_PREF_MEMORY_BASE, 0xfff0);
1594 devpciR3SetWord(pBridge, VBOX_PCI_PREF_MEMORY_LIMIT, 0x0000);
1595 devpciR3SetDWord(pBridge, VBOX_PCI_PREF_BASE_UPPER32, 0x00000000);
1596 devpciR3SetDWord(pBridge, VBOX_PCI_PREF_LIMIT_UPPER32, 0x00000000);
1597}
1598
1599static int ich9pciBiosInitDeviceGetRegions(PPDMPCIDEV pPciDev)
1600{
1601 uint8_t uHeaderType = devpciR3GetByte(pPciDev, VBOX_PCI_HEADER_TYPE) & 0x7f;
1602 if (uHeaderType == 0x00)
1603 /* Ignore ROM region here, which is included in VBOX_PCI_NUM_REGIONS. */
1604 return VBOX_PCI_NUM_REGIONS - 1;
1605 else if (uHeaderType == 0x01)
1606 /* PCI bridges have 2 BARs. */
1607 return 2;
1608 else
1609 {
1610 AssertMsgFailed(("invalid header type %#x\n", uHeaderType));
1611 return 0;
1612 }
1613}
1614
1615static void ich9pciBiosInitDeviceBARs(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, PPDMPCIDEV pPciDev)
1616{
1617 int cRegions = ich9pciBiosInitDeviceGetRegions(pPciDev);
1618 bool fSuppressMem = false;
1619 bool fActiveMemRegion = false;
1620 bool fActiveIORegion = false;
1621 for (int iRegion = 0; iRegion < cRegions; iRegion++)
1622 {
1623 uint32_t u32Address = devpciGetRegionReg(iRegion);
1624
1625 /* Calculate size - we write all 1s into the BAR, and then evaluate which bits
1626 are cleared. */
1627 uint8_t u8ResourceType = devpciR3GetByte(pPciDev, u32Address);
1628
1629 bool fPrefetch = (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_IO)))
1630 == PCI_ADDRESS_SPACE_MEM_PREFETCH;
1631 bool f64Bit = (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
1632 == PCI_ADDRESS_SPACE_BAR64;
1633 bool fIsPio = ((u8ResourceType & PCI_ADDRESS_SPACE_IO) == PCI_ADDRESS_SPACE_IO);
1634 uint64_t cbRegSize64 = 0;
1635
1636 /* Hack: initialize prefetchable BARs for devices on the root bus
1637 * early, but for all other prefetchable BARs do it after the
1638 * non-prefetchable BARs are initialized on all buses. */
1639 if (fPrefetch && pBus->iBus != 0)
1640 {
1641 fSuppressMem = true;
1642 if (f64Bit)
1643 iRegion++; /* skip next region */
1644 continue;
1645 }
1646
1647 if (f64Bit)
1648 {
1649 devpciR3SetDWord(pPciDev, u32Address, UINT32_C(0xffffffff));
1650 devpciR3SetDWord(pPciDev, u32Address+4, UINT32_C(0xffffffff));
1651 cbRegSize64 = RT_MAKE_U64(devpciR3GetDWord(pPciDev, u32Address),
1652 devpciR3GetDWord(pPciDev, u32Address+4));
1653 cbRegSize64 &= ~UINT64_C(0x0f);
1654 cbRegSize64 = (~cbRegSize64) + 1;
1655
1656 /* No 64-bit PIO regions possible. */
1657#ifndef DEBUG_bird /* EFI triggers this for DevAHCI. */
1658 AssertMsg((u8ResourceType & PCI_ADDRESS_SPACE_IO) == 0, ("type=%#x rgn=%d\n", u8ResourceType, iRegion));
1659#endif
1660 }
1661 else
1662 {
1663 uint32_t cbRegSize32;
1664 devpciR3SetDWord(pPciDev, u32Address, UINT32_C(0xffffffff));
1665 cbRegSize32 = devpciR3GetDWord(pPciDev, u32Address);
1666
1667 /* Clear resource information depending on resource type. */
1668 if (fIsPio) /* PIO */
1669 cbRegSize32 &= ~UINT32_C(0x01);
1670 else /* MMIO */
1671 cbRegSize32 &= ~UINT32_C(0x0f);
1672
1673 /*
1674 * Invert all bits and add 1 to get size of the region.
1675 * (From PCI implementation note)
1676 */
1677 if (fIsPio && (cbRegSize32 & UINT32_C(0xffff0000)) == 0)
1678 cbRegSize32 = (~(cbRegSize32 | UINT32_C(0xffff0000))) + 1;
1679 else
1680 cbRegSize32 = (~cbRegSize32) + 1;
1681
1682 cbRegSize64 = cbRegSize32;
1683 }
1684 Log2Func(("Size of region %u for device %d on bus %d is %lld\n", iRegion, pPciDev->uDevFn, pBus->iBus, cbRegSize64));
1685
1686 if (cbRegSize64)
1687 {
1688 /* Try 32-bit base first. */
1689 uint32_t* paddr = fIsPio ? &pPciRoot->uPciBiosIo : &pPciRoot->uPciBiosMmio;
1690 uint64_t uNew = *paddr;
1691 /* Align starting address to region size. */
1692 uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
1693 if (fIsPio)
1694 uNew &= UINT32_C(0xffff);
1695 /* Unconditionally exclude I/O-APIC/HPET/ROM. Pessimistic, but better than causing a mess. */
1696 if ( !uNew
1697 || (uNew <= UINT32_C(0xffffffff) && uNew + cbRegSize64 - 1 >= UINT32_C(0xfec00000))
1698 || uNew >= _4G)
1699 {
1700 /* Only prefetchable regions can be placed above 4GB, as the
1701 * address decoder for non-prefetchable addresses in bridges
1702 * is limited to 32 bits. */
1703 if (f64Bit && fPrefetch)
1704 {
1705 /* Map a 64-bit region above 4GB. */
1706 Assert(!fIsPio);
1707 uNew = pPciRoot->uPciBiosMmio64;
1708 /* Align starting address to region size. */
1709 uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
1710 LogFunc(("Start address of 64-bit MMIO region %u/%u is %#llx\n", iRegion, iRegion + 1, uNew));
1711 devpciR3BiosInitSetRegionAddress(pBus, pPciDev, iRegion, uNew);
1712 fActiveMemRegion = true;
1713 pPciRoot->uPciBiosMmio64 = uNew + cbRegSize64;
1714 Log2Func(("New 64-bit address is %#llx\n", pPciRoot->uPciBiosMmio64));
1715 }
1716 else
1717 {
1718 uint16_t uVendor = devpciR3GetWord(pPciDev, VBOX_PCI_VENDOR_ID);
1719 uint16_t uDevice = devpciR3GetWord(pPciDev, VBOX_PCI_DEVICE_ID);
1720 LogRel(("PCI: no space left for BAR%u of device %u/%u/%u (vendor=%#06x device=%#06x)\n",
1721 iRegion, pBus->iBus, pPciDev->uDevFn >> 3, pPciDev->uDevFn & 7, uVendor, uDevice)); /** @todo make this a VM start failure later. */
1722 /* Undo the mapping mess caused by the size probing. */
1723 devpciR3SetDWord(pPciDev, u32Address, UINT32_C(0));
1724 }
1725 }
1726 else
1727 {
1728 LogFunc(("Start address of %s region %u is %#x\n", (fIsPio ? "I/O" : "MMIO"), iRegion, uNew));
1729 devpciR3BiosInitSetRegionAddress(pBus, pPciDev, iRegion, uNew);
1730 if (fIsPio)
1731 fActiveIORegion = true;
1732 else
1733 fActiveMemRegion = true;
1734 *paddr = uNew + cbRegSize64;
1735 Log2Func(("New 32-bit address is %#x\n", *paddr));
1736 }
1737
1738 if (f64Bit)
1739 iRegion++; /* skip next region */
1740 }
1741 }
1742
1743 /* Update the command word appropriately. */
1744 uint16_t uCmd = devpciR3GetWord(pPciDev, VBOX_PCI_COMMAND);
1745 if (fActiveMemRegion && !fSuppressMem)
1746 uCmd |= VBOX_PCI_COMMAND_MEMORY; /* Enable MMIO access. */
1747 if (fActiveIORegion)
1748 uCmd |= VBOX_PCI_COMMAND_IO; /* Enable I/O space access. */
1749 devpciR3SetWord(pPciDev, VBOX_PCI_COMMAND, uCmd);
1750}
1751
1752static bool ich9pciBiosInitDevicePrefetchableBARs(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, PPDMPCIDEV pPciDev, bool fUse64Bit, bool fDryrun)
1753{
1754 int cRegions = ich9pciBiosInitDeviceGetRegions(pPciDev);
1755 bool fActiveMemRegion = false;
1756 for (int iRegion = 0; iRegion < cRegions; iRegion++)
1757 {
1758 uint32_t u32Address = devpciGetRegionReg(iRegion);
1759 uint8_t u8ResourceType = devpciR3GetByte(pPciDev, u32Address);
1760 bool fPrefetch = (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_IO)))
1761 == PCI_ADDRESS_SPACE_MEM_PREFETCH;
1762 bool f64Bit = (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
1763 == PCI_ADDRESS_SPACE_BAR64;
1764 uint64_t cbRegSize64 = 0;
1765
1766 /* Everything besides prefetchable regions has been set up already. */
1767 if (!fPrefetch)
1768 continue;
1769
1770 if (f64Bit)
1771 {
1772 devpciR3SetDWord(pPciDev, u32Address, UINT32_C(0xffffffff));
1773 devpciR3SetDWord(pPciDev, u32Address+4, UINT32_C(0xffffffff));
1774 cbRegSize64 = RT_MAKE_U64(devpciR3GetDWord(pPciDev, u32Address),
1775 devpciR3GetDWord(pPciDev, u32Address+4));
1776 cbRegSize64 &= ~UINT64_C(0x0f);
1777 cbRegSize64 = (~cbRegSize64) + 1;
1778 }
1779 else
1780 {
1781 uint32_t cbRegSize32;
1782 devpciR3SetDWord(pPciDev, u32Address, UINT32_C(0xffffffff));
1783 cbRegSize32 = devpciR3GetDWord(pPciDev, u32Address);
1784 cbRegSize32 &= ~UINT32_C(0x0f);
1785 cbRegSize32 = (~cbRegSize32) + 1;
1786
1787 cbRegSize64 = cbRegSize32;
1788 }
1789 Log2Func(("Size of region %u for device %d on bus %d is %lld\n", iRegion, pPciDev->uDevFn, pBus->iBus, cbRegSize64));
1790
1791 if (cbRegSize64)
1792 {
1793 uint64_t uNew;
1794 if (!fUse64Bit)
1795 {
1796 uNew = pPciRoot->uPciBiosMmio;
1797 /* Align starting address to region size. */
1798 uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
1799 /* Unconditionally exclude I/O-APIC/HPET/ROM. Pessimistic, but better than causing a mess. Okay for BIOS. */
1800 if ( !uNew
1801 || (uNew <= UINT32_C(0xffffffff) && uNew + cbRegSize64 - 1 >= UINT32_C(0xfec00000))
1802 || uNew >= _4G)
1803 {
1804 Log2Func(("region #%u: Rejecting address range: %#x LB %#RX64\n", iRegion, uNew, cbRegSize64));
1805 Assert(fDryrun);
1806 return true;
1807 }
1808 if (!fDryrun)
1809 {
1810 LogFunc(("Start address of MMIO region %u is %#x\n", iRegion, uNew));
1811 devpciR3BiosInitSetRegionAddress(pBus, pPciDev, iRegion, uNew);
1812 fActiveMemRegion = true;
1813 }
1814 pPciRoot->uPciBiosMmio = uNew + cbRegSize64;
1815 }
1816 else
1817 {
1818 /* Can't handle 32-bit BARs when forcing 64-bit allocs. */
1819 if (!f64Bit)
1820 {
1821 Assert(fDryrun);
1822 return true;
1823 }
1824 uNew = pPciRoot->uPciBiosMmio64;
1825 /* Align starting address to region size. */
1826 uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
1827 pPciRoot->uPciBiosMmio64 = uNew + cbRegSize64;
1828 if (!fDryrun)
1829 {
1830 LogFunc(("Start address of 64-bit MMIO region %u/%u is %#llx\n", iRegion, iRegion + 1, uNew));
1831 devpciR3BiosInitSetRegionAddress(pBus, pPciDev, iRegion, uNew);
1832 fActiveMemRegion = true;
1833 }
1834 }
1835
1836 if (f64Bit)
1837 iRegion++; /* skip next region */
1838 }
1839 }
1840
1841 if (!fDryrun)
1842 {
1843 /* Update the command word appropriately. */
1844 uint16_t uCmd = devpciR3GetWord(pPciDev, VBOX_PCI_COMMAND);
1845 if (fActiveMemRegion)
1846 uCmd |= VBOX_PCI_COMMAND_MEMORY; /* Enable MMIO access. */
1847 devpciR3SetWord(pPciDev, VBOX_PCI_COMMAND, uCmd);
1848 }
1849 else
1850 Assert(!fActiveMemRegion);
1851
1852 return false;
1853}
1854
1855static bool ich9pciBiosInitBridgePrefetchable(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, bool fUse64Bit, bool fDryrun)
1856{
1857 PPDMPCIDEV pBridge = &pBus->PciDev;
1858 Log(("BIOS init bridge (prefetch): %02x:%02x.%d use64bit=%d dryrun=%d\n", pBus->iBus, pBridge->uDevFn >> 3, pBridge->uDevFn & 7, fUse64Bit, fDryrun));
1859
1860 pPciRoot->uPciBiosMmio = RT_ALIGN_32(pPciRoot->uPciBiosMmio, _1M);
1861 pPciRoot->uPciBiosMmio64 = RT_ALIGN_64(pPciRoot->uPciBiosMmio64, _1M);
1862
1863 /* Save values to compare later to. */
1864 uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
1865 uint64_t u64MMIOAddressBase = pPciRoot->uPciBiosMmio64;
1866
1867 /* Init all devices behind the bridge (recursing to further buses). */
1868 bool fRes = ich9pciBiosInitAllDevicesPrefetchableOnBus(pPciRoot, pBus, fUse64Bit, fDryrun);
1869 if (fDryrun)
1870 return fRes;
1871 Assert(!fRes);
1872
1873 /* Set prefetchable MMIO limit register with 1MB boundary. */
1874 uint64_t uBase, uLimit;
1875 if (fUse64Bit)
1876 {
1877 if (u64MMIOAddressBase == pPciRoot->uPciBiosMmio64)
1878 return false;
1879 uBase = u64MMIOAddressBase;
1880 uLimit = RT_ALIGN_64(pPciRoot->uPciBiosMmio64, _1M) - 1;
1881 }
1882 else
1883 {
1884 if (u32MMIOAddressBase == pPciRoot->uPciBiosMmio)
1885 return false;
1886 uBase = u32MMIOAddressBase;
1887 uLimit = RT_ALIGN_32(pPciRoot->uPciBiosMmio, _1M) - 1;
1888 }
1889 devpciR3SetDWord(pBridge, VBOX_PCI_PREF_BASE_UPPER32, uBase >> 32);
1890 devpciR3SetWord(pBridge, VBOX_PCI_PREF_MEMORY_BASE, (uint32_t)(uBase >> 16) & UINT32_C(0xfff0));
1891 devpciR3SetDWord(pBridge, VBOX_PCI_PREF_LIMIT_UPPER32, uLimit >> 32);
1892 devpciR3SetWord(pBridge, VBOX_PCI_PREF_MEMORY_LIMIT, (uint32_t)(uLimit >> 16) & UINT32_C(0xfff0));
1893
1894 return false;
1895}
1896
1897static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, bool fUse64Bit, bool fDryrun)
1898{
1899 /* First pass: assign resources to all devices. */
1900 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
1901 {
1902 PPDMPCIDEV pPciDev = pBus->apDevices[uDevFn];
1903
1904 /* check if device is present */
1905 if (!pPciDev)
1906 continue;
1907
1908 Log(("BIOS init device (prefetch): %02x:%02x.%d\n", pBus->iBus, uDevFn >> 3, uDevFn & 7));
1909
1910 /* prefetchable memory mappings */
1911 bool fRes = ich9pciBiosInitDevicePrefetchableBARs(pPciRoot, pBus, pPciDev, fUse64Bit, fDryrun);
1912 if (fRes)
1913 {
1914 Assert(fDryrun);
1915 return fRes;
1916 }
1917 }
1918
1919 /* Second pass: handle bridges recursively. */
1920 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
1921 {
1922 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
1923 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
1924 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
1925 PDEVPCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
1926
1927 bool fRes = ich9pciBiosInitBridgePrefetchable(pPciRoot, pChildBus, fUse64Bit, fDryrun);
1928 if (fRes)
1929 {
1930 Assert(fDryrun);
1931 return fRes;
1932 }
1933 }
1934 return false;
1935}
1936
1937static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus)
1938{
1939 /* First pass: assign resources to all devices and map the interrupt. */
1940 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
1941 {
1942 PPDMPCIDEV pPciDev = pBus->apDevices[uDevFn];
1943
1944 /* check if device is present */
1945 if (!pPciDev)
1946 continue;
1947
1948 Log(("BIOS init device: %02x:%02x.%d\n", pBus->iBus, uDevFn >> 3, uDevFn & 7));
1949
1950 /* default memory mappings */
1951 ich9pciBiosInitDeviceBARs(pPciRoot, pBus, pPciDev);
1952 uint16_t uDevClass = devpciR3GetWord(pPciDev, VBOX_PCI_CLASS_DEVICE);
1953 switch (uDevClass)
1954 {
1955 case 0x0101:
1956 /* IDE controller */
1957 devpciR3SetWord(pPciDev, 0x40, 0x8000); /* enable IDE0 */
1958 devpciR3SetWord(pPciDev, 0x42, 0x8000); /* enable IDE1 */
1959 break;
1960 case 0x0300:
1961 {
1962 /* VGA controller */
1963
1964 /* NB: Default Bochs VGA LFB address is 0xE0000000. Old guest
1965 * software may break if the framebuffer isn't mapped there.
1966 */
1967
1968 /*
1969 * Legacy VGA I/O ports are implicitly decoded by a VGA class device. But
1970 * only the framebuffer (i.e., a memory region) is explicitly registered via
1971 * ich9pciSetRegionAddress, so don't forget to enable I/O decoding.
1972 */
1973 uint16_t uCmd = devpciR3GetWord(pPciDev, VBOX_PCI_COMMAND);
1974 devpciR3SetWord(pPciDev, VBOX_PCI_COMMAND, uCmd | VBOX_PCI_COMMAND_IO);
1975 break;
1976 }
1977 default:
1978 break;
1979 }
1980
1981 /* map the interrupt */
1982 uint8_t iPin = devpciR3GetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN);
1983 if (iPin != 0)
1984 {
1985 iPin--;
1986
1987 /* We need to go up to the host bus to see which irq pin this
1988 * device will use there. See logic in ich9pcibridgeSetIrq().
1989 */
1990 for (PDEVPCIBUS pParent = pBus; pParent->iBus != 0; pParent = pParent->PciDev.Int.s.pBusR3)
1991 {
1992 /* Get the pin the device would assert on the bridge. */
1993 iPin = ((pParent->PciDev.uDevFn >> 3) + iPin) & 3;
1994 }
1995
1996 int iIrq = aPciIrqs[ich9pciSlotGetPirq(pBus->iBus, uDevFn, iPin)];
1997 Log(("Using pin %d and IRQ %d for device %02x:%02x.%d\n",
1998 iPin, iIrq, pBus->iBus, uDevFn>>3, uDevFn&7));
1999 devpciR3SetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE, iIrq);
2000 }
2001 }
2002
2003 /* Second pass: handle bridges recursively. */
2004 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2005 {
2006 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
2007 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
2008 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
2009 PDEVPCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2010
2011 ich9pciBiosInitBridge(pPciRoot, pChildBus);
2012 }
2013
2014 /* Third pass (only for bus 0): set up prefetchable BARs recursively. */
2015 if (pBus->iBus == 0)
2016 {
2017 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2018 {
2019 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
2020 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
2021 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
2022 PDEVPCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2023
2024 Log(("BIOS init prefetchable memory behind bridge: %02x:%02x.%d\n", pChildBus->iBus, pBridge->uDevFn >> 3, pBridge->uDevFn & 7));
2025 /* Save values for the prefetchable dryruns. */
2026 uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
2027 uint64_t u64MMIOAddressBase = pPciRoot->uPciBiosMmio64;
2028
2029 bool fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, pChildBus, false /* fUse64Bit */, true /* fDryrun */);
2030 pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
2031 pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
2032 if (fProbe)
2033 {
2034 fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, pChildBus, true /* fUse64Bit */, true /* fDryrun */);
2035 pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
2036 pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
2037 if (fProbe)
2038 LogRel(("PCI: unresolvable prefetchable memory behind bridge %02x:%02x.%d\n", pChildBus->iBus, pBridge->uDevFn >> 3, pBridge->uDevFn & 7));
2039 else
2040 ich9pciBiosInitBridgePrefetchable(pPciRoot, pChildBus, true /* fUse64Bit */, false /* fDryrun */);
2041 }
2042 else
2043 ich9pciBiosInitBridgePrefetchable(pPciRoot, pChildBus, false /* fUse64Bit */, false /* fDryrun */);
2044 }
2045 }
2046}
2047
2048/**
2049 * Initializes bridges registers used for routing.
2050 *
2051 * We ASSUME PDM bus assignments are the same as the PCI bus assignments and
2052 * will complain if we find any conflicts. This because it is just soo much
2053 * simpler to have the two numbers match one another by default.
2054 *
2055 * @returns Max subordinate bus number.
2056 * @param pPciRoot Global device instance data used to generate unique bus numbers.
2057 * @param pBus The PCI bus to initialize.
2058 * @param pbmUsed Pointer to a 32-bit bitmap tracking which device
2059 * (ranges) has been used.
2060 * @param uBusPrimary The primary bus number the bus is connected to.
2061 */
2062static uint8_t ich9pciBiosInitBridgeTopology(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, uint32_t *pbmUsed, uint8_t uBusPrimary)
2063{
2064 PPDMPCIDEV pBridgeDev = &pBus->PciDev;
2065
2066 /* Check if the PDM bus assignment makes sense. */
2067 AssertLogRelMsg(!(*pbmUsed & RT_BIT_32(pBus->iBus)),
2068 ("PCIBIOS: Bad PCI bridge config! Conflict for bus %#x. Make sure to instantiate bridges for a sub-trees in sequence!\n",
2069 pBus->iBus));
2070 *pbmUsed |= RT_BIT_32(pBus->iBus);
2071
2072 /* Set only if we are not on the root bus, it has no primary bus attached. */
2073 if (pBus->iBus != 0)
2074 {
2075 devpciR3SetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS, uBusPrimary);
2076 devpciR3SetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS, pBus->iBus);
2077 /* Since the subordinate bus value can only be finalized once we
2078 * finished recursing through everything behind the bridge, the only
2079 * solution is temporarily configuring the subordinate to the maximum
2080 * possible value. This makes sure that the config space accesses work
2081 * (for our own sloppy emulation it apparently doesn't matter, but
2082 * this is vital for real PCI bridges/devices in passthrough mode). */
2083 devpciR3SetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, 0xff);
2084 }
2085
2086 uint8_t uMaxSubNum = pBus->iBus;
2087 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2088 {
2089 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
2090 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
2091 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
2092 PDEVPCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2093 uint8_t uMaxChildSubBus = ich9pciBiosInitBridgeTopology(pPciRoot, pChildBus, pbmUsed, pBus->iBus);
2094 uMaxSubNum = RT_MAX(uMaxSubNum, uMaxChildSubBus);
2095 }
2096
2097 if (pBus->iBus != 0)
2098 devpciR3SetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, uMaxSubNum);
2099 for (uint32_t i = pBus->iBus; i <= uMaxSubNum; i++)
2100 *pbmUsed |= RT_BIT_32(i);
2101
2102 /* Make sure that transactions are able to get through the bridge. Not
2103 * strictly speaking necessary this early (before any device is set up),
2104 * but on the other hand it can't hurt either. */
2105 if (pBus->iBus != 0)
2106 devpciR3SetWord(pBridgeDev, VBOX_PCI_COMMAND,
2107 VBOX_PCI_COMMAND_IO
2108 | VBOX_PCI_COMMAND_MEMORY
2109 | VBOX_PCI_COMMAND_MASTER);
2110
2111 /* safe, only needs to go to the config space array */
2112 Log2Func(("for bus %p: primary=%d secondary=%d subordinate=%d\n",
2113 pBus,
2114 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS),
2115 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS),
2116 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS)
2117 ));
2118
2119 return uMaxSubNum;
2120}
2121
2122
2123/**
2124 * Worker for Fake PCI BIOS config
2125 *
2126 * @returns VBox status code.
2127 *
2128 * @param pDevIns ICH9 device instance.
2129 */
2130static int ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
2131{
2132 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
2133 PVM pVM = PDMDevHlpGetVM(pDevIns);
2134 uint32_t const cbBelow4GB = MMR3PhysGetRamSizeBelow4GB(pVM);
2135 uint64_t const cbAbove4GB = MMR3PhysGetRamSizeAbove4GB(pVM);
2136
2137 LogRel(("PCI: setting up topology, resources and interrupts\n"));
2138
2139 /** @todo r=klaus this needs to do the same elcr magic as DevPCI.cpp, as the BIOS can't be trusted to do the right thing. Of course it's more difficult than with the old code, as there are bridges to be handled. The interrupt routing needs to be taken into account. Also I highly suspect that the chipset has 8 interrupt lines which we might be able to use for handling things on the root bus better (by treating them as devices on the mainboard). */
2140
2141 /*
2142 * Set the start addresses.
2143 */
2144 pPciRoot->uPciBiosBus = 0;
2145 pPciRoot->uPciBiosIo = 0xd000;
2146 pPciRoot->uPciBiosMmio = cbBelow4GB;
2147 pPciRoot->uPciBiosMmio64 = cbAbove4GB + _4G;
2148
2149 /* NB: Assume that if PCI controller MMIO range is enabled, it is below the beginning of the memory hole. */
2150 if (pPciRoot->u64PciConfigMMioAddress)
2151 {
2152 AssertRelease(pPciRoot->u64PciConfigMMioAddress >= cbBelow4GB);
2153 pPciRoot->uPciBiosMmio = pPciRoot->u64PciConfigMMioAddress + pPciRoot->u64PciConfigMMioLength;
2154 }
2155 Log(("cbBelow4GB: %#RX32, uPciBiosMmio: %#RX64, cbAbove4GB: %#RX64, uPciBiosMmio64=%#RX64\n",
2156 cbBelow4GB, pPciRoot->uPciBiosMmio, cbAbove4GB, pPciRoot->uPciBiosMmio64));
2157
2158 /*
2159 * Assign bridge topology, for further routing to work.
2160 */
2161 PDEVPCIBUS pBus = &pPciRoot->PciBus;
2162 AssertLogRel(pBus->iBus == 0);
2163 uint32_t bmUsed = 0;
2164 ich9pciBiosInitBridgeTopology(pPciRoot, pBus, &bmUsed, 0);
2165
2166 /*
2167 * Init all devices on bus 0 (recursing to further buses).
2168 */
2169 ich9pciBiosInitAllDevicesOnBus(pPciRoot, pBus);
2170
2171 return VINF_SUCCESS;
2172}
2173
2174
2175/* -=-=-=-=-=- PCI Config Space -=-=-=-=-=- */
2176
2177
2178/**
2179 * @callback_method_impl{PFNPCICONFIGREAD, Default config space read callback.}
2180 */
2181DECLCALLBACK(uint32_t) devpciR3CommonDefaultConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb)
2182{
2183 NOREF(pDevIns);
2184
2185 uint32_t uValue;
2186 if (uAddress + cb <= 256)
2187 {
2188 switch (cb)
2189 {
2190 case 1:
2191 /* safe, only needs to go to the config space array */
2192 uValue = PDMPciDevGetByte(pPciDev, uAddress);
2193 break;
2194 case 2:
2195 /* safe, only needs to go to the config space array */
2196 uValue = PDMPciDevGetWord(pPciDev, uAddress);
2197 break;
2198 case 4:
2199 /* safe, only needs to go to the config space array */
2200 uValue = PDMPciDevGetDWord(pPciDev, uAddress);
2201 break;
2202 default:
2203 AssertFailed();
2204 uValue = 0;
2205 break;
2206 }
2207
2208#ifdef LOG_ENABLED
2209 if ( pciDevIsMsiCapable(pPciDev)
2210 && uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset < (uint32_t)pPciDev->Int.s.u8MsiCapSize )
2211 Log2Func(("MSI CAP: %#x LB %u -> %#x\n", uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset, cb, uValue));
2212 else if ( pciDevIsMsixCapable(pPciDev)
2213 && uAddress - (uint32_t)pPciDev->Int.s.u8MsixCapOffset < (uint32_t)pPciDev->Int.s.u8MsixCapSize)
2214 Log2Func(("MSI-X CAP: %#x LB %u -> %#x\n", uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset, cb, uValue));
2215#endif
2216 }
2217 else
2218 {
2219 if (uAddress + cb < _4K)
2220 LogRel(("PCI: %8s/%u: Read from extended register %d fallen back to generic code\n",
2221 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, uAddress));
2222 else
2223 AssertFailed();
2224 uValue = 0;
2225 }
2226 return uValue;
2227}
2228
2229
2230/**
2231 * Worker for devpciR3ResetDevice and devpciR3UpdateMappings that unmaps a region.
2232 *
2233 * @returns VBox status code.
2234 * @param pDev The PCI device.
2235 * @param iRegion The region to unmap.
2236 */
2237static int devpciR3UnmapRegion(PPDMPCIDEV pDev, int iRegion)
2238{
2239 PCIIORegion *pRegion = &pDev->Int.s.aIORegions[iRegion];
2240 AssertReturn(pRegion->size != 0, VINF_SUCCESS);
2241
2242 int rc;
2243 if (pRegion->addr == INVALID_PCI_ADDRESS)
2244 rc = VINF_SUCCESS;
2245 else
2246 {
2247 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2248 {
2249 /* Port IO */
2250 rc = PDMDevHlpIOPortDeregister(pDev->Int.s.pDevInsR3, pRegion->addr, pRegion->size);
2251 AssertRC(rc);
2252 }
2253 else
2254 {
2255 PDEVPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
2256 RTGCPHYS GCPhysBase = pRegion->addr;
2257 if (pBus->pPciHlpR3->pfnIsMMIOExBase(pBus->pDevInsR3, pDev->Int.s.pDevInsR3, GCPhysBase))
2258 {
2259 /* unmap it. */
2260 rc = pRegion->map_func(pDev->Int.s.pDevInsR3, pDev, iRegion,
2261 NIL_RTGCPHYS, pRegion->size, (PCIADDRESSSPACE)(pRegion->type));
2262 AssertRC(rc);
2263 rc = PDMDevHlpMMIOExUnmap(pDev->Int.s.pDevInsR3, pDev, iRegion, GCPhysBase);
2264 }
2265 else
2266 rc = PDMDevHlpMMIODeregister(pDev->Int.s.pDevInsR3, GCPhysBase, pRegion->size);
2267 AssertRC(rc);
2268 }
2269 pRegion->addr = INVALID_PCI_ADDRESS;
2270 }
2271 return rc;
2272}
2273
2274
2275/**
2276 * Worker for devpciR3CommonDefaultConfigWrite that updates BAR and ROM mappings.
2277 *
2278 * @returns VINF_SUCCESS of DBGFSTOP result.
2279 * @param pPciDev The PCI device to update the mappings for.
2280 * @param fP2PBridge Whether this is a PCI to PCI bridge or not.
2281 */
2282static VBOXSTRICTRC devpciR3UpdateMappings(PPDMPCIDEV pPciDev, bool fP2PBridge)
2283{
2284 /* safe, only needs to go to the config space array */
2285 uint16_t const u16Cmd = PDMPciDevGetWord(pPciDev, VBOX_PCI_COMMAND);
2286 Log4(("devpciR3UpdateMappings: dev %u/%u (%s): u16Cmd=%#x\n",
2287 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK, pPciDev->pszNameR3, u16Cmd));
2288 for (unsigned iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
2289 {
2290 /* Skip over BAR2..BAR5 for bridges, as they have a different meaning there. */
2291 if (fP2PBridge && iRegion >= 2 && iRegion <= 5)
2292 continue;
2293 PCIIORegion *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2294 uint64_t const cbRegion = pRegion->size;
2295 if (cbRegion != 0)
2296 {
2297 uint32_t const offCfgReg = devpciGetRegionReg(iRegion);
2298 bool const f64Bit = (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
2299 == PCI_ADDRESS_SPACE_BAR64;
2300 uint64_t uNew = INVALID_PCI_ADDRESS;
2301
2302 /*
2303 * Port I/O region. Check if mapped and within 1..65535 range.
2304 */
2305 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2306 {
2307 if (u16Cmd & VBOX_PCI_COMMAND_IO)
2308 {
2309 /* safe, only needs to go to the config space array */
2310 uint32_t uIoBase = PDMPciDevGetDWord(pPciDev, offCfgReg);
2311 uIoBase &= ~(uint32_t)(cbRegion - 1);
2312
2313 uint64_t uLast = cbRegion - 1 + uIoBase;
2314 if ( uLast < _64K
2315 && uIoBase < uLast
2316 && uIoBase > 0)
2317 uNew = uIoBase;
2318 else
2319 Log4(("devpciR3UpdateMappings: dev %u/%u (%s): region #%u: Disregarding invalid I/O port range: %#RX32..%#RX64\n",
2320 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK,
2321 pPciDev->pszNameR3, iRegion, uIoBase, uLast));
2322 }
2323 }
2324 /*
2325 * MMIO or ROM. Check ROM enable bit and range.
2326 *
2327 * Note! We exclude the I/O-APIC/HPET/ROM area at the end of the first 4GB to
2328 * prevent the (fake) PCI BIOS and others from making a mess. Pure paranoia.
2329 * Additionally addresses with the top 32 bits all set are excluded, to
2330 * catch silly OSes which probe 64-bit BARs without disabling the
2331 * corresponding transactions.
2332 *
2333 * Update: The pure paranoia above broke NT 3.51, so it was changed to only
2334 * exclude the 64KB BIOS mapping at the top. NT 3.51 excludes the
2335 * top 256KB, btw.
2336 */
2337 /** @todo Query upper boundrary from CPUM and PGMPhysRom instead of making
2338 * incorrect assumptions. */
2339 else if (u16Cmd & VBOX_PCI_COMMAND_MEMORY)
2340 {
2341 /* safe, only needs to go to the config space array */
2342 uint64_t uMemBase = PDMPciDevGetDWord(pPciDev, offCfgReg);
2343 if (f64Bit)
2344 {
2345 Assert(iRegion < VBOX_PCI_ROM_SLOT);
2346 /* safe, only needs to go to the config space array */
2347 uMemBase |= (uint64_t)PDMPciDevGetDWord(pPciDev, offCfgReg + 4) << 32;
2348 }
2349 if ( iRegion != PCI_ROM_SLOT
2350 || (uMemBase & RT_BIT_32(0))) /* ROM enable bit. */
2351 {
2352 uMemBase &= ~(cbRegion - 1);
2353
2354 uint64_t uLast = uMemBase + cbRegion - 1;
2355 if ( uMemBase < uLast
2356 && uMemBase > 0)
2357 {
2358 if ( ( uMemBase > UINT32_C(0xffffffff)
2359 || uLast < UINT32_C(0xffff0000) ) /* UINT32_C(0xfec00000) - breaks NT3.51! */
2360 && uMemBase < UINT64_C(0xffffffff00000000) )
2361 uNew = uMemBase;
2362 else
2363 Log(("devpciR3UpdateMappings: dev %u/%u (%s): region #%u: Rejecting address range: %#RX64..%#RX64!\n",
2364 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK,
2365 pPciDev->pszNameR3, iRegion, uMemBase, uLast));
2366 }
2367 else
2368 Log2(("devpciR3UpdateMappings: dev %u/%u (%s): region #%u: Disregarding invalid address range: %#RX64..%#RX64\n",
2369 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK,
2370 pPciDev->pszNameR3, iRegion, uMemBase, uLast));
2371 }
2372 }
2373
2374 /*
2375 * Do real unmapping and/or mapping if the address change.
2376 */
2377 Log4(("devpciR3UpdateMappings: dev %u/%u (%s): iRegion=%u addr=%#RX64 uNew=%#RX64\n",
2378 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK, pPciDev->pszNameR3,
2379 iRegion, pRegion->addr, uNew));
2380 if (uNew != pRegion->addr)
2381 {
2382 LogRel2(("PCI: config dev %u/%u (%s) BAR%i: %#RX64 -> %#RX64 (LB %RX64 (%RU64))\n",
2383 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK,
2384 pPciDev->pszNameR3, iRegion, pRegion->addr, uNew, cbRegion, cbRegion));
2385
2386 devpciR3UnmapRegion(pPciDev, iRegion);
2387 pRegion->addr = uNew;
2388 if (uNew != INVALID_PCI_ADDRESS)
2389 {
2390 int rc = pRegion->map_func(pPciDev->Int.s.pDevInsR3, pPciDev, iRegion, uNew, cbRegion,
2391 (PCIADDRESSSPACE)(pRegion->type));
2392 AssertRC(rc);
2393 }
2394 }
2395
2396 if (f64Bit)
2397 iRegion++;
2398 }
2399 /* else: size == 0: unused region */
2400 }
2401
2402 return VINF_SUCCESS;
2403}
2404
2405
2406/**
2407 * Worker for devpciR3CommonDefaultConfigWrite that write a byte to a BAR.
2408 *
2409 * @param pPciDev The PCI device.
2410 * @param iRegion The region.
2411 * @param off The BAR offset.
2412 * @param bVal The byte to write.
2413 */
2414DECLINLINE(void) devpciR3WriteBarByte(PPDMPCIDEV pPciDev, uint32_t iRegion, uint32_t off, uint8_t bVal)
2415{
2416 PCIIORegion *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2417 Log3Func(("region=%d off=%d val=%#x size=%#llx\n", iRegion, off, bVal, pRegion->size));
2418 Assert(off <= 3);
2419
2420 /* Check if we're writing to upper part of 64-bit BAR. */
2421 if (pRegion->type == 0xff)
2422 {
2423 AssertLogRelReturnVoid(iRegion > 0 && iRegion < VBOX_PCI_ROM_SLOT);
2424 pRegion--;
2425 iRegion--;
2426 off += 4;
2427 Assert(pRegion->type & PCI_ADDRESS_SPACE_BAR64);
2428 }
2429
2430 /* Ignore zero sized regions (they don't exist). */
2431 if (pRegion->size != 0)
2432 {
2433 uint32_t uAddr = devpciGetRegionReg(iRegion) + off;
2434 Assert((pRegion->size & (pRegion->size - 1)) == 0); /* Region size must be power of two. */
2435 uint8_t bMask = ( (pRegion->size - 1) >> (off * 8) ) & 0xff;
2436 if (off == 0)
2437 bMask |= (pRegion->type & PCI_ADDRESS_SPACE_IO)
2438 ? (1 << 2) - 1 /* 2 lowest bits for IO region */ :
2439 (1 << 4) - 1 /* 4 lowest bits for memory region, also ROM enable bit for ROM region */;
2440
2441 /* safe, only needs to go to the config space array */
2442 uint8_t bOld = PDMPciDevGetByte(pPciDev, uAddr) & bMask;
2443 bVal = (bOld & bMask) | (bVal & ~bMask);
2444
2445 Log3Func(("%x changed to %x\n", bOld, bVal));
2446
2447 /* safe, only needs to go to the config space array */
2448 PDMPciDevSetByte(pPciDev, uAddr, bVal);
2449 }
2450}
2451
2452
2453/**
2454 * Checks if the given configuration byte is writable.
2455 *
2456 * @returns true if writable, false if not
2457 * @param uAddress The config space byte byte.
2458 * @param bHeaderType The device header byte.
2459 */
2460DECLINLINE(bool) devpciR3IsConfigByteWritable(uint32_t uAddress, uint8_t bHeaderType)
2461{
2462 switch (bHeaderType)
2463 {
2464 case 0x00: /* normal device */
2465 case 0x80: /* multi-function device */
2466 switch (uAddress)
2467 {
2468 /* Read-only registers. */
2469 case VBOX_PCI_VENDOR_ID:
2470 case VBOX_PCI_VENDOR_ID+1:
2471 case VBOX_PCI_DEVICE_ID:
2472 case VBOX_PCI_DEVICE_ID+1:
2473 case VBOX_PCI_REVISION_ID:
2474 case VBOX_PCI_CLASS_PROG:
2475 case VBOX_PCI_CLASS_SUB:
2476 case VBOX_PCI_CLASS_BASE:
2477 case VBOX_PCI_HEADER_TYPE:
2478 case VBOX_PCI_SUBSYSTEM_VENDOR_ID:
2479 case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1:
2480 case VBOX_PCI_SUBSYSTEM_ID:
2481 case VBOX_PCI_SUBSYSTEM_ID+1:
2482 case VBOX_PCI_ROM_ADDRESS:
2483 case VBOX_PCI_ROM_ADDRESS+1:
2484 case VBOX_PCI_ROM_ADDRESS+2:
2485 case VBOX_PCI_ROM_ADDRESS+3:
2486 case VBOX_PCI_CAPABILITY_LIST:
2487 case VBOX_PCI_INTERRUPT_PIN:
2488 return false;
2489 /* Other registers can be written. */
2490 default:
2491 return true;
2492 }
2493 break;
2494 case 0x01: /* PCI-PCI bridge */
2495 switch (uAddress)
2496 {
2497 /* Read-only registers. */
2498 case VBOX_PCI_VENDOR_ID:
2499 case VBOX_PCI_VENDOR_ID+1:
2500 case VBOX_PCI_DEVICE_ID:
2501 case VBOX_PCI_DEVICE_ID+1:
2502 case VBOX_PCI_REVISION_ID:
2503 case VBOX_PCI_CLASS_PROG:
2504 case VBOX_PCI_CLASS_SUB:
2505 case VBOX_PCI_CLASS_BASE:
2506 case VBOX_PCI_HEADER_TYPE:
2507 case VBOX_PCI_ROM_ADDRESS_BR:
2508 case VBOX_PCI_ROM_ADDRESS_BR+1:
2509 case VBOX_PCI_ROM_ADDRESS_BR+2:
2510 case VBOX_PCI_ROM_ADDRESS_BR+3:
2511 case VBOX_PCI_INTERRUPT_PIN:
2512 return false;
2513 /* Other registers can be written. */
2514 default:
2515 return true;
2516 }
2517 break;
2518 default:
2519 AssertMsgFailed(("Unknown header type %#x\n", bHeaderType));
2520 return false;
2521 }
2522}
2523
2524
2525/**
2526 * @callback_method_impl{PFNPCICONFIGWRITE,
2527 * Default config space write callback.}
2528 *
2529 * See paragraph 7.5 of PCI Express specification (p. 349) for
2530 * definition of registers and their writability policy.
2531 */
2532DECLCALLBACK(VBOXSTRICTRC) devpciR3CommonDefaultConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
2533 uint32_t uAddress, uint32_t u32Value, unsigned cb)
2534{
2535 NOREF(pDevIns);
2536 Assert(cb <= 4);
2537 VBOXSTRICTRC rcRet = VINF_SUCCESS;
2538
2539 if (uAddress + cb <= 256)
2540 {
2541 /*
2542 * MSI and MSI-X capabilites needs to be handled separately.
2543 */
2544 if ( pciDevIsMsiCapable(pPciDev)
2545 && uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset < (uint32_t)pPciDev->Int.s.u8MsiCapSize)
2546 MsiPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
2547 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
2548 pPciDev, uAddress, u32Value, cb);
2549 else if ( pciDevIsMsixCapable(pPciDev)
2550 && uAddress - (uint32_t)pPciDev->Int.s.u8MsixCapOffset < (uint32_t)pPciDev->Int.s.u8MsixCapSize)
2551 MsixPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
2552 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
2553 pPciDev, uAddress, u32Value, cb);
2554 else
2555 {
2556 /*
2557 * Handle the writes byte-by-byte to catch all possible cases.
2558 *
2559 * Note! Real hardware may not necessarily handle non-dword writes like
2560 * we do here and even produce erratic behavior. We don't (yet)
2561 * try emulate that.
2562 */
2563 uint8_t const bHeaderType = devpciR3GetByte(pPciDev, VBOX_PCI_HEADER_TYPE);
2564 bool const fP2PBridge = bHeaderType == 0x01; /* PCI-PCI bridge */
2565 bool fUpdateMappings = false;
2566 while (cb-- > 0)
2567 {
2568 bool fWritable = devpciR3IsConfigByteWritable(uAddress, bHeaderType);
2569 uint8_t bVal = (uint8_t)u32Value;
2570 bool fRom = false;
2571 switch (uAddress)
2572 {
2573 case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */
2574 if (fWritable)
2575 {
2576 /* safe, only needs to go to the config space array */
2577 PDMPciDevSetByte(pPciDev, uAddress, bVal);
2578 fUpdateMappings = true;
2579 }
2580 break;
2581
2582 case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */
2583 if (fWritable)
2584 {
2585 /* don't change reserved bits (11-15) */
2586 bVal &= ~UINT8_C(0xf8);
2587 /* safe, only needs to go to the config space array */
2588 PDMPciDevSetByte(pPciDev, uAddress, bVal);
2589 fUpdateMappings = true;
2590 }
2591 break;
2592
2593 case VBOX_PCI_STATUS: /* Status register, bits 0-7. */
2594 /* don't change read-only bits => actually all lower bits are read-only */
2595 bVal &= ~UINT8_C(0xff);
2596 /* status register, low part: clear bits by writing a '1' to the corresponding bit */
2597 pPciDev->abConfig[uAddress] &= ~bVal;
2598 break;
2599
2600 case VBOX_PCI_STATUS+1: /* Status register, bits 8-15. */
2601 /* don't change read-only bits */
2602 bVal &= ~UINT8_C(0x06);
2603 /* status register, high part: clear bits by writing a '1' to the corresponding bit */
2604 pPciDev->abConfig[uAddress] &= ~bVal;
2605 break;
2606
2607 case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS +1: case VBOX_PCI_ROM_ADDRESS +2: case VBOX_PCI_ROM_ADDRESS +3:
2608 fRom = true;
2609 RT_FALL_THRU();
2610 case VBOX_PCI_BASE_ADDRESS_0: case VBOX_PCI_BASE_ADDRESS_0+1: case VBOX_PCI_BASE_ADDRESS_0+2: case VBOX_PCI_BASE_ADDRESS_0+3:
2611 case VBOX_PCI_BASE_ADDRESS_1: case VBOX_PCI_BASE_ADDRESS_1+1: case VBOX_PCI_BASE_ADDRESS_1+2: case VBOX_PCI_BASE_ADDRESS_1+3:
2612 case VBOX_PCI_BASE_ADDRESS_2: case VBOX_PCI_BASE_ADDRESS_2+1: case VBOX_PCI_BASE_ADDRESS_2+2: case VBOX_PCI_BASE_ADDRESS_2+3:
2613 case VBOX_PCI_BASE_ADDRESS_3: case VBOX_PCI_BASE_ADDRESS_3+1: case VBOX_PCI_BASE_ADDRESS_3+2: case VBOX_PCI_BASE_ADDRESS_3+3:
2614 case VBOX_PCI_BASE_ADDRESS_4: case VBOX_PCI_BASE_ADDRESS_4+1: case VBOX_PCI_BASE_ADDRESS_4+2: case VBOX_PCI_BASE_ADDRESS_4+3:
2615 case VBOX_PCI_BASE_ADDRESS_5: case VBOX_PCI_BASE_ADDRESS_5+1: case VBOX_PCI_BASE_ADDRESS_5+2: case VBOX_PCI_BASE_ADDRESS_5+3:
2616 /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */
2617 if (!fP2PBridge)
2618 {
2619 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2;
2620 devpciR3WriteBarByte(pPciDev, iRegion, uAddress & 0x3, bVal);
2621 fUpdateMappings = true;
2622 break;
2623 }
2624 else if (uAddress < VBOX_PCI_BASE_ADDRESS_2 || uAddress > VBOX_PCI_BASE_ADDRESS_5+3)
2625 {
2626 /* PCI bridges have only BAR0, BAR1 and ROM */
2627 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2;
2628 devpciR3WriteBarByte(pPciDev, iRegion, uAddress & 0x3, bVal);
2629 fUpdateMappings = true;
2630 break;
2631 }
2632 else if ( uAddress == VBOX_PCI_IO_BASE
2633 || uAddress == VBOX_PCI_IO_LIMIT
2634 || uAddress == VBOX_PCI_MEMORY_BASE
2635 || uAddress == VBOX_PCI_MEMORY_LIMIT
2636 || uAddress == VBOX_PCI_PREF_MEMORY_BASE
2637 || uAddress == VBOX_PCI_PREF_MEMORY_LIMIT)
2638 {
2639 /* All bridge address decoders have the low 4 bits
2640 * as readonly, and all but the prefetchable ones
2641 * have the low 4 bits as 0 (the prefetchable have
2642 * it as 1 to show the 64-bit decoder support. */
2643 bVal &= 0xf0;
2644 if ( uAddress == VBOX_PCI_PREF_MEMORY_BASE
2645 || uAddress == VBOX_PCI_PREF_MEMORY_LIMIT)
2646 bVal |= 0x01;
2647 }
2648 /* (bridge config space which isn't a BAR) */
2649 RT_FALL_THRU();
2650 default:
2651 if (fWritable)
2652 /* safe, only needs to go to the config space array */
2653 PDMPciDevSetByte(pPciDev, uAddress, bVal);
2654 break;
2655 }
2656 uAddress++;
2657 u32Value >>= 8;
2658 }
2659
2660 /*
2661 * Update the region mappings if anything changed related to them (command, BARs, ROM).
2662 */
2663 if (fUpdateMappings)
2664 rcRet = devpciR3UpdateMappings(pPciDev, fP2PBridge);
2665 }
2666 }
2667 else if (uAddress + cb <= _4K)
2668 LogRel(("PCI: %8s/%u: Write to extended register %d fallen back to generic code\n",
2669 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, uAddress));
2670 else
2671 AssertMsgFailed(("Write after end of PCI config space\n"));
2672
2673 return rcRet;
2674}
2675
2676
2677/* -=-=-=-=-=- Debug Info Handlers -=-=-=-=-=- */
2678
2679/**
2680 * Indents an info line.
2681 * @param pHlp The info helper.
2682 * @param iIndentLvl The desired indentation level.
2683 */
2684static void devpciR3InfoIndent(PCDBGFINFOHLP pHlp, unsigned iIndentLvl)
2685{
2686 for (unsigned i = 0; i < iIndentLvl; i++)
2687 pHlp->pfnPrintf(pHlp, " ");
2688}
2689
2690static const char *devpciR3InInfoPciBusClassName(uint8_t iBaseClass)
2691{
2692 static const char *s_szBaseClass[] =
2693 {
2694 /* 00h */ "unknown",
2695 /* 01h */ "mass storage controller",
2696 /* 02h */ "network controller",
2697 /* 03h */ "display controller",
2698 /* 04h */ "multimedia controller",
2699 /* 05h */ "memory controller",
2700 /* 06h */ "bridge device",
2701 /* 07h */ "simple communication controllers",
2702 /* 08h */ "base system peripherals",
2703 /* 09h */ "input devices",
2704 /* 0Ah */ "docking stations",
2705 /* 0Bh */ "processors",
2706 /* 0Ch */ "serial bus controllers",
2707 /* 0Dh */ "wireless controller",
2708 /* 0Eh */ "intelligent I/O controllers",
2709 /* 0Fh */ "satellite communication controllers",
2710 /* 10h */ "encryption/decryption controllers",
2711 /* 11h */ "data acquisition and signal processing controllers"
2712 };
2713 if (iBaseClass < RT_ELEMENTS(s_szBaseClass))
2714 return s_szBaseClass[iBaseClass];
2715 if (iBaseClass < 0xFF)
2716 return "reserved";
2717 return "device does not fit in any defined classes";
2718}
2719
2720
2721/**
2722 * Recursive worker for devpciR3InfoPci.
2723 *
2724 * @param pBus The bus to show info for.
2725 * @param pHlp The info helpers.
2726 * @param iIndentLvl The indentation level.
2727 * @param fRegisters Whether to show device registers or not.
2728 */
2729static void devpciR3InfoPciBus(PDEVPCIBUS pBus, PCDBGFINFOHLP pHlp, unsigned iIndentLvl, bool fRegisters)
2730{
2731 /* This has to use the callbacks for accuracy reasons. Otherwise it can get
2732 * confusing in the passthrough case or when the callbacks for some device
2733 * are doing something non-trivial (like implementing an indirect
2734 * passthrough approach), because then the abConfig array is an imprecise
2735 * cache needed for efficiency (so that certain reads can be done from
2736 * R0/RC), but far from authoritative or what the guest would see. */
2737
2738 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
2739 {
2740 PPDMPCIDEV pPciDev = pBus->apDevices[uDevFn];
2741 if (pPciDev != NULL)
2742 {
2743 devpciR3InfoIndent(pHlp, iIndentLvl);
2744
2745 /*
2746 * For passthrough devices MSI/MSI-X mostly reflects the way interrupts delivered to the guest,
2747 * as host driver handles real devices interrupts.
2748 */
2749 pHlp->pfnPrintf(pHlp, "%02x:%02x.%d %s%s: %04x-%04x %s%s%s",
2750 pBus->iBus, (uDevFn >> 3) & 0xff, uDevFn & 0x7,
2751 pPciDev->pszNameR3,
2752 pciDevIsPassthrough(pPciDev) ? " (PASSTHROUGH)" : "",
2753 devpciR3GetWord(pPciDev, VBOX_PCI_VENDOR_ID), devpciR3GetWord(pPciDev, VBOX_PCI_DEVICE_ID),
2754 pBus->fTypeIch9 ? "ICH9" : pBus->fTypePiix3 ? "PIIX3" : "?type?",
2755 pciDevIsMsiCapable(pPciDev) ? " MSI" : "",
2756 pciDevIsMsixCapable(pPciDev) ? " MSI-X" : ""
2757 );
2758 if (devpciR3GetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN) != 0)
2759 {
2760 pHlp->pfnPrintf(pHlp, " IRQ%d", devpciR3GetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE));
2761 pHlp->pfnPrintf(pHlp, " (INTA#->IRQ%d)", 0x10 + ich9pciSlot2ApicIrq(uDevFn >> 3, 0));
2762 }
2763 pHlp->pfnPrintf(pHlp, "\n");
2764 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2765 uint8_t uClassBase = devpciR3GetByte(pPciDev, VBOX_PCI_CLASS_BASE);
2766 uint8_t uClassSub = devpciR3GetByte(pPciDev, VBOX_PCI_CLASS_SUB);
2767 pHlp->pfnPrintf(pHlp, "Class base/sub: %02x%02x (%s)\n",
2768 uClassBase, uClassSub, devpciR3InInfoPciBusClassName(uClassBase));
2769
2770 if (pciDevIsMsiCapable(pPciDev) || pciDevIsMsixCapable(pPciDev))
2771 {
2772 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2773
2774 if (pciDevIsMsiCapable(pPciDev))
2775 pHlp->pfnPrintf(pHlp, "MSI: %s ", MsiIsEnabled(pPciDev) ? "on" : "off");
2776
2777 if (pciDevIsMsixCapable(pPciDev))
2778 pHlp->pfnPrintf(pHlp, "MSI-X: %s ", MsixIsEnabled(pPciDev) ? "on" : "off");
2779
2780 pHlp->pfnPrintf(pHlp, "\n");
2781 }
2782
2783 for (unsigned iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
2784 {
2785 PCIIORegion const *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2786 uint64_t const cbRegion = pRegion->size;
2787
2788 if (cbRegion == 0)
2789 continue;
2790
2791 uint32_t uAddr = devpciR3GetDWord(pPciDev, devpciGetRegionReg(iRegion));
2792 const char * pszDesc;
2793 char szDescBuf[128];
2794
2795 bool f64Bit = (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
2796 == PCI_ADDRESS_SPACE_BAR64;
2797 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2798 {
2799 pszDesc = "IO";
2800 uAddr &= ~0x3;
2801 }
2802 else
2803 {
2804 RTStrPrintf(szDescBuf, sizeof(szDescBuf), "MMIO%s%s",
2805 f64Bit ? "64" : "32",
2806 pRegion->type & PCI_ADDRESS_SPACE_MEM_PREFETCH ? " PREFETCH" : "");
2807 pszDesc = szDescBuf;
2808 uAddr &= ~0xf;
2809 }
2810
2811 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2812 pHlp->pfnPrintf(pHlp, "%s region #%u: ", pszDesc, iRegion);
2813 if (f64Bit)
2814 {
2815 uint32_t u32High = devpciR3GetDWord(pPciDev, devpciGetRegionReg(iRegion+1));
2816 uint64_t u64Addr = RT_MAKE_U64(uAddr, u32High);
2817 pHlp->pfnPrintf(pHlp, "%RX64..%RX64\n", u64Addr, u64Addr + cbRegion - 1);
2818 iRegion++;
2819 }
2820 else
2821 pHlp->pfnPrintf(pHlp, "%x..%x\n", uAddr, uAddr + (uint32_t)cbRegion - 1);
2822 }
2823
2824 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2825 uint16_t iCmd = devpciR3GetWord(pPciDev, VBOX_PCI_COMMAND);
2826 uint16_t iStatus = devpciR3GetWord(pPciDev, VBOX_PCI_STATUS);
2827 pHlp->pfnPrintf(pHlp, "Command: %04x, Status: %04x\n", iCmd, iStatus);
2828 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2829 pHlp->pfnPrintf(pHlp, "Bus master: %s\n", iCmd & VBOX_PCI_COMMAND_MASTER ? "Yes" : "No");
2830 if (iCmd != PDMPciDevGetCommand(pPciDev))
2831 {
2832 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2833 pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: Command: %04x\n", PDMPciDevGetCommand(pPciDev));
2834 }
2835
2836 if (fRegisters)
2837 {
2838 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2839 pHlp->pfnPrintf(pHlp, "PCI registers:\n");
2840 for (unsigned iReg = 0; iReg < 0x100; )
2841 {
2842 unsigned iPerLine = 0x10;
2843 Assert(0x100 % iPerLine == 0);
2844 devpciR3InfoIndent(pHlp, iIndentLvl + 3);
2845
2846 while (iPerLine-- > 0)
2847 pHlp->pfnPrintf(pHlp, "%02x ", devpciR3GetByte(pPciDev, iReg++));
2848 pHlp->pfnPrintf(pHlp, "\n");
2849 }
2850 }
2851 }
2852 }
2853
2854 if (pBus->cBridges > 0)
2855 {
2856 devpciR3InfoIndent(pHlp, iIndentLvl);
2857 pHlp->pfnPrintf(pHlp, "Registered %d bridges, subordinate buses info follows\n", pBus->cBridges);
2858 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2859 {
2860 PDEVPCIBUS pBusSub = PDMINS_2_DATA(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2861 uint8_t uPrimary = devpciR3GetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS);
2862 uint8_t uSecondary = devpciR3GetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS);
2863 uint8_t uSubordinate = devpciR3GetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS);
2864 devpciR3InfoIndent(pHlp, iIndentLvl);
2865 pHlp->pfnPrintf(pHlp, "%02x:%02x.%d: bridge topology: primary=%d secondary=%d subordinate=%d\n",
2866 uPrimary, pBusSub->PciDev.uDevFn >> 3, pBusSub->PciDev.uDevFn & 7,
2867 uPrimary, uSecondary, uSubordinate);
2868 if ( uPrimary != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS)
2869 || uSecondary != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS)
2870 || uSubordinate != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS))
2871 {
2872 devpciR3InfoIndent(pHlp, iIndentLvl);
2873 pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: primary=%d secondary=%d subordinate=%d\n",
2874 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS),
2875 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS),
2876 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS));
2877 }
2878 devpciR3InfoIndent(pHlp, iIndentLvl);
2879 pHlp->pfnPrintf(pHlp, "behind bridge: ");
2880 uint8_t uIoBase = devpciR3GetByte(&pBusSub->PciDev, VBOX_PCI_IO_BASE);
2881 uint8_t uIoLimit = devpciR3GetByte(&pBusSub->PciDev, VBOX_PCI_IO_LIMIT);
2882 pHlp->pfnPrintf(pHlp, "I/O %#06x..%#06x",
2883 (uIoBase & 0xf0) << 8,
2884 (uIoLimit & 0xf0) << 8 | 0xfff);
2885 if (uIoBase > uIoLimit)
2886 pHlp->pfnPrintf(pHlp, " (IGNORED)");
2887 pHlp->pfnPrintf(pHlp, "\n");
2888 devpciR3InfoIndent(pHlp, iIndentLvl);
2889 pHlp->pfnPrintf(pHlp, "behind bridge: ");
2890 uint32_t uMemoryBase = devpciR3GetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_BASE);
2891 uint32_t uMemoryLimit = devpciR3GetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_LIMIT);
2892 pHlp->pfnPrintf(pHlp, "memory %#010x..%#010x",
2893 (uMemoryBase & 0xfff0) << 16,
2894 (uMemoryLimit & 0xfff0) << 16 | 0xfffff);
2895 if (uMemoryBase > uMemoryLimit)
2896 pHlp->pfnPrintf(pHlp, " (IGNORED)");
2897 pHlp->pfnPrintf(pHlp, "\n");
2898 devpciR3InfoIndent(pHlp, iIndentLvl);
2899 pHlp->pfnPrintf(pHlp, "behind bridge: ");
2900 uint32_t uPrefMemoryRegBase = devpciR3GetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_BASE);
2901 uint32_t uPrefMemoryRegLimit = devpciR3GetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_LIMIT);
2902 uint64_t uPrefMemoryBase = (uPrefMemoryRegBase & 0xfff0) << 16;
2903 uint64_t uPrefMemoryLimit = (uPrefMemoryRegLimit & 0xfff0) << 16 | 0xfffff;
2904 if ( (uPrefMemoryRegBase & 0xf) == 1
2905 && (uPrefMemoryRegLimit & 0xf) == 1)
2906 {
2907 uPrefMemoryBase |= (uint64_t)devpciR3GetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_BASE_UPPER32) << 32;
2908 uPrefMemoryLimit |= (uint64_t)devpciR3GetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_LIMIT_UPPER32) << 32;
2909 pHlp->pfnPrintf(pHlp, "64-bit ");
2910 }
2911 else
2912 pHlp->pfnPrintf(pHlp, "32-bit ");
2913 pHlp->pfnPrintf(pHlp, "prefetch memory %#018llx..%#018llx", uPrefMemoryBase, uPrefMemoryLimit);
2914 if (uPrefMemoryBase > uPrefMemoryLimit)
2915 pHlp->pfnPrintf(pHlp, " (IGNORED)");
2916 pHlp->pfnPrintf(pHlp, "\n");
2917 devpciR3InfoPciBus(pBusSub, pHlp, iIndentLvl + 1, fRegisters);
2918 }
2919 }
2920}
2921
2922
2923/**
2924 * @callback_method_impl{FNDBGFHANDLERDEV, 'pci'}
2925 */
2926DECLCALLBACK(void) devpciR3InfoPci(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2927{
2928 PDEVPCIBUS pBus = DEVINS_2_DEVPCIBUS(pDevIns);
2929
2930 if (pszArgs == NULL || !*pszArgs || !strcmp(pszArgs, "basic"))
2931 devpciR3InfoPciBus(pBus, pHlp, 0 /*iIndentLvl*/, false /*fRegisters*/);
2932 else if (!strcmp(pszArgs, "verbose"))
2933 devpciR3InfoPciBus(pBus, pHlp, 0 /*iIndentLvl*/, true /*fRegisters*/);
2934 else
2935 pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'verbose'.\n");
2936}
2937
2938
2939/**
2940 * @callback_method_impl{FNDBGFHANDLERDEV, 'pciirq'}
2941 */
2942DECLCALLBACK(void) devpciR3InfoPciIrq(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2943{
2944 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
2945 NOREF(pszArgs);
2946
2947 pHlp->pfnPrintf(pHlp, "PCI I/O APIC IRQ levels:\n");
2948 for (int i = 0; i < DEVPCI_APIC_IRQ_PINS; ++i)
2949 pHlp->pfnPrintf(pHlp, " IRQ%02d: %u\n", 0x10 + i, pPciRoot->auPciApicIrqLevels[i]);
2950}
2951
2952
2953/**
2954 * @interface_method_impl{PDMDEVREG,pfnConstruct}
2955 */
2956static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2957{
2958 RT_NOREF1(iInstance);
2959 Assert(iInstance == 0);
2960 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2961
2962 /*
2963 * Validate and read configuration.
2964 */
2965 if (!CFGMR3AreValuesValid(pCfg,
2966 "IOAPIC\0"
2967 "GCEnabled\0"
2968 "R0Enabled\0"
2969 "McfgBase\0"
2970 "McfgLength\0"
2971 ))
2972 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2973
2974 /* query whether we got an IOAPIC */
2975 bool fUseIoApic;
2976 int rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fUseIoApic, false);
2977 if (RT_FAILURE(rc))
2978 return PDMDEV_SET_ERROR(pDevIns, rc,
2979 N_("Configuration error: Failed to query boolean value \"IOAPIC\""));
2980
2981 /* check if RC code is enabled. */
2982 bool fGCEnabled;
2983 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
2984 if (RT_FAILURE(rc))
2985 return PDMDEV_SET_ERROR(pDevIns, rc,
2986 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
2987 /* check if R0 code is enabled. */
2988 bool fR0Enabled;
2989 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
2990 if (RT_FAILURE(rc))
2991 return PDMDEV_SET_ERROR(pDevIns, rc,
2992 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
2993
2994 Log(("PCI: fUseIoApic=%RTbool fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fUseIoApic, fGCEnabled, fR0Enabled));
2995
2996 /*
2997 * Init data.
2998 */
2999 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
3000 PDEVPCIBUS pBus = &pPciRoot->PciBus;
3001 /* Zero out everything */
3002 memset(pPciRoot, 0, sizeof(*pPciRoot));
3003 /* And fill values */
3004 if (!fUseIoApic)
3005 return PDMDEV_SET_ERROR(pDevIns, rc,
3006 N_("Must use IO-APIC with ICH9 chipset"));
3007 rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pPciRoot->u64PciConfigMMioAddress, 0);
3008 if (RT_FAILURE(rc))
3009 return PDMDEV_SET_ERROR(pDevIns, rc,
3010 N_("Configuration error: Failed to read \"McfgBase\""));
3011 rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pPciRoot->u64PciConfigMMioLength, 0);
3012 if (RT_FAILURE(rc))
3013 return PDMDEV_SET_ERROR(pDevIns, rc,
3014 N_("Configuration error: Failed to read \"McfgLength\""));
3015
3016 pPciRoot->fUseIoApic = fUseIoApic;
3017 pPciRoot->pDevInsR3 = pDevIns;
3018 pPciRoot->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3019 pPciRoot->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3020
3021 pPciRoot->PciBus.fTypePiix3 = false;
3022 pPciRoot->PciBus.fTypeIch9 = true;
3023 pPciRoot->PciBus.fPureBridge = false;
3024 pPciRoot->PciBus.pDevInsR3 = pDevIns;
3025 pPciRoot->PciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3026 pPciRoot->PciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3027 pPciRoot->PciBus.papBridgesR3 = (PPDMPCIDEV *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPDMPCIDEV) * RT_ELEMENTS(pPciRoot->PciBus.apDevices));
3028 AssertLogRelReturn(pPciRoot->PciBus.papBridgesR3, VERR_NO_MEMORY);
3029
3030 /*
3031 * Register bus
3032 */
3033 PDMPCIBUSREG PciBusReg;
3034 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
3035 PciBusReg.pfnRegisterR3 = pciR3MergedRegister;
3036 PciBusReg.pfnRegisterMsiR3 = ich9pciRegisterMsi;
3037 PciBusReg.pfnIORegionRegisterR3 = devpciR3CommonIORegionRegister;
3038 PciBusReg.pfnSetConfigCallbacksR3 = devpciR3CommonSetConfigCallbacks;
3039 PciBusReg.pfnSetIrqR3 = ich9pciSetIrq;
3040 PciBusReg.pszSetIrqRC = fGCEnabled ? "ich9pciSetIrq" : NULL;
3041 PciBusReg.pszSetIrqR0 = fR0Enabled ? "ich9pciSetIrq" : NULL;
3042 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3, &pBus->iBus);
3043 if (RT_FAILURE(rc))
3044 return PDMDEV_SET_ERROR(pDevIns, rc,
3045 N_("Failed to register ourselves as a PCI Bus"));
3046 Assert(pBus->iBus == 0);
3047 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
3048 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
3049 N_("PCI helper version mismatch; got %#x expected %#x"),
3050 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
3051
3052 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3053 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
3054
3055 /*
3056 * Fill in PCI configs and add them to the bus.
3057 */
3058 /** @todo Disabled for now because this causes error messages with Linux guests.
3059 * The guest loads the x38_edac device which tries to map a memory region
3060 * using an address given at place 0x48 - 0x4f in the PCI config space.
3061 * This fails. because we don't register such a region.
3062 */
3063#if 0
3064 /* Host bridge device */
3065 PDMPciDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */
3066 PDMPciDevSetDeviceId( &pBus->PciDev, 0x29e0); /* Desktop */
3067 PDMPciDevSetRevisionId(&pBus->PciDev, 0x01); /* rev. 01 */
3068 PDMPciDevSetClassBase( &pBus->PciDev, 0x06); /* bridge */
3069 PDMPciDevSetClassSub( &pBus->PciDev, 0x00); /* Host/PCI bridge */
3070 PDMPciDevSetClassProg( &pBus->PciDev, 0x00); /* Host/PCI bridge */
3071 PDMPciDevSetHeaderType(&pBus->PciDev, 0x00); /* bridge */
3072 PDMPciDevSetWord(&pBus->PciDev, VBOX_PCI_SEC_STATUS, 0x0280); /* secondary status */
3073
3074 pBus->PciDev.pDevIns = pDevIns;
3075 /* We register Host<->PCI controller on the bus */
3076 ich9pciRegisterInternal(pBus, 0, &pBus->PciDev, "dram");
3077#endif
3078
3079 /*
3080 * Register I/O ports and save state.
3081 */
3082 rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 1, NULL, ich9pciIOPortAddressWrite, ich9pciIOPortAddressRead, NULL, NULL, "ICH9 (PCI)");
3083 if (RT_FAILURE(rc))
3084 return rc;
3085 rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cfc, 4, NULL, ich9pciIOPortDataWrite, ich9pciIOPortDataRead, NULL, NULL, "ICH9 (PCI)");
3086 if (RT_FAILURE(rc))
3087 return rc;
3088 if (fGCEnabled)
3089 {
3090 rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cf8, 1, NIL_RTGCPTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
3091 if (RT_FAILURE(rc))
3092 return rc;
3093 rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cfc, 4, NIL_RTGCPTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
3094 if (RT_FAILURE(rc))
3095 return rc;
3096 }
3097 if (fR0Enabled)
3098 {
3099 rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cf8, 1, NIL_RTR0PTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
3100 if (RT_FAILURE(rc))
3101 return rc;
3102 rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cfc, 4, NIL_RTR0PTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
3103 if (RT_FAILURE(rc))
3104 return rc;
3105 }
3106
3107 rc = PDMDevHlpIOPortRegister(pDevIns, 0x0410, 1, NULL, ich9pciR3IOPortMagicPCIWrite, ich9pciR3IOPortMagicPCIRead, NULL, NULL, "ICH9 (Fake PCI BIOS trigger)");
3108 if (RT_FAILURE(rc))
3109 return rc;
3110
3111 if (pPciRoot->u64PciConfigMMioAddress != 0)
3112 {
3113 rc = PDMDevHlpMMIORegister(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength, NULL /*pvUser*/,
3114 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
3115 ich9pciMcfgMMIOWrite, ich9pciMcfgMMIORead, "MCFG ranges");
3116 AssertMsgRCReturn(rc, ("rc=%Rrc %#llx/%#llx\n", rc, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength), rc);
3117
3118 if (fGCEnabled)
3119 {
3120 rc = PDMDevHlpMMIORegisterRC(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength,
3121 NIL_RTRCPTR /*pvUser*/, "ich9pciMcfgMMIOWrite", "ich9pciMcfgMMIORead");
3122 AssertRCReturn(rc, rc);
3123 }
3124
3125
3126 if (fR0Enabled)
3127 {
3128 rc = PDMDevHlpMMIORegisterR0(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength,
3129 NIL_RTR0PTR /*pvUser*/, "ich9pciMcfgMMIOWrite", "ich9pciMcfgMMIORead");
3130 AssertRCReturn(rc, rc);
3131 }
3132 }
3133
3134 rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
3135 sizeof(*pBus) + 16*128, "pgm",
3136 NULL, NULL, NULL,
3137 NULL, ich9pciR3SaveExec, NULL,
3138 NULL, ich9pciR3LoadExec, NULL);
3139 if (RT_FAILURE(rc))
3140 return rc;
3141
3142
3143 /** @todo other chipset devices shall be registered too */
3144
3145 PDMDevHlpDBGFInfoRegister(pDevIns, "pci",
3146 "Display PCI bus status. Recognizes 'basic' or 'verbose' as arguments, defaults to 'basic'.",
3147 devpciR3InfoPci);
3148 PDMDevHlpDBGFInfoRegister(pDevIns, "pciirq", "Display PCI IRQ state. (no arguments)", devpciR3InfoPciIrq);
3149
3150 return VINF_SUCCESS;
3151}
3152
3153
3154/**
3155 * @interface_method_impl{PDMDEVREG,pfnDestruct}
3156 */
3157static DECLCALLBACK(int) ich9pciDestruct(PPDMDEVINS pDevIns)
3158{
3159 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
3160 if (pPciRoot->PciBus.papBridgesR3)
3161 {
3162 PDMDevHlpMMHeapFree(pDevIns, pPciRoot->PciBus.papBridgesR3);
3163 pPciRoot->PciBus.papBridgesR3 = NULL;
3164 }
3165 return VINF_SUCCESS;
3166}
3167
3168
3169void devpciR3ResetDevice(PPDMPCIDEV pDev)
3170{
3171 /* Clear regions */
3172 for (int iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
3173 {
3174 PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
3175 if (pRegion->size == 0)
3176 continue;
3177 bool const f64Bit = (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
3178 == PCI_ADDRESS_SPACE_BAR64;
3179
3180 devpciR3UnmapRegion(pDev, iRegion);
3181
3182 if (f64Bit)
3183 iRegion++;
3184 }
3185
3186 if (pciDevIsPassthrough(pDev))
3187 {
3188 // no reset handler - we can do what we need in PDM reset handler
3189 /// @todo is it correct?
3190 }
3191 else
3192 {
3193 devpciR3SetWord(pDev, VBOX_PCI_COMMAND,
3194 devpciR3GetWord(pDev, VBOX_PCI_COMMAND)
3195 & ~(VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY |
3196 VBOX_PCI_COMMAND_MASTER | VBOX_PCI_COMMAND_SPECIAL |
3197 VBOX_PCI_COMMAND_PARITY | VBOX_PCI_COMMAND_SERR |
3198 VBOX_PCI_COMMAND_FAST_BACK | VBOX_PCI_COMMAND_INTX_DISABLE));
3199
3200 /* Bridge device reset handlers processed later */
3201 if (!pciDevIsPci2PciBridge(pDev))
3202 {
3203 devpciR3SetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
3204 devpciR3SetByte(pDev, VBOX_PCI_INTERRUPT_LINE, 0x0);
3205 }
3206
3207 /* Reset MSI message control. */
3208 if (pciDevIsMsiCapable(pDev))
3209 {
3210 devpciR3SetWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL,
3211 devpciR3GetWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL) & 0xff8e);
3212 }
3213
3214 /* Reset MSI-X message control. */
3215 if (pciDevIsMsixCapable(pDev))
3216 {
3217 devpciR3SetWord(pDev, pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL,
3218 devpciR3GetWord(pDev, pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL) & 0x3fff);
3219 }
3220 }
3221}
3222
3223/**
3224 * Returns the PCI express encoding for the given PCI Express Device/Port type string.
3225 *
3226 * @returns PCI express encoding.
3227 * @param pszExpressPortType The string identifier for the port/device type.
3228 */
3229static uint8_t ich9pcibridgeR3GetExpressPortTypeFromString(const char *pszExpressPortType)
3230{
3231 if (!RTStrCmp(pszExpressPortType, "EndPtDev"))
3232 return VBOX_PCI_EXP_TYPE_ENDPOINT;
3233 else if (!RTStrCmp(pszExpressPortType, "LegEndPtDev"))
3234 return VBOX_PCI_EXP_TYPE_LEG_END;
3235 else if (!RTStrCmp(pszExpressPortType, "RootCmplxRootPort"))
3236 return VBOX_PCI_EXP_TYPE_ROOT_PORT;
3237 else if (!RTStrCmp(pszExpressPortType, "ExpressSwUpstream"))
3238 return VBOX_PCI_EXP_TYPE_UPSTREAM;
3239 else if (!RTStrCmp(pszExpressPortType, "ExpressSwDownstream"))
3240 return VBOX_PCI_EXP_TYPE_DOWNSTREAM;
3241 else if (!RTStrCmp(pszExpressPortType, "Express2PciBridge"))
3242 return VBOX_PCI_EXP_TYPE_PCI_BRIDGE;
3243 else if (!RTStrCmp(pszExpressPortType, "Pci2ExpressBridge"))
3244 return VBOX_PCI_EXP_TYPE_PCIE_BRIDGE;
3245 else if (!RTStrCmp(pszExpressPortType, "RootCmplxIntEp"))
3246 return VBOX_PCI_EXP_TYPE_ROOT_INT_EP;
3247 else if (!RTStrCmp(pszExpressPortType, "RootCmplxEc"))
3248 return VBOX_PCI_EXP_TYPE_ROOT_EC;
3249
3250 AssertLogRelMsgFailedReturn(("Unknown express port type specified"), VBOX_PCI_EXP_TYPE_ROOT_INT_EP);
3251}
3252
3253/**
3254 * Recursive worker for ich9pciReset.
3255 *
3256 * @param pDevIns ICH9 bridge (root or PCI-to-PCI) instance.
3257 */
3258static void ich9pciResetBridge(PPDMDEVINS pDevIns)
3259{
3260 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3261
3262 /* PCI-specific reset for each device. */
3263 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
3264 {
3265 if (pBus->apDevices[uDevFn])
3266 devpciR3ResetDevice(pBus->apDevices[uDevFn]);
3267 }
3268
3269 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
3270 {
3271 if (pBus->papBridgesR3[iBridge])
3272 ich9pciResetBridge(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns));
3273 }
3274
3275 /* Reset topology config for non-root bridge. Last thing to do, otherwise
3276 * the secondary and subordinate are instantly unreachable. */
3277 if (pBus->iBus != 0)
3278 {
3279 devpciR3SetByte(&pBus->PciDev, VBOX_PCI_PRIMARY_BUS, 0);
3280 devpciR3SetByte(&pBus->PciDev, VBOX_PCI_SECONDARY_BUS, 0);
3281 devpciR3SetByte(&pBus->PciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
3282 /* Not resetting the address decoders of the bridge to 0, since the
3283 * PCI-to-PCI Bridge spec says that there is no default value. */
3284 }
3285}
3286
3287
3288/**
3289 * @interface_method_impl{PDMDEVREG,pfnReset}
3290 */
3291static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
3292{
3293 /* Reset everything under the root bridge. */
3294 ich9pciResetBridge(pDevIns);
3295}
3296
3297
3298/**
3299 * @interface_method_impl{PDMDEVREG,pfnRelocate}
3300 */
3301DECLCALLBACK(void) devpciR3BusRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
3302{
3303 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3304
3305 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3306 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3307
3308 /* Relocate RC pointers for the attached pci devices. */
3309 for (uint32_t uDevFn = 0; uDevFn < RT_ELEMENTS(pBus->apDevices); uDevFn++)
3310 {
3311 PPDMPCIDEV pDev = pBus->apDevices[uDevFn];
3312 if (pDev)
3313 {
3314 pDev->Int.s.pBusRC += offDelta;
3315 if (pDev->Int.s.pMsixPageRC)
3316 pDev->Int.s.pMsixPageRC += offDelta;
3317 }
3318 }
3319}
3320
3321
3322/**
3323 * @interface_method_impl{PDMDEVREG,pfnRelocate}
3324 */
3325DECLCALLBACK(void) devpciR3RootRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
3326{
3327 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
3328 pPciRoot->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3329
3330 AssertCompileMemberOffset(DEVPCIROOT, PciBus, 0);
3331 devpciR3BusRelocate(pDevIns, offDelta);
3332}
3333
3334
3335/**
3336 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
3337 */
3338static DECLCALLBACK(void *) ich9pcibridgeQueryInterface(PPDMIBASE pInterface, const char *pszIID)
3339{
3340 PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
3341 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
3342 /* Special access to the PDMPCIDEV structure of a ich9pcibridge instance. */
3343 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3344 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIICH9BRIDGEPDMPCIDEV, &pBus->PciDev);
3345 return NULL;
3346}
3347
3348
3349/**
3350 * @interface_method_impl{PDMDEVREG,pfnConstruct}
3351 */
3352static DECLCALLBACK(int) ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
3353 int iInstance,
3354 PCFGMNODE pCfg)
3355{
3356 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
3357
3358 /*
3359 * Validate and read configuration.
3360 */
3361 if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0" "ExpressEnabled\0" "ExpressPortType\0"))
3362 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
3363
3364 /* check if RC code is enabled. */
3365 bool fGCEnabled;
3366 int rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
3367 if (RT_FAILURE(rc))
3368 return PDMDEV_SET_ERROR(pDevIns, rc,
3369 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
3370
3371 /* check if R0 code is enabled. */
3372 bool fR0Enabled;
3373 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
3374 if (RT_FAILURE(rc))
3375 return PDMDEV_SET_ERROR(pDevIns, rc,
3376 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
3377 Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
3378
3379 /* check if we're supposed to implement a PCIe bridge. */
3380 bool fExpress;
3381 rc = CFGMR3QueryBoolDef(pCfg, "ExpressEnabled", &fExpress, false);
3382 if (RT_FAILURE(rc))
3383 return PDMDEV_SET_ERROR(pDevIns, rc,
3384 N_("Configuration error: Failed to query boolean value \"ExpressEnabled\""));
3385
3386 char *pszExpressPortType;
3387 rc = CFGMR3QueryStringAllocDef(pCfg, "ExpressPortType",
3388 &pszExpressPortType, "RootCmplxIntEp");
3389 if (RT_FAILURE(rc))
3390 return PDMDEV_SET_ERROR(pDevIns, rc,
3391 N_("LsiLogic configuration error: failed to read \"ExpressPortType\" as string"));
3392
3393 uint8_t uExpressPortType = ich9pcibridgeR3GetExpressPortTypeFromString(pszExpressPortType);
3394 MMR3HeapFree(pszExpressPortType);
3395
3396 pDevIns->IBase.pfnQueryInterface = ich9pcibridgeQueryInterface;
3397
3398 /*
3399 * Init data and register the PCI bus.
3400 */
3401 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3402 pBus->fTypePiix3 = false;
3403 pBus->fTypeIch9 = true;
3404 pBus->fPureBridge = true;
3405 pBus->pDevInsR3 = pDevIns;
3406 pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3407 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3408 /** @todo r=klaus figure out how to extend this to allow PCIe config space
3409 * extension, which increases the config space from 256 bytes to 4K. */
3410 pBus->papBridgesR3 = (PPDMPCIDEV *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPDMPCIDEV) * RT_ELEMENTS(pBus->apDevices));
3411 AssertLogRelReturn(pBus->papBridgesR3, VERR_NO_MEMORY);
3412
3413 PDMPCIBUSREG PciBusReg;
3414 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
3415 PciBusReg.pfnRegisterR3 = pcibridgeR3MergedRegisterDevice;
3416 PciBusReg.pfnRegisterMsiR3 = ich9pciRegisterMsi;
3417 PciBusReg.pfnIORegionRegisterR3 = devpciR3CommonIORegionRegister;
3418 PciBusReg.pfnSetConfigCallbacksR3 = devpciR3CommonSetConfigCallbacks;
3419 PciBusReg.pfnSetIrqR3 = ich9pcibridgeSetIrq;
3420 PciBusReg.pszSetIrqRC = fGCEnabled ? "ich9pcibridgeSetIrq" : NULL;
3421 PciBusReg.pszSetIrqR0 = fR0Enabled ? "ich9pcibridgeSetIrq" : NULL;
3422 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3, &pBus->iBus);
3423 if (RT_FAILURE(rc))
3424 return PDMDEV_SET_ERROR(pDevIns, rc,
3425 N_("Failed to register ourselves as a PCI Bus"));
3426 Assert(pBus->iBus == (uint32_t)iInstance + 1); /* Can be removed when adding support for multiple bridge implementations. */
3427 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
3428 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
3429 N_("PCI helper version mismatch; got %#x expected %#x"),
3430 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
3431
3432 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3433 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
3434 LogRel(("PCI: Registered bridge instance #%u as PDM bus no %u.\n", iInstance, pBus->iBus));
3435
3436
3437 /* Disable default device locking. */
3438 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
3439 AssertRCReturn(rc, rc);
3440
3441 /*
3442 * Fill in PCI configs and add them to the bus.
3443 */
3444 PDMPciDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */
3445 if (fExpress)
3446 {
3447 PDMPciDevSetDeviceId(&pBus->PciDev, 0x29e1); /* 82X38/X48 Express Host-Primary PCI Express Bridge. */
3448 PDMPciDevSetRevisionId(&pBus->PciDev, 0x01);
3449 }
3450 else
3451 {
3452 PDMPciDevSetDeviceId(&pBus->PciDev, 0x2448); /* 82801 Mobile PCI bridge. */
3453 PDMPciDevSetRevisionId(&pBus->PciDev, 0xf2);
3454 }
3455 PDMPciDevSetClassSub( &pBus->PciDev, 0x04); /* pci2pci */
3456 PDMPciDevSetClassBase( &pBus->PciDev, 0x06); /* PCI_bridge */
3457 if (fExpress)
3458 PDMPciDevSetClassProg(&pBus->PciDev, 0x00); /* Normal decoding. */
3459 else
3460 PDMPciDevSetClassProg(&pBus->PciDev, 0x01); /* Supports subtractive decoding. */
3461 PDMPciDevSetHeaderType(&pBus->PciDev, 0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
3462 if (fExpress)
3463 {
3464 PDMPciDevSetCommand(&pBus->PciDev, VBOX_PCI_COMMAND_SERR);
3465 PDMPciDevSetStatus(&pBus->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* Has capabilities. */
3466 PDMPciDevSetByte(&pBus->PciDev, VBOX_PCI_CACHE_LINE_SIZE, 8); /* 32 bytes */
3467 /* PCI Express */
3468 PDMPciDevSetByte(&pBus->PciDev, 0xa0 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
3469 PDMPciDevSetByte(&pBus->PciDev, 0xa0 + 1, 0); /* next */
3470 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 2,
3471 /* version */ 0x2
3472 | (uExpressPortType << 4));
3473 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 4, VBOX_PCI_EXP_DEVCAP_RBE); /* Device capabilities. */
3474 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 8, 0x0000); /* Device control. */
3475 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 10, 0x0000); /* Device status. */
3476 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 12,
3477 /* Max Link Speed */ 2
3478 | /* Maximum Link Width */ (16 << 4)
3479 | /* Active State Power Management (ASPM) Sopport */ (0 << 10)
3480 | VBOX_PCI_EXP_LNKCAP_LBNC
3481 | /* Port Number */ ((2 + iInstance) << 24)); /* Link capabilities. */
3482 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 16, VBOX_PCI_EXP_LNKCTL_CLOCK); /* Link control. */
3483 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 18,
3484 /* Current Link Speed */ 2
3485 | /* Negotiated Link Width */ (16 << 4)
3486 | VBOX_PCI_EXP_LNKSTA_SL_CLK); /* Link status. */
3487 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 20,
3488 /* Slot Power Limit Value */ (75 << 7)
3489 | /* Physical Slot Number */ (0 << 19)); /* Slot capabilities. */
3490 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 24, 0x0000); /* Slot control. */
3491 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 26, 0x0000); /* Slot status. */
3492 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 28, 0x0000); /* Root control. */
3493 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 30, 0x0000); /* Root capabilities. */
3494 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 32, 0x00000000); /* Root status. */
3495 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 36, 0x00000000); /* Device capabilities 2. */
3496 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 40, 0x0000); /* Device control 2. */
3497 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 42, 0x0000); /* Device status 2. */
3498 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 44,
3499 /* Supported Link Speeds Vector */ (2 << 1)); /* Link capabilities 2. */
3500 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 48,
3501 /* Target Link Speed */ 2); /* Link control 2. */
3502 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 50, 0x0000); /* Link status 2. */
3503 PDMPciDevSetDWord(&pBus->PciDev, 0xa0 + 52, 0x00000000); /* Slot capabilities 2. */
3504 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 56, 0x0000); /* Slot control 2. */
3505 PDMPciDevSetWord(&pBus->PciDev, 0xa0 + 58, 0x0000); /* Slot status 2. */
3506 PDMPciDevSetCapabilityList(&pBus->PciDev, 0xa0);
3507 }
3508 else
3509 {
3510 PDMPciDevSetCommand(&pBus->PciDev, 0x00);
3511 PDMPciDevSetStatus(&pBus->PciDev, 0x20); /* 66MHz Capable. */
3512 }
3513 PDMPciDevSetInterruptLine(&pBus->PciDev, 0x00); /* This device does not assert interrupts. */
3514
3515 /*
3516 * This device does not generate interrupts. Interrupt delivery from
3517 * devices attached to the bus is unaffected.
3518 */
3519 PDMPciDevSetInterruptPin (&pBus->PciDev, 0x00);
3520
3521 if (fExpress)
3522 {
3523 /** @todo r=klaus set up the PCIe config space beyond the old 256 byte
3524 * limit, containing additional capability descriptors. */
3525 }
3526
3527 /*
3528 * Register this PCI bridge. The called function will take care on which bus we will get registered.
3529 */
3530 rc = PDMDevHlpPCIRegisterEx(pDevIns, &pBus->PciDev, PDMPCIDEVREG_CFG_PRIMARY, PDMPCIDEVREG_F_PCI_BRIDGE,
3531 PDMPCIDEVREG_DEV_NO_FIRST_UNUSED, PDMPCIDEVREG_FUN_NO_FIRST_UNUSED, "ich9pcibridge");
3532 if (RT_FAILURE(rc))
3533 return rc;
3534 pBus->PciDev.Int.s.pfnBridgeConfigRead = ich9pcibridgeConfigRead;
3535 pBus->PciDev.Int.s.pfnBridgeConfigWrite = ich9pcibridgeConfigWrite;
3536
3537 /*
3538 * Register SSM handlers. We use the same saved state version as for the host bridge
3539 * to make changes easier.
3540 */
3541 rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
3542 sizeof(*pBus) + 16*128,
3543 "pgm" /* before */,
3544 NULL, NULL, NULL,
3545 NULL, ich9pcibridgeR3SaveExec, NULL,
3546 NULL, ich9pcibridgeR3LoadExec, NULL);
3547 if (RT_FAILURE(rc))
3548 return rc;
3549
3550
3551 return VINF_SUCCESS;
3552}
3553
3554/**
3555 * @interface_method_impl{PDMDEVREG,pfnDestruct}
3556 */
3557static DECLCALLBACK(int) ich9pcibridgeDestruct(PPDMDEVINS pDevIns)
3558{
3559 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3560 if (pBus->papBridgesR3)
3561 {
3562 PDMDevHlpMMHeapFree(pDevIns, pBus->papBridgesR3);
3563 pBus->papBridgesR3 = NULL;
3564 }
3565 return VINF_SUCCESS;
3566}
3567
3568
3569
3570/**
3571 * The PCI bus device registration structure.
3572 */
3573const PDMDEVREG g_DevicePciIch9 =
3574{
3575 /* u32Version */
3576 PDM_DEVREG_VERSION,
3577 /* szName */
3578 "ich9pci",
3579 /* szRCMod */
3580 "VBoxDDRC.rc",
3581 /* szR0Mod */
3582 "VBoxDDR0.r0",
3583 /* pszDescription */
3584 "ICH9 PCI bridge",
3585 /* fFlags */
3586 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
3587 /* fClass */
3588 PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
3589 /* cMaxInstances */
3590 1,
3591 /* cbInstance */
3592 sizeof(DEVPCIROOT),
3593 /* pfnConstruct */
3594 ich9pciConstruct,
3595 /* pfnDestruct */
3596 ich9pciDestruct,
3597 /* pfnRelocate */
3598 devpciR3RootRelocate,
3599 /* pfnMemSetup */
3600 NULL,
3601 /* pfnPowerOn */
3602 NULL,
3603 /* pfnReset */
3604 ich9pciReset,
3605 /* pfnSuspend */
3606 NULL,
3607 /* pfnResume */
3608 NULL,
3609 /* pfnAttach */
3610 NULL,
3611 /* pfnDetach */
3612 NULL,
3613 /* pfnQueryInterface */
3614 NULL,
3615 /* pfnInitComplete */
3616 NULL,
3617 /* pfnPowerOff */
3618 NULL,
3619 /* pfnSoftReset */
3620 NULL,
3621 /* u32VersionEnd */
3622 PDM_DEVREG_VERSION
3623};
3624
3625/**
3626 * The device registration structure
3627 * for the PCI-to-PCI bridge.
3628 */
3629const PDMDEVREG g_DevicePciIch9Bridge =
3630{
3631 /* u32Version */
3632 PDM_DEVREG_VERSION,
3633 /* szName */
3634 "ich9pcibridge",
3635 /* szRCMod */
3636 "VBoxDDRC.rc",
3637 /* szR0Mod */
3638 "VBoxDDR0.r0",
3639 /* pszDescription */
3640 "ICH9 PCI to PCI bridge",
3641 /* fFlags */
3642 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
3643 /* fClass */
3644 PDM_DEVREG_CLASS_BUS_PCI,
3645 /* cMaxInstances */
3646 ~0U,
3647 /* cbInstance */
3648 sizeof(DEVPCIBUS),
3649 /* pfnConstruct */
3650 ich9pcibridgeConstruct,
3651 /* pfnDestruct */
3652 ich9pcibridgeDestruct,
3653 /* pfnRelocate */
3654 devpciR3BusRelocate,
3655 /* pfnMemSetup */
3656 NULL,
3657 /* pfnPowerOn */
3658 NULL,
3659 /* pfnReset */
3660 NULL, /* Must be NULL, to make sure only bus driver handles reset */
3661 /* pfnSuspend */
3662 NULL,
3663 /* pfnResume */
3664 NULL,
3665 /* pfnAttach */
3666 NULL,
3667 /* pfnDetach */
3668 NULL,
3669 /* pfnQueryInterface */
3670 NULL,
3671 /* pfnInitComplete */
3672 NULL,
3673 /* pfnPowerOff */
3674 NULL,
3675 /* pfnSoftReset */
3676 NULL,
3677 /* u32VersionEnd */
3678 PDM_DEVREG_VERSION
3679};
3680
3681#endif /* IN_RING3 */
3682
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette