VirtualBox

Ignore:
Timestamp:
Nov 12, 2024 12:09:04 PM (2 months ago)
Author:
vboxsync
Message:

Main/ResourceAssignmentManager: Rewrite to accomodate for the fact that Windows guests have several requirements on where devices are located (TPM needs to be at fixed 0xfed40000, PL061 GPIO driver doesn't support 64bit MMIO, the GIC re-disitributor emulated by Hyper-V requires 128KiB of MMIO space rather than the 64KiB we currently reserve). This will break saved state compatibility (whether we want to restore this functionality is up for discussion), bugref:10732

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp

    r106061 r106957  
    3535#include "ResourceAssignmentManager.h"
    3636
     37#include <VBox/com/array.h>
     38
    3739#include <iprt/asm.h>
     40#include <iprt/mem.h>
    3841#include <iprt/string.h>
    39 
    40 #include <VBox/vmm/cfgm.h>
    41 #include <VBox/vmm/vmmr3vtable.h>
    42 #include <VBox/com/array.h>
    43 
    44 #include <map>
    45 #include <vector>
    46 #include <algorithm>
    4742
    4843
     
    5045*   Structures and Typedefs                                                                                                      *
    5146*********************************************************************************************************************************/
     47/**
     48 * Address space range type.
     49 */
     50typedef enum RESOURCEREGIONTYPE
     51{
     52    /** Free region. */
     53    kResourceRegionType_Free = 0,
     54    /** RAM. */
     55    kResourceRegionType_Ram,
     56    /** ROM. */
     57    kResourceRegionType_Rom,
     58    /** MMIO. */
     59    kResourceRegionType_Mmio,
     60    /** 32bit hack. */
     61    kResourceRegionType_32Bit_Hack = 0x7fffffff
     62} RESOURCEREGIONTYPE;
     63
     64
     65/**
     66 * Address space range descriptor.
     67 */
     68typedef struct RESOURCEREGION
     69{
     70    /** Region name. */
     71    char                szName[32];
     72    /** Physical start address of the region. */
     73    RTGCPHYS            GCPhysStart;
     74    /** Physical end address of the region. */
     75    RTGCPHYS            GCPhysEnd;
     76    /** Region type. */
     77    RESOURCEREGIONTYPE  enmType;
     78    /** Padding. */
     79    uint32_t            u32Pad;
     80} RESOURCEREGION;
     81AssertCompileSize(RESOURCEREGION, 56);
     82/** Pointer to a resource region. */
     83typedef RESOURCEREGION *PRESOURCEREGION;
     84/** Pointer to a const resource region. */
     85typedef const RESOURCEREGION *PCRESOURCEREGION;
    5286
    5387
     
    6397struct ResourceAssignmentManager::State
    6498{
    65     struct MemoryRange
    66     {
    67         char          szDevName[32];
    68         RTGCPHYS      mGCPhysStart;
    69         RTGCPHYS      mGCPhysEnd;
    70 
    71         MemoryRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)
    72         {
    73             RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
    74             this->mGCPhysStart = GCPhysStart;
    75             this->mGCPhysEnd   = GCPhysEnd;
    76         }
    77 
    78         bool operator==(const MemoryRange &a) const
    79         {
    80             return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;
    81         }
    82     };
    83 
    84     typedef std::vector<MemoryRange> AddrRangeList;
    85 
    8699    ChipsetType_T    mChipsetType;
    87100    IommuType_T      mIommuType;
    88     PCVMMR3VTABLE    mpVMM;
    89     AddrRangeList    mAddrRanges;
    90 
    91     RTGCPHYS         mGCPhysMmioStartOrig;
    92     RTGCPHYS         mGCPhysMmioStart;
    93     RTGCPHYS         mGCPhysMmio32StartOrig;
    94     RTGCPHYS         mGCPhysMmio32Start;
    95     RTGCPHYS         mcbMmio32;
    96     RTGCPHYS         mGCPhysRamStart;
     101
     102    /** Pointer to the array of regions (sorted by address, not overlapping, adjacent). */
     103    PRESOURCEREGION  m_paRegions;
     104    /** Number of used regions. */
     105    uint32_t         m_cRegions;
     106    /** Number of regions the allocated array can hold. */
     107    uint32_t         m_cRegionsMax;
     108
    97109    uint32_t         mcInterrupts;
    98110    uint32_t         miInterrupt;
    99111
    100112    State()
    101         : mChipsetType(ChipsetType_Null), mpVMM(NULL)
     113        : mChipsetType(ChipsetType_Null)
     114        , mIommuType(IommuType_None)
     115        , m_paRegions(NULL)
     116        , m_cRegions(0)
     117        , m_cRegionsMax(0)
     118        , mcInterrupts(0)
     119        , miInterrupt(0)
    102120    {}
    103121    ~State()
    104122    {}
    105123
    106     HRESULT init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
    107                  RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
    108                  RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts);
    109 
    110     HRESULT addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd);
     124    HRESULT init(ChipsetType_T chipsetType, IommuType_T iommuType, uint32_t cInterrupts);
     125
     126    HRESULT ensureAdditionalRegions(uint32_t cRegions);
     127    void setRegion(PRESOURCEREGION pRegion, const char *pszName, RESOURCEREGIONTYPE enmType,
     128                   RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd);
     129    HRESULT addAddrRange(const char *pszName, RESOURCEREGIONTYPE enmType, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd);
     130    HRESULT findNextFreeAddrRange(RTGCPHYS cbRegion, RTGCPHYS cbAlignment, RTGCPHYS GCPhysMax, RTGCPHYS GCPhysHint,
     131                                  PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion);
     132
     133    void dumpToReleaseLog(void);
    111134};
    112135
    113136
    114 HRESULT ResourceAssignmentManager::State::init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
    115                                                RTGCPHYS GCPhysMmioStart, RTGCPHYS GCPhysRamStart,
    116                                                RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts)
    117 {
    118     mpVMM = pVMM;
    119 
     137HRESULT ResourceAssignmentManager::State::init(ChipsetType_T chipsetType, IommuType_T iommuType,
     138                                               uint32_t cInterrupts)
     139{
    120140    Assert(chipsetType == ChipsetType_ARMv8Virtual);
    121141    Assert(iommuType == IommuType_None); /* For now no IOMMU support on ARMv8. */
     
    123143    mChipsetType           = chipsetType;
    124144    mIommuType             = iommuType;
    125     mGCPhysMmioStart       = GCPhysMmioStart;
    126     mGCPhysMmioStartOrig   = GCPhysMmioStart;
    127     mGCPhysRamStart        = GCPhysRamStart;
    128     mGCPhysMmio32Start     = GCPhysMmio32Start;
    129     mGCPhysMmio32StartOrig = GCPhysMmio32Start;
    130     mcbMmio32              = cbMmio32;
    131145    mcInterrupts           = cInterrupts;
    132146    miInterrupt            = 0;
    133     return S_OK;
    134 }
    135 
    136 HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
    137 {
    138     MemoryRange memRange(pszName, GCPhysStart, GCPhysStart + cbRegion - 1);
    139     mAddrRanges.push_back(memRange);
    140     return S_OK;
    141 }
     147
     148    m_paRegions = (PRESOURCEREGION)RTMemRealloc(m_paRegions, 32 * sizeof(*m_paRegions));
     149    if (!m_paRegions)
     150        return E_OUTOFMEMORY;
     151
     152    m_paRegions[m_cRegions].enmType     = kResourceRegionType_Free;
     153    m_paRegions[m_cRegions].GCPhysStart = 0;
     154    m_paRegions[m_cRegions].GCPhysEnd   = UINT64_MAX;
     155    strcpy(&m_paRegions[m_cRegions].szName[0], "Free");
     156    m_cRegions++;
     157
     158    return S_OK;
     159}
     160
     161
     162HRESULT ResourceAssignmentManager::State::ensureAdditionalRegions(uint32_t cRegions)
     163{
     164    if (m_cRegions + cRegions == m_cRegionsMax)
     165    {
     166        uint32_t const cRegionsNew = m_cRegionsMax + 32;
     167        PRESOURCEREGION paDescsNew = (PRESOURCEREGION)RTMemRealloc(m_paRegions, cRegionsNew * sizeof(*paDescsNew));
     168        if (!paDescsNew)
     169            return E_OUTOFMEMORY;
     170
     171        m_paRegions   = paDescsNew;
     172        m_cRegionsMax = cRegionsNew;
     173    }
     174
     175    return S_OK;
     176}
     177
     178
     179void ResourceAssignmentManager::State::setRegion(PRESOURCEREGION pRegion, const char *pszName, RESOURCEREGIONTYPE enmType,
     180                                                 RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)
     181{
     182    strncpy(&pRegion->szName[0], pszName, sizeof(pRegion->szName));
     183    pRegion->szName[sizeof(pRegion->szName) - 1] = '\0';
     184    pRegion->enmType     = enmType;
     185    pRegion->GCPhysStart = GCPhysStart;
     186    pRegion->GCPhysEnd   = GCPhysEnd;
     187}
     188
     189
     190HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RESOURCEREGIONTYPE enmType,
     191                                                       RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
     192{
     193    RTGCPHYS GCPhysEnd = GCPhysStart + cbRegion - 1;
     194
     195    /* Find the right spot in the array where to insert the range, it must not overlap with an existing used range. */
     196    uint32_t iRegion = 0;
     197    while (   iRegion < m_cRegions
     198           && GCPhysStart > m_paRegions[iRegion].GCPhysEnd)
     199        iRegion++;
     200
     201    Assert(   iRegion == m_cRegions - 1
     202           || m_paRegions[iRegion].enmType != m_paRegions[iRegion + 1].enmType);
     203
     204    /* Check that there is sufficient free space. */
     205    if (   (m_paRegions[iRegion].enmType != kResourceRegionType_Free)
     206        || GCPhysEnd > m_paRegions[iRegion].GCPhysEnd)
     207        return E_INVALIDARG;
     208
     209    Assert(m_paRegions[iRegion].enmType == kResourceRegionType_Free);
     210
     211    /* Requested region fits exactly into the free region. */
     212    if (   GCPhysStart == m_paRegions[iRegion].GCPhysStart
     213        && GCPhysEnd   == m_paRegions[iRegion].GCPhysEnd)
     214    {
     215        setRegion(&m_paRegions[iRegion], pszName, enmType, GCPhysStart, GCPhysEnd);
     216        return S_OK;
     217    }
     218
     219    HRESULT hrc = ensureAdditionalRegions(2 /*cRegions*/); /* Need two additional region descriptors max. */
     220    if (FAILED(hrc))
     221        return hrc;
     222
     223    /* Need to split the region into two or three depending on where the requested region lies. */
     224    if (GCPhysStart == m_paRegions[iRegion].GCPhysStart)
     225    {
     226        /* At the start, move the free regions and everything at the end. */
     227        memmove(&m_paRegions[iRegion + 1], &m_paRegions[iRegion], (m_cRegions - iRegion) * sizeof(*m_paRegions));
     228        setRegion(&m_paRegions[iRegion], pszName, enmType, GCPhysStart, GCPhysEnd);
     229
     230        /* Adjust the free region. */
     231        m_paRegions[iRegion + 1].GCPhysStart = GCPhysStart + cbRegion;
     232        m_cRegions++;
     233    }
     234    else if (GCPhysStart + cbRegion - 1 == m_paRegions[iRegion].GCPhysEnd)
     235    {
     236        /* At the end of the region, move the remaining regions and adjust ranges. */
     237        if (iRegion < m_cRegions)
     238            memmove(&m_paRegions[iRegion + 2], &m_paRegions[iRegion + 1], (m_cRegions - iRegion) * sizeof(*m_paRegions));
     239        setRegion(&m_paRegions[iRegion + 1], pszName, enmType, GCPhysStart, GCPhysEnd);
     240        m_paRegions[iRegion].GCPhysEnd = GCPhysStart - 1;
     241        m_cRegions++;
     242    }
     243    else
     244    {
     245        /* Somewhere in the middle, split into three regions. */
     246        if (iRegion < m_cRegions)
     247            memmove(&m_paRegions[iRegion + 3], &m_paRegions[iRegion + 1], (m_cRegions - iRegion) * sizeof(*m_paRegions));
     248        setRegion(&m_paRegions[iRegion + 1], pszName, enmType, GCPhysStart, GCPhysEnd);
     249        setRegion(&m_paRegions[iRegion + 2], "Free", kResourceRegionType_Free, GCPhysStart + cbRegion, m_paRegions[iRegion].GCPhysEnd);
     250        m_paRegions[iRegion].GCPhysEnd = GCPhysStart - 1;
     251        m_cRegions += 2;
     252    }
     253
     254    return S_OK;
     255}
     256
     257
     258HRESULT ResourceAssignmentManager::State::findNextFreeAddrRange(RTGCPHYS cbRegion, RTGCPHYS cbAlignment, RTGCPHYS GCPhysMax,
     259                                                                RTGCPHYS GCPhysHint, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
     260{
     261    AssertReturn(GCPhysMax >= cbRegion, E_FAIL);
     262    GCPhysMax -= cbRegion;
     263
     264    uint32_t iRegion = 0;
     265    if (GCPhysHint)
     266    {
     267        /* Look for free address range downwards from the hint first. */
     268        iRegion = m_cRegions - 1;
     269        while (iRegion)
     270        {
     271            PCRESOURCEREGION pRegion = &m_paRegions[iRegion];
     272
     273            /* Region must be free and satisfy the alignment++ requirements. */
     274            RTGCPHYS GCPhysStartAligned = RT_ALIGN_T(pRegion->GCPhysEnd - cbRegion + 1, cbAlignment, RTGCPHYS);
     275            if (   pRegion->enmType == kResourceRegionType_Free
     276                && GCPhysHint >= pRegion->GCPhysEnd
     277                && GCPhysMax >= pRegion->GCPhysEnd
     278                && GCPhysStartAligned >= pRegion->GCPhysStart
     279                && pRegion->GCPhysEnd - GCPhysStartAligned + 1 >= cbRegion)
     280            {
     281                *pGCPhysStart = GCPhysStartAligned;
     282                *pcbRegion    = cbRegion;
     283                return S_OK;
     284            }
     285
     286            iRegion--;
     287        }
     288    }
     289
     290    /* Find a free region which satisfies or requirements. */
     291    while (   iRegion < m_cRegions
     292           && GCPhysMax >= m_paRegions[iRegion].GCPhysStart)
     293    {
     294        PCRESOURCEREGION pRegion = &m_paRegions[iRegion];
     295
     296        /* Region must be free and satisfy the alignment++ requirements. */
     297        RTGCPHYS GCPhysStartAligned = RT_ALIGN_T(pRegion->GCPhysStart, cbAlignment, RTGCPHYS);
     298        if (   pRegion->enmType == kResourceRegionType_Free
     299            && GCPhysStartAligned >= pRegion->GCPhysStart
     300            && pRegion->GCPhysEnd - GCPhysStartAligned + 1 >= cbRegion)
     301        {
     302            *pGCPhysStart = pRegion->GCPhysStart;
     303            *pcbRegion    = cbRegion;
     304            return S_OK;
     305        }
     306
     307        iRegion++;
     308    }
     309
     310    return E_OUTOFMEMORY;
     311}
     312
     313
     314static const char *resourceManagerRegionType2Str(RESOURCEREGIONTYPE enmType)
     315{
     316    switch (enmType)
     317    {
     318        case kResourceRegionType_Free: return "FREE";
     319        case kResourceRegionType_Ram:  return "RAM ";
     320        case kResourceRegionType_Rom:  return "ROM ";
     321        case kResourceRegionType_Mmio: return "MMIO";
     322        default: AssertFailed(); return "UNKNOWN";
     323    }
     324}
     325
     326
     327void ResourceAssignmentManager::State::dumpToReleaseLog(void)
     328{
     329    LogRel(("Memory Regions:\n"));
     330    for (uint32_t iRegion = 0; iRegion < m_cRegions; iRegion++)
     331    {
     332        LogRel(("    %RGp - %RGp (%zu) %s %s\n",
     333                m_paRegions[iRegion].GCPhysStart,
     334                m_paRegions[iRegion].GCPhysEnd,
     335                m_paRegions[iRegion].GCPhysEnd - m_paRegions[iRegion].GCPhysStart + 1,
     336                m_paRegions[iRegion].szName));
     337    }
     338}
     339
    142340
    143341ResourceAssignmentManager::ResourceAssignmentManager()
    144     : pState(NULL)
    145 {
    146     pState = new State();
    147     Assert(pState);
    148 }
     342    : m_pState(NULL)
     343{
     344    m_pState = new State();
     345    Assert(m_pState);
     346}
     347
    149348
    150349ResourceAssignmentManager::~ResourceAssignmentManager()
    151350{
    152     if (pState)
    153     {
    154         delete pState;
    155         pState = NULL;
    156     }
    157 }
     351    if (m_pState)
     352    {
     353        delete m_pState;
     354        m_pState = NULL;
     355    }
     356}
     357
    158358
    159359ResourceAssignmentManager *ResourceAssignmentManager::createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
    160                                                                      RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
    161                                                                      RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32,
    162                                                                      uint32_t cInterrupts)
    163 {
     360                                                                     uint32_t cInterrupts, RTGCPHYS GCPhysMmioHint)
     361{
     362    RT_NOREF(pVMM);
     363
    164364    ResourceAssignmentManager *pInstance = new ResourceAssignmentManager();
    165     pInstance->pState->init(pVMM, chipsetType, iommuType, GCPhysMmioTop, GCPhysRamStart, GCPhysMmio32Start, cbMmio32, cInterrupts);
     365
     366    pInstance->m_GCPhysMmioHint = GCPhysMmioHint;
     367    pInstance->m_pState->init(chipsetType, iommuType, cInterrupts);
    166368    Assert(pInstance);
    167369    return pInstance;
    168370}
    169371
     372
     373HRESULT ResourceAssignmentManager::assignFixedRomRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
     374{
     375    return m_pState->addAddrRange(pszName, kResourceRegionType_Rom, GCPhysStart, cbRegion);
     376}
     377
     378
     379HRESULT ResourceAssignmentManager::assignFixedRamRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
     380{
     381    return m_pState->addAddrRange(pszName, kResourceRegionType_Ram, GCPhysStart, cbRegion);
     382}
     383
     384
     385HRESULT ResourceAssignmentManager::assignFixedMmioRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
     386{
     387    return m_pState->addAddrRange(pszName, kResourceRegionType_Mmio, GCPhysStart, cbRegion);
     388}
     389
     390
     391HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion,
     392                                                           bool fOnly32Bit)
     393{
     394    RTGCPHYS GCPhysRegionStart;
     395    RTGCPHYS cbRegionFinal;
     396    HRESULT hrc = m_pState->findNextFreeAddrRange(cbRegion, cbAlignment, fOnly32Bit ? _4G : RTGCPHYS_MAX,
     397                                                  m_GCPhysMmioHint, &GCPhysRegionStart, &cbRegionFinal);
     398    if (SUCCEEDED(hrc))
     399    {
     400        *pGCPhysStart = GCPhysRegionStart;
     401        *pcbRegion    = cbRegionFinal;
     402        return assignFixedMmioRegion(pszName, GCPhysRegionStart, cbRegion);
     403    }
     404
     405    return hrc;
     406}
     407
     408
    170409HRESULT ResourceAssignmentManager::assignMmioRegion(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
    171410{
    172     RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
    173     RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart;
    174 
    175     *pGCPhysStart = GCPhysMmioStart;
    176     *pcbRegion    = cbRegionAligned;
    177     pState->mGCPhysMmioStart += cbRegionAligned;
    178     pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
    179     return S_OK;
    180 }
     411    return assignMmioRegionAligned(pszName, cbRegion, _4K, pGCPhysStart, pcbRegion, false /*fOnly32Bit*/);
     412}
     413
    181414
    182415HRESULT ResourceAssignmentManager::assignMmio32Region(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
    183416{
    184     RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
    185     RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmio32Start;
    186 
    187     if (GCPhysMmioStart > pState->mGCPhysRamStart)
    188     {
    189         AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO32 range for %s would overlap RAM region\n", pszName));
    190         return E_INVALIDARG;
    191     }
    192 
    193     *pGCPhysStart = GCPhysMmioStart;
    194     *pcbRegion    = cbRegionAligned;
    195     pState->mGCPhysMmio32Start += cbRegionAligned;
    196     pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
    197     return S_OK;
    198 }
    199 
    200 HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
    201 {
    202     RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, cbAlignment, RTGCPHYS);
    203     RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart;
    204 
    205     GCPhysMmioStart = RT_ALIGN_T(GCPhysMmioStart, cbAlignment, RTGCPHYS);
    206 
    207     *pGCPhysStart = GCPhysMmioStart;
    208     *pcbRegion    = cbRegionAligned;
    209     pState->mGCPhysMmioStart = GCPhysMmioStart + cbRegionAligned;
    210     pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
    211     return S_OK;
    212 }
    213 
    214 HRESULT ResourceAssignmentManager::assignFixedAddress(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
    215 {
    216     RT_NOREF(pszName, GCPhysStart, cbRegion);
    217     AssertReleaseFailed();
    218     return S_OK;
    219 }
    220 
    221 HRESULT ResourceAssignmentManager::assignRamRegion(const char *pszName, RTGCPHYS cbRam, PRTGCPHYS pGCPhysStart)
    222 {
    223     *pGCPhysStart = pState->mGCPhysRamStart;
    224     pState->mGCPhysRamStart += cbRam;
    225     pState->addAddrRange(pszName, *pGCPhysStart, cbRam);
    226     return S_OK;
    227 }
     417    return assignMmioRegionAligned(pszName, cbRegion, _4K, pGCPhysStart, pcbRegion, true /*fOnly32Bit*/);
     418}
     419
    228420
    229421HRESULT ResourceAssignmentManager::assignInterrupts(const char *pszName, uint32_t cInterrupts, uint32_t *piInterruptFirst)
    230422{
    231     if (pState->miInterrupt + cInterrupts > pState->mcInterrupts)
     423    if (m_pState->miInterrupt + cInterrupts > m_pState->mcInterrupts)
    232424    {
    233425        AssertLogRelMsgFailed(("ResourceAssignmentManager: Interrupt count for %s exceeds number of available interrupts\n", pszName));
     
    235427    }
    236428
    237     *piInterruptFirst = pState->miInterrupt;
    238     pState->miInterrupt += cInterrupts;
    239     return S_OK;
    240 }
     429    *piInterruptFirst = m_pState->miInterrupt;
     430    m_pState->miInterrupt += cInterrupts;
     431    return S_OK;
     432}
     433
     434HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
     435{
     436    /*
     437     * This ASSUMES that there are adjacent MMIO regions above 4GiB which can be combined into one single region
     438     * (adjacent and no ROM/RAM regions inbetween).
     439     */
     440    *pGCPhysMmioStart = 0;
     441    *pcbMmio          = 0;
     442
     443    /* Look for the start. */
     444    for (uint32_t i = 0; i < m_pState->m_cRegions; i++)
     445    {
     446        PCRESOURCEREGION pRegion = &m_pState->m_paRegions[i];
     447
     448        if (   pRegion->GCPhysStart >= _4G
     449            && pRegion->enmType == kResourceRegionType_Mmio)
     450        {
     451            RTGCPHYS cbMmio = pRegion->GCPhysEnd - pRegion->GCPhysStart + 1;
     452
     453            *pGCPhysMmioStart = pRegion->GCPhysStart;
     454
     455            /* Add up any remaining MMIO regions adjacent to this one. */
     456            for (uint32_t j = i; j < m_pState->m_cRegions; j++)
     457            {
     458                pRegion = &m_pState->m_paRegions[i];
     459                if (   pRegion->enmType == kResourceRegionType_Mmio
     460                    && pRegion->GCPhysStart == *pGCPhysMmioStart + cbMmio)
     461                    cbMmio += pRegion->GCPhysEnd - pRegion->GCPhysStart + 1;
     462                else
     463                    break;
     464            }
     465
     466            *pcbMmio = cbMmio;
     467            return S_OK;
     468        }
     469    }
     470
     471    return S_OK;
     472}
     473
     474
     475HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
     476{
     477    RT_NOREF(pGCPhysMmioStart, pcbMmio);
     478    return S_OK;
     479}
     480
    241481
    242482HRESULT ResourceAssignmentManager::assignSingleInterrupt(const char *pszName, uint32_t *piInterrupt)
     
    245485}
    246486
    247 HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
    248 {
    249     *pGCPhysMmioStart = pState->mGCPhysMmioStartOrig;
    250     *pcbMmio          = pState->mGCPhysMmioStart - pState->mGCPhysMmioStartOrig;
    251     return S_OK;
    252 }
    253 
    254 HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
    255 {
    256     *pGCPhysMmioStart = pState->mGCPhysMmio32StartOrig;
    257     *pcbMmio          = pState->mcbMmio32;
    258     return S_OK;
    259 }
     487
     488void ResourceAssignmentManager::dumpMemoryRegionsToReleaseLog(void)
     489{
     490    m_pState->dumpToReleaseLog();
     491}
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