VirtualBox

Changeset 46365 in vbox


Ignore:
Timestamp:
Jun 3, 2013 3:02:41 PM (11 years ago)
Author:
vboxsync
Message:

VMM/HMSVMR0: AMD-V bits.

File:
1 edited

Legend:

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

    r46310 r46365  
    2525#endif
    2626
     27
     28/*******************************************************************************
     29*   Defined Constants And Macros                                               *
     30*******************************************************************************/
     31
     32/**
     33 * MSR-bitmap read permissions.
     34 */
     35typedef enum SVMMSREXITREAD
     36{
     37    /** Reading this MSR causes a VM-exit. */
     38    SVMMSREXIT_INTERCEPT_READ = 0xb,
     39    /** Reading this MSR does not cause a VM-exit. */
     40    SVMMSREXIT_PASSTHRU_READ
     41} VMXMSREXITREAD;
     42
     43/**
     44 * MSR-bitmap write permissions.
     45 */
     46typedef enum SVMMSREXITWRITE
     47{
     48    /** Writing to this MSR causes a VM-exit. */
     49    SVMMSREXIT_INTERCEPT_WRITE = 0xd,
     50    /** Writing to this MSR does not cause a VM-exit. */
     51    SVMMSREXIT_PASSTHRU_WRITE
     52} VMXMSREXITWRITE;
     53
     54
    2755/*******************************************************************************
    2856*   Internal Functions                                                         *
    2957*******************************************************************************/
    30 
    31 
    32 /*******************************************************************************
    33 *   Defined Constants And Macros                                               *
    34 *******************************************************************************/
     58static void hmR0SvmSetMSRPermission(PVMCPU pVCpu, unsigned uMsr, SVMMSREXITREAD enmRead, SVMMSREXITWRITE enmWrite);
    3559
    3660
     
    305329    Assert(pVM->hm.s.svm.fSupported);
    306330
    307     for (uint32_t i = 0; i < pVM->cCpus; i++)
     331    for (VMCPUID i = 0; i < pVM->cCpus; i++)
    308332    {
    309333        PVMCPU   pVCpu = &pVM->aCpus[i];
     
    312336        AssertMsgReturn(pVmcb, ("Invalid pVmcb\n"), VERR_SVM_INVALID_PVMCB);
    313337
    314         /* Intercept traps. */
     338        /* Trap exceptions unconditionally (debug purposes). */
    315339#ifdef HMSVM_ALWAYS_TRAP_PF
    316340        pVmcb->ctrl.u32InterceptException |=   RT_BIT(X86_XCPT_PF);
     
    320344                                             | RT_BIT(X86_XCPT_DB)
    321345                                             | RT_BIT(X86_XCPT_DE)
     346                                             | RT_BIT(X86_XCPT_NM)
    322347                                             | RT_BIT(X86_XCPT_UD)
    323348                                             | RT_BIT(X86_XCPT_NP)
    324349                                             | RT_BIT(X86_XCPT_SS)
    325350                                             | RT_BIT(X86_XCPT_GP)
    326                                              | RT_BIT(X86_XCPT_MF)
    327                                              | RT_BIT(X86_XCPT_PF);
     351                                             | RT_BIT(X86_XCPT_PF)
     352                                             | RT_BIT(X86_XCPT_MF);
    328353#endif
    329354
    330         /* -XXX- todo. */
     355        /* Set up unconditional intercepts and conditions. */
     356        pVmcb->ctrl.u32InterceptCtrl1 =   SVM_CTRL1_INTERCEPT_INTR          /* External interrupt causes a VM-exit. */
     357                                        | SVM_CTRL1_INTERCEPT_VINTR         /* When guest enabled interrupts cause a VM-exit. */
     358                                        | SVM_CTRL1_INTERCEPT_NMI           /* Non-Maskable Interrupts causes a VM-exit. */
     359                                        | SVM_CTRL1_INTERCEPT_SMI           /* System Management Interrupt cause a VM-exit. */
     360                                        | SVM_CTRL1_INTERCEPT_INIT          /* INIT signal causes a VM-exit. */
     361                                        | SVM_CTRL1_INTERCEPT_RDPMC         /* RDPMC causes a VM-exit. */
     362                                        | SVM_CTRL1_INTERCEPT_CPUID         /* CPUID causes a VM-exit. */
     363                                        | SVM_CTRL1_INTERCEPT_RSM           /* RSM causes a VM-exit. */
     364                                        | SVM_CTRL1_INTERCEPT_HLT           /* HLT causes a VM-exit. */
     365                                        | SVM_CTRL1_INTERCEPT_INOUT_BITMAP  /* Use the IOPM to cause IOIO VM-exits. */
     366                                        | SVM_CTRL1_INTERCEPT_MSR_SHADOW    /* MSR access not covered by MSRPM causes a VM-exit.*/
     367                                        | SVM_CTRL1_INTERCEPT_INVLPGA       /* INVLPGA causes a VM-exit. */
     368                                        | SVM_CTRL1_INTERCEPT_SHUTDOWN      /* Shutdown events causes a VM-exit. */
     369                                        | SVM_CTRL1_INTERCEPT_FERR_FREEZE;  /* Intercept "freezing" during legacy FPU handling. */
     370
     371        pVmcb->ctrl.u32InterceptCtrl2 =   SVM_CTRL2_INTERCEPT_VMRUN         /* VMRUN causes a VM-exit. */
     372                                        | SVM_CTRL2_INTERCEPT_VMMCALL       /* VMMCALL causes a VM-exit. */
     373                                        | SVM_CTRL2_INTERCEPT_VMLOAD        /* VMLOAD causes a VM-exit. */
     374                                        | SVM_CTRL2_INTERCEPT_VMSAVE        /* VMSAVE causes a VM-exit. */
     375                                        | SVM_CTRL2_INTERCEPT_STGI          /* STGI causes a VM-exit. */
     376                                        | SVM_CTRL2_INTERCEPT_CLGI          /* CLGI causes a VM-exit. */
     377                                        | SVM_CTRL2_INTERCEPT_SKINIT        /* SKINIT causes a VM-exit. */
     378                                        | SVM_CTRL2_INTERCEPT_WBINVD        /* WBINVD causes a VM-exit. */
     379                                        | SVM_CTRL2_INTERCEPT_MONITOR       /* MONITOR causes a VM-exit. */
     380                                        | SVM_CTRL2_INTERCEPT_MWAIT_UNCOND; /* MWAIT causes a VM-exit. */
     381
     382        /* CR0, CR4 reads must be intercepted, our shadow values are not necessarily the same as the guest's. */
     383        pVmcb->ctrl.u16InterceptRdCRx = RT_BIT(0) | RT_BIT(4);
     384
     385        /* CR0, CR4 writes must be intercepted for obvious reasons. */
     386        pVmcb->ctrl.u16InterceptWrCRx = RT_BIT(0) | RT_BIT(4);
     387
     388        /* Intercept all DRx reads and writes by default. Changed later on. */
     389        pVmcb->ctrl.u16InterceptRdDRx = 0xffff;
     390        pVmcb->ctrl.u16InterceptWrDRx = 0xffff;
     391
     392        /* Virtualize masking of INTR interrupts. (reads/writes from/to CR8 go to the V_TPR register) */
     393        pVmcb->ctrl.IntCtrl.n.u1VIrqMasking = 1;
     394
     395        /* Ignore the priority in the TPR; just deliver it to the guest when we tell it to. */
     396        pVmcb->ctrl.IntCtrl.n.u1IgnoreTPR   = 1;
     397
     398        /* Set IO and MSR bitmap permission bitmap physical addresses. */
     399        pVmcb->ctrl.u64IOPMPhysAddr  = g_HCPhysIOBitmap;
     400        pVmcb->ctrl.u64MSRPMPhysAddr = pVCpu->hm.s.svm.HCPhysMsrBitmap;
     401
     402        /* No LBR virtualization. */
     403        pVmcb->ctrl.u64LBRVirt = 0;
     404
     405        /* The ASID must start at 1; the host uses 0. */
     406        pVmcb->ctrl.TLBCtrl.n.u32ASID = 1;
     407
     408        /*
     409         * Setup the PAT MSR (applicable for Nested Paging only).
     410         * The default value should be 0x0007040600070406ULL, but we want to treat all guest memory as WB,
     411         * so choose type 6 for all PAT slots.
     412         */
     413        pVmcb->guest.u64GPAT = UINT64_C(0x0006060606060606);
     414
     415        /* Without Nested Paging, we need additionally intercepts. */
     416        if (!pVM->hm.s.fNestedPaging)
     417        {
     418            /* CR3 reads/writes must be intercepted; our shadow values differ from the guest values. */
     419            pVmcb->ctrl.u16InterceptRdCRx |= RT_BIT(3);
     420            pVmcb->ctrl.u16InterceptWrCRx |= RT_BIT(3);
     421
     422            /* Intercept INVLPG and task switches (may change CR3, EFLAGS, LDT). */
     423            pVmcb->ctrl.u32InterceptCtrl1 |=   SVM_CTRL1_INTERCEPT_INVLPG
     424                                             | SVM_CTRL1_INTERCEPT_TASK_SWITCH;
     425
     426            /* Page faults must be intercepted to implement shadow paging. */
     427            pVmcb->ctrl.u32InterceptException |= RT_BIT(X86_XCPT_PF);
     428        }
     429
     430        /*
     431         * The following MSRs are saved/restored automatically during the world-switch.
     432         * Don't intercept guest read/write accesses to these MSRs.
     433         */
     434        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_LSTAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     435        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_CSTAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     436        hmR0SvmSetMSRPermission(pVCpu, MSR_K6_STAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     437        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_SF_MASK, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     438        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_FS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     439        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_GS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     440        hmR0SvmSetMSRPermission(pVCpu, MSR_K8_KERNEL_GS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     441        hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_CS, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     442        hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_ESP, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
     443        hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_EIP, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE);
    331444    }
    332445
     
    334447}
    335448
     449
     450/**
     451 * Sets the permission bits for the specified MSR.
     452 *
     453 * @param   pVCpu       Pointer to the VMCPU.
     454 * @param   uMsr       The MSR.
     455 * @param   fRead       Whether reading is allowed.
     456 * @param   fWrite      Whether writing is allowed.
     457 */
     458static void hmR0SvmSetMSRPermission(PVMCPU pVCpu, uint32_t uMsr, SVMMSREXITREAD enmRead, SVMMSREXITWRITE enmWrite)
     459{
     460    unsigned ulBit;
     461    uint8_t *pbMsrBitmap = (uint8_t *)pVCpu->hm.s.svm.pvMsrBitmap;
     462
     463    /*
     464     * Layout:
     465     * Byte offset       MSR range
     466     * 0x000  - 0x7ff    0x00000000 - 0x00001fff
     467     * 0x800  - 0xfff    0xc0000000 - 0xc0001fff
     468     * 0x1000 - 0x17ff   0xc0010000 - 0xc0011fff
     469     * 0x1800 - 0x1fff           Reserved
     470     */
     471    if (uMsr <= 0x00001FFF)
     472    {
     473        /* Pentium-compatible MSRs */
     474        ulBit    = uMsr * 2;
     475    }
     476    else if (   uMsr >= 0xC0000000
     477             && uMsr <= 0xC0001FFF)
     478    {
     479        /* AMD Sixth Generation x86 Processor MSRs and SYSCALL */
     480        ulBit = (uMsr - 0xC0000000) * 2;
     481        pbMsrBitmap += 0x800;
     482    }
     483    else if (   uMsr >= 0xC0010000
     484             && uMsr <= 0xC0011FFF)
     485    {
     486        /* AMD Seventh and Eighth Generation Processor MSRs */
     487        ulBit = (uMsr - 0xC0001000) * 2;
     488        pbMsrBitmap += 0x1000;
     489    }
     490    else
     491    {
     492        AssertFailed();
     493        return;
     494    }
     495
     496    Assert(ulBit < 0x3fff /* 16 * 1024 - 1 */);
     497    if (enmRead == SVMMSREXIT_INTERCEPT_READ)
     498        ASMBitSet(pbMsrBitmap, ulBit);
     499    else
     500        ASMBitClear(pbMsrBitmap, ulBit);
     501
     502    if (enmWrite == SVMMSREXIT_INTERCEPT_WRITE)
     503        ASMBitSet(pbMsrBitmap, ulBit + 1);
     504    else
     505        ASMBitClear(pbMsrBitmap, ulBit + 1);
     506}
     507
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