Move the VMCB initialization into svm.c in preparation for changes to the

interrupt injection logic.

Discussed with:	Anish Gupta (akgupt3@gmail.com)
This commit is contained in:
Neel Natu 2014-09-10 02:35:19 +00:00
parent 840b1a2760
commit e5397c9fdd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bhyve_svm/; revision=271346
3 changed files with 79 additions and 84 deletions

View File

@ -394,6 +394,84 @@ vcpu_set_dirty(struct svm_softc *sc, int vcpu, uint32_t dirtybits)
vcpustate->dirty |= dirtybits;
}
static void
vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa,
uint64_t msrpm_base_pa, uint64_t np_pml4)
{
struct vmcb_ctrl *ctrl;
struct vmcb_state *state;
uint16_t cr_shadow;
ctrl = svm_get_vmcb_ctrl(sc, vcpu);
state = svm_get_vmcb_state(sc, vcpu);
ctrl->iopm_base_pa = iopm_base_pa;
ctrl->msrpm_base_pa = msrpm_base_pa;
/* Enable nested paging */
ctrl->np_enable = 1;
ctrl->n_cr3 = np_pml4;
/*
* Intercept accesses to the control registers that are not shadowed
* in the VMCB - i.e. all except cr0, cr2, cr3, cr4 and cr8.
*/
cr_shadow = BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(8);
ctrl->cr_write = ctrl->cr_read = ~cr_shadow;
/* Intercept Machine Check exceptions. */
ctrl->exception = BIT(IDT_MC);
/* Intercept various events (for e.g. I/O, MSR and CPUID accesses) */
ctrl->ctrl1 = VMCB_INTCPT_IO |
VMCB_INTCPT_MSR |
VMCB_INTCPT_HLT |
VMCB_INTCPT_CPUID |
VMCB_INTCPT_INTR |
VMCB_INTCPT_VINTR |
VMCB_INTCPT_INIT |
VMCB_INTCPT_NMI |
VMCB_INTCPT_SMI |
VMCB_INTCPT_FERR_FREEZE |
VMCB_INTCPT_SHUTDOWN;
/*
* From section "Canonicalization and Consistency Checks" in APMv2
* the VMRUN intercept bit must be set to pass the consistency check.
*/
ctrl->ctrl2 = VMCB_INTCPT_VMRUN;
/*
* The ASID will be set to a non-zero value just before VMRUN.
*/
ctrl->asid = 0;
/*
* Section 15.21.1, Interrupt Masking in EFLAGS
* Section 15.21.2, Virtualizing APIC.TPR
*
* This must be set for %rflag and %cr8 isolation of guest and host.
*/
ctrl->v_intr_masking = 1;
/* Enable Last Branch Record aka LBR for debugging */
ctrl->lbr_virt_en = 1;
state->dbgctl = BIT(0);
/* EFER_SVM must always be set when the guest is executing */
state->efer = EFER_SVM;
/* Set up the PAT to power-on state */
state->g_pat = PAT_VALUE(0, PAT_WRITE_BACK) |
PAT_VALUE(1, PAT_WRITE_THROUGH) |
PAT_VALUE(2, PAT_UNCACHED) |
PAT_VALUE(3, PAT_UNCACHEABLE) |
PAT_VALUE(4, PAT_WRITE_BACK) |
PAT_VALUE(5, PAT_WRITE_THROUGH) |
PAT_VALUE(6, PAT_UNCACHED) |
PAT_VALUE(7, PAT_UNCACHEABLE);
}
/*
* Initialise a virtual machine.
*/
@ -452,7 +530,7 @@ svm_vminit(struct vm *vm, pmap_t pmap)
vcpu = svm_get_vcpu(svm_sc, i);
vcpu->lastcpu = NOCPU;
vcpu->vmcb_pa = vtophys(&vcpu->vmcb);
svm_init_vmcb(&vcpu->vmcb, iopm_pa, msrpm_pa, pml4_pa);
vmcb_init(svm_sc, i, iopm_pa, msrpm_pa, pml4_pa);
}
return (svm_sc);
}

View File

@ -48,87 +48,6 @@ __FBSDID("$FreeBSD$");
* - guest processor state (e.g. general purpose registers)
*/
/*
* Initialize SVM h/w context i.e. the VMCB control and saved state areas.
*/
void
svm_init_vmcb(struct vmcb *vmcb, uint64_t iopm_base_pa, uint64_t msrpm_base_pa,
uint64_t np_pml4)
{
struct vmcb_ctrl *ctrl;
struct vmcb_state *state;
uint16_t cr_shadow;
ctrl = &vmcb->ctrl;
state = &vmcb->state;
ctrl->iopm_base_pa = iopm_base_pa;
ctrl->msrpm_base_pa = msrpm_base_pa;
/* Enable nested paging */
ctrl->np_enable = 1;
ctrl->n_cr3 = np_pml4;
/*
* Intercept accesses to the control registers that are not shadowed
* in the VMCB - i.e. all except cr0, cr2, cr3, cr4 and cr8.
*/
cr_shadow = BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(8);
ctrl->cr_write = ctrl->cr_read = ~cr_shadow;
/* Intercept Machine Check exceptions. */
ctrl->exception = BIT(IDT_MC);
/* Intercept various events (for e.g. I/O, MSR and CPUID accesses) */
ctrl->ctrl1 = VMCB_INTCPT_IO |
VMCB_INTCPT_MSR |
VMCB_INTCPT_HLT |
VMCB_INTCPT_CPUID |
VMCB_INTCPT_INTR |
VMCB_INTCPT_VINTR |
VMCB_INTCPT_INIT |
VMCB_INTCPT_NMI |
VMCB_INTCPT_SMI |
VMCB_INTCPT_FERR_FREEZE |
VMCB_INTCPT_SHUTDOWN;
/*
* From section "Canonicalization and Consistency Checks" in APMv2
* the VMRUN intercept bit must be set to pass the consistency check.
*/
ctrl->ctrl2 = VMCB_INTCPT_VMRUN;
/*
* The ASID will be set to a non-zero value just before VMRUN.
*/
ctrl->asid = 0;
/*
* Section 15.21.1, Interrupt Masking in EFLAGS
* Section 15.21.2, Virtualizing APIC.TPR
*
* This must be set for %rflag and %cr8 isolation of guest and host.
*/
ctrl->v_intr_masking = 1;
/* Enable Last Branch Record aka LBR for debugging */
ctrl->lbr_virt_en = 1;
state->dbgctl = BIT(0);
/* EFER_SVM must always be set when the guest is executing */
state->efer = EFER_SVM;
/* Set up the PAT to power-on state */
state->g_pat = PAT_VALUE(0, PAT_WRITE_BACK) |
PAT_VALUE(1, PAT_WRITE_THROUGH) |
PAT_VALUE(2, PAT_UNCACHED) |
PAT_VALUE(3, PAT_UNCACHEABLE) |
PAT_VALUE(4, PAT_WRITE_BACK) |
PAT_VALUE(5, PAT_WRITE_THROUGH) |
PAT_VALUE(6, PAT_UNCACHED) |
PAT_VALUE(7, PAT_UNCACHEABLE);
}
/*
* Read from segment selector, control and general purpose register of VMCB.
*/

View File

@ -277,8 +277,6 @@ struct vmcb {
CTASSERT(sizeof(struct vmcb) == PAGE_SIZE);
CTASSERT(offsetof(struct vmcb, state) == 0x400);
void svm_init_vmcb(struct vmcb *vmcb, uint64_t iopm_base_pa,
uint64_t msrpm_base_pa, uint64_t np_pml4);
int vmcb_read(struct vmcb *vmcb, int ident, uint64_t *retval);
int vmcb_write(struct vmcb *vmcb, int ident, uint64_t val);
struct vmcb_segment *vmcb_seg(struct vmcb *vmcb, int type);