VirtualBox

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

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

PDM: Address the todos for cleaning up the PDMDEVHLP structure, bring the reserved slots back to the nominal numver and bump the major version (20 ended up being used by 5.1). Eliminate redundant PDMDEVHLP version dependent conditional compilation

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