VirtualBox

Changeset 47429 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jul 26, 2013 5:12:55 PM (12 years ago)
Author:
vboxsync
Message:

IEM: Implemented I/O permission bitmap checks.

Location:
trunk/src/VBox/VMM/VMMAll
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r47427 r47429  
    710710static VBOXSTRICTRC     iemMemFetchDataU32(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
    711711static VBOXSTRICTRC     iemMemFetchDataU64(PIEMCPU pIemCpu, uint64_t *pu64Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
     712static VBOXSTRICTRC     iemMemFetchSysU8(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
     713static VBOXSTRICTRC     iemMemFetchSysU16(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
    712714static VBOXSTRICTRC     iemMemFetchSysU32(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
    713715static VBOXSTRICTRC     iemMemFetchSysU64(PIEMCPU pIemCpu, uint64_t *pu64Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
     
    66376639{
    66386640    return iemMemCommitAndUnmap(pIemCpu, (void *)pvMem, IEM_ACCESS_STACK_R);
     6641}
     6642
     6643
     6644/**
     6645 * Fetches a system table byte.
     6646 *
     6647 * @returns Strict VBox status code.
     6648 * @param   pIemCpu             The IEM per CPU data.
     6649 * @param   pbDst               Where to return the byte.
     6650 * @param   iSegReg             The index of the segment register to use for
     6651 *                              this access.  The base and limits are checked.
     6652 * @param   GCPtrMem            The address of the guest memory.
     6653 */
     6654static VBOXSTRICTRC iemMemFetchSysU8(PIEMCPU pIemCpu, uint8_t *pbDst, uint8_t iSegReg, RTGCPTR GCPtrMem)
     6655{
     6656    /* The lazy approach for now... */
     6657    uint8_t const *pbSrc;
     6658    VBOXSTRICTRC rc = iemMemMap(pIemCpu, (void **)&pbSrc, sizeof(*pbSrc), iSegReg, GCPtrMem, IEM_ACCESS_SYS_R);
     6659    if (rc == VINF_SUCCESS)
     6660    {
     6661        *pbDst = *pbSrc;
     6662        rc = iemMemCommitAndUnmap(pIemCpu, (void *)pbSrc, IEM_ACCESS_SYS_R);
     6663    }
     6664    return rc;
     6665}
     6666
     6667
     6668/**
     6669 * Fetches a system table word.
     6670 *
     6671 * @returns Strict VBox status code.
     6672 * @param   pIemCpu             The IEM per CPU data.
     6673 * @param   pu16Dst             Where to return the word.
     6674 * @param   iSegReg             The index of the segment register to use for
     6675 *                              this access.  The base and limits are checked.
     6676 * @param   GCPtrMem            The address of the guest memory.
     6677 */
     6678static VBOXSTRICTRC iemMemFetchSysU16(PIEMCPU pIemCpu, uint16_t *pu16Dst, uint8_t iSegReg, RTGCPTR GCPtrMem)
     6679{
     6680    /* The lazy approach for now... */
     6681    uint16_t const *pu16Src;
     6682    VBOXSTRICTRC rc = iemMemMap(pIemCpu, (void **)&pu16Src, sizeof(*pu16Src), iSegReg, GCPtrMem, IEM_ACCESS_SYS_R);
     6683    if (rc == VINF_SUCCESS)
     6684    {
     6685        *pu16Dst = *pu16Src;
     6686        rc = iemMemCommitAndUnmap(pIemCpu, (void *)pu16Src, IEM_ACCESS_SYS_R);
     6687    }
     6688    return rc;
    66396689}
    66406690
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r47379 r47429  
    2121 */
    2222
     23
     24/**
     25 * Worker function for iemHlpCheckPortIOPermission, don't call directly.
     26 *
     27 * @returns Strict VBox status code.
     28 *
     29 * @param   pIemCpu             The IEM per CPU data.
     30 * @param   pCtx                The register context.
     31 * @param   u16Port             The port number.
     32 * @param   cbOperand           The operand size.
     33 */
     34static VBOXSTRICTRC iemHlpCheckPortIOPermissionBitmap(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint16_t u16Port, uint8_t cbOperand)
     35{
     36    /* The TSS bits we're interested in are the same on 386 and AMD64. */
     37    AssertCompile(AMD64_SEL_TYPE_SYS_TSS_BUSY  == X86_SEL_TYPE_SYS_386_TSS_BUSY);
     38    AssertCompile(AMD64_SEL_TYPE_SYS_TSS_AVAIL == X86_SEL_TYPE_SYS_386_TSS_AVAIL);
     39    AssertCompileMembersAtSameOffset(X86TSS32, offIoBitmap, X86TSS64, offIoBitmap);
     40    AssertCompile(sizeof(X86TSS32) == sizeof(X86TSS64));
     41
     42    /*
     43     * Check the TSS type, 16-bit TSSes doesn't have any I/O permission bitmap.
     44     */
     45    Assert(!pCtx->tr.Attr.n.u1DescType);
     46    if (RT_UNLIKELY(   pCtx->tr.Attr.n.u4Type != AMD64_SEL_TYPE_SYS_TSS_BUSY
     47                    && pCtx->tr.Attr.n.u4Type != AMD64_SEL_TYPE_SYS_TSS_AVAIL))
     48    {
     49        Log(("iomInterpretCheckPortIOAccess: Port=%#x cb=%d - TSS type %#x (attr=%#x) has no I/O bitmap -> #GP(0)\n",
     50             u16Port, cbOperand, pCtx->tr.Attr.n.u4Type, pCtx->tr.Attr.u));
     51        return iemRaiseGeneralProtectionFault0(pIemCpu);
     52    }
     53
     54    /*
     55     * Read the bitmap offset (may #PF).
     56     */
     57    uint16_t offBitmap;
     58    VBOXSTRICTRC rcStrict = iemMemFetchSysU16(pIemCpu, &offBitmap, UINT8_MAX,
     59                                              pCtx->tr.u64Base + RT_OFFSETOF(X86TSS64, offIoBitmap));
     60    if (rcStrict != VINF_SUCCESS)
     61    {
     62        Log(("iomInterpretCheckPortIOAccess: Error reading offIoBitmap (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
     63        return rcStrict;
     64    }
     65
     66    /*
     67     * The bit range from u16Port to (u16Port + cbOperand - 1), however intel
     68     * describes the CPU actually reading two bytes regardless of whether the
     69     * bit range crosses a byte boundrary.  Thus the + 1 in the test below.
     70     */
     71    uint32_t offFirstBit = (uint32_t)u16Port / 8 + offBitmap;
     72    /** @todo check if real CPUs ensures that offBitmap has a minimum value of
     73     *        for instance sizeof(X86TSS32). */
     74    if (offFirstBit + 1 > pCtx->tr.u32Limit) /* the limit is inclusive */
     75    {
     76        Log(("iomInterpretCheckPortIOAccess: offFirstBit=%#x + 1 is beyond u32Limit=%#x -> #GP(0)\n",
     77             offFirstBit, pCtx->tr.u32Limit));
     78        return iemRaiseGeneralProtectionFault0(pIemCpu);
     79    }
     80
     81    /*
     82     * Read the necessary bits.
     83     */
     84    /** @todo Test the assertion in the intel manual that the CPU reads two
     85     *        bytes.  The question is how this works wrt to #PF and #GP on the
     86     *        2nd byte when it's not required. */
     87    uint16_t bmBytes = UINT16_MAX;
     88    rcStrict = iemMemFetchSysU16(pIemCpu, &bmBytes, UINT8_MAX, pCtx->tr.u64Base + offFirstBit);
     89    if (rcStrict != VINF_SUCCESS)
     90    {
     91        Log(("iomInterpretCheckPortIOAccess: Error reading I/O bitmap @%#x (%Rrc)\n", offFirstBit, VBOXSTRICTRC_VAL(rcStrict)));
     92        return rcStrict;
     93    }
     94
     95    /*
     96     * Perform the check.
     97     */
     98    uint16_t fPortMask = (1 << cbOperand) - 1;
     99    bmBytes >>= (u16Port & 7);
     100    if (bmBytes & fPortMask)
     101    {
     102        Log(("iomInterpretCheckPortIOAccess: u16Port=%#x LB %u - access denied (bm=%#x mask=%#x) -> #GP(0)\n",
     103             u16Port, cbOperand, bmBytes, fPortMask));
     104        return iemRaiseGeneralProtectionFault0(pIemCpu);
     105    }
     106
     107    return VINF_SUCCESS;
     108}
     109
     110
    23111/**
    24112 * Checks if we are allowed to access the given I/O port, raising the
     
    40128        && (    pIemCpu->uCpl > Efl.Bits.u2IOPL
    41129            ||  Efl.Bits.u1VM) )
    42     {
    43         NOREF(u16Port); NOREF(cbOperand); /** @todo I/O port permission bitmap check */
    44         IEM_RETURN_ASPECT_NOT_IMPLEMENTED_LOG(("Implement I/O permission bitmap\n"));
    45     }
     130        return iemHlpCheckPortIOPermissionBitmap(pIemCpu, pCtx, u16Port, cbOperand);
    46131    return VINF_SUCCESS;
    47132}
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