VirtualBox

Changeset 32714 in vbox


Ignore:
Timestamp:
Sep 23, 2010 12:28:55 PM (14 years ago)
Author:
vboxsync
Message:

PCI: extended address space access

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pci.h

    r32589 r32714  
    187187 * @returns The register value.
    188188 * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
    189  * @param   Address         The configuration space register address. [0..255]
     189 * @param   Address         The configuration space register address. [0..4096]
    190190 * @param   cb              The register size. [1,2,4]
    191191 */
     
    200200 *
    201201 * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
    202  * @param   Address         The configuration space register address. [0..255]
     202 * @param   Address         The configuration space register address. [0..4096]
    203203 * @param   u32Value        The value that's being written. The number of bits actually used from
    204204 *                          this value is determined by the cb parameter.
  • trunk/src/VBox/Devices/Bus/DevPciIch9.cpp

    r32637 r32714  
    106106     uint64_t            u64PciConfigMMioAddress;
    107107    /* Length of PCI config space MMIO region */
    108     uint64_t            u64PciConfigMMioLength;
     108    uint64_t             u64PciConfigMMioLength;
    109109
    110110
     
    117117} PCIGLOBALS, *PPCIGLOBALS;
    118118
     119
     120typedef struct {
     121    uint8_t  iBus;
     122    uint8_t  iDeviceFunc;
     123    uint16_t iRegister;
     124} PciAddress;
    119125
    120126/*******************************************************************************
     
    176182#endif
    177183
     184// See 7.2.2. PCI Express Enhanced Configuration Mechanism for details of address
     185// mapping, we take n=8 approach
     186DECLINLINE(void) ich9pciPhysToPciAddr(RTGCPHYS GCPhysAddr, PciAddress* pPciAddr)
     187{
     188    pPciAddr->iBus          = (GCPhysAddr >> 20) & ((1<<8)       - 1);
     189    pPciAddr->iDeviceFunc   = (GCPhysAddr >> 15) & ((1<<(5+3))   - 1); // 5 bits - device, 3 bits - function
     190    pPciAddr->iRegister     = (GCPhysAddr >>  0) & ((1<<(6+4+2)) - 1); // 6 bits - register, 4 bits - extended register, 2 bits -Byte Enable
     191}
     192
     193DECLINLINE(void) ich9pciStateToPciAddr(PPCIGLOBALS pGlobals, RTGCPHYS addr, PciAddress* pPciAddr)
     194{
     195    pPciAddr->iBus         = (pGlobals->uConfigReg >> 16) & 0xff;
     196    pPciAddr->iDeviceFunc  = (pGlobals->uConfigReg >> 8) & 0xff;
     197    pPciAddr->iRegister    = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
     198}
     199
    178200PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
    179201{
     
    264286}
    265287
    266 static int ich9pciDataWrite(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
    267 {
    268     uint8_t iBus, iDevice;
    269     uint32_t uConfigReg;
    270 
    271     Log(("ich9pciDataWrite: addr=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
    272 
    273     if (!(pGlobals->uConfigReg & (1 << 31)))
    274         return VINF_SUCCESS;
    275 
    276     if ((pGlobals->uConfigReg & 0x3) != 0)
    277         return VINF_SUCCESS;
    278 
    279     /* Compute destination device */
    280     iBus = (pGlobals->uConfigReg >> 16) & 0xff;
    281     iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
    282     /* And config register */
    283     uConfigReg = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
    284     if (iBus != 0)
     288static int ich9pciDataWriteAddr(PPCIGLOBALS pGlobals, PciAddress* pAddr, uint32_t val, int len)
     289{
     290    if (pAddr->iBus != 0)
    285291    {
    286292        if (pGlobals->aPciBus.cBridges)
    287293        {
    288294#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
    289             PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, iBus);
     295            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pAddr->iBus);
    290296            if (pBridgeDevice)
    291297            {
    292298                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
    293                 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, uConfigReg, val, len);
     299                pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, pAddr->iBus, pAddr->iDeviceFunc, pAddr->iRegister, val, len);
    294300            }
    295301#else
     
    300306    else
    301307    {
    302         if (pGlobals->aPciBus.apDevices[iDevice])
     308        if (pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc])
    303309        {
    304310#ifdef IN_RING3
    305             R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[iDevice];
    306             Log(("ich9pciConfigWrite: %s: addr=%02x val=%08x len=%d\n", aDev->name, uConfigReg, val, len));
    307             aDev->Int.s.pfnConfigWrite(aDev, uConfigReg, val, len);
     311            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc];
     312            Log(("ich9pciConfigWrite: %s: addr=%02x val=%08x len=%d\n", aDev->name, pAddr->iRegister, val, len));
     313            aDev->Int.s.pfnConfigWrite(aDev, pAddr->iRegister, val, len);
    308314#else
    309315            return VINF_IOM_HC_IOPORT_WRITE;
     
    312318    }
    313319    return VINF_SUCCESS;
     320}
     321
     322static int ich9pciDataWrite(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
     323{
     324    PciAddress aPciAddr;
     325    uint32_t uConfigReg;
     326
     327    Log(("ich9pciDataWrite: addr=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
     328
     329    if (!(pGlobals->uConfigReg & (1 << 31)))
     330        return VINF_SUCCESS;
     331
     332    if ((pGlobals->uConfigReg & 0x3) != 0)
     333        return VINF_SUCCESS;
     334
     335    /* Compute destination device */
     336    ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
     337
     338    return ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len);
    314339}
    315340
     
    341366}
    342367
    343 static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int len, uint32_t *pu32)
    344 {
    345     uint8_t iBus, iDevice;
    346     uint32_t uConfigReg;
    347 
    348     *pu32 = 0xffffffff;
    349 
    350     if (!(pGlobals->uConfigReg & (1 << 31)))
    351         return VINF_SUCCESS;
    352 
    353     if ((pGlobals->uConfigReg & 0x3) != 0)
    354         return VINF_SUCCESS;
    355 
    356     /* Compute destination device */
    357     iBus = (pGlobals->uConfigReg >> 16) & 0xff;
    358     iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
    359     /* And config register */
    360     uConfigReg = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
    361     if (iBus != 0)
     368static int ich9pciDataReadAddr(PPCIGLOBALS pGlobals, PciAddress* pPciAddr, int len, uint32_t *pu32)
     369{
     370    if (pPciAddr->iBus != 0)
    362371    {
    363372        if (pGlobals->aPciBus.cBridges)
    364373        {
    365374#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
    366             PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, iBus);
     375            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pPciAddr->iBus);
    367376            if (pBridgeDevice)
    368377            {
    369378                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
    370                 *pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, uConfigReg, len);
     379                *pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, pPciAddr->iBus, pPciAddr->iDeviceFunc, pPciAddr->iRegister, len);
    371380            }
    372381#else
     
    377386    else
    378387    {
    379         if (pGlobals->aPciBus.apDevices[iDevice])
     388        if (pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc])
    380389        {
    381390#ifdef IN_RING3
    382             R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[iDevice];
    383             *pu32 = aDev->Int.s.pfnConfigRead(aDev, uConfigReg, len);
    384             Log(("ich9pciConfigRead: %s: addr=%02x val=%08x len=%d\n", aDev->name, uConfigReg, *pu32, len));
     391            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc];
     392            *pu32 = aDev->Int.s.pfnConfigRead(aDev, pPciAddr->iRegister, len);
     393            Log(("ich9pciConfigRead: %s: addr=%02x val=%08x len=%d\n", aDev->name, pPciAddr->iRegister, *pu32, len));
    385394#else
    386395            return VINF_IOM_HC_IOPORT_READ;
     
    390399
    391400    return VINF_SUCCESS;
     401}
     402
     403
     404static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int len, uint32_t *pu32)
     405{
     406    PciAddress aPciAddr;
     407    uint32_t uConfigReg;
     408
     409    *pu32 = 0xffffffff;
     410
     411    if (!(pGlobals->uConfigReg & (1 << 31)))
     412        return VINF_SUCCESS;
     413
     414    if ((pGlobals->uConfigReg & 0x3) != 0)
     415        return VINF_SUCCESS;
     416
     417    /* Compute destination device */
     418    ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
     419
     420    return ich9pciDataReadAddr(pGlobals, &aPciAddr, len, pu32);
    392421}
    393422
     
    503532}
    504533
     534PDMBOTHCBDECL(int)  ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
     535{
     536    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     537    PciAddress aDest;
     538    uint32_t u32 = 0;
     539
     540    ich9pciPhysToPciAddr(GCPhysAddr, &aDest);
     541
     542    PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
     543    switch (cb)
     544    {
     545        case 1:
     546            u32 = *(uint8_t*)pv;
     547            break;
     548        case 2:
     549            u32 = *(uint16_t*)pv;
     550            break;
     551        case 4:
     552            u32 = *(uint32_t*)pv;
     553            break;
     554        default:
     555            Assert(false);
     556            break;
     557    }
     558    int rc = ich9pciDataWriteAddr(pGlobals, &aDest, u32, cb);
     559    PCI_UNLOCK(pDevIns);
     560    Assert(false);
     561
     562    return rc;
     563}
     564
     565PDMBOTHCBDECL(int)  ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
     566{
     567    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     568    PciAddress  aDest;
     569    uint32_t    rv = 0;
     570
     571    ich9pciPhysToPciAddr(GCPhysAddr, &aDest);
     572
     573    PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
     574    int rc = ich9pciDataReadAddr(pGlobals, &aDest, cb, &rv);
     575    if (rc == VINF_SUCCESS)
     576    {
     577        switch (cb)
     578        {
     579            case 1:
     580                *(uint8_t*)pv   = (uint8_t)rv;
     581                break;
     582            case 2:
     583                *(uint16_t*)pv  = (uint16_t)rv;
     584                break;
     585            case 4:
     586                *(uint32_t*)pv  = (uint32_t)rv;
     587                break;
     588            default:
     589                Assert(false);
     590                break;
     591        }
     592    }
     593    PCI_UNLOCK(pDevIns);
     594
     595    Assert(false);
     596    return rc;
     597}
     598
    505599#ifdef IN_RING3
    506 
    507 PDMBOTHCBDECL(int)  ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    508 {
    509     //PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
    510     Assert(false);
    511     return VINF_IOM_MMIO_UNUSED_FF;
    512 }
    513 
    514 PDMBOTHCBDECL(int)  ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    515 {
    516     //PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
    517     Assert(false);
    518     return VINF_IOM_MMIO_UNUSED_FF;
    519 }
    520600
    521601DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus)
     
    597677                       mappings, we handle specific values as invalid
    598678                       mappings. */
    599                     if (uLast <= uNew || uNew == 0 || uLast == ~0U)
     679                    if (uLast <= uNew || uNew == 0 || uLast == INVALID_PCI_ADDRESS)
    600680                        uNew = INVALID_PCI_ADDRESS;
    601681                }
     
    705785     */
    706786    PPCIIOREGION pRegion = &pPciDev->Int.s.aIORegions[iRegion];
    707     pRegion->addr        = ~0U;
     787    pRegion->addr        = INVALID_PCI_ADDRESS;
    708788    pRegion->size        = cbRegion;
    709789    pRegion->type        = enmType;
     
    14001480static DECLCALLBACK(uint32_t) ich9pciConfigRead(PCIDevice *aDev, uint32_t u32Address, unsigned len)
    14011481{
     1482    if ((u32Address + len) > 256 && (u32Address + len) < 4096)
     1483    {
     1484        AssertMsgReturn(false, ("Read from extended registers falled back to generic code\n"), 0);
     1485    }
     1486
    14021487    AssertMsgReturn(u32Address + len <= 256, ("Read after end of PCI config space\n"),
    14031488                    0);
     
    14221507                                             uint32_t val, unsigned len)
    14231508{
     1509    if ((u32Address + len) > 256 && (u32Address + len) < 4096)
     1510    {
     1511        AssertMsgReturnVoid(false, ("Write to extended registers falled back to generic code\n"));
     1512    }
     1513
     1514    AssertMsgReturnVoid(u32Address + len <= 256, ("Write after end of PCI config space\n"));
     1515
    14241516    /* Fast case - update one of BARs or ROM address, 'while' only for 'break' */
    14251517    while (   len == 4
     
    17441836     * Validate and read configuration.
    17451837     */
    1746     if (!CFGMR3AreValuesValid(pCfg, 
    1747                               "IOAPIC\0" 
    1748                               "GCEnabled\0" 
     1838    if (!CFGMR3AreValuesValid(pCfg,
     1839                              "IOAPIC\0"
     1840                              "GCEnabled\0"
    17491841                              "R0Enabled\0"
    17501842                              "McfgBase\0"
     
    18911983            return rc;
    18921984        }
     1985
     1986         if (fGCEnabled)
     1987         {
     1988
     1989             rc = PDMDevHlpMMIORegisterRC(pDevIns,
     1990                                          pGlobals->u64PciConfigMMioAddress,
     1991                                          pGlobals->u64PciConfigMMioLength,
     1992                                          0,
     1993                                          "ich9pciMcfgMMIOWrite",
     1994                                          "ich9pciMcfgMMIORead",
     1995                                          NULL);
     1996             if (RT_FAILURE(rc))
     1997             {
     1998                 AssertMsgRC(rc, ("Cannot register MCFG MMIO (GC): %Rrc\n", rc));
     1999                 return rc;
     2000             }
     2001         }
     2002
     2003
     2004         if (fR0Enabled)
     2005         {
     2006
     2007             rc = PDMDevHlpMMIORegisterR0(pDevIns,
     2008                                          pGlobals->u64PciConfigMMioAddress,
     2009                                          pGlobals->u64PciConfigMMioLength,
     2010                                          0,
     2011                                          "ich9pciMcfgMMIOWrite",
     2012                                          "ich9pciMcfgMMIORead",
     2013                                          NULL);
     2014             if (RT_FAILURE(rc))
     2015             {
     2016                 AssertMsgRC(rc, ("Cannot register MCFG MMIO (R0): %Rrc\n", rc));
     2017                 return rc;
     2018             }
     2019         }
    18932020    }
    18942021
  • trunk/src/VBox/Devices/PC/vbox.dsl

    r32637 r32714  
    565565                    {
    566566                        Memory32Fixed (ReadOnly,
    567                             0xE0000000,         // Address Base
     567                            0xD0000000,         // Address Base
    568568                            0x10000000,         // Address Length
    569569                            _Y13)
Note: See TracChangeset for help on using the changeset viewer.

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