Deleted Added
full compact
28c28
< __FBSDID("$FreeBSD: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c 256867 2013-10-21 23:46:37Z neel $");
---
> __FBSDID("$FreeBSD: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c 259579 2013-12-18 23:39:42Z grehan $");
64c64
< * SVM CPUID function 0x8000_000Ai, edx bit decoding.
---
> * SVM CPUID function 0x8000_000A, edx bit decoding.
82c82
< static int svm_vmexit(struct svm_softc *svm_sc, int vcpu,
---
> static bool svm_vmexit(struct svm_softc *svm_sc, int vcpu,
101,105d100
< /*
< * Statistics
< */
< static VMM_STAT_AMD(VMEXIT_NPF_LAPIC, "vm exits due to Local APIC access");
<
115a111,112
> static VMM_STAT_AMD(VCPU_EXITINTINFO, "Valid EXITINTINFO");
>
126c123
< if (enable) {
---
> if (enable)
128c125
< } else {
---
> else
130d126
< }
134,138d129
< if(rdmsr(MSR_EFER) != efer_msr) {
< ERR("SVM couldn't be enabled on CPU%d.\n", curcpu);
< return (EIO);
< }
<
202c193
< * XXX: BHyVe need EPT or RVI to work.
---
> * bhyve need RVI to work.
209,210c200
< if (svm_feature & (AMD_CPUID_SVM_NRIP_SAVE |
< AMD_CPUID_SVM_DECODE_ASSIST)) {
---
> if (svm_feature & AMD_CPUID_SVM_NRIP_SAVE)
212,215c202
< }
< /* XXX: Should never be here? */
< printf("Processor doesn't support nRIP or decode assist, can't"
< "run BhyVe.\n");
---
>
270c257
< if (err) {
---
> if (err)
272c259
< }
---
>
279c266
< return(0);
---
> return (0);
386c373
< svm_vminit(struct vm *vm)
---
> svm_vminit(struct vm *vm, pmap_t pmap)
404c391
<
---
> svm_sc->nptp = (vm_offset_t)vtophys(pmap->pm_pml4);
407c394
< * ASID(Addres Space Identifier) are used by TLB entries.
---
> * ASID(Address Space Identifier) is used by TLB entry.
441c428
< pml4_pa = vtophys(svm_sc->np_pml4);
---
> pml4_pa = svm_sc->nptp;
461c448
< static int
---
> static bool
480c467
< return (1);
---
> return (false);
483,489c470,471
< /*
< * SVM Nested Page(RVI) Fault handler.
< * Nested page fault handler used by local APIC emulation.
< */
< static int
< svm_handle_npf(struct vm *vm, int vcpu, uint64_t gpa, uint64_t rip,
< uint64_t exitinfo1, uint64_t cr3, struct vie *vie)
---
> static void
> svm_npf_paging(uint64_t exitinfo1, int *type, int *prot)
491d472
< int err;
493,496c474,477
< if (exitinfo1 & VMCB_NPF_INFO1_ID) {
< VMM_CTR0(vm, vcpu, "SVM:NPF for code access.");
< return (0);
< }
---
> if (exitinfo1 & VMCB_NPF_INFO1_W)
> *type = VM_PROT_WRITE;
> else
> *type = VM_PROT_READ;
498,501c479,485
< if (exitinfo1 & VMCB_NPF_INFO1_RSV) {
< VMM_CTR0(vm, vcpu, "SVM:NPF reserved bits are set.");
< return (0);
< }
---
> /* XXX: protection is not used. */
> *prot = 0;
> }
>
> static bool
> svm_npf_emul_fault(uint64_t exitinfo1)
> {
503,505c487,488
< if (exitinfo1 & VMCB_NPF_INFO1_GPT) {
< VMM_CTR0(vm, vcpu, "SVM:NPF during guest page table walk.");
< return (0);
---
> if (exitinfo1 & VMCB_NPF_INFO1_ID) {
> return (false);
508,518c491,492
< /*
< * nRIP is NULL for NPF so we don't have the length of instruction,
< * we rely on instruction decode s/w to determine the size of
< * instruction.
< *
< * XXX: DecodeAssist can use instruction from buffer.
< */
< if (vmm_fetch_instruction(vm, vcpu, rip, VIE_INST_SIZE,
< cr3, vie) != 0) {
< ERR("SVM:NPF instruction fetch failed, RIP:0x%lx\n", rip);
< return (EINVAL);
---
> if (exitinfo1 & VMCB_NPF_INFO1_GPT) {
> return (false);
521,531c495,496
< KASSERT(vie->num_valid, ("No instruction to emulate."));
< /*
< * SVM doesn't provide GLA unlike Intel VM-x. VIE_INVALID_GLA
< * which is a non-cannonical address indicate that GLA is not
< * available to instruction emulation.
< *
< * XXX: Which SVM capability can provided GLA?
< */
< if(vmm_decode_instruction(vm, vcpu, VIE_INVALID_GLA, vie)) {
< ERR("SVM: Couldn't decode instruction.\n");
< return (0);
---
> if ((exitinfo1 & VMCB_NPF_INFO1_GPA) == 0) {
> return (false);
534,547c499
< /*
< * XXX: Decoding for user space(IOAPIC) should be done in
< * user space.
< */
< if (gpa < DEFAULT_APIC_BASE || gpa >= (DEFAULT_APIC_BASE + PAGE_SIZE)) {
< VMM_CTR2(vm, vcpu, "SVM:NPF GPA(0x%lx) outside of local APIC"
< " range(0x%x)\n", gpa, DEFAULT_APIC_BASE);
< return (0);
< }
<
< err = vmm_emulate_instruction(vm, vcpu, gpa, vie, lapic_mmio_read,
< lapic_mmio_write, 0);
<
< return (err ? 0 : 1);
---
> return (true);
574,577c526,529
< * Determine the cause of virtual cpu exit and return to user space if exit
< * demand so.
< * Return: 1 - Return to user space.
< * 0 - Continue vcpu run.
---
> * Determine the cause of virtual cpu exit and handle VMEXIT.
> * Return: false - Break vcpu execution loop and handle vmexit
> * in kernel or user space.
> * true - Continue vcpu run.
579c531
< static int
---
> static bool
587,589c539
< int user; /* Flag for user mode */
< int update_rip; /* Flag for updating RIP */
< int inst_len;
---
> bool update_rip, loop;
596,601c546
< update_rip = 1;
< user = 0;
<
< vmexit->exitcode = VM_EXITCODE_VMX;
< vmexit->u.vmx.error = 0;
< code = ctrl->exitcode;
---
> code = ctrl->exitcode;
605,609c550,553
< if (ctrl->nrip) {
< inst_len = ctrl->nrip - state->rip;
< } else {
< inst_len = ctrl->inst_decode_size;
< }
---
> update_rip = true;
> loop = true;
> vmexit->exitcode = VM_EXITCODE_VMX;
> vmexit->u.vmx.error = 0;
615c559
< user = 1;
---
> loop = false;
631c575,576
< vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_WRMSR, 1);
---
> vmm_stat_incr(svm_sc->vm, vcpu,
> VMEXIT_WRMSR, 1);
637c582
< user = 1;
---
> loop = false;
641c586
< user ? "user" : "kernel", val, ecx);
---
> loop ? "kernel" : "user", val, ecx);
643c588,589
< vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_RDMSR, 1);
---
> vmm_stat_incr(svm_sc->vm, vcpu,
> VMEXIT_RDMSR, 1);
647c593
< user = 1;
---
> loop = false;
650,651c596,597
< " 0x%lx,%lx @0x%x", ctx->e.g.sctx_rdx,
< state->rax, ecx);
---
> " MSB=0x%08x, LSB=%08x @0x%x",
> ctx->e.g.sctx_rdx, state->rax, ecx);
662c608
< user = 0;
---
> loop = true;
665c611
< case VMCB_EXIT_INTR:
---
> case VMCB_EXIT_INTR:
671,672c617
< user = 0;
< update_rip = 0;
---
> update_rip = false;
680,682c625,626
< user = svm_handle_io(svm_sc, vcpu, vmexit);
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:I/O VMEXIT RIP:0x%lx\n",
< state->rip);
---
> loop = svm_handle_io(svm_sc, vcpu, vmexit);
> update_rip = true;
693d636
< user = 0;
700d642
< user = 0;
709c651
< user = 1;
---
> loop = false;
721a664,675
> loop = false;
> update_rip = false;
> vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_EPT_FAULT, 1);
>
> if (info1 & VMCB_NPF_INFO1_RSV) {
> VMM_CTR2(svm_sc->vm, vcpu, "SVM_ERR:NPT"
> " reserved bit is set,"
> "INFO1:0x%lx INFO2:0x%lx .\n",
> info1, info2);
> break;
> }
>
723,726c677,680
< if (!svm_handle_npf(svm_sc->vm, vcpu, info2,
< state->rip, info1, state->cr3,
< &vmexit->u.paging.vie)) {
< /* I/O APIC for MSI/X. */
---
> if(vm_mem_allocated(svm_sc->vm, info2)) {
> VMM_CTR3(svm_sc->vm, vcpu, "SVM:NPF-paging,"
> "RIP:0x%lx INFO1:0x%lx INFO2:0x%lx .\n",
> state->rip, info1, info2);
728d681
< user = 1;
730,734c683,693
< } else {
< /* Local APIC NPF */
< update_rip = 1;
< vmm_stat_incr(svm_sc->vm, vcpu,
< VMEXIT_NPF_LAPIC, 1);
---
> svm_npf_paging(info1, &vmexit->u.paging.fault_type,
> &vmexit->u.paging.protection);
> } else if (svm_npf_emul_fault(info1)) {
> VMM_CTR3(svm_sc->vm, vcpu, "SVM:NPF-inst_emul,"
> "RIP:0x%lx INFO1:0x%lx INFO2:0x%lx .\n",
> state->rip, info1, info2);
> vmexit->exitcode = VM_EXITCODE_INST_EMUL;
> vmexit->u.inst_emul.gpa = info2;
> vmexit->u.inst_emul.gla = VIE_INVALID_GLA;
> vmexit->u.inst_emul.cr3 = state->cr3;
> vmexit->inst_length = VIE_INST_SIZE;
737,741d695
< vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_EPT_FAULT, 1);
< inst_len = vmexit->u.paging.vie.num_processed;
< VMM_CTR3(svm_sc->vm, vcpu, "VMEXIT NPF, GPA:0x%lx "
< "user=%d instr len=%d.\n", info2, user,
< inst_len);
745,747c699,700
< VMM_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT guest shutdown.");
< user = 1;
< vmexit->exitcode = VM_EXITCODE_VMX;
---
> VMM_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT shutdown.");
> loop = false;
752,753c705
< user = 1;
< vmexit->exitcode = VM_EXITCODE_VMX;
---
> loop = false;
758,759c710,711
< user = 1;
< update_rip = 0;
---
> loop = false;
> update_rip = false;
770,774d721
< if (ctrl->v_irq) {
< VMM_CTR2(svm_sc->vm, vcpu, "SVM:SVM intr pending vector:0x%x"
< " priority:0x%x", ctrl->v_intr_vector, ctrl->v_intr_prio);
< }
<
777c724,729
< vmexit->rip += inst_len;
---
> if (ctrl->nrip == 0) {
> VMM_CTR1(svm_sc->vm, vcpu, "SVM_ERR:nRIP is not set "
> "for RIP0x%lx.\n", state->rip);
> vmexit->exitcode = VM_EXITCODE_VMX;
> } else
> vmexit->rip = ctrl->nrip;
780,784c732,734
< /* Return to userland for APs to start. */
< if (vmexit->exitcode == VM_EXITCODE_SPINUP_AP) {
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:Starting APs, RIP0x%lx.\n",
< vmexit->rip);
< user = 1;
---
> /* If vcpu execution is continued, update RIP. */
> if (loop) {
> state->rip = vmexit->rip;
787,789c737,739
< /* XXX: Set next RIP before restarting virtual cpus. */
< if (ctrl->nrip == 0) {
< ctrl->nrip = state->rip;
---
> if (state->rip == 0) {
> VMM_CTR0(svm_sc->vm, vcpu, "SVM_ERR:RIP is NULL\n");
> vmexit->exitcode = VM_EXITCODE_VMX;
792c742
< return (user);
---
> return (loop);
811c761
< if (vmcb_eventinject(ctrl, VM_NMI, IDT_NMI, 0, FALSE)) {
---
> if (vmcb_eventinject(ctrl, VM_NMI, IDT_NMI, 0, false)) {
849c799
< goto inject_failed;
---
> return;
851,857d800
<
< /* Make sure no interrupt is pending.*/
< if (ctrl->v_irq) {
< VMM_CTR0(svm_sc->vm, vcpu,
< "SVM:virtual interrupt is pending.\n");
< goto inject_failed;
< }
865,867d807
< if (vector < 0) {
< return;
< }
868a809,812
> /* No interrupt is pending. */
> if (vector < 0)
> return;
>
870c814,816
< ERR("Invalid vector number:%d\n", vector);
---
> VMM_CTR1(svm_sc->vm, vcpu, "SVM_ERR:Event injection"
> "invalid vector=%d.\n", vector);
> ERR("SVM_ERR:Event injection invalid vector=%d.\n", vector);
876c822
< goto inject_failed;
---
> return;
879,881c825,827
< if(vmcb_eventinject(ctrl, VM_HW_INTR, vector, 0, FALSE)) {
< VMM_CTR2(svm_sc->vm, vcpu, "SVM:Event injection failed to"
< " VCPU%d,vector=%d.\n", vcpu, vector);
---
> if (vmcb_eventinject(ctrl, VM_HW_INTR, vector, 0, false)) {
> VMM_CTR1(svm_sc->vm, vcpu, "SVM:Event injection failed to"
> " vector=%d.\n", vector);
888,890d833
<
< inject_failed:
< return;
910a854,881
> static void
> svm_handle_exitintinfo(struct svm_softc *svm_sc, int vcpu)
> {
> struct vmcb_ctrl *ctrl;
> uint64_t intinfo;
>
> ctrl = svm_get_vmcb_ctrl(svm_sc, vcpu);
>
> /*
> * VMEXIT while delivering an exception or interrupt.
> * Inject it as virtual interrupt.
> * Section 15.7.2 Intercepts during IDT interrupt delivery.
> */
> intinfo = ctrl->exitintinfo;
>
> if (intinfo & VMCB_EXITINTINFO_VALID) {
> vmm_stat_incr(svm_sc->vm, vcpu, VCPU_EXITINTINFO, 1);
> VMM_CTR1(svm_sc->vm, vcpu, "SVM:EXITINTINFO:0x%lx is valid\n",
> intinfo);
> if (vmcb_eventinject(ctrl, VMCB_EXITINTINFO_TYPE(intinfo),
> VMCB_EXITINTINFO_VECTOR(intinfo),
> VMCB_EXITINTINFO_EC(intinfo),
> VMCB_EXITINTINFO_EC_VALID & intinfo)) {
> VMM_CTR1(svm_sc->vm, vcpu, "SVM:couldn't inject pending"
> " interrupt, exitintinfo:0x%lx\n", intinfo);
> }
> }
> }
915c886
< svm_vmrun(void *arg, int vcpu, register_t rip)
---
> svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap)
923d893
< int user;
925a896
> bool loop; /* Continue vcpu execution loop. */
927c898
< user = 0;
---
> loop = true;
930,931d900
< KASSERT(vcpu < svm_sc->vcpu_cnt, ("Guest doesn't have VCPU%d", vcpu));
<
933,939c902,904
< state = svm_get_vmcb_state(svm_sc, vcpu);
< ctrl = svm_get_vmcb_ctrl(svm_sc, vcpu);
< vmexit = vm_exitinfo(svm_sc->vm , vcpu);
< if (vmexit->exitcode == VM_EXITCODE_VMX) {
< ERR("vcpu%d shouldn't run again.\n", vcpu);
< return(EIO);
< }
---
> state = svm_get_vmcb_state(svm_sc, vcpu);
> ctrl = svm_get_vmcb_ctrl(svm_sc, vcpu);
> vmexit = vm_exitinfo(svm_sc->vm, vcpu);
977d941
<
981c945,947
<
---
> VMM_CTR3(svm_sc->vm, vcpu, "SVM:Enter vmrun old RIP:0x%lx"
> " new RIP:0x%lx inst len=%d\n",
> state->rip, rip, vmexit->inst_length);
985,986d950
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:entered with RIP:0x%lx\n",
< state->rip);
987a952
> vmexit->inst_length = 0;
991d955
< vmexit->inst_length = 0;
993,994c957,959
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:gave up cpu, RIP:0x%lx\n",
< state->rip);
---
> VMM_CTR1(svm_sc->vm, vcpu,
> "SVM: gave up CPU, RIP:0x%lx\n", state->rip);
> vmexit->rip = state->rip;
1001a967,968
> svm_handle_exitintinfo(svm_sc, vcpu);
>
1016c983,984
<
---
>
>
1019c987
<
---
>
1048c1016
< user = svm_vmexit(svm_sc, vcpu, vmexit);
---
> loop = svm_vmexit(svm_sc, vcpu, vmexit);
1052,1058c1020
< /* Update RIP since we are continuing vcpu execution.*/
< state->rip = vmexit->rip;
<
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:loop RIP:0x%lx\n", state->rip);
< } while (!user);
< VMM_CTR1(svm_sc->vm, vcpu, "SVM:exited with RIP:0x%lx\n",
< state->rip);
---
> } while (loop);
1075d1036
< svm_npt_cleanup(svm_sc);
1116c1077
< ERR("Unknown register requested.\n");
---
> ERR("Unknown register requested, reg=%d.\n", reg);
1143a1105
>
1149c1111
< ERR("reg type %x is not saved n VMCB\n", ident);
---
> ERR("SVM_ERR:reg type %x is not saved in VMCB.\n", ident);
1179c1141
< ERR("reg type %x is not saved n VMCB\n", ident);
---
> ERR("SVM_ERR:reg type %x is not saved in VMCB.\n", ident);
1204c1166
< ERR("Unsupported seg type %d\n", type);
---
> ERR("SVM_ERR:Unsupported segment type%d\n", type);
1235c1197
< ERR("Unsupported seg type %d\n", type);
---
> ERR("SVM_ERR:Unsupported segment type%d\n", type);
1369,1370d1330
< svm_npt_vmmap_set,
< svm_npt_vmmap_get,
1377c1337,1339
< svm_setcap
---
> svm_setcap,
> svm_npt_alloc,
> svm_npt_free