svn commit: r260383 - in head/sys/amd64/vmm: . intel io
Neel Natu
neel at FreeBSD.org
Tue Jan 7 00:38:24 UTC 2014
Author: neel
Date: Tue Jan 7 00:38:22 2014
New Revision: 260383
URL: http://svnweb.freebsd.org/changeset/base/260383
Log:
Allow vlapic_set_intr_ready() to return a value that indicates whether or not
the vcpu should be kicked to process a pending interrupt. This will be useful
in the implementation of the Posted Interrupt APICv feature.
Change the return value of 'vlapic_pending_intr()' to indicate whether or not
an interrupt is available to be delivered to the vcpu depending on the value
of the PPR.
Add KTR tracepoints to debug guest IPI delivery.
Modified:
head/sys/amd64/vmm/intel/vmx.c
head/sys/amd64/vmm/io/vlapic.c
head/sys/amd64/vmm/io/vlapic.h
head/sys/amd64/vmm/vmm.c
head/sys/amd64/vmm/vmm_lapic.c
Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c Mon Jan 6 23:51:26 2014 (r260382)
+++ head/sys/amd64/vmm/intel/vmx.c Tue Jan 7 00:38:22 2014 (r260383)
@@ -989,8 +989,7 @@ vmx_inject_interrupts(struct vmx *vmx, i
return;
/* Ask the local apic for a vector to inject */
- vector = vlapic_pending_intr(vlapic);
- if (vector < 0)
+ if (!vlapic_pending_intr(vlapic, &vector))
return;
if (vector < 32 || vector > 255)
Modified: head/sys/amd64/vmm/io/vlapic.c
==============================================================================
--- head/sys/amd64/vmm/io/vlapic.c Mon Jan 6 23:51:26 2014 (r260382)
+++ head/sys/amd64/vmm/io/vlapic.c Tue Jan 7 00:38:22 2014 (r260383)
@@ -289,27 +289,29 @@ vlapic_esr_write_handler(struct vlapic *
vlapic->esr_pending = 0;
}
-void
+int
vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
{
- struct LAPIC *lapic = vlapic->apic_page;
- uint32_t *irrptr, *tmrptr, mask;
- int idx;
+ struct LAPIC *lapic;
+ uint32_t *irrptr, *tmrptr, mask;
+ int idx;
- if (vector < 0 || vector >= 256)
- panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
+ KASSERT(vector >= 0 && vector < 256, ("invalid vector %d", vector));
+ lapic = vlapic->apic_page;
if (!(lapic->svr & APIC_SVR_ENABLE)) {
VLAPIC_CTR1(vlapic, "vlapic is software disabled, ignoring "
"interrupt %d", vector);
- return;
+ return (0);
}
if (vector < 16) {
vlapic_set_error(vlapic, APIC_ESR_RECEIVE_ILLEGAL_VECTOR);
- return;
+ VLAPIC_CTR1(vlapic, "vlapic ignoring interrupt to vector %d",
+ vector);
+ return (1);
}
-
+
idx = (vector / 32) * 4;
mask = 1 << (vector % 32);
@@ -328,6 +330,7 @@ vlapic_set_intr_ready(struct vlapic *vla
atomic_clear_int(&tmrptr[idx], mask);
VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
+ return (1);
}
static __inline uint32_t *
@@ -473,8 +476,8 @@ vlapic_fire_lvt(struct vlapic *vlapic, u
vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR);
return (0);
}
- vlapic_set_intr_ready(vlapic, vec, false);
- vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true);
+ if (vlapic_set_intr_ready(vlapic, vec, false))
+ vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true);
break;
case APIC_LVT_DM_NMI:
vm_inject_nmi(vlapic->vm, vlapic->vcpuid);
@@ -935,9 +938,12 @@ vlapic_icrlo_write_handler(struct vlapic
if (mode == APIC_DELMODE_FIXED && vec < 16) {
vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR);
+ VLAPIC_CTR1(vlapic, "Ignoring invalid IPI %d", vec);
return (0);
}
-
+
+ VLAPIC_CTR2(vlapic, "icrlo 0x%016lx triggered ipi %d", icrval, vec);
+
if (mode == APIC_DELMODE_FIXED || mode == APIC_DELMODE_NMI) {
switch (icrval & APIC_DEST_MASK) {
case APIC_DEST_DESTFLD:
@@ -967,8 +973,13 @@ vlapic_icrlo_write_handler(struct vlapic
lapic_intr_edge(vlapic->vm, i, vec);
vmm_stat_array_incr(vlapic->vm, vlapic->vcpuid,
IPIS_SENT, i, 1);
- } else
+ VLAPIC_CTR2(vlapic, "vlapic sending ipi %d "
+ "to vcpuid %d", vec, i);
+ } else {
vm_inject_nmi(vlapic->vm, i);
+ VLAPIC_CTR1(vlapic, "vlapic sending ipi nmi "
+ "to vcpuid %d", i);
+ }
}
return (0); /* handled completely in the kernel */
@@ -1023,7 +1034,7 @@ vlapic_icrlo_write_handler(struct vlapic
}
int
-vlapic_pending_intr(struct vlapic *vlapic)
+vlapic_pending_intr(struct vlapic *vlapic, int *vecptr)
{
struct LAPIC *lapic = vlapic->apic_page;
int idx, i, bitpos, vector;
@@ -1043,12 +1054,14 @@ vlapic_pending_intr(struct vlapic *vlapi
vector = i * 32 + (bitpos - 1);
if (PRIO(vector) > PRIO(lapic->ppr)) {
VLAPIC_CTR1(vlapic, "pending intr %d", vector);
- return (vector);
+ if (vecptr != NULL)
+ *vecptr = vector;
+ return (1);
} else
break;
}
}
- return (-1);
+ return (0);
}
void
Modified: head/sys/amd64/vmm/io/vlapic.h
==============================================================================
--- head/sys/amd64/vmm/io/vlapic.h Mon Jan 6 23:51:26 2014 (r260382)
+++ head/sys/amd64/vmm/io/vlapic.h Tue Jan 7 00:38:22 2014 (r260383)
@@ -38,16 +38,16 @@ int vlapic_read(struct vlapic *vlapic, u
bool *retu);
/*
- * Returns a vector between 32 and 255 if an interrupt is pending in the
- * IRR that can be delivered based on the current state of ISR and TPR.
+ * Returns 0 if there is no eligible vector that can be delivered to the
+ * guest at this time and non-zero otherwise.
+ *
+ * If an eligible vector number is found and 'vecptr' is not NULL then it will
+ * be stored in the location pointed to by 'vecptr'.
*
* Note that the vector does not automatically transition to the ISR as a
* result of calling this function.
- *
- * Returns -1 if there is no eligible vector that can be delivered to the
- * guest at this time.
*/
-int vlapic_pending_intr(struct vlapic *vlapic);
+int vlapic_pending_intr(struct vlapic *vlapic, int *vecptr);
/*
* Transition 'vector' from IRR to ISR. This function is called with the
@@ -57,7 +57,18 @@ int vlapic_pending_intr(struct vlapic *v
*/
void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
-void vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level);
+/*
+ * Returns 1 if the vcpu needs to be notified of the interrupt and 0 otherwise.
+ */
+int vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level);
+
+/*
+ * Post an interrupt to the vcpu running on 'hostcpu'. This will use a
+ * hardware assist if available (e.g. Posted Interrupt) or fall back to
+ * sending an IPI to interrupt the 'hostcpu'.
+ */
+void vlapic_post_intr(struct vlapic *vlapic, int hostcpu);
+
void vlapic_set_error(struct vlapic *vlapic, uint32_t mask);
void vlapic_fire_cmci(struct vlapic *vlapic);
int vlapic_trigger_lvt(struct vlapic *vlapic, int vector);
@@ -69,7 +80,6 @@ bool vlapic_enabled(struct vlapic *vlapi
void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys,
int delmode, int vec);
-void vlapic_post_intr(struct vlapic *vlapic, int hostcpu);
/* APIC write handlers */
void vlapic_id_write_handler(struct vlapic *vlapic);
Modified: head/sys/amd64/vmm/vmm.c
==============================================================================
--- head/sys/amd64/vmm/vmm.c Mon Jan 6 23:51:26 2014 (r260382)
+++ head/sys/amd64/vmm/vmm.c Tue Jan 7 00:38:22 2014 (r260383)
@@ -910,7 +910,7 @@ vm_handle_hlt(struct vm *vm, int vcpuid,
* returned from VMRUN() and before we grabbed the vcpu lock.
*/
if (!vm_nmi_pending(vm, vcpuid) &&
- (intr_disabled || vlapic_pending_intr(vcpu->vlapic) < 0)) {
+ (intr_disabled || !vlapic_pending_intr(vcpu->vlapic, NULL))) {
t = ticks;
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
if (vlapic_enabled(vcpu->vlapic)) {
Modified: head/sys/amd64/vmm/vmm_lapic.c
==============================================================================
--- head/sys/amd64/vmm/vmm_lapic.c Mon Jan 6 23:51:26 2014 (r260382)
+++ head/sys/amd64/vmm/vmm_lapic.c Tue Jan 7 00:38:22 2014 (r260383)
@@ -62,8 +62,8 @@ lapic_set_intr(struct vm *vm, int cpu, i
return (EINVAL);
vlapic = vm_lapic(vm, cpu);
- vlapic_set_intr_ready(vlapic, vector, level);
- vcpu_notify_event(vm, cpu, true);
+ if (vlapic_set_intr_ready(vlapic, vector, level))
+ vcpu_notify_event(vm, cpu, true);
return (0);
}
More information about the svn-src-all
mailing list