VirtualBox

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

Last change on this file since 65538 was 65538, checked in by vboxsync, 8 years ago

DevPciIch9.cpp: fix "supports 64-bit prefetchable decoding" value for the bridge's config space

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