VirtualBox

Changeset 46470 in vbox


Ignore:
Timestamp:
Jun 10, 2013 3:14:27 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
86313
Message:

VMM/HMSVMR0: AMD-V bits.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r46444 r46470  
    6565        pCtx->reg.Attr.u    = HMSVM_VMCB_2_CPU_SEG_ATTR(pVmcb->guest.REG.u16Attr); \
    6666    } while (0)
    67 /** @}  */
     67/** @} */
     68
     69/** @name VMCB Clean Bits used for VMCB-state caching. */
     70/** All intercepts vectors, TSC offset, PAUSE filter counter. */
     71#define HMSVM_VMCB_CLEAN_INTERCEPTS             RT_BIT(0)
     72/** I/O permission bitmap, MSR permission bitmap. */
     73#define HMSVM_VMCB_CLEAN_IOPM_MSRPM             RT_BIT(1)
     74/** ASID.  */
     75#define HMSVM_VMCB_CLEAN_ASID                   RT_BIT(2)
     76/** TRP: V_TPR, V_IRQ, V_INTR_PRIO, V_IGN_TPR, V_INTR_MASKING,
     77V_INTR_VECTOR. */
     78#define HMSVM_VMCB_CLEAN_TPR                    RT_BIT(3)
     79/** Nested Paging: Nested CR3 (nCR3), PAT. */
     80#define HMSVM_VMCB_CLEAN_NP                     RT_BIT(4)
     81/** Control registers (CR0, CR3, CR4, EFER). */
     82#define HMSVM_VMCB_CLEAN_CRX                    RT_BIT(5)
     83/** Debug registers (DR6, DR7). */
     84#define HMSVM_VMCB_CLEAN_DRX                    RT_BIT(6)
     85/** GDT, IDT limit and base. */
     86#define HMSVM_VMCB_CLEAN_DT                     RT_BIT(7)
     87/** Segment register: CS, SS, DS, ES limit and base. */
     88#define HMSVM_VMCB_CLEAN_SEG                    RT_BIT(8)
     89/** CR2.*/
     90#define HMSVM_VMCB_CLEAN_CR2                    RT_BIT(9)
     91/** Last-branch record (DbgCtlMsr, br_from, br_to, lastint_from, lastint_to) */
     92#define HMSVM_VMCB_CLEAN_LBR                    RT_BIT(10)
     93/** AVIC (AVIC APIC_BAR; AVIC APIC_BACKING_PAGE, AVIC
     94PHYSICAL_TABLE and AVIC LOGICAL_TABLE Pointers). */
     95#define HMSVM_VMCB_CLEAN_AVIC                   RT_BIT(11)
     96/** @} */
    6897
    6998/**
     
    788817
    789818
    790 DECLINLINE(void) hmR0VmxSvmAddXcptIntercept(uint32_t u32Xcpt)
    791 {
    792     if (!(pVmcb->ctrl.u32InterceptException & u32Xcpt)
    793     {
    794         pVmcb->ctrl.u32InterceptException |= u32Xcpt;
    795         pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_SVM_INTERCEPT_VECTORS;
    796     }
    797 }
    798 
    799 DECLINLINE(void) hmR0VmxSvmRemoveXcptIntercept(uint32_t u32Xcpt)
    800 {
    801     if (pVmcb->ctrl.u32InterceptException & u32Xcpt)
    802     {
    803         pVmcb->ctrl.u32InterceptException &= ~u32Xcpt;
    804         pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_SVM_INTERCEPT_VECTORS;
    805     }
     819DECLINLINE(void) hmR0SvmAddXcptIntercept(uint32_t u32Xcpt)
     820{
     821    if (!(pVmcb->ctrl.u32InterceptException & RT_BIT(u32Xcpt))
     822    {
     823        pVmcb->ctrl.u32InterceptException |= RT_BIT(u32Xcpt);
     824        pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS;
     825    }
     826}
     827
     828DECLINLINE(void) hmR0SvmRemoveXcptIntercept(uint32_t u32Xcpt)
     829{
     830#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
     831    if (pVmcb->ctrl.u32InterceptException & RT_BIT(u32Xcpt))
     832    {
     833        pVmcb->ctrl.u32InterceptException &= ~RT_BIT(u32Xcpt);
     834        pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS;
     835    }
     836#endif
    806837}
    807838
     
    829860
    830861        /*
    831          * With Nested Paging, the guest is allowed to run with paging disabled; guest-physical to host-physical translations
    832          * will remain active through the Nested CR3. AMD supports paged real-mode, See AMD spec. 15.19 "Paged Real Mode".
     862         * When Nested Paging is not available use shadow page tables and intercept #PFs (latter done in SVMR0SetupVM()).
    833863         */
    834864        if (!pVM->hm.s.fNestedPaging)
    835865        {
    836             u64GuestCR0 |= X86_CR0_PG;  /* When Nested Paging is not available use shadow page tables. */
     866            u64GuestCR0 |= X86_CR0_PG;  /* When Nested Paging is not available, use shadow page tables. */
    837867            u64GuestCR0 |= X86_CR0_WP;  /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
    838868        }
     
    865895         */
    866896        if (fInterceptNM)
    867             hmR0VmxSvmAddXcptIntercept(RT_BIT(X86_XCPT_NM));
     897            hmR0SvmAddXcptIntercept(X86_XCPT_NM);
    868898        else
    869             hmR0VmxSvmRemoveXcptIntercept(RT_BIT(X86_XCPT_NM));
     899            hmR0SvmRemoveXcptIntercept(X86_XCPT_NM);
    870900
    871901        if (fInterceptMF)
    872             hmR0VmxSvmAddXcptIntercept(RT_BIT(X86_XCPT_MF));
     902            hmR0SvmAddXcptIntercept(X86_XCPT_MF);
    873903        else
    874             hmR0VmxSvmRemoveXcptIntercept(RT_BIT(X86_XCPT_MF));
     904            hmR0SvmRemoveXcptIntercept(X86_XCPT_MF);
    875905
    876906        pVmcb->guest.u64CR0 = u64GuestCR0;
     
    10561086}
    10571087
     1088/**
     1089 * Loads the guest debug registers into the VMCB.
     1090 *
     1091 * @param   pVCpu       Pointer to the VMCPU.
     1092 * @param   pCtx        Pointer to the guest-CPU context.
     1093 *
     1094 * @remarks No-long-jump zone!!!
     1095 */
     1096static void hmR0SvmLoadGuestDebugRegs(PVMCPU pVCpu, PCPUMCTX pCtx)
     1097{
     1098    if (!(pVCpu->hm.s.fContextUseFlags & HM_CHANGED_GUEST_DEBUG))
     1099        return;
     1100
     1101    /** @todo Turn these into assertions if possible. */
     1102    pCtx->dr[6] |= X86_DR6_INIT_VAL;                                          /* Set reserved bits to 1. */
     1103    pCtx->dr[6] &= ~RT_BIT(12);                                               /* MBZ. */
     1104
     1105    pCtx->dr[7] &= 0xffffffff;                                                /* Upper 32 bits MBZ. */
     1106    pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));      /* MBZ. */
     1107    pCtx->dr[7] |= 0x400;                                                     /* MB1. */
     1108
     1109    /* Update DR6, DR7 with the guest values. */
     1110    pVmcb->guest.u64DR7 = pCtx->dr[7];
     1111    pVmcb->guest.u64DR6 = pCtx->dr[6];
     1112    pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX;
     1113
     1114    bool fInterceptDB     = false;
     1115    bool fInterceptMovDRx = false;
     1116    if (DBGFIsStepping(pVCpu))
     1117    {
     1118        /* AMD-V doesn't have any monitor-trap flag equivalent. Instead, enable tracing in the guest and trap #DB. */
     1119        pVmcb->guest.u64RFlags |= X86_EFL_TF;
     1120        fInterceptDB = true;
     1121    }
     1122
     1123    if (CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
     1124    {
     1125        if (!CPUMIsHyperDebugStateActive(pVCpu))
     1126        {
     1127            rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pMixedCtx, true /* include DR6 */);
     1128            AssertRC(rc);
     1129
     1130            /* Update DR6, DR7 with the hypervisor values. */
     1131            pVmcb->guest.u64DR7 = CPUMGetHyperDR7(pVCpu);
     1132            pVmcb->guest.u64DR6 = CPUMGetHyperDR6(pVCpu);
     1133            pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX;
     1134        }
     1135        Assert(CPUMIsHyperDebugStateActive(pVCpu));
     1136        fInterceptMovDRx = true;
     1137    }
     1138    else if (pMixedCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
     1139    {
     1140        if (!CPUMIsGuestDebugStateActive(pVCpu))
     1141        {
     1142            rc = CPUMR0LoadGuestDebugState(pVM, pVCpu, pMixedCtx, true /* include DR6 */);
     1143            AssertRC(rc);
     1144            STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
     1145        }
     1146        Assert(CPUMIsGuestDebugStateActive(pVCpu));
     1147        Assert(fInterceptMovDRx == false);
     1148    }
     1149    else if (!CPUMIsGuestDebugStateActive(pVCpu))
     1150    {
     1151        /* For the first time we would need to intercept MOV DRx accesses even when the guest debug registers aren't loaded. */
     1152        fInterceptMovDRx = true;
     1153    }
     1154
     1155    if (fInterceptDB)
     1156        hmR0SvmAddXcptIntercept(X86_XCPT_DB);
     1157    else
     1158        hmR0SvmRemoveXcptIntercept(X86_XCPT_DB);
     1159
     1160    if (fInterceptMovDRx)
     1161    {
     1162        if (   pVmcb->ctrl.u16InterceptRdDRx != 0xffff
     1163            || pVmcb->ctrl.u16InterceptWrDRx != 0xffff)
     1164        {
     1165            pVmcb->ctrl.u16InterceptRdDRx = 0xffff;
     1166            pVmcb->ctrl.u16InterceptWrDRx = 0xffff;
     1167            pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS;
     1168        }
     1169    }
     1170    else
     1171    {
     1172        if (   pVmcb->ctrl.u16InterceptRdDRx
     1173            || pVmcb->ctrl.u16InterceptWrDRx)
     1174        {
     1175            pVmcb->ctrl.u16InterceptRdDRx = 0;
     1176            pVmcb->ctrl.u16InterceptWrDRx = 0;
     1177            pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS;
     1178        }
     1179    }
     1180
     1181    pVCpu->hm.s.fContextUseFlags &= ~HM_CHANGED_GUEST_DEBUG;
     1182}
    10581183
    10591184/**
     
    11271252    pVmcb->guest.u8CPL     = pCtx->ss.Attr.n.u2Dpl;
    11281253
     1254    /* hmR0SvmLoadGuestDebugRegs() must be called -after- updating guest RFLAGS as the RFLAGS may need to be changed. */
     1255    hmR0SvmLoadGuestDebugRegs(pVCpu, pCtx);
     1256
    11291257    /* Guest RAX (VMRUN uses RAX as an implicit parameter). */
    11301258    pVmcb->guest.u64RAX    = pCtx->rax;
     1259
     1260    /* -XXX tsc offsetting */
    11311261
    11321262    rc = hmR0SvmSetupVMRunHandler(pVCpu, pMixedCtx);
Note: See TracChangeset for help on using the changeset viewer.

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