Changeset View
Standalone View
sys/amd64/vmm/intel/vmx.c
Context not available. | |||||
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1); | vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1); | ||||
vmexit->exitcode = VM_EXITCODE_HLT; | vmexit->exitcode = VM_EXITCODE_HLT; | ||||
vmexit->u.hlt.rflags = vmcs_read(VMCS_GUEST_RFLAGS); | vmexit->u.hlt.rflags = vmcs_read(VMCS_GUEST_RFLAGS); | ||||
vmexit->u.hlt.intr_status = vmcs_read(VMCS_GUEST_INTR_STATUS); | |||||
jhb: I had one more question about this that I thought of after my first comment. Is there any… | |||||
Not Done Inline ActionsI've just tested this on system with hw.vmm.vmx.cap.virtual_interrupt_delivery = 0 and in this case vmcs_read(VMCS_GUEST_INTR_STATUS) simply returns zero. I'm going to extrapolate that this is behavior on all generations of CPUs which don't support the 1-setting of the “virtual-interrupt delivery” VM-execution control :-) tychon: I've just tested this on system with hw.vmm.vmx.cap.virtual_interrupt_delivery = 0 and in this… | |||||
break; | break; | ||||
case EXIT_REASON_MTF: | case EXIT_REASON_MTF: | ||||
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1); | vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1); | ||||
Context not available. | |||||
* interrupt by reevaluating virtual interrupts | * interrupt by reevaluating virtual interrupts | ||||
* following Section 29.2.1 in the Intel SDM Volume 3. | * following Section 29.2.1 in the Intel SDM Volume 3. | ||||
*/ | */ | ||||
uint64_t val; | struct vm_exit *vmexit; | ||||
uint8_t rvi, ppr; | uint8_t rvi, ppr; | ||||
vmx_getreg(vlapic_vtx->vmx, vlapic->vcpuid, | vmexit = vm_exitinfo(vlapic->vm, vlapic->vcpuid); | ||||
VMCS_IDENT(VMCS_GUEST_INTR_STATUS), &val); | rvi = vmexit->u.hlt.intr_status & APIC_TPR_INT; | ||||
jhbUnsubmitted Not Done Inline ActionsDo you want a KASSERT(vmexit->exitcode == VM_EXITCODE_HLT) here or is that too silly? It seem from my reading that this is in fact true (and there's a comment at the start of this function saying it is true), but it is not trivially obvious from the code (e.g. the vlapic_pending_intr() in vmx_inject_interrupts() is called from a non-HLT exit, but only in the !virtual_interrupt_delivery case and this function is only used to implement vlapic_pending_intr() in the virtual_interrupt_delivery case). I do think the idea is sound and prefer it to D14382. jhb: Do you want a KASSERT(vmexit->exitcode == VM_EXITCODE_HLT) here or is that too silly? It seem… | |||||
rvi = val & APIC_TPR_INT; | |||||
lapic = vlapic->apic_page; | lapic = vlapic->apic_page; | ||||
ppr = lapic->ppr & APIC_TPR_INT; | ppr = lapic->ppr & APIC_TPR_INT; | ||||
if (rvi > ppr) { | if (rvi > ppr) { | ||||
Context not available. |
I had one more question about this that I thought of after my first comment. Is there any chance that this VMCS field isn't valid to read such that vmcs_read() could fault in the !virtual_interrupt_delivery case? If the vmcs_read() will always succeed and just return zero in that case then this is fine. If it would fault on an old CPU that doesn't support virtual interrupts then it should be conditional. (I just can't recall if VMCS fields are always readable vs if some of them might fault if you try to read them for an unsupported feature.)