From owner-svn-src-head@FreeBSD.ORG Sat Jan 25 20:58:07 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2953180E; Sat, 25 Jan 2014 20:58:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 0ADC11601; Sat, 25 Jan 2014 20:58:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s0PKw6HC019026; Sat, 25 Jan 2014 20:58:06 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s0PKw5ZN019015; Sat, 25 Jan 2014 20:58:05 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201401252058.s0PKw5ZN019015@svn.freebsd.org> From: Neel Natu Date: Sat, 25 Jan 2014 20:58:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261170 - in head/sys/amd64: include vmm vmm/intel vmm/io X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Jan 2014 20:58:07 -0000 Author: neel Date: Sat Jan 25 20:58:05 2014 New Revision: 261170 URL: http://svnweb.freebsd.org/changeset/base/261170 Log: Support level triggered interrupts with VT-x virtual interrupt delivery. The VMCS field EOI_bitmap[] is an array of 256 bits - one for each vector. If a bit is set to '1' in the EOI_bitmap[] then the processor will trigger an EOI-induced VM-exit when it is doing EOI virtualization. The EOI-induced VM-exit results in the EOI being forwarded to the vioapic so that level triggered interrupts can be properly handled. Tested by: Anish Gupta (akgupt3@gmail.com) Modified: head/sys/amd64/include/vmm.h head/sys/amd64/vmm/intel/vmcs.h head/sys/amd64/vmm/intel/vmx.c head/sys/amd64/vmm/io/vlapic.c head/sys/amd64/vmm/io/vlapic_priv.h head/sys/amd64/vmm/vmm.c Modified: head/sys/amd64/include/vmm.h ============================================================================== --- head/sys/amd64/include/vmm.h Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/include/vmm.h Sat Jan 25 20:58:05 2014 (r261170) @@ -298,6 +298,7 @@ enum vm_exitcode { VM_EXITCODE_SPINUP_AP, VM_EXITCODE_SPINDOWN_CPU, VM_EXITCODE_RENDEZVOUS, + VM_EXITCODE_IOAPIC_EOI, VM_EXITCODE_MAX }; @@ -354,6 +355,9 @@ struct vm_exit { struct { uint64_t rflags; } hlt; + struct { + int vector; + } ioapic_eoi; } u; }; Modified: head/sys/amd64/vmm/intel/vmcs.h ============================================================================== --- head/sys/amd64/vmm/intel/vmcs.h Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/vmm/intel/vmcs.h Sat Jan 25 20:58:05 2014 (r261170) @@ -136,6 +136,7 @@ vmcs_write(uint32_t encoding, uint64_t v #define VMCS_EOI_EXIT1 0x0000201E #define VMCS_EOI_EXIT2 0x00002020 #define VMCS_EOI_EXIT3 0x00002022 +#define VMCS_EOI_EXIT(vector) (VMCS_EOI_EXIT0 + ((vector) / 64) * 2) /* 64-bit read-only fields */ #define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 @@ -318,6 +319,7 @@ vmcs_write(uint32_t encoding, uint64_t v #define EXIT_REASON_MCE 41 #define EXIT_REASON_TPR 43 #define EXIT_REASON_APIC_ACCESS 44 +#define EXIT_REASON_VIRTUALIZED_EOI 45 #define EXIT_REASON_GDTR_IDTR 46 #define EXIT_REASON_LDTR_TR 47 #define EXIT_REASON_EPT_FAULT 48 Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/vmm/intel/vmx.c Sat Jan 25 20:58:05 2014 (r261170) @@ -1726,6 +1726,11 @@ vmx_exit_process(struct vmx *vmx, int vc (qual & EXIT_QUAL_NMIUDTI) != 0) vmx_restore_nmi_blocking(vmx, vcpu); break; + case EXIT_REASON_VIRTUALIZED_EOI: + vmexit->exitcode = VM_EXITCODE_IOAPIC_EOI; + vmexit->u.ioapic_eoi.vector = qual & 0xFF; + vmexit->inst_length = 0; /* trap-like */ + break; case EXIT_REASON_APIC_ACCESS: handled = vmx_handle_apic_access(vmx, vcpu, vmexit); break; @@ -2320,6 +2325,7 @@ vmx_setcap(void *arg, int vcpu, int type struct vlapic_vtx { struct vlapic vlapic; struct pir_desc *pir_desc; + struct vmx *vmx; }; #define VMX_CTR_PIR(vm, vcpuid, pir_desc, notify, vector, level, msg) \ @@ -2345,9 +2351,6 @@ vmx_set_intr_ready(struct vlapic *vlapic uint64_t mask; int idx, notify; - /* - * XXX need to deal with level triggered interrupts - */ vlapic_vtx = (struct vlapic_vtx *)vlapic; pir_desc = vlapic_vtx->pir_desc; @@ -2422,6 +2425,33 @@ vmx_intr_accepted(struct vlapic *vlapic, } static void +vmx_set_tmr(struct vlapic *vlapic, int vector, bool level) +{ + struct vlapic_vtx *vlapic_vtx; + struct vmx *vmx; + struct vmcs *vmcs; + uint64_t mask, val; + + KASSERT(vector >= 0 && vector <= 255, ("invalid vector %d", vector)); + KASSERT(!vcpu_is_running(vlapic->vm, vlapic->vcpuid, NULL), + ("vmx_set_tmr: vcpu cannot be running")); + + vlapic_vtx = (struct vlapic_vtx *)vlapic; + vmx = vlapic_vtx->vmx; + vmcs = &vmx->vmcs[vlapic->vcpuid]; + mask = 1UL << (vector % 64); + + VMPTRLD(vmcs); + val = vmcs_read(VMCS_EOI_EXIT(vector)); + if (level) + val |= mask; + else + val &= ~mask; + vmcs_write(VMCS_EOI_EXIT(vector), val); + VMCLEAR(vmcs); +} + +static void vmx_post_intr(struct vlapic *vlapic, int hostcpu) { @@ -2519,11 +2549,13 @@ vmx_vlapic_init(void *arg, int vcpuid) vlapic_vtx = (struct vlapic_vtx *)vlapic; vlapic_vtx->pir_desc = &vmx->pir_desc[vcpuid]; + vlapic_vtx->vmx = vmx; if (virtual_interrupt_delivery) { vlapic->ops.set_intr_ready = vmx_set_intr_ready; vlapic->ops.pending_intr = vmx_pending_intr; vlapic->ops.intr_accepted = vmx_intr_accepted; + vlapic->ops.set_tmr = vmx_set_tmr; } if (posted_interrupts) Modified: head/sys/amd64/vmm/io/vlapic.c ============================================================================== --- head/sys/amd64/vmm/io/vlapic.c Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/vmm/io/vlapic.c Sat Jan 25 20:58:05 2014 (r261170) @@ -1300,6 +1300,7 @@ vlapic_reset(struct vlapic *vlapic) lapic->dfr = 0xffffffff; lapic->svr = APIC_SVR_VECTOR; vlapic_mask_lvts(vlapic); + vlapic_reset_tmr(vlapic); lapic->dcr_timer = 0; vlapic_dcr_write_handler(vlapic); @@ -1457,32 +1458,42 @@ vlapic_enabled(struct vlapic *vlapic) return (false); } +static void +vlapic_set_tmr(struct vlapic *vlapic, int vector, bool level) +{ + struct LAPIC *lapic; + uint32_t *tmrptr, mask; + int idx; + + lapic = vlapic->apic_page; + tmrptr = &lapic->tmr0; + idx = (vector / 32) * 4; + mask = 1 << (vector % 32); + if (level) + tmrptr[idx] |= mask; + else + tmrptr[idx] &= ~mask; + + if (vlapic->ops.set_tmr != NULL) + (*vlapic->ops.set_tmr)(vlapic, vector, level); +} + void vlapic_reset_tmr(struct vlapic *vlapic) { - struct LAPIC *lapic; + int vector; VLAPIC_CTR0(vlapic, "vlapic resetting all vectors to edge-triggered"); - lapic = vlapic->apic_page; - lapic->tmr0 = 0; - lapic->tmr1 = 0; - lapic->tmr2 = 0; - lapic->tmr3 = 0; - lapic->tmr4 = 0; - lapic->tmr5 = 0; - lapic->tmr6 = 0; - lapic->tmr7 = 0; + for (vector = 0; vector <= 255; vector++) + vlapic_set_tmr(vlapic, vector, false); } void vlapic_set_tmr_level(struct vlapic *vlapic, uint32_t dest, bool phys, int delmode, int vector) { - struct LAPIC *lapic; - uint32_t *tmrptr, mask; cpuset_t dmask; - int idx; bool lowprio; KASSERT(vector >= 0 && vector <= 255, ("invalid vector %d", vector)); @@ -1502,11 +1513,6 @@ vlapic_set_tmr_level(struct vlapic *vlap if (!CPU_ISSET(vlapic->vcpuid, &dmask)) return; - lapic = vlapic->apic_page; - tmrptr = &lapic->tmr0; - idx = (vector / 32) * 4; - mask = 1 << (vector % 32); - tmrptr[idx] |= mask; - VLAPIC_CTR1(vlapic, "vector %d set to level-triggered", vector); + vlapic_set_tmr(vlapic, vector, true); } Modified: head/sys/amd64/vmm/io/vlapic_priv.h ============================================================================== --- head/sys/amd64/vmm/io/vlapic_priv.h Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/vmm/io/vlapic_priv.h Sat Jan 25 20:58:05 2014 (r261170) @@ -139,6 +139,7 @@ struct vlapic_ops { int (*pending_intr)(struct vlapic *vlapic, int *vecptr); void (*intr_accepted)(struct vlapic *vlapic, int vector); void (*post_intr)(struct vlapic *vlapic, int hostcpu); + void (*set_tmr)(struct vlapic *vlapic, int vector, bool level); }; struct vlapic { Modified: head/sys/amd64/vmm/vmm.c ============================================================================== --- head/sys/amd64/vmm/vmm.c Sat Jan 25 20:39:23 2014 (r261169) +++ head/sys/amd64/vmm/vmm.c Sat Jan 25 20:58:05 2014 (r261170) @@ -1150,6 +1150,10 @@ restart: if (error == 0) { retu = false; switch (vme->exitcode) { + case VM_EXITCODE_IOAPIC_EOI: + vioapic_process_eoi(vm, vcpuid, + vme->u.ioapic_eoi.vector); + break; case VM_EXITCODE_RENDEZVOUS: vm_handle_rendezvous(vm, vcpuid); error = 0;