Split the VMCS setup between 'vmcs_init()' that does initialization and

'vmx_vminit()' that does customization.

This makes it easier to turn on optional features (e.g. APICv) without
having to keep adding new parameters to 'vmcs_set_defaults()'.

Reviewed by:	grehan@
This commit is contained in:
neel 2014-01-06 23:16:39 +00:00
parent 9f8536f282
commit 35066c7a68
3 changed files with 27 additions and 64 deletions

View File

@ -315,11 +315,7 @@ vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count)
}
int
vmcs_set_defaults(struct vmcs *vmcs,
u_long host_rip, u_long host_rsp, uint64_t eptp,
uint32_t pinbased_ctls, uint32_t procbased_ctls,
uint32_t procbased_ctls2, uint32_t exit_ctls,
uint32_t entry_ctls, u_long msr_bitmap, uint16_t vpid)
vmcs_init(struct vmcs *vmcs)
{
int error, codesel, datasel, tsssel;
u_long cr0, cr4, efer;
@ -335,22 +331,6 @@ vmcs_set_defaults(struct vmcs *vmcs,
*/
VMPTRLD(vmcs);
/*
* Load the VMX controls
*/
if ((error = vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls)) != 0)
goto done;
if ((error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls)) != 0)
goto done;
if ((error = vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2)) != 0)
goto done;
if ((error = vmwrite(VMCS_EXIT_CTLS, exit_ctls)) != 0)
goto done;
if ((error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls)) != 0)
goto done;
/* Guest state */
/* Initialize guest IA32_PAT MSR with the default value */
pat = PAT_VALUE(0, PAT_WRITE_BACK) |
PAT_VALUE(1, PAT_WRITE_THROUGH) |
@ -422,23 +402,7 @@ vmcs_set_defaults(struct vmcs *vmcs,
goto done;
/* instruction pointer */
if ((error = vmwrite(VMCS_HOST_RIP, host_rip)) != 0)
goto done;
/* stack pointer */
if ((error = vmwrite(VMCS_HOST_RSP, host_rsp)) != 0)
goto done;
/* eptp */
if ((error = vmwrite(VMCS_EPTP, eptp)) != 0)
goto done;
/* vpid */
if ((error = vmwrite(VMCS_VPID, vpid)) != 0)
goto done;
/* msr bitmap */
if ((error = vmwrite(VMCS_MSR_BITMAP, msr_bitmap)) != 0)
if ((error = vmwrite(VMCS_HOST_RIP, (u_long)vmx_exit_guest)) != 0)
goto done;
/* exception bitmap */

View File

@ -46,12 +46,7 @@ struct msr_entry {
};
int vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count);
int vmcs_set_defaults(struct vmcs *vmcs, u_long host_rip, u_long host_rsp,
uint64_t eptp,
uint32_t pinbased_ctls, uint32_t procbased_ctls,
uint32_t procbased_ctls2, uint32_t exit_ctls,
uint32_t entry_ctls, u_long msr_bitmap,
uint16_t vpid);
int vmcs_init(struct vmcs *vmcs);
int vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *rv);
int vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val);
int vmcs_getdesc(struct vmcs *vmcs, int ident,

View File

@ -678,6 +678,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
uint16_t vpid[VM_MAXCPU];
int i, error, guest_msr_count;
struct vmx *vmx;
struct vmcs *vmcs;
vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
if ((uintptr_t)vmx & PAGE_MASK) {
@ -743,26 +744,30 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
vpid_alloc(vpid, VM_MAXCPU);
for (i = 0; i < VM_MAXCPU; i++) {
vmx->vmcs[i].identifier = vmx_revision();
error = vmclear(&vmx->vmcs[i]);
vmcs = &vmx->vmcs[i];
vmcs->identifier = vmx_revision();
error = vmclear(vmcs);
if (error != 0) {
panic("vmx_vminit: vmclear error %d on vcpu %d\n",
error, i);
}
error = vmcs_set_defaults(&vmx->vmcs[i],
(u_long)vmx_exit_guest,
(u_long)&vmx->ctx[i],
vmx->eptp,
pinbased_ctls,
procbased_ctls,
procbased_ctls2,
exit_ctls, entry_ctls,
vtophys(vmx->msr_bitmap),
vpid[i]);
error = vmcs_init(vmcs);
KASSERT(error == 0, ("vmcs_init error %d", error));
if (error != 0)
panic("vmx_vminit: vmcs_set_defaults error %d", error);
VMPTRLD(vmcs);
error = 0;
error += vmwrite(VMCS_HOST_RSP, (u_long)&vmx->ctx[i]);
error += vmwrite(VMCS_EPTP, vmx->eptp);
error += vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls);
error += vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls);
error += vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2);
error += vmwrite(VMCS_EXIT_CTLS, exit_ctls);
error += vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
error += vmwrite(VMCS_MSR_BITMAP, vtophys(vmx->msr_bitmap));
error += vmwrite(VMCS_VPID, vpid[i]);
VMCLEAR(vmcs);
KASSERT(error == 0, ("vmx_vminit: error customizing the vmcs"));
vmx->cap[i].set = 0;
vmx->cap[i].proc_ctls = procbased_ctls;
@ -773,9 +778,8 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
msr_save_area_init(vmx->guest_msrs[i], &guest_msr_count);
error = vmcs_set_msr_save(&vmx->vmcs[i],
vtophys(vmx->guest_msrs[i]),
guest_msr_count);
error = vmcs_set_msr_save(vmcs, vtophys(vmx->guest_msrs[i]),
guest_msr_count);
if (error != 0)
panic("vmcs_set_msr_save error %d", error);
@ -785,11 +789,11 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
* CR0 - 0x60000010
* CR4 - 0
*/
error = vmx_setup_cr0_shadow(&vmx->vmcs[i], 0x60000010);
error = vmx_setup_cr0_shadow(vmcs, 0x60000010);
if (error != 0)
panic("vmx_setup_cr0_shadow %d", error);
error = vmx_setup_cr4_shadow(&vmx->vmcs[i], 0);
error = vmx_setup_cr4_shadow(vmcs, 0);
if (error != 0)
panic("vmx_setup_cr4_shadow %d", error);
@ -1455,7 +1459,7 @@ vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap)
* from a different process than the one that actually runs it.
*
* If the life of a virtual machine was spent entirely in the context
* of a single process we could do this once in vmcs_set_defaults().
* of a single process we could do this once in vmx_vminit().
*/
vmcs_write(VMCS_HOST_CR3, rcr3());