VirtualBox

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

Last change on this file since 76565 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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