VirtualBox

Changeset 37475 in vbox


Ignore:
Timestamp:
Jun 15, 2011 4:42:55 PM (14 years ago)
Author:
vboxsync
Message:

DevAPIC: Locking reworking in progress.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmdev.h

    r37466 r37475  
    10741074
    10751075    /**
    1076      * Write MSR in APIC range.
     1076     * Write to a MSR in APIC range.
    10771077     *
    10781078     * @returns VBox status code.
    10791079     * @param   pDevIns         Device instance of the APIC.
    10801080     * @param   idCpu           Target CPU.
    1081      * @param   u32Reg          MSR to write.
    1082      * @param   u64Value        Value to write.
     1081     * @param   u32Reg          The MSR begin written to.
     1082     * @param   u64Value        The value to write.
     1083     *
     1084     * @remarks Unlike the other callbacks, the PDM lock is not taken before
     1085     *          calling this method.
    10831086     */
    10841087    DECLR3CALLBACKMEMBER(int, pfnWriteMSRR3, (PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value));
    10851088
    10861089    /**
    1087      * Read MSR in APIC range.
     1090     * Read from a MSR in APIC range.
    10881091     *
    10891092     * @returns VBox status code.
     
    10911094     * @param   idCpu           Target CPU.
    10921095     * @param   u32Reg          MSR to read.
    1093      * @param   pu64Value       Value read.
     1096     * @param   pu64Value       Where to return the read value.
    10941097     */
    10951098    DECLR3CALLBACKMEMBER(int, pfnReadMSRR3, (PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t *pu64Value));
     
    10981101     * Private interface between the IOAPIC and APIC.
    10991102     *
    1100      * This is a low-level, APIC/IOAPIC implementation specific interface
    1101      * which is registered with PDM only because it makes life so much
    1102      * simpler right now (GC bits). This is a bad bad hack! The correct
    1103      * way of doing this would involve some way of querying GC interfaces
    1104      * and relocating them. Perhaps doing some kind of device init in GC...
     1103     * This is a low-level, APIC/IOAPIC implementation specific interface which
     1104     * is registered with PDM only because it makes life so much simpler right
     1105     * now (GC bits).  This is a bad bad hack!  The correct way of doing this
     1106     * would involve some way of querying GC interfaces and relocating them.
     1107     * Perhaps doing some kind of device init in GC...
    11051108     *
    11061109     * @returns status code.
  • trunk/src/VBox/Devices/PC/DevAPIC.cpp

    r37466 r37475  
    7979#define APIC_UNLOCK(pThis) \
    8080    PDMCritSectLeave((pThis)->CTX_SUFF(pCritSect))
     81
     82/** @def APIC_AND_TM_LOCK
     83 * Acquires the virtual sync clock lock as well as the PDM lock. */
     84#define APIC_AND_TM_LOCK(a_pDev, a_pAcpi, rcBusy) \
     85    do { \
     86        int rc2 = TMTimerLock((a_pAcpi)->CTX_SUFF(pTimer), (rcBusy)); \
     87        if (rc2 != VINF_SUCCESS) \
     88            return rc2; \
     89        rc2 = PDMCritSectEnter((a_pDev)->CTX_SUFF(pCritSect), (rcBusy)); \
     90        if (rc2 != VINF_SUCCESS) \
     91        { \
     92            TMTimerUnlock((a_pAcpi)->CTX_SUFF(pTimer)); \
     93            return rc2; \
     94        } \
     95    } while (0)
     96
     97/** @def APIC_AND_TM_UNLOCK
     98 * Releases the PDM lock as well as the TM virtual sync clock lock.  */
     99#define APIC_AND_TM_UNLOCK(a_pDev, a_pAcpi) \
     100    do { \
     101        TMTimerUnlock((a_pAcpi)->CTX_SUFF(pTimer)); \
     102        PDMCritSectLeave((a_pDev)->CTX_SUFF(pCritSect)); \
     103    } while (0)
     104
    81105
    82106/** @def IOAPIC_LOCK
     
    575599
    576600/**
    577  * x2APIC MSR write interface.
     601 * Writes to an APIC register via MMIO or MSR.
    578602 *
    579  * @returns VBox status code.
    580  *
    581  * @param   pDevIns         The device instance.
    582  * @param   idCpu           The ID of the virtual CPU and thereby APIC index.
    583  * @param   u32Reg          Register to write (ecx).
    584  * @param   u64Value        The value to write (eax:edx / rax).
    585  *
     603 * @returns Strict VBox status code.
     604 * @param   pDev                The PDM device instance.
     605 * @param   pApic               The APIC being written to.
     606 * @param   iReg                The APIC register index.
     607 * @param   u64Value            The value being written.
     608 * @param   rcBusy              The busy return code to employ.  See
     609 *                              PDMCritSectEnter for a description.
     610 * @param   fMsr                Set if called via MSR, clear if MMIO.
    586611 */
    587 PDMBOTHCBDECL(int) apicWriteMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value)
    588 {
    589     APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    590     Assert(PDMCritSectIsOwner(dev->CTX_SUFF(pCritSect)));
     612static int acpiWriteRegister(APICDeviceInfo *pDev, APICState *pApic, uint32_t iReg, uint64_t u64Value,
     613                             int rcBusy, bool fMsr)
     614{
     615    Assert(!PDMCritSectIsOwner(pDev->CTX_SUFF(pCritSect)));
     616
    591617    int rc = VINF_SUCCESS;
    592 
    593     if (dev->enmVersion < PDMAPICVERSION_X2APIC)
    594         return VERR_EM_INTERPRETER;
    595 
    596     APICState *pThis = getLapicById(dev, idCpu);
    597 
    598     uint32_t index = (u32Reg - MSR_IA32_APIC_START) & 0xff;
    599     switch (index)
     618    switch (iReg)
    600619    {
    601620        case 0x02:
    602             pThis->id = (u64Value >> 24);
    603             break;
     621            APIC_LOCK(pDev, rcBusy);
     622            pApic->id = (u64Value >> 24); /** @todo r=bird: Is the range supposed to be 40 bits??? */
     623            APIC_UNLOCK(pDev);
     624            break;
     625
    604626        case 0x03:
    605             break;
     627            /* read only, ignore write. */
     628            break;
     629
    606630        case 0x08:
    607             apic_update_tpr(dev, pThis, u64Value);
    608             break;
     631            APIC_LOCK(pDev, rcBusy);
     632            apic_update_tpr(pDev, pApic, u64Value);
     633            APIC_UNLOCK(pDev);
     634            break;
     635
    609636        case 0x09: case 0x0a:
    610             Log(("apicWriteMSR: write to read-only register %d ignored\n", index));
    611             break;
     637            Log(("acpiWriteRegister: write to read-only register %d ignored\n", iReg));
     638            break;
     639
    612640        case 0x0b: /* EOI */
    613             apic_eoi(dev, pThis);
    614             break;
     641            APIC_LOCK(pDev, rcBusy);
     642            apic_eoi(pDev, pApic);
     643            APIC_UNLOCK(pDev);
     644            break;
     645
    615646        case 0x0d:
    616             pThis->log_dest = u64Value >> 24;
    617             break;
     647            APIC_LOCK(pDev, rcBusy);
     648            pApic->log_dest = (u64Value >> 24) & 0xff;
     649            APIC_UNLOCK(pDev);
     650            break;
     651
    618652        case 0x0e:
    619             pThis->dest_mode = u64Value >> 28;
    620             break;
     653            APIC_LOCK(pDev, rcBusy);
     654            pApic->dest_mode = u64Value >> 28; /** @todo r=bird: range?  This used to be 32-bit before morphed into an MSR handler. */
     655            APIC_UNLOCK(pDev);
     656            break;
     657
    621658        case 0x0f:
    622             pThis->spurious_vec = u64Value & 0x1ff;
    623             apic_update_irq(dev, pThis);
    624             break;
     659            APIC_LOCK(pDev, rcBusy);
     660            pApic->spurious_vec = u64Value & 0x1ff;
     661            apic_update_irq(pDev, pApic);
     662            APIC_UNLOCK(pDev);
     663            break;
     664
    625665        case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    626666        case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
    627667        case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
    628668        case 0x28:
    629             Log(("apicWriteMSR: write to read-only register %d ignored\n", index));
     669            Log(("acpiWriteRegister: write to read-only register %d ignored\n", iReg));
    630670            break;
    631671
    632672        case 0x30:
    633             /* Here one of the differences with regular APIC: ICR is single 64-bit register */
    634             pThis->icr[0] = (uint32_t)u64Value;
    635             pThis->icr[1] = (uint32_t)(u64Value >> 32);
    636             rc = apic_deliver(dev, pThis, (pThis->icr[1] >> 24) & 0xff, (pThis->icr[0] >> 11) & 1,
    637                              (pThis->icr[0] >>  8) & 7, (pThis->icr[0] & 0xff),
    638                              (pThis->icr[0] >> 14) & 1, (pThis->icr[0] >> 15) & 1);
    639             break;
     673            APIC_LOCK(pDev, rcBusy);
     674            pApic->icr[0] = (uint32_t)u64Value;
     675            if (fMsr) /* Here one of the differences with regular APIC: ICR is single 64-bit register */
     676                pApic->icr[1] = (uint32_t)(u64Value >> 32);
     677            rc = apic_deliver(pDev, pApic, (pApic->icr[1] >> 24) & 0xff, (pApic->icr[0] >> 11) & 1,
     678                              (pApic->icr[0] >>  8) & 7, (pApic->icr[0] & 0xff),
     679                              (pApic->icr[0] >> 14) & 1, (pApic->icr[0] >> 15) & 1);
     680            APIC_UNLOCK(pDev);
     681            break;
     682
     683        case 0x31:
     684            APIC_LOCK(pDev, rcBusy);
     685            if (!fMsr)
     686                pApic->icr[1] = (uint64_t)u64Value;
     687            else
     688                pApic->esr |= ESR_ILLEGAL_ADDRESS;
     689            APIC_UNLOCK(pDev);
     690            break;
     691
    640692        case 0x32 + APIC_LVT_TIMER:
    641693            AssertCompile(APIC_LVT_TIMER == 0);
    642             apicTimerSetLvt(dev, pThis, u64Value);
     694            APIC_AND_TM_LOCK(pDev, pApic, rcBusy);
     695            apicTimerSetLvt(pDev, pApic, u64Value);
     696            APIC_AND_TM_UNLOCK(pDev, pApic);
    643697            break;
    644698
    645699        case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
    646             pThis->lvt[index - 0x32] = u64Value;
    647             break;
     700            APIC_LOCK(pDev, rcBusy);
     701            pApic->lvt[iReg - 0x32] = u64Value;
     702            APIC_UNLOCK(pDev);
     703            break;
     704
    648705        case 0x38:
    649             apicTimerSetInitialCount(dev, pThis, u64Value);
    650             break;
     706            APIC_AND_TM_LOCK(pDev, pApic, rcBusy);
     707            apicTimerSetInitialCount(pDev, pApic, u64Value);
     708            APIC_AND_TM_UNLOCK(pDev, pApic);
     709            break;
     710
    651711        case 0x39:
    652             Log(("apicWriteMSR: write to read-only register %d ignored\n", index));
    653             break;
     712            Log(("acpiWriteRegister: write to read-only register %d ignored\n", iReg));
     713            break;
     714
    654715        case 0x3e:
    655716        {
    656             int v;
    657             pThis->divide_conf = u64Value & 0xb;
    658             v = (pThis->divide_conf & 3) | ((pThis->divide_conf >> 1) & 4);
    659             pThis->count_shift = (v + 1) & 7;
     717            APIC_LOCK(pDev, rcBusy);
     718            pApic->divide_conf = u64Value & 0xb;
     719            int v = (pApic->divide_conf & 3) | ((pApic->divide_conf >> 1) & 4);
     720            pApic->count_shift = (v + 1) & 7;
     721            APIC_UNLOCK(pDev);
    660722            break;
    661723        }
     724
    662725        case 0x3f:
    663         {
    664             /* Self IPI, see x2APIC book 2.4.5 */
    665             int vector = u64Value & 0xff;
    666             rc = apic_bus_deliver(dev,
    667                                   1 << getLapicById(dev, idCpu)->id /* Self */,
    668                                   0 /* Delivery mode - fixed */,
    669                                   vector,
    670                                   0 /* Polarity - conform to the bus */,
    671                                   0 /* Trigger mode - edge */);
    672             break;
    673         }
     726            if (fMsr)
     727            {
     728                /* Self IPI, see x2APIC book 2.4.5 */
     729                APIC_LOCK(pDev, rcBusy);
     730                int vector = u64Value & 0xff;
     731                rc = apic_bus_deliver(pDev,
     732                                      1 << pApic->id /* Self */,
     733                                      0 /* Delivery mode - fixed */,
     734                                      vector,
     735                                      0 /* Polarity - conform to the bus */,
     736                                      0 /* Trigger mode - edge */);
     737                APIC_UNLOCK(pDev);
     738                break;
     739            }
     740            /* else: fall thru */
    674741        default:
    675             AssertMsgFailed(("apicWriteMSR: unknown index %x\n", index));
    676             pThis->esr |= ESR_ILLEGAL_ADDRESS;
     742            AssertMsgFailed(("unknown iReg %x\n", iReg));
     743            pApic->esr |= ESR_ILLEGAL_ADDRESS;
    677744            break;
    678745    }
     
    682749
    683750/**
    684  * x2APIC MSR read interface.
    685  *
    686  * @returns VBox status code.
    687  *
    688  * @param   pDevIns         The device instance.
    689  * @param   idCpu           The ID of the virtual CPU and thereby APIC index.
    690  * @param   u32Reg          Register to write (ecx).
    691  * @param   pu64Value       Where to return the value (eax:edx / rax).
     751 * @interface_method_impl{PDMAPICREG,pfnWriteMSRR3}
     752 */
     753PDMBOTHCBDECL(int) apicWriteMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value)
     754{
     755    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
     756    if (pDev->enmVersion < PDMAPICVERSION_X2APIC)
     757        return VERR_EM_INTERPRETER; /** @todo tell the caller to raise hell (\#GP(0)).  */
     758
     759    APICState      *pApic = getLapicById(pDev, idCpu);
     760    uint32_t        iReg = (u32Reg - MSR_IA32_APIC_START) & 0xff;
     761    return acpiWriteRegister(pDev, pApic, iReg, u64Value, VINF_SUCCESS /*rcBusy*/, true /*fMsr*/);
     762}
     763
     764
     765/**
     766 * @interface_method_impl{PDMAPICREG,pfnReadMSRR3}
    692767 */
    693768PDMBOTHCBDECL(int) apicReadMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t *pu64Value)
     
    10781153    s->spurious_vec = 0xff;
    10791154    s->log_dest = 0;
    1080     s->dest_mode = 0xff;
     1155    s->dest_mode = 0xff; /** @todo 0xff???? */
    10811156    memset(s->isr, 0, sizeof(s->isr));
    10821157    memset(s->tmr, 0, sizeof(s->tmr));
     
    13161391{
    13171392    STAM_COUNTER_INC(&pThis->StatTimerSetLvt);
    1318 
    1319     /* Acquire the timer lock w/ lock order kludge. */
    1320     PDMCritSectLeave(dev->CTX_SUFF(pCritSect));
    1321     TMTimerLock(pThis->CTX_SUFF(pTimer), VINF_SUCCESS);
    1322     PDMCritSectEnter(dev->CTX_SUFF(pCritSect), VINF_SUCCESS);
    13231393
    13241394    /*
     
    14071477    else
    14081478        STAM_COUNTER_INC(&pThis->StatTimerSetLvtNoRelevantChange);
    1409 
    1410     TMTimerUnlock(pThis->CTX_SUFF(pTimer));
    14111479}
    14121480
     
    15351603}
    15361604
    1537 static int apic_mem_writel(APICDeviceInfo* dev, APICState *s, RTGCPHYS addr, uint32_t val)
    1538 {
    1539     int rc = VINF_SUCCESS;
    1540     int index;
    1541 
    1542 #ifdef DEBUG_APIC
    1543     Log(("CPU%d: APIC write: %08x = %08x\n", s->phys_id, (uint32_t)addr, val));
    1544 #endif
    1545 
    1546     index = (addr >> 4) & 0xff;
    1547 
    1548     switch(index) {
    1549     case 0x02:
    1550         s->id = (val >> 24);
    1551         break;
    1552     case 0x03:
    1553         Log(("apic_mem_writel: write to version register; ignored\n"));
    1554         break;
    1555     case 0x08:
    1556         apic_update_tpr(dev, s, val);
    1557         break;
    1558     case 0x09:
    1559     case 0x0a:
    1560         Log(("apic_mem_writel: write to read-only register %d ignored\n", index));
    1561         break;
    1562     case 0x0b: /* EOI */
    1563         apic_eoi(dev, s);
    1564         break;
    1565     case 0x0d:
    1566         s->log_dest = val >> 24;
    1567         break;
    1568     case 0x0e:
    1569         s->dest_mode = val >> 28;
    1570         break;
    1571     case 0x0f:
    1572         s->spurious_vec = val & 0x1ff;
    1573         apic_update_irq(dev, s);
    1574         break;
    1575     case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    1576     case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
    1577     case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
    1578     case 0x28:
    1579         Log(("apic_mem_writel: write to read-only register %d ignored\n", index));
    1580         break;
    1581 
    1582     case 0x30:
    1583         s->icr[0] = val;
    1584         rc = apic_deliver(dev, s, (s->icr[1] >> 24) & 0xff,
    1585                           (s->icr[0] >> 11) & 1,
    1586                           (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
    1587                           (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
    1588         break;
    1589     case 0x31:
    1590         s->icr[1] = val;
    1591         break;
    1592     case 0x32 + APIC_LVT_TIMER:
    1593         AssertCompile(APIC_LVT_TIMER == 0);
    1594         apicTimerSetLvt(dev, s, val);
    1595         break;
    1596     case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
    1597         {
    1598             int n = index - 0x32;
    1599             s->lvt[n] = val;
    1600         }
    1601         break;
    1602     case 0x38:
    1603         apicTimerSetInitialCount(dev, s, val);
    1604         break;
    1605     case 0x39:
    1606         Log(("apic_mem_writel: write to read-only register %d ignored\n", index));
    1607         break;
    1608     case 0x3e:
    1609         {
    1610             int v;
    1611             s->divide_conf = val & 0xb;
    1612             v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
    1613             s->count_shift = (v + 1) & 7;
    1614         }
    1615         break;
    1616     default:
    1617         AssertMsgFailed(("apic_mem_writel: unknown index %x\n", index));
    1618         s->esr |= ESR_ILLEGAL_ADDRESS;
    1619         break;
    1620     }
    1621     return rc;
    1622 }
    1623 
    16241605#ifdef IN_RING3
    16251606
     
    20141995
    20151996        case 4:
    2016         {
    2017             int rc;
    2018             APIC_LOCK(dev, VINF_IOM_HC_MMIO_WRITE);
    2019             rc = apic_mem_writel(dev, s, GCPhysAddr, *(uint32_t *)pv);
    2020             APIC_UNLOCK(dev);
    2021             return rc;
    2022         }
     1997            /* It does its own locking. */
     1998            return acpiWriteRegister(dev, s, (GCPhysAddr >> 4) & 0xff, *(uint32_t const *)pv,
     1999                                     VINF_IOM_HC_MMIO_WRITE, false /*fMsr*/);
    20232000
    20242001        default:
  • trunk/src/VBox/Devices/PC/DevPit-i8254.cpp

    r35853 r37475  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
  • trunk/src/VBox/VMM/VMMAll/PDMAll.cpp

    r37452 r37475  
    315315    if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
    316316    {
    317         Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR));
    318         pdmLock(pVM);
    319         pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, u64Value);
    320         pdmUnlock(pVM);
    321         return VINF_SUCCESS;
     317        AssertPtr(pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR));
     318        return pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, u64Value);
    322319    }
    323320    return VERR_PDM_NO_APIC_INSTANCE;
     
    338335    if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
    339336    {
    340         Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR));
    341         pdmLock(pVM);
    342         pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, pu64Value);
    343         pdmUnlock(pVM);
    344         return VINF_SUCCESS;
     337        AssertPtr(pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR));
     338        pdmLock(pVM);
     339        int rc = pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, pu64Value);
     340        pdmUnlock(pVM);
     341        return rc;
    345342    }
    346343    return VERR_PDM_NO_APIC_INSTANCE;
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