VirtualBox

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

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

pdmpcidev.h: Modified FNPCICONFIGWRITE to return a status code to facilitate PDMDevHlpDBGFStop use in implementations.

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

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