VirtualBox

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

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

DevPciIch9.cpp: implement init of prefetchable BARs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 136.6 KB
Line 
1/* $Id: DevPciIch9.cpp 65489 2017-01-27 16:12:00Z 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, 0x0, 2);
1623 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, 0x00, 4);
1624 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, 0x00, 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 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, uBase >> 32, 4);
1922 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_BASE, (uint32_t)(uBase >> 16) & UINT32_C(0xfff0), 2);
1923 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, uLimit >> 32, 4);
1924 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_LIMIT, (uint32_t)(uLimit >> 16) & UINT32_C(0xfff0), 2);
1925
1926 return false;
1927}
1928
1929static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus, bool fUse64Bit, bool fDryrun)
1930{
1931 /* First pass: assign resources to all devices. */
1932 for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
1933 {
1934 /* check if device is present */
1935 uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
1936 if (uVendor == 0xffff)
1937 continue;
1938
1939 Log(("BIOS init device (prefetch): %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
1940
1941 /* prefetchable memory mappings */
1942 bool fRes = ich9pciBiosInitDevicePrefetchableBARs(pPciRoot, uBus, uDevFn, fUse64Bit, fDryrun);
1943 if (fRes)
1944 {
1945 Assert(fDryrun);
1946 return fRes;
1947 }
1948 }
1949
1950 /* Second pass: handle bridges recursively. */
1951 for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
1952 {
1953 /* check if device is present */
1954 uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
1955 if (uVendor == 0xffff)
1956 continue;
1957
1958 /* only handle PCI-to-PCI bridges */
1959 uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
1960 if (uDevClass != 0x0604)
1961 continue;
1962
1963 Log(("BIOS init bridge (prefetch): %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
1964 bool fRes = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, fUse64Bit, fDryrun);
1965 if (fRes)
1966 {
1967 Assert(fDryrun);
1968 return fRes;
1969 }
1970 }
1971 return false;
1972}
1973
1974static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus)
1975{
1976 /* First pass: assign resources to all devices and map the interrupt. */
1977 for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
1978 {
1979 /* check if device is present */
1980 uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
1981 if (uVendor == 0xffff)
1982 continue;
1983
1984 Log(("BIOS init device: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
1985
1986 /* default memory mappings */
1987 ich9pciBiosInitDeviceBARs(pPciRoot, uBus, uDevFn);
1988 uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
1989 switch (uDevClass)
1990 {
1991 case 0x0101:
1992 /* IDE controller */
1993 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, 0x40, 0x8000, 2); /* enable IDE0 */
1994 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, 0x42, 0x8000, 2); /* enable IDE1 */
1995 break;
1996 case 0x0300:
1997 {
1998 /* VGA controller */
1999
2000 /* NB: Default Bochs VGA LFB address is 0xE0000000. Old guest
2001 * software may break if the framebuffer isn't mapped there.
2002 */
2003
2004 /*
2005 * Legacy VGA I/O ports are implicitly decoded by a VGA class device. But
2006 * only the framebuffer (i.e., a memory region) is explicitly registered via
2007 * ich9pciSetRegionAddress, so don't forget to enable I/O decoding.
2008 */
2009 uint8_t uCmd = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_COMMAND, 1);
2010 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_COMMAND,
2011 uCmd | VBOX_PCI_COMMAND_IO,
2012 1);
2013 break;
2014 }
2015 default:
2016 break;
2017 }
2018
2019 /* map the interrupt */
2020 uint32_t iPin = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_INTERRUPT_PIN, 1);
2021 if (iPin != 0)
2022 {
2023 iPin--;
2024
2025 if (uBus != 0)
2026 {
2027 /* Find bus this device attached to. */
2028 PDEVPCIBUS pBus = &pPciRoot->PciBus;
2029 while (1)
2030 {
2031 PPDMPCIDEV pBridge = ich9pciFindBridge(pBus, uBus);
2032 if (!pBridge)
2033 {
2034 Assert(false);
2035 break;
2036 }
2037 /* safe, only needs to go to the config space array */
2038 if (uBus == PDMPciDevGetByte(pBridge, VBOX_PCI_SECONDARY_BUS))
2039 {
2040 /* OK, found bus this device attached to. */
2041 break;
2042 }
2043 pBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2044 }
2045
2046 /* We need to go up to the host bus to see which irq pin this
2047 * device will use there. See logic in ich9pcibridgeSetIrq().
2048 */
2049 while (pBus->iBus != 0)
2050 {
2051 /* Get the pin the device would assert on the bridge. */
2052 iPin = ((pBus->PciDev.uDevFn >> 3) + iPin) & 3;
2053 pBus = pBus->PciDev.Int.s.pBusR3;
2054 };
2055 }
2056
2057 int iIrq = aPciIrqs[ich9pciSlotGetPirq(uBus, uDevFn, iPin)];
2058 Log(("Using pin %d and IRQ %d for device %02x:%02x.%d\n",
2059 iPin, iIrq, uBus, uDevFn>>3, uDevFn&7));
2060 ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_INTERRUPT_LINE, iIrq, 1);
2061 }
2062 }
2063
2064 /* Second pass: handle bridges recursively. */
2065 for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
2066 {
2067 /* check if device is present */
2068 uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
2069 if (uVendor == 0xffff)
2070 continue;
2071
2072 /* only handle PCI-to-PCI bridges */
2073 uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
2074 if (uDevClass != 0x0604)
2075 continue;
2076
2077 Log(("BIOS init bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
2078 ich9pciBiosInitBridge(pPciRoot, uBus, uDevFn);
2079 }
2080
2081 /* Third pass (only for bus 0): set up prefetchable bars recursively. */
2082 if (uBus == 0)
2083 {
2084 for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
2085 {
2086 /* check if device is present */
2087 uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
2088 if (uVendor == 0xffff)
2089 continue;
2090
2091 /* only handle PCI-to-PCI bridges */
2092 uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
2093 if (uDevClass != 0x0604)
2094 continue;
2095
2096 Log(("BIOS init prefetchable memory behind bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
2097 /* Save values for the prefetchable dryruns. */
2098 uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
2099 uint64_t u64MMIOAddressBase = pPciRoot->uPciBiosMmio64;
2100
2101 bool fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, false /* fUse64Bit */, true /* fDryrun */);
2102 pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
2103 pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
2104 if (fProbe)
2105 {
2106 fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, true /* fUse64Bit */, true /* fDryrun */);
2107 pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
2108 pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
2109 if (fProbe)
2110 LogRel(("PCI: unresolvable prefetchable memory behind bridge %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
2111 else
2112 ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, true /* fUse64Bit */, false /* fDryrun */);
2113 }
2114 else
2115 ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, false /* fUse64Bit */, false /* fDryrun */);
2116 }
2117 }
2118}
2119
2120/**
2121 * Initializes bridges registers used for routing.
2122 *
2123 * We ASSUME PDM bus assignments are the same as the PCI bus assignments and
2124 * will complain if we find any conflicts. This because it is just soo much
2125 * simpler to have the two numbers match one another by default.
2126 *
2127 * @returns Max subordinate bus number.
2128 * @param pPciRoot Global device instance data used to generate unique bus numbers.
2129 * @param pBus The PCI bus to initialize.
2130 * @param pbmUsed Pointer to a 32-bit bitmap tracking which device
2131 * (ranges) has been used.
2132 * @param uBusPrimary The primary bus number the bus is connected to.
2133 */
2134static uint8_t ich9pciBiosInitBridgeTopology(PDEVPCIROOT pPciRoot, PDEVPCIBUS pBus, uint32_t *pbmUsed, uint8_t uBusPrimary)
2135{
2136 PPDMPCIDEV pBridgeDev = &pBus->PciDev;
2137
2138 /* Check if the PDM bus assignment makes sense. */
2139 AssertLogRelMsg(!(*pbmUsed & RT_BIT_32(pBus->iBus)),
2140 ("PCIBIOS: Bad PCI bridge config! Conflict for bus %#x. Make sure to instantiate bridges for a sub-trees in sequence!\n",
2141 pBus->iBus));
2142 *pbmUsed |= RT_BIT_32(pBus->iBus);
2143
2144 /* Set only if we are not on the root bus, it has no primary bus attached. */
2145 if (pBus->iBus != 0)
2146 {
2147 ich9pciSetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS, uBusPrimary);
2148 ich9pciSetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS, pBus->iBus);
2149 /* Since the subordinate bus value can only be finalized once we
2150 * finished recursing through everything behind the bridge, the only
2151 * solution is temporarily configuring the subordinate to the maximum
2152 * possible value. This makes sure that the config space accesses work
2153 * (for our own sloppy emulation it apparently doesn't matter, but
2154 * this is vital for real PCI bridges/devices in passthrough mode). */
2155 ich9pciSetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, 0xff);
2156 }
2157
2158 uint8_t uMaxSubNum = pBus->iBus;
2159 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2160 {
2161 PPDMPCIDEV pBridge = pBus->papBridgesR3[iBridge];
2162 AssertMsg(pBridge && pciDevIsPci2PciBridge(pBridge),
2163 ("Device is not a PCI bridge but on the list of PCI bridges\n"));
2164 PDEVPCIBUS pChildBus = PDMINS_2_DATA(pBridge->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2165 uint8_t uMaxChildSubBus = ich9pciBiosInitBridgeTopology(pPciRoot, pChildBus, pbmUsed, pBus->iBus);
2166 uMaxSubNum = RT_MAX(uMaxSubNum, uMaxChildSubBus);
2167 }
2168
2169 if (pBus->iBus != 0)
2170 ich9pciSetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS, uMaxSubNum);
2171 for (uint32_t i = pBus->iBus; i <= uMaxSubNum; i++)
2172 *pbmUsed |= RT_BIT_32(i);
2173
2174 /* Make sure that transactions are able to get through the bridge. Not
2175 * strictly speaking necessary this early (before any device is set up),
2176 * but on the other hand it can't hurt either. */
2177 if (pBus->iBus != 0)
2178 ich9pciSetWord(pBridgeDev, VBOX_PCI_COMMAND,
2179 VBOX_PCI_COMMAND_IO
2180 | VBOX_PCI_COMMAND_MEMORY
2181 | VBOX_PCI_COMMAND_MASTER);
2182
2183 /* safe, only needs to go to the config space array */
2184 Log2(("ich9pciBiosInitBridgeTopology: for bus %p: primary=%d secondary=%d subordinate=%d\n",
2185 pBus,
2186 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_PRIMARY_BUS),
2187 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SECONDARY_BUS),
2188 PDMPciDevGetByte(pBridgeDev, VBOX_PCI_SUBORDINATE_BUS)
2189 ));
2190
2191 return uMaxSubNum;
2192}
2193
2194
2195/**
2196 * @interface_method_impl{PDMPCIBUSREG,pfnFakePCIBIOSR3}
2197 */
2198static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
2199{
2200 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
2201 PVM pVM = PDMDevHlpGetVM(pDevIns);
2202 uint32_t const cbBelow4GB = MMR3PhysGetRamSizeBelow4GB(pVM);
2203 uint64_t const cbAbove4GB = MMR3PhysGetRamSizeAbove4GB(pVM);
2204
2205 /*
2206 * Set the start addresses.
2207 */
2208 pPciRoot->uPciBiosBus = 0;
2209 pPciRoot->uPciBiosIo = 0xd000;
2210 pPciRoot->uPciBiosMmio = cbBelow4GB;
2211 pPciRoot->uPciBiosMmio64 = cbAbove4GB + _4G;
2212
2213 /* NB: Assume that if PCI controller MMIO range is enabled, it is below the beginning of the memory hole. */
2214 if (pPciRoot->u64PciConfigMMioAddress)
2215 {
2216 AssertRelease(pPciRoot->u64PciConfigMMioAddress >= cbBelow4GB);
2217 pPciRoot->uPciBiosMmio = pPciRoot->u64PciConfigMMioAddress + pPciRoot->u64PciConfigMMioLength;
2218 }
2219 Log(("cbBelow4GB: %#RX32, uPciBiosMmio: %#RX64, cbAbove4GB: %#RX64, uPciBiosMmio64=%#RX64\n",
2220 cbBelow4GB, pPciRoot->uPciBiosMmio, cbAbove4GB, pPciRoot->uPciBiosMmio64));
2221
2222 /*
2223 * Assign bridge topology, for further routing to work.
2224 */
2225 PDEVPCIBUS pBus = &pPciRoot->PciBus;
2226 AssertLogRel(pBus->iBus == 0);
2227 uint32_t bmUsed = 0;
2228 ich9pciBiosInitBridgeTopology(pPciRoot, pBus, &bmUsed, 0);
2229
2230 /*
2231 * Init all devices on bus 0 (recursing to further buses).
2232 */
2233 ich9pciBiosInitAllDevicesOnBus(pPciRoot, 0);
2234
2235 return VINF_SUCCESS;
2236}
2237
2238
2239/* -=-=-=-=-=- PCI Config Space -=-=-=-=-=- */
2240
2241
2242/**
2243 * @callback_method_impl{PFNPCICONFIGREAD, Default config space read callback.}
2244 */
2245DECLCALLBACK(uint32_t) devpciR3CommonDefaultConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb)
2246{
2247 NOREF(pDevIns);
2248
2249 uint32_t uValue;
2250 if (uAddress + cb <= 256)
2251 {
2252 switch (cb)
2253 {
2254 case 1:
2255 /* safe, only needs to go to the config space array */
2256 uValue = PDMPciDevGetByte(pPciDev, uAddress);
2257 break;
2258 case 2:
2259 /* safe, only needs to go to the config space array */
2260 uValue = PDMPciDevGetWord(pPciDev, uAddress);
2261 break;
2262 case 4:
2263 /* safe, only needs to go to the config space array */
2264 uValue = PDMPciDevGetDWord(pPciDev, uAddress);
2265 break;
2266 default:
2267 AssertFailed();
2268 uValue = 0;
2269 break;
2270 }
2271
2272#ifdef LOG_ENABLED
2273 if ( pciDevIsMsiCapable(pPciDev)
2274 && uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset < (uint32_t)pPciDev->Int.s.u8MsiCapSize )
2275 Log2(("devpciR3CommonDefaultConfigRead: MSI CAP: %#x LB %u -> %#x\n", uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset, cb, uValue));
2276 else if ( pciDevIsMsixCapable(pPciDev)
2277 && uAddress - (uint32_t)pPciDev->Int.s.u8MsixCapOffset < (uint32_t)pPciDev->Int.s.u8MsixCapSize)
2278 Log2(("devpciR3CommonDefaultConfigRead: MSI-X CAP: %#x LB %u -> %#x\n", uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset, cb, uValue));
2279#endif
2280 }
2281 else
2282 {
2283 if (uAddress + cb < 4096)
2284 LogRel(("PCI: %8s/%u: Read from extended register %d fallen back to generic code\n",
2285 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, uAddress));
2286 else
2287 AssertFailed();
2288 uValue = 0;
2289 }
2290 return uValue;
2291}
2292
2293
2294/**
2295 * Worker for ich9pciResetDevice and devpciR3UpdateMappings that unmaps a region.
2296 *
2297 * @returns VBox status code.
2298 * @param pDev The PCI device.
2299 * @param iRegion The region to unmap.
2300 */
2301static int ich9pciUnmapRegion(PPDMPCIDEV pDev, int iRegion)
2302{
2303 PCIIORegion *pRegion = &pDev->Int.s.aIORegions[iRegion];
2304 AssertReturn(pRegion->size != 0, VINF_SUCCESS);
2305
2306 int rc;
2307 if (pRegion->addr == INVALID_PCI_ADDRESS)
2308 rc = VINF_SUCCESS;
2309 else
2310 {
2311 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2312 {
2313 /* Port IO */
2314 rc = PDMDevHlpIOPortDeregister(pDev->Int.s.pDevInsR3, pRegion->addr, pRegion->size);
2315 AssertRC(rc);
2316 }
2317 else
2318 {
2319 PDEVPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
2320 RTGCPHYS GCPhysBase = pRegion->addr;
2321 if (pBus->pPciHlpR3->pfnIsMMIOExBase(pBus->pDevInsR3, pDev->Int.s.pDevInsR3, GCPhysBase))
2322 {
2323 /* unmap it. */
2324 rc = pRegion->map_func(pDev->Int.s.pDevInsR3, pDev, iRegion,
2325 NIL_RTGCPHYS, pRegion->size, (PCIADDRESSSPACE)(pRegion->type));
2326 AssertRC(rc);
2327 rc = PDMDevHlpMMIOExUnmap(pDev->Int.s.pDevInsR3, pDev, iRegion, GCPhysBase);
2328 }
2329 else
2330 rc = PDMDevHlpMMIODeregister(pDev->Int.s.pDevInsR3, GCPhysBase, pRegion->size);
2331 AssertRC(rc);
2332 }
2333 pRegion->addr = INVALID_PCI_ADDRESS;
2334 }
2335 return rc;
2336}
2337
2338
2339/**
2340 * Worker for devpciR3IsConfigByteWritable that update BAR and ROM mappings.
2341 *
2342 * @param pPciDev The PCI device to update the mappings for.
2343 * @param fP2PBridge Whether this is a PCI to PCI bridge or not.
2344 */
2345static void devpciR3UpdateMappings(PPDMPCIDEV pPciDev, bool fP2PBridge)
2346{
2347 uint16_t const u16Cmd = ich9pciGetWord(pPciDev, VBOX_PCI_COMMAND);
2348 for (unsigned iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
2349 {
2350 /* Skip over BAR2..BAR5 for bridges, as they have a different meaning there. */
2351 if (fP2PBridge && iRegion >= 2 && iRegion <= 5)
2352 continue;
2353 PCIIORegion *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2354 uint64_t const cbRegion = pRegion->size;
2355 if (cbRegion != 0)
2356 {
2357 uint32_t const offCfgReg = ich9pciGetRegionReg(iRegion);
2358 bool const f64Bit = (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
2359 == PCI_ADDRESS_SPACE_BAR64;
2360 uint64_t uNew = INVALID_PCI_ADDRESS;
2361
2362 /*
2363 * Port I/O region. Check if mapped and within 1..65535 range.
2364 */
2365 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2366 {
2367 if (u16Cmd & VBOX_PCI_COMMAND_IO)
2368 {
2369 uint32_t uIoBase = ich9pciGetDWord(pPciDev, offCfgReg);
2370 uIoBase &= ~(uint32_t)(cbRegion - 1);
2371
2372 uint64_t uLast = cbRegion - 1 + uIoBase;
2373 if ( uLast < _64K
2374 && uIoBase < uLast
2375 && uIoBase > 0)
2376 uNew = uIoBase;
2377 }
2378 }
2379 /*
2380 * MMIO or ROM. Check ROM enable bit and range.
2381 *
2382 * Note! We exclude the I/O-APIC/HPET/ROM area at the end of the first 4GB to
2383 * prevent the (fake) PCI BIOS and others from making a mess. Pure paranoia.
2384 * Additionally addresses with the top 32 bits all set are excluded, to
2385 * catch silly OSes which probe 64-bit BARs without disabling the
2386 * corresponding transactions.
2387 */
2388 else if (u16Cmd & VBOX_PCI_COMMAND_MEMORY)
2389 {
2390 uint64_t uMemBase = ich9pciGetDWord(pPciDev, offCfgReg);
2391 if (f64Bit)
2392 {
2393 Assert(iRegion < VBOX_PCI_ROM_SLOT);
2394 uMemBase |= (uint64_t)ich9pciGetDWord(pPciDev, offCfgReg + 4) << 32;
2395 }
2396 if ( iRegion != PCI_ROM_SLOT
2397 || (uMemBase & RT_BIT_32(0))) /* ROM enable bit. */
2398 {
2399 uMemBase &= ~(cbRegion - 1);
2400
2401 uint64_t uLast = uMemBase + cbRegion - 1;
2402 if ( uMemBase < uLast
2403 && uMemBase > 0
2404 && !( uMemBase <= UINT32_C(0xffffffff)
2405 && uLast >= UINT32_C(0xfec00000))
2406 && uMemBase < UINT64_C(0xffffffff00000000) )
2407 uNew = uMemBase;
2408 }
2409 }
2410
2411 /*
2412 * Do real unmapping and/or mapping if the address change.
2413 */
2414 if (uNew != pRegion->addr)
2415 {
2416 LogRel2(("PCI: config dev %u/%u (%s) BAR%i: %#RX64 -> %#RX64 (LB %RX64 (%RU64))\n",
2417 pPciDev->uDevFn >> VBOX_PCI_DEVFN_DEV_SHIFT, pPciDev->uDevFn & VBOX_PCI_DEVFN_FUN_MASK,
2418 pPciDev->pszNameR3, iRegion, pRegion->addr, uNew, cbRegion, cbRegion));
2419
2420 ich9pciUnmapRegion(pPciDev, iRegion);
2421 pRegion->addr = uNew;
2422 if (uNew != INVALID_PCI_ADDRESS)
2423 {
2424 int rc = pRegion->map_func(pPciDev->Int.s.pDevInsR3, pPciDev, iRegion, uNew, cbRegion,
2425 (PCIADDRESSSPACE)(pRegion->type));
2426 AssertRC(rc);
2427 }
2428 }
2429
2430 if (f64Bit)
2431 iRegion++;
2432 }
2433 /* else: size == 0: unused region */
2434 }
2435}
2436
2437
2438/**
2439 * Worker for devpciR3CommonDefaultConfigWrite that write a byte to a BAR.
2440 *
2441 * @param pPciDev The PCI device.
2442 * @param iRegion The region.
2443 * @param off The BAR offset.
2444 * @param bVal The byte to write.
2445 */
2446DECLINLINE(void) devpciR3WriteBarByte(PPDMPCIDEV pPciDev, uint32_t iRegion, uint32_t off, uint8_t bVal)
2447{
2448 PCIIORegion *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2449 Log3(("devpciR3WriteBarByte: region=%d off=%d val=%#x size=%#llx\n", iRegion, off, bVal, pRegion->size));
2450 Assert(off <= 3);
2451
2452 /* Check if we're writing to upper part of 64-bit BAR. */
2453 if (pRegion->type == 0xff)
2454 {
2455 AssertLogRelReturnVoid(iRegion > 0 && iRegion < VBOX_PCI_ROM_SLOT);
2456 pRegion--;
2457 iRegion--;
2458 off += 4;
2459 Assert(pRegion->type & PCI_ADDRESS_SPACE_BAR64);
2460 }
2461
2462 /* Ignore zero sized regions (they don't exist). */
2463 if (pRegion->size != 0)
2464 {
2465 uint32_t uAddr = ich9pciGetRegionReg(iRegion) + off;
2466 Assert((pRegion->size & (pRegion->size - 1)) == 0); /* Region size must be power of two. */
2467 uint8_t bMask = ( (pRegion->size - 1) >> (off * 8) ) & 0xff;
2468 if (off == 0)
2469 bMask |= (pRegion->type & PCI_ADDRESS_SPACE_IO)
2470 ? (1 << 2) - 1 /* 2 lowest bits for IO region */ :
2471 (1 << 4) - 1 /* 4 lowest bits for memory region, also ROM enable bit for ROM region */;
2472
2473 /* safe, only needs to go to the config space array */
2474 uint8_t bOld = PDMPciDevGetByte(pPciDev, uAddr) & bMask;
2475 bVal = (bOld & bMask) | (bVal & ~bMask);
2476
2477 Log3(("devpciR3WriteBarByte: %x changed to %x\n", bOld, bVal));
2478
2479 /* safe, only needs to go to the config space array */
2480 PDMPciDevSetByte(pPciDev, uAddr, bVal);
2481 }
2482}
2483
2484
2485/**
2486 * Checks if the given configuration byte is writable.
2487 *
2488 * @returns true if writable, false if not
2489 * @param uAddress The config space byte byte.
2490 * @param bHeaderType The device header byte.
2491 */
2492DECLINLINE(bool) devpciR3IsConfigByteWritable(uint32_t uAddress, uint8_t bHeaderType)
2493{
2494 switch (bHeaderType)
2495 {
2496 case 0x00: /* normal device */
2497 case 0x80: /* multi-function device */
2498 switch (uAddress)
2499 {
2500 /* Read-only registers. */
2501 case VBOX_PCI_VENDOR_ID:
2502 case VBOX_PCI_VENDOR_ID+1:
2503 case VBOX_PCI_DEVICE_ID:
2504 case VBOX_PCI_DEVICE_ID+1:
2505 case VBOX_PCI_REVISION_ID:
2506 case VBOX_PCI_CLASS_PROG:
2507 case VBOX_PCI_CLASS_SUB:
2508 case VBOX_PCI_CLASS_BASE:
2509 case VBOX_PCI_HEADER_TYPE:
2510 case VBOX_PCI_SUBSYSTEM_VENDOR_ID:
2511 case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1:
2512 case VBOX_PCI_SUBSYSTEM_ID:
2513 case VBOX_PCI_SUBSYSTEM_ID+1:
2514 case VBOX_PCI_ROM_ADDRESS:
2515 case VBOX_PCI_ROM_ADDRESS+1:
2516 case VBOX_PCI_ROM_ADDRESS+2:
2517 case VBOX_PCI_ROM_ADDRESS+3:
2518 case VBOX_PCI_CAPABILITY_LIST:
2519 case VBOX_PCI_INTERRUPT_PIN:
2520 return false;
2521 /* Other registers can be written. */
2522 default:
2523 return true;
2524 }
2525 break;
2526 case 0x01: /* PCI-PCI bridge */
2527 switch (uAddress)
2528 {
2529 /* Read-only registers. */
2530 case VBOX_PCI_VENDOR_ID:
2531 case VBOX_PCI_VENDOR_ID+1:
2532 case VBOX_PCI_DEVICE_ID:
2533 case VBOX_PCI_DEVICE_ID+1:
2534 case VBOX_PCI_REVISION_ID:
2535 case VBOX_PCI_CLASS_PROG:
2536 case VBOX_PCI_CLASS_SUB:
2537 case VBOX_PCI_CLASS_BASE:
2538 case VBOX_PCI_HEADER_TYPE:
2539 case VBOX_PCI_ROM_ADDRESS_BR:
2540 case VBOX_PCI_ROM_ADDRESS_BR+1:
2541 case VBOX_PCI_ROM_ADDRESS_BR+2:
2542 case VBOX_PCI_ROM_ADDRESS_BR+3:
2543 case VBOX_PCI_INTERRUPT_PIN:
2544 return false;
2545 /* Other registers can be written. */
2546 default:
2547 return true;
2548 }
2549 break;
2550 default:
2551 AssertMsgFailed(("Unknown header type %#x\n", bHeaderType));
2552 return false;
2553 }
2554}
2555
2556
2557/**
2558 * @callback_method_impl{PFNPCICONFIGWRITE,
2559 * Default config space write callback.}
2560 *
2561 * See paragraph 7.5 of PCI Express specification (p. 349) for
2562 * definition of registers and their writability policy.
2563 */
2564DECLCALLBACK(void) devpciR3CommonDefaultConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
2565 uint32_t uAddress, uint32_t u32Value, unsigned cb)
2566{
2567 NOREF(pDevIns);
2568 Assert(cb <= 4);
2569
2570 if (uAddress + cb <= 256)
2571 {
2572 /*
2573 * MSI and MSI-X capabilites needs to be handled separately.
2574 */
2575 if ( pciDevIsMsiCapable(pPciDev)
2576 && uAddress - (uint32_t)pPciDev->Int.s.u8MsiCapOffset < (uint32_t)pPciDev->Int.s.u8MsiCapSize)
2577 MsiPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
2578 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
2579 pPciDev, uAddress, u32Value, cb);
2580 else if ( pciDevIsMsixCapable(pPciDev)
2581 && uAddress - (uint32_t)pPciDev->Int.s.u8MsixCapOffset < (uint32_t)pPciDev->Int.s.u8MsixCapSize)
2582 MsixPciConfigWrite(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
2583 pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
2584 pPciDev, uAddress, u32Value, cb);
2585 else
2586 {
2587 /*
2588 * Handle the writes byte-by-byte to catch all possible cases.
2589 *
2590 * Note! Real hardware may not necessarily handle non-dword writes like
2591 * we do here and even produce erratic behavior. We don't (yet)
2592 * try emulate that.
2593 */
2594 uint8_t const bHeaderType = ich9pciGetByte(pPciDev, VBOX_PCI_HEADER_TYPE);
2595 bool const fP2PBridge = bHeaderType == 0x01; /* PCI-PCI bridge */
2596 bool fUpdateMappings = false;
2597 while (cb-- > 0)
2598 {
2599 bool fWritable = devpciR3IsConfigByteWritable(uAddress, bHeaderType);
2600 uint8_t bVal = (uint8_t)u32Value;
2601 bool fRom = false;
2602 switch (uAddress)
2603 {
2604 case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */
2605 if (fWritable)
2606 {
2607 /* safe, only needs to go to the config space array */
2608 PDMPciDevSetByte(pPciDev, uAddress, bVal);
2609 fUpdateMappings = true;
2610 }
2611 break;
2612
2613 case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */
2614 if (fWritable)
2615 {
2616 /* don't change reserved bits (11-15) */
2617 bVal &= ~UINT8_C(0xf8);
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_STATUS: /* Status register, bits 0-7. */
2625 /* don't change read-only bits => actually all lower bits are read-only */
2626 bVal &= ~UINT8_C(0xff);
2627 /* status register, low part: clear bits by writing a '1' to the corresponding bit */
2628 pPciDev->abConfig[uAddress] &= ~bVal;
2629 break;
2630
2631 case VBOX_PCI_STATUS+1: /* Status register, bits 8-15. */
2632 /* don't change read-only bits */
2633 bVal &= ~UINT8_C(0x06);
2634 /* status register, high part: clear bits by writing a '1' to the corresponding bit */
2635 pPciDev->abConfig[uAddress] &= ~bVal;
2636 break;
2637
2638 case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS +1: case VBOX_PCI_ROM_ADDRESS +2: case VBOX_PCI_ROM_ADDRESS +3:
2639 fRom = true;
2640 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:
2641 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:
2642 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:
2643 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:
2644 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:
2645 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:
2646 /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */
2647 if (!fP2PBridge)
2648 {
2649 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2;
2650 devpciR3WriteBarByte(pPciDev, iRegion, uAddress & 0x3, bVal);
2651 fUpdateMappings = true;
2652 break;
2653 }
2654 else if (uAddress < VBOX_PCI_BASE_ADDRESS_2 || uAddress > VBOX_PCI_BASE_ADDRESS_5+3)
2655 {
2656 /* PCI bridges have only BAR0, BAR1 and ROM */
2657 uint32_t iRegion = fRom ? VBOX_PCI_ROM_SLOT : (uAddress - VBOX_PCI_BASE_ADDRESS_0) >> 2;
2658 devpciR3WriteBarByte(pPciDev, iRegion, uAddress & 0x3, bVal);
2659 fUpdateMappings = true;
2660 break;
2661 }
2662 /* fall thru (bridge config space which isn't a BAR) */
2663 default:
2664 if (fWritable)
2665 /* safe, only needs to go to the config space array */
2666 PDMPciDevSetByte(pPciDev, uAddress, bVal);
2667 break;
2668 }
2669 uAddress++;
2670 u32Value >>= 8;
2671 }
2672
2673 /*
2674 * Update the region mappings if anything changed related to them (command, BARs, ROM).
2675 */
2676 if (fUpdateMappings)
2677 devpciR3UpdateMappings(pPciDev, fP2PBridge);
2678 }
2679 }
2680 else if (uAddress + cb <= 4096)
2681 LogRel(("PCI: %8s/%u: Write to extended register %d fallen back to generic code\n",
2682 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, uAddress));
2683 else
2684 AssertMsgFailed(("Write after end of PCI config space\n"));
2685}
2686
2687
2688/* -=-=-=-=-=- Debug Info Handlers -=-=-=-=-=- */
2689
2690/**
2691 * Indents an info line.
2692 * @param pHlp The info helper.
2693 * @param iIndentLvl The desired indentation level.
2694 */
2695static void devpciR3InfoIndent(PCDBGFINFOHLP pHlp, unsigned iIndentLvl)
2696{
2697 for (unsigned i = 0; i < iIndentLvl; i++)
2698 pHlp->pfnPrintf(pHlp, " ");
2699}
2700
2701
2702/**
2703 * Recursive worker for devpciR3InfoPci.
2704 *
2705 * @param pBus The bus to show info for.
2706 * @param pHlp The info helpers.
2707 * @param iIndentLvl The indentation level.
2708 * @param fRegisters Whether to show device registers or not.
2709 */
2710static void devpciR3InfoPciBus(PDEVPCIBUS pBus, PCDBGFINFOHLP pHlp, unsigned iIndentLvl, bool fRegisters)
2711{
2712 /* This has to use the callbacks for accuracy reasons. Otherwise it can get
2713 * confusing in the passthrough case or when the callbacks for some device
2714 * are doing something non-trivial (like implementing an indirect
2715 * passthrough approach), because then the abConfig array is an imprecise
2716 * cache needed for efficiency (so that certain reads can be done from
2717 * R0/RC), but far from authoritative or what the guest would see. */
2718
2719 for (uint32_t iDev = 0; iDev < RT_ELEMENTS(pBus->apDevices); iDev++)
2720 {
2721 PPDMPCIDEV pPciDev = pBus->apDevices[iDev];
2722 if (pPciDev != NULL)
2723 {
2724 devpciR3InfoIndent(pHlp, iIndentLvl);
2725
2726 /*
2727 * For passthrough devices MSI/MSI-X mostly reflects the way interrupts delivered to the guest,
2728 * as host driver handles real devices interrupts.
2729 */
2730 pHlp->pfnPrintf(pHlp, "%02x:%02x.%d %s%s: %04x-%04x %s%s%s",
2731 pBus->iBus, (iDev >> 3) & 0xff, iDev & 0x7,
2732 pPciDev->pszNameR3,
2733 pciDevIsPassthrough(pPciDev) ? " (PASSTHROUGH)" : "",
2734 ich9pciGetWord(pPciDev, VBOX_PCI_VENDOR_ID), ich9pciGetWord(pPciDev, VBOX_PCI_DEVICE_ID),
2735 pBus->fTypeIch9 ? "ICH9" : pBus->fTypePiix3 ? "PIIX3" : "?type?",
2736 pciDevIsMsiCapable(pPciDev) ? " MSI" : "",
2737 pciDevIsMsixCapable(pPciDev) ? " MSI-X" : ""
2738 );
2739 if (ich9pciGetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN) != 0)
2740 {
2741 pHlp->pfnPrintf(pHlp, " IRQ%d", ich9pciGetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE));
2742 pHlp->pfnPrintf(pHlp, " (INTA#->IRQ%d)", 0x10 + ich9pciSlot2ApicIrq(iDev >> 3, 0));
2743 }
2744 pHlp->pfnPrintf(pHlp, "\n");
2745
2746 if (pciDevIsMsiCapable(pPciDev) || pciDevIsMsixCapable(pPciDev))
2747 {
2748 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2749
2750 if (pciDevIsMsiCapable(pPciDev))
2751 pHlp->pfnPrintf(pHlp, "MSI:%s ", MsiIsEnabled(pPciDev) ? "on" : "off");
2752
2753 if (pciDevIsMsixCapable(pPciDev))
2754 pHlp->pfnPrintf(pHlp, "MSI-X:%s ", MsixIsEnabled(pPciDev) ? "on" : "off");
2755
2756 pHlp->pfnPrintf(pHlp, "\n");
2757 }
2758
2759 for (unsigned iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
2760 {
2761 PCIIORegion const *pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2762 uint64_t const cbRegion = pRegion->size;
2763
2764 if (cbRegion == 0)
2765 continue;
2766
2767 uint32_t uAddr = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion));
2768 const char * pszDesc;
2769 char szDescBuf[128];
2770
2771 bool f64Bit = (pRegion->type & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
2772 == PCI_ADDRESS_SPACE_BAR64;
2773 if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2774 {
2775 pszDesc = "IO";
2776 uAddr &= ~0x3;
2777 }
2778 else
2779 {
2780 RTStrPrintf(szDescBuf, sizeof(szDescBuf), "MMIO%s%s",
2781 f64Bit ? "64" : "32",
2782 pRegion->type & PCI_ADDRESS_SPACE_MEM_PREFETCH ? " PREFETCH" : "");
2783 pszDesc = szDescBuf;
2784 uAddr &= ~0xf;
2785 }
2786
2787 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2788 pHlp->pfnPrintf(pHlp, "%s region #%u: ", pszDesc, iRegion);
2789 if (f64Bit)
2790 {
2791 uint32_t u32High = ich9pciGetDWord(pPciDev, ich9pciGetRegionReg(iRegion+1));
2792 uint64_t u64Addr = RT_MAKE_U64(uAddr, u32High);
2793 pHlp->pfnPrintf(pHlp, "%RX64..%RX64\n", u64Addr, u64Addr + cbRegion - 1);
2794 iRegion++;
2795 }
2796 else
2797 pHlp->pfnPrintf(pHlp, "%x..%x\n", uAddr, uAddr + (uint32_t)cbRegion - 1);
2798 }
2799
2800 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2801 uint16_t iCmd = ich9pciGetWord(pPciDev, VBOX_PCI_COMMAND);
2802 uint16_t iStatus = ich9pciGetWord(pPciDev, VBOX_PCI_STATUS);
2803 pHlp->pfnPrintf(pHlp, "Command: %04x, Status: %04x\n", iCmd, iStatus);
2804 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2805 pHlp->pfnPrintf(pHlp, "Bus master: %s\n", iCmd & VBOX_PCI_COMMAND_MASTER ? "Yes" : "No");
2806 if (iCmd != PDMPciDevGetCommand(pPciDev))
2807 {
2808 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2809 pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: Command: %04x\n", PDMPciDevGetCommand(pPciDev));
2810 }
2811
2812 if (fRegisters)
2813 {
2814 devpciR3InfoIndent(pHlp, iIndentLvl + 2);
2815 pHlp->pfnPrintf(pHlp, "PCI registers:\n");
2816 for (unsigned iReg = 0; iReg < 0x100; )
2817 {
2818 unsigned iPerLine = 0x10;
2819 Assert(0x100 % iPerLine == 0);
2820 devpciR3InfoIndent(pHlp, iIndentLvl + 3);
2821
2822 while (iPerLine-- > 0)
2823 pHlp->pfnPrintf(pHlp, "%02x ", ich9pciGetByte(pPciDev, iReg++));
2824 pHlp->pfnPrintf(pHlp, "\n");
2825 }
2826 }
2827 }
2828 }
2829
2830 if (pBus->cBridges > 0)
2831 {
2832 devpciR3InfoIndent(pHlp, iIndentLvl);
2833 pHlp->pfnPrintf(pHlp, "Registered %d bridges, subordinate buses info follows\n", pBus->cBridges);
2834 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2835 {
2836 PDEVPCIBUS pBusSub = PDMINS_2_DATA(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns), PDEVPCIBUS);
2837 uint8_t uPrimary = ich9pciGetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS);
2838 uint8_t uSecondary = ich9pciGetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS);
2839 uint8_t uSubordinate = ich9pciGetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS);
2840 devpciR3InfoIndent(pHlp, iIndentLvl);
2841 pHlp->pfnPrintf(pHlp, "bridge topology: primary=%d secondary=%d subordinate=%d\n",
2842 uPrimary, uSecondary, uSubordinate);
2843 if ( uPrimary != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS)
2844 || uSecondary != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS)
2845 || uSubordinate != PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS))
2846 {
2847 devpciR3InfoIndent(pHlp, iIndentLvl);
2848 pHlp->pfnPrintf(pHlp, "CACHE INCONSISTENCY: primary=%d secondary=%d subordinate=%d\n",
2849 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_PRIMARY_BUS),
2850 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SECONDARY_BUS),
2851 PDMPciDevGetByte(&pBusSub->PciDev, VBOX_PCI_SUBORDINATE_BUS));
2852 }
2853 devpciR3InfoIndent(pHlp, iIndentLvl);
2854 pHlp->pfnPrintf(pHlp, "behind bridge: I/O %#06x..%#06x\n",
2855 (ich9pciGetByte(&pBusSub->PciDev, VBOX_PCI_IO_BASE) & 0xf0) << 8,
2856 (ich9pciGetByte(&pBusSub->PciDev, VBOX_PCI_IO_LIMIT) & 0xf0) << 8 | 0xfff);
2857 devpciR3InfoIndent(pHlp, iIndentLvl);
2858 pHlp->pfnPrintf(pHlp, "behind bridge: memory %#010x..%#010x\n",
2859 (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_BASE) & 0xfff0) << 16,
2860 (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_LIMIT) & 0xfff0) << 16 | 0xfffff);
2861 devpciR3InfoIndent(pHlp, iIndentLvl);
2862 pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#018llx..%#018llx\n",
2863 ( ((uint64_t)ich9pciGetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_BASE_UPPER32) << 32)
2864 | (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_BASE) & 0xfff0) << 16),
2865 ( ((uint64_t)ich9pciGetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_LIMIT_UPPER32) << 32)
2866 | (uint32_t)(ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_LIMIT) & 0xfff0) << 16)
2867 | 0xfffff);
2868 devpciR3InfoPciBus(pBusSub, pHlp, iIndentLvl + 1, fRegisters);
2869 }
2870 }
2871}
2872
2873
2874/**
2875 * @callback_method_impl{FNDBGFHANDLERDEV, 'pci'}
2876 */
2877DECLCALLBACK(void) devpciR3InfoPci(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2878{
2879 PDEVPCIBUS pBus = DEVINS_2_DEVPCIBUS(pDevIns);
2880
2881 if (pszArgs == NULL || !*pszArgs || !strcmp(pszArgs, "basic"))
2882 devpciR3InfoPciBus(pBus, pHlp, 0 /*iIndentLvl*/, false /*fRegisters*/);
2883 else if (!strcmp(pszArgs, "verbose"))
2884 devpciR3InfoPciBus(pBus, pHlp, 0 /*iIndentLvl*/, true /*fRegisters*/);
2885 else
2886 pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'verbose'.\n");
2887}
2888
2889
2890/**
2891 * @callback_method_impl{FNDBGFHANDLERDEV, 'pciirq'}
2892 */
2893DECLCALLBACK(void) devpciR3InfoPciIrq(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2894{
2895 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
2896 NOREF(pszArgs);
2897
2898 pHlp->pfnPrintf(pHlp, "PCI I/O APIC IRQ levels:\n");
2899 for (int i = 0; i < DEVPCI_APIC_IRQ_PINS; ++i)
2900 pHlp->pfnPrintf(pHlp, " IRQ%02d: %u\n", 0x10 + i, pPciRoot->auPciApicIrqLevels[i]);
2901}
2902
2903
2904
2905static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2906{
2907 RT_NOREF1(iInstance);
2908 Assert(iInstance == 0);
2909 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2910
2911 /*
2912 * Validate and read configuration.
2913 */
2914 if (!CFGMR3AreValuesValid(pCfg,
2915 "IOAPIC\0"
2916 "GCEnabled\0"
2917 "R0Enabled\0"
2918 "McfgBase\0"
2919 "McfgLength\0"
2920 ))
2921 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2922
2923 /* query whether we got an IOAPIC */
2924 bool fUseIoApic;
2925 int rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fUseIoApic, false);
2926 if (RT_FAILURE(rc))
2927 return PDMDEV_SET_ERROR(pDevIns, rc,
2928 N_("Configuration error: Failed to query boolean value \"IOAPIC\""));
2929
2930 /* check if RC code is enabled. */
2931 bool fGCEnabled;
2932 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
2933 if (RT_FAILURE(rc))
2934 return PDMDEV_SET_ERROR(pDevIns, rc,
2935 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
2936 /* check if R0 code is enabled. */
2937 bool fR0Enabled;
2938 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
2939 if (RT_FAILURE(rc))
2940 return PDMDEV_SET_ERROR(pDevIns, rc,
2941 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
2942
2943 Log(("PCI: fUseIoApic=%RTbool fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fUseIoApic, fGCEnabled, fR0Enabled));
2944
2945 /*
2946 * Init data.
2947 */
2948 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
2949 PDEVPCIBUS pBus = &pPciRoot->PciBus;
2950 /* Zero out everything */
2951 memset(pPciRoot, 0, sizeof(*pPciRoot));
2952 /* And fill values */
2953 if (!fUseIoApic)
2954 return PDMDEV_SET_ERROR(pDevIns, rc,
2955 N_("Must use IO-APIC with ICH9 chipset"));
2956 rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pPciRoot->u64PciConfigMMioAddress, 0);
2957 if (RT_FAILURE(rc))
2958 return PDMDEV_SET_ERROR(pDevIns, rc,
2959 N_("Configuration error: Failed to read \"McfgBase\""));
2960 rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pPciRoot->u64PciConfigMMioLength, 0);
2961 if (RT_FAILURE(rc))
2962 return PDMDEV_SET_ERROR(pDevIns, rc,
2963 N_("Configuration error: Failed to read \"McfgLength\""));
2964
2965 pPciRoot->fUseIoApic = fUseIoApic;
2966 pPciRoot->pDevInsR3 = pDevIns;
2967 pPciRoot->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2968 pPciRoot->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2969
2970 pPciRoot->PciBus.fTypePiix3 = false;
2971 pPciRoot->PciBus.fTypeIch9 = true;
2972 pPciRoot->PciBus.fPureBridge = false;
2973 pPciRoot->PciBus.pDevInsR3 = pDevIns;
2974 pPciRoot->PciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2975 pPciRoot->PciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2976 pPciRoot->PciBus.papBridgesR3 = (PPDMPCIDEV *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPDMPCIDEV) * RT_ELEMENTS(pPciRoot->PciBus.apDevices));
2977 AssertLogRelReturn(pPciRoot->PciBus.papBridgesR3, VERR_NO_MEMORY);
2978
2979 /*
2980 * Register bus
2981 */
2982 PDMPCIBUSREG PciBusReg;
2983 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
2984 PciBusReg.pfnRegisterR3 = pciR3MergedRegister;
2985 PciBusReg.pfnRegisterMsiR3 = ich9pciRegisterMsi;
2986 PciBusReg.pfnIORegionRegisterR3 = devpciR3CommonIORegionRegister;
2987 PciBusReg.pfnSetConfigCallbacksR3 = devpciR3CommonSetConfigCallbacks;
2988 PciBusReg.pfnSetIrqR3 = ich9pciSetIrq;
2989 PciBusReg.pfnFakePCIBIOSR3 = ich9pciFakePCIBIOS;
2990 PciBusReg.pszSetIrqRC = fGCEnabled ? "ich9pciSetIrq" : NULL;
2991 PciBusReg.pszSetIrqR0 = fR0Enabled ? "ich9pciSetIrq" : NULL;
2992#if PDM_DEVHLPR3_VERSION >= PDM_VERSION_MAKE_PP(0xffe7, 20, 0)
2993 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3, &pBus->iBus);
2994#else
2995 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
2996 pBus->iBus = rc;
2997#endif
2998 if (RT_FAILURE(rc))
2999 return PDMDEV_SET_ERROR(pDevIns, rc,
3000 N_("Failed to register ourselves as a PCI Bus"));
3001 Assert(pBus->iBus == 0);
3002 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
3003 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
3004 N_("PCI helper version mismatch; got %#x expected %#x"),
3005 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
3006
3007 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3008 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
3009
3010 /*
3011 * Fill in PCI configs and add them to the bus.
3012 */
3013 /** @todo Disabled for now because this causes error messages with Linux guests.
3014 * The guest loads the x38_edac device which tries to map a memory region
3015 * using an address given at place 0x48 - 0x4f in the PCi config space.
3016 * This fails. because we don't register such a region.
3017 */
3018#if 0
3019 /* Host bridge device */
3020 PDMPciDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */
3021 PDMPciDevSetDeviceId( &pBus->PciDev, 0x29e0); /* Desktop */
3022 PDMPciDevSetRevisionId(&pBus->PciDev, 0x01); /* rev. 01 */
3023 PDMPciDevSetClassBase( &pBus->PciDev, 0x06); /* bridge */
3024 PDMPciDevSetClassSub( &pBus->PciDev, 0x00); /* Host/PCI bridge */
3025 PDMPciDevSetClassProg( &pBus->PciDev, 0x00); /* Host/PCI bridge */
3026 PDMPciDevSetHeaderType(&pBus->PciDev, 0x00); /* bridge */
3027 PDMPciDevSetWord(&pBus->PciDev, VBOX_PCI_SEC_STATUS, 0x0280); /* secondary status */
3028
3029 pBus->PciDev.pDevIns = pDevIns;
3030 /* We register Host<->PCI controller on the bus */
3031 ich9pciRegisterInternal(pBus, 0, &pBus->PciDev, "dram");
3032#endif
3033
3034 /*
3035 * Register I/O ports and save state.
3036 */
3037 rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 1, NULL, ich9pciIOPortAddressWrite, ich9pciIOPortAddressRead, NULL, NULL, "ICH9 (PCI)");
3038 if (RT_FAILURE(rc))
3039 return rc;
3040 rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cfc, 4, NULL, ich9pciIOPortDataWrite, ich9pciIOPortDataRead, NULL, NULL, "ICH9 (PCI)");
3041 if (RT_FAILURE(rc))
3042 return rc;
3043 if (fGCEnabled)
3044 {
3045 rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cf8, 1, NIL_RTGCPTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
3046 if (RT_FAILURE(rc))
3047 return rc;
3048 rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cfc, 4, NIL_RTGCPTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
3049 if (RT_FAILURE(rc))
3050 return rc;
3051 }
3052 if (fR0Enabled)
3053 {
3054 rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cf8, 1, NIL_RTR0PTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
3055 if (RT_FAILURE(rc))
3056 return rc;
3057 rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cfc, 4, NIL_RTR0PTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
3058 if (RT_FAILURE(rc))
3059 return rc;
3060 }
3061
3062 if (pPciRoot->u64PciConfigMMioAddress != 0)
3063 {
3064 rc = PDMDevHlpMMIORegister(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength, NULL /*pvUser*/,
3065 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
3066 ich9pciMcfgMMIOWrite, ich9pciMcfgMMIORead, "MCFG ranges");
3067 AssertMsgRCReturn(rc, ("rc=%Rrc %#llx/%#llx\n", rc, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength), rc);
3068
3069 if (fGCEnabled)
3070 {
3071 rc = PDMDevHlpMMIORegisterRC(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength,
3072 NIL_RTRCPTR /*pvUser*/, "ich9pciMcfgMMIOWrite", "ich9pciMcfgMMIORead");
3073 AssertRCReturn(rc, rc);
3074 }
3075
3076
3077 if (fR0Enabled)
3078 {
3079 rc = PDMDevHlpMMIORegisterR0(pDevIns, pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength,
3080 NIL_RTR0PTR /*pvUser*/, "ich9pciMcfgMMIOWrite", "ich9pciMcfgMMIORead");
3081 AssertRCReturn(rc, rc);
3082 }
3083 }
3084
3085 rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
3086 sizeof(*pBus) + 16*128, "pgm",
3087 NULL, NULL, NULL,
3088 NULL, ich9pciR3SaveExec, NULL,
3089 NULL, ich9pciR3LoadExec, NULL);
3090 if (RT_FAILURE(rc))
3091 return rc;
3092
3093
3094 /** @todo other chipset devices shall be registered too */
3095
3096 PDMDevHlpDBGFInfoRegister(pDevIns, "pci",
3097 "Display PCI bus status. Recognizes 'basic' or 'verbose' as arguments, defaults to 'basic'.",
3098 devpciR3InfoPci);
3099 PDMDevHlpDBGFInfoRegister(pDevIns, "pciirq", "Display PCI IRQ state. (no arguments)", devpciR3InfoPciIrq);
3100
3101 return VINF_SUCCESS;
3102}
3103
3104static void ich9pciResetDevice(PPDMPCIDEV pDev)
3105{
3106 /* Clear regions */
3107 for (int iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
3108 {
3109 PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
3110 if (pRegion->size == 0)
3111 continue;
3112
3113 ich9pciUnmapRegion(pDev, iRegion);
3114 }
3115
3116 if (pciDevIsPassthrough(pDev))
3117 {
3118 // no reset handler - we can do what we need in PDM reset handler
3119 /// @todo is it correct?
3120 }
3121 else
3122 {
3123 ich9pciSetWord(pDev, VBOX_PCI_COMMAND,
3124 ich9pciGetWord(pDev, VBOX_PCI_COMMAND)
3125 & ~(VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY |
3126 VBOX_PCI_COMMAND_MASTER | VBOX_PCI_COMMAND_SPECIAL |
3127 VBOX_PCI_COMMAND_PARITY | VBOX_PCI_COMMAND_SERR |
3128 VBOX_PCI_COMMAND_FAST_BACK | VBOX_PCI_COMMAND_INTX_DISABLE));
3129
3130 /* Bridge device reset handlers processed later */
3131 if (!pciDevIsPci2PciBridge(pDev))
3132 {
3133 ich9pciSetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
3134 ich9pciSetByte(pDev, VBOX_PCI_INTERRUPT_LINE, 0x0);
3135 }
3136
3137 /* Reset MSI message control. */
3138 if (pciDevIsMsiCapable(pDev))
3139 {
3140 /* Extracted from MsiPciConfigWrite(). */
3141 pDev->abConfig[pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL] &= 0x8e;
3142 }
3143
3144 /* Reset MSI-X message control. */
3145 if (pciDevIsMsixCapable(pDev))
3146 {
3147 /* Extracted from MsixPciConfigWrite(); no side effects. */
3148 pDev->abConfig[pDev->Int.s.u8MsixCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL + 1] &= 0x3f;
3149 }
3150 }
3151}
3152
3153
3154/**
3155 * @copydoc FNPDMDEVRESET
3156 */
3157static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
3158{
3159 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
3160 PDEVPCIBUS pBus = &pPciRoot->PciBus;
3161
3162 /* PCI-specific reset for each device. */
3163 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
3164 {
3165 if (pBus->apDevices[i])
3166 ich9pciResetDevice(pBus->apDevices[i]);
3167 }
3168
3169 for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
3170 {
3171 if (pBus->papBridgesR3[iBridge])
3172 ich9pcibridgeReset(pBus->papBridgesR3[iBridge]->Int.s.CTX_SUFF(pDevIns));
3173 }
3174
3175 ich9pciFakePCIBIOS(pDevIns);
3176}
3177
3178
3179/**
3180 * @interface_method_impl{PDMDEVREG,pfnRelocate}
3181 */
3182DECLCALLBACK(void) devpciR3BusRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
3183{
3184 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3185
3186 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3187 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3188
3189 /* Relocate RC pointers for the attached pci devices. */
3190 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
3191 {
3192 PPDMPCIDEV pDev = pBus->apDevices[i];
3193 if (pDev)
3194 {
3195 pDev->Int.s.pBusRC += offDelta;
3196 if (pDev->Int.s.pMsixPageRC)
3197 pDev->Int.s.pMsixPageRC += offDelta;
3198 }
3199 }
3200}
3201
3202
3203/**
3204 * @interface_method_impl{PDMDEVREG,pfnRelocate}
3205 */
3206DECLCALLBACK(void) devpciR3RootRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
3207{
3208 PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
3209 pPciRoot->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3210
3211 AssertCompileMemberOffset(DEVPCIROOT, PciBus, 0);
3212 devpciR3BusRelocate(pDevIns, offDelta);
3213}
3214
3215
3216/**
3217 * @interface_method_impl{PDMDEVREG,pfnConstruct}
3218 */
3219static DECLCALLBACK(int) ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
3220 int iInstance,
3221 PCFGMNODE pCfg)
3222{
3223 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
3224
3225 /*
3226 * Validate and read configuration.
3227 */
3228 if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
3229 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
3230
3231 /* check if RC code is enabled. */
3232 bool fGCEnabled;
3233 int rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
3234 if (RT_FAILURE(rc))
3235 return PDMDEV_SET_ERROR(pDevIns, rc,
3236 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
3237
3238 /* check if R0 code is enabled. */
3239 bool fR0Enabled;
3240 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
3241 if (RT_FAILURE(rc))
3242 return PDMDEV_SET_ERROR(pDevIns, rc,
3243 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
3244 Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
3245
3246 /*
3247 * Init data and register the PCI bus.
3248 */
3249 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3250 pBus->fTypePiix3 = false;
3251 pBus->fTypeIch9 = true;
3252 pBus->fPureBridge = true;
3253 pBus->pDevInsR3 = pDevIns;
3254 pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3255 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3256 pBus->papBridgesR3 = (PPDMPCIDEV *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPDMPCIDEV) * RT_ELEMENTS(pBus->apDevices));
3257 AssertLogRelReturn(pBus->papBridgesR3, VERR_NO_MEMORY);
3258
3259 PDMPCIBUSREG PciBusReg;
3260 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
3261 PciBusReg.pfnRegisterR3 = pcibridgeR3MergedRegisterDevice;
3262 PciBusReg.pfnRegisterMsiR3 = ich9pciRegisterMsi;
3263 PciBusReg.pfnIORegionRegisterR3 = devpciR3CommonIORegionRegister;
3264 PciBusReg.pfnSetConfigCallbacksR3 = devpciR3CommonSetConfigCallbacks;
3265 PciBusReg.pfnSetIrqR3 = ich9pcibridgeSetIrq;
3266 PciBusReg.pfnFakePCIBIOSR3 = NULL; /* Only needed for the first bus. */
3267 PciBusReg.pszSetIrqRC = fGCEnabled ? "ich9pcibridgeSetIrq" : NULL;
3268 PciBusReg.pszSetIrqR0 = fR0Enabled ? "ich9pcibridgeSetIrq" : NULL;
3269#if PDM_DEVHLPR3_VERSION >= PDM_VERSION_MAKE_PP(0xffe7, 20, 0)
3270 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3, &pBus->iBus);
3271#else
3272 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
3273 pBus->iBus = rc;
3274#endif
3275 if (RT_FAILURE(rc))
3276 return PDMDEV_SET_ERROR(pDevIns, rc,
3277 N_("Failed to register ourselves as a PCI Bus"));
3278 Assert(pBus->iBus == (uint32_t)iInstance + 1); /* Can be removed when adding support for multiple bridge implementations. */
3279 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
3280 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
3281 N_("PCI helper version mismatch; got %#x expected %#x"),
3282 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
3283
3284 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
3285 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
3286 LogRel(("PCI: Registered bridge instance #%u as PDM bus no %u.\n", iInstance, pBus->iBus));
3287
3288
3289 /* Disable default device locking. */
3290 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
3291 AssertRCReturn(rc, rc);
3292
3293 /*
3294 * Fill in PCI configs and add them to the bus.
3295 */
3296 PDMPciDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */
3297 PDMPciDevSetDeviceId( &pBus->PciDev, 0x2448); /* 82801 Mobile PCI bridge. */
3298 PDMPciDevSetRevisionId(&pBus->PciDev, 0xf2);
3299 PDMPciDevSetClassSub( &pBus->PciDev, 0x04); /* pci2pci */
3300 PDMPciDevSetClassBase( &pBus->PciDev, 0x06); /* PCI_bridge */
3301 PDMPciDevSetClassProg( &pBus->PciDev, 0x01); /* Supports subtractive decoding. */
3302 PDMPciDevSetHeaderType(&pBus->PciDev, 0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
3303 PDMPciDevSetCommand( &pBus->PciDev, 0x00);
3304 PDMPciDevSetStatus( &pBus->PciDev, 0x20); /* 66MHz Capable. */
3305 PDMPciDevSetInterruptLine(&pBus->PciDev, 0x00); /* This device does not assert interrupts. */
3306
3307 /*
3308 * This device does not generate interrupts. Interrupt delivery from
3309 * devices attached to the bus is unaffected.
3310 */
3311 PDMPciDevSetInterruptPin (&pBus->PciDev, 0x00);
3312
3313 /*
3314 * Register this PCI bridge. The called function will take care on which bus we will get registered.
3315 */
3316 rc = PDMDevHlpPCIRegisterEx(pDevIns, &pBus->PciDev, PDMPCIDEVREG_CFG_PRIMARY, PDMPCIDEVREG_F_PCI_BRIDGE,
3317 PDMPCIDEVREG_DEV_NO_FIRST_UNUSED, PDMPCIDEVREG_FUN_NO_FIRST_UNUSED, "ich9pcibridge");
3318 if (RT_FAILURE(rc))
3319 return rc;
3320 pBus->PciDev.Int.s.pfnBridgeConfigRead = ich9pcibridgeConfigRead;
3321 pBus->PciDev.Int.s.pfnBridgeConfigWrite = ich9pcibridgeConfigWrite;
3322
3323 /*
3324 * Register SSM handlers. We use the same saved state version as for the host bridge
3325 * to make changes easier.
3326 */
3327 rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
3328 sizeof(*pBus) + 16*128,
3329 "pgm" /* before */,
3330 NULL, NULL, NULL,
3331 NULL, ich9pcibridgeR3SaveExec, NULL,
3332 NULL, ich9pcibridgeR3LoadExec, NULL);
3333 if (RT_FAILURE(rc))
3334 return rc;
3335
3336
3337 return VINF_SUCCESS;
3338}
3339
3340/**
3341 * @copydoc FNPDMDEVRESET
3342 */
3343static void ich9pcibridgeReset(PPDMDEVINS pDevIns)
3344{
3345 PDEVPCIBUS pBus = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
3346
3347 /* Reset config space to default values. */
3348 ich9pciSetByte(&pBus->PciDev, VBOX_PCI_PRIMARY_BUS, 0);
3349 ich9pciSetByte(&pBus->PciDev, VBOX_PCI_SECONDARY_BUS, 0);
3350 ich9pciSetByte(&pBus->PciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
3351
3352 /* PCI-specific reset for each device. */
3353 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
3354 {
3355 if (pBus->apDevices[i])
3356 ich9pciResetDevice(pBus->apDevices[i]);
3357 }
3358}
3359
3360
3361
3362/**
3363 * The PCI bus device registration structure.
3364 */
3365const PDMDEVREG g_DevicePciIch9 =
3366{
3367 /* u32Version */
3368 PDM_DEVREG_VERSION,
3369 /* szName */
3370 "ich9pci",
3371 /* szRCMod */
3372 "VBoxDDRC.rc",
3373 /* szR0Mod */
3374 "VBoxDDR0.r0",
3375 /* pszDescription */
3376 "ICH9 PCI bridge",
3377 /* fFlags */
3378 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
3379 /* fClass */
3380 PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
3381 /* cMaxInstances */
3382 1,
3383 /* cbInstance */
3384 sizeof(DEVPCIROOT),
3385 /* pfnConstruct */
3386 ich9pciConstruct,
3387 /* pfnDestruct */
3388 NULL,
3389 /* pfnRelocate */
3390 devpciR3RootRelocate,
3391 /* pfnMemSetup */
3392 NULL,
3393 /* pfnPowerOn */
3394 NULL,
3395 /* pfnReset */
3396 ich9pciReset,
3397 /* pfnSuspend */
3398 NULL,
3399 /* pfnResume */
3400 NULL,
3401 /* pfnAttach */
3402 NULL,
3403 /* pfnDetach */
3404 NULL,
3405 /* pfnQueryInterface */
3406 NULL,
3407 /* pfnInitComplete */
3408 NULL,
3409 /* pfnPowerOff */
3410 NULL,
3411 /* pfnSoftReset */
3412 NULL,
3413 /* u32VersionEnd */
3414 PDM_DEVREG_VERSION
3415};
3416
3417/**
3418 * The device registration structure
3419 * for the PCI-to-PCI bridge.
3420 */
3421const PDMDEVREG g_DevicePciIch9Bridge =
3422{
3423 /* u32Version */
3424 PDM_DEVREG_VERSION,
3425 /* szName */
3426 "ich9pcibridge",
3427 /* szRCMod */
3428 "VBoxDDRC.rc",
3429 /* szR0Mod */
3430 "VBoxDDR0.r0",
3431 /* pszDescription */
3432 "ICH9 PCI to PCI bridge",
3433 /* fFlags */
3434 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
3435 /* fClass */
3436 PDM_DEVREG_CLASS_BUS_PCI,
3437 /* cMaxInstances */
3438 ~0U,
3439 /* cbInstance */
3440 sizeof(DEVPCIBUS),
3441 /* pfnConstruct */
3442 ich9pcibridgeConstruct,
3443 /* pfnDestruct */
3444 NULL,
3445 /* pfnRelocate */
3446 devpciR3BusRelocate,
3447 /* pfnMemSetup */
3448 NULL,
3449 /* pfnPowerOn */
3450 NULL,
3451 /* pfnReset */
3452 NULL, /* Must be NULL, to make sure only bus driver handles reset */
3453 /* pfnSuspend */
3454 NULL,
3455 /* pfnResume */
3456 NULL,
3457 /* pfnAttach */
3458 NULL,
3459 /* pfnDetach */
3460 NULL,
3461 /* pfnQueryInterface */
3462 NULL,
3463 /* pfnInitComplete */
3464 NULL,
3465 /* pfnPowerOff */
3466 NULL,
3467 /* pfnSoftReset */
3468 NULL,
3469 /* u32VersionEnd */
3470 PDM_DEVREG_VERSION
3471};
3472
3473#endif /* IN_RING3 */
3474
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