KVM: Remove irq_pending bitmap
Only one interrupt vector can be injected from userspace irqchip at any given time so no need to store it in a bitmap. Put it into interrupt queue directly. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
@@ -266,8 +266,6 @@ struct kvm_mmu {
|
|||||||
|
|
||||||
struct kvm_vcpu_arch {
|
struct kvm_vcpu_arch {
|
||||||
u64 host_tsc;
|
u64 host_tsc;
|
||||||
unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
|
|
||||||
DECLARE_BITMAP(irq_pending, KVM_NR_INTERRUPTS);
|
|
||||||
/*
|
/*
|
||||||
* rip and regs accesses must go through
|
* rip and regs accesses must go through
|
||||||
* kvm_{register,rip}_{read,write} functions.
|
* kvm_{register,rip}_{read,write} functions.
|
||||||
|
@@ -50,7 +50,7 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
|
|||||||
struct kvm_pic *s;
|
struct kvm_pic *s;
|
||||||
|
|
||||||
if (!irqchip_in_kernel(v->kvm))
|
if (!irqchip_in_kernel(v->kvm))
|
||||||
return v->arch.irq_summary;
|
return v->arch.interrupt.pending;
|
||||||
|
|
||||||
if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
|
if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
|
||||||
if (kvm_apic_accept_pic_intr(v)) {
|
if (kvm_apic_accept_pic_intr(v)) {
|
||||||
@@ -72,7 +72,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
|
|||||||
int vector;
|
int vector;
|
||||||
|
|
||||||
if (!irqchip_in_kernel(v->kvm))
|
if (!irqchip_in_kernel(v->kvm))
|
||||||
return kvm_pop_irq(v);
|
return v->arch.interrupt.nr;
|
||||||
|
|
||||||
vector = kvm_get_apic_interrupt(v); /* APIC */
|
vector = kvm_get_apic_interrupt(v); /* APIC */
|
||||||
if (vector == -1) {
|
if (vector == -1) {
|
||||||
|
@@ -1441,8 +1441,7 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
|
|||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
vcpu_load(vcpu);
|
vcpu_load(vcpu);
|
||||||
|
|
||||||
set_bit(irq->irq, vcpu->arch.irq_pending);
|
kvm_queue_interrupt(vcpu, irq->irq);
|
||||||
set_bit(irq->irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
|
|
||||||
|
|
||||||
vcpu_put(vcpu);
|
vcpu_put(vcpu);
|
||||||
|
|
||||||
@@ -3583,12 +3582,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
|
|||||||
sregs->efer = vcpu->arch.shadow_efer;
|
sregs->efer = vcpu->arch.shadow_efer;
|
||||||
sregs->apic_base = kvm_get_apic_base(vcpu);
|
sregs->apic_base = kvm_get_apic_base(vcpu);
|
||||||
|
|
||||||
if (irqchip_in_kernel(vcpu->kvm))
|
memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap);
|
||||||
memset(sregs->interrupt_bitmap, 0,
|
|
||||||
sizeof sregs->interrupt_bitmap);
|
|
||||||
else
|
|
||||||
memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
|
|
||||||
sizeof sregs->interrupt_bitmap);
|
|
||||||
|
|
||||||
if (vcpu->arch.interrupt.pending)
|
if (vcpu->arch.interrupt.pending)
|
||||||
set_bit(vcpu->arch.interrupt.nr,
|
set_bit(vcpu->arch.interrupt.nr,
|
||||||
@@ -4058,7 +4052,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|||||||
struct kvm_sregs *sregs)
|
struct kvm_sregs *sregs)
|
||||||
{
|
{
|
||||||
int mmu_reset_needed = 0;
|
int mmu_reset_needed = 0;
|
||||||
int i, pending_vec, max_bits;
|
int pending_vec, max_bits;
|
||||||
struct descriptor_table dt;
|
struct descriptor_table dt;
|
||||||
|
|
||||||
vcpu_load(vcpu);
|
vcpu_load(vcpu);
|
||||||
@@ -4100,24 +4094,14 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|||||||
if (mmu_reset_needed)
|
if (mmu_reset_needed)
|
||||||
kvm_mmu_reset_context(vcpu);
|
kvm_mmu_reset_context(vcpu);
|
||||||
|
|
||||||
if (!irqchip_in_kernel(vcpu->kvm)) {
|
max_bits = (sizeof sregs->interrupt_bitmap) << 3;
|
||||||
memcpy(vcpu->arch.irq_pending, sregs->interrupt_bitmap,
|
pending_vec = find_first_bit(
|
||||||
sizeof vcpu->arch.irq_pending);
|
(const unsigned long *)sregs->interrupt_bitmap, max_bits);
|
||||||
vcpu->arch.irq_summary = 0;
|
if (pending_vec < max_bits) {
|
||||||
for (i = 0; i < ARRAY_SIZE(vcpu->arch.irq_pending); ++i)
|
kvm_queue_interrupt(vcpu, pending_vec);
|
||||||
if (vcpu->arch.irq_pending[i])
|
pr_debug("Set back pending irq %d\n", pending_vec);
|
||||||
__set_bit(i, &vcpu->arch.irq_summary);
|
if (irqchip_in_kernel(vcpu->kvm))
|
||||||
} else {
|
kvm_pic_clear_isr_ack(vcpu->kvm);
|
||||||
max_bits = (sizeof sregs->interrupt_bitmap) << 3;
|
|
||||||
pending_vec = find_first_bit(
|
|
||||||
(const unsigned long *)sregs->interrupt_bitmap,
|
|
||||||
max_bits);
|
|
||||||
/* Only pending external irq is handled here */
|
|
||||||
if (pending_vec < max_bits) {
|
|
||||||
kvm_queue_interrupt(vcpu, pending_vec);
|
|
||||||
pr_debug("Set back pending irq %d\n", pending_vec);
|
|
||||||
}
|
|
||||||
kvm_pic_clear_isr_ack(vcpu->kvm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
|
kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
|
||||||
|
@@ -19,18 +19,6 @@ static inline void kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
|
|||||||
vcpu->arch.interrupt.pending = false;
|
vcpu->arch.interrupt.pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 kvm_pop_irq(struct kvm_vcpu *vcpu)
|
|
||||||
{
|
|
||||||
int word_index = __ffs(vcpu->arch.irq_summary);
|
|
||||||
int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
|
|
||||||
int irq = word_index * BITS_PER_LONG + bit_index;
|
|
||||||
|
|
||||||
clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
|
|
||||||
if (!vcpu->arch.irq_pending[word_index])
|
|
||||||
clear_bit(word_index, &vcpu->arch.irq_summary);
|
|
||||||
return irq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
|
static inline bool kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
return vcpu->arch.exception.pending || vcpu->arch.interrupt.pending ||
|
return vcpu->arch.exception.pending || vcpu->arch.interrupt.pending ||
|
||||||
|
Reference in New Issue
Block a user