diff options
Diffstat (limited to 'arch/x86/kvm/ioapic.c')
| -rw-r--r-- | arch/x86/kvm/ioapic.c | 26 | 
1 files changed, 13 insertions, 13 deletions
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index b1947e0f3e10..28146f03c514 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -206,6 +206,8 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,  	old_irr = ioapic->irr;  	ioapic->irr |= mask; +	if (edge) +		ioapic->irr_delivered &= ~mask;  	if ((edge && old_irr == ioapic->irr) ||  	    (!edge && entry.fields.remote_irr)) {  		ret = 0; @@ -349,7 +351,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)  	irqe.shorthand = 0;  	if (irqe.trig_mode == IOAPIC_EDGE_TRIG) -		ioapic->irr &= ~(1 << irq); +		ioapic->irr_delivered |= 1 << irq;  	if (irq == RTC_GSI && line_status) {  		/* @@ -422,6 +424,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,  			struct kvm_ioapic *ioapic, int vector, int trigger_mode)  {  	int i; +	struct kvm_lapic *apic = vcpu->arch.apic;  	for (i = 0; i < IOAPIC_NUM_PINS; i++) {  		union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i]; @@ -443,7 +446,8 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,  		kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);  		spin_lock(&ioapic->lock); -		if (trigger_mode != IOAPIC_LEVEL_TRIG) +		if (trigger_mode != IOAPIC_LEVEL_TRIG || +		    kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)  			continue;  		ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); @@ -471,13 +475,6 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,  	}  } -bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector) -{ -	struct kvm_ioapic *ioapic = kvm->arch.vioapic; -	smp_rmb(); -	return test_bit(vector, ioapic->handled_vectors); -} -  void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_mode)  {  	struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; @@ -498,8 +495,8 @@ static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr)  		 (addr < ioapic->base_address + IOAPIC_MEM_LENGTH)));  } -static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, -			    void *val) +static int ioapic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this, +				gpa_t addr, int len, void *val)  {  	struct kvm_ioapic *ioapic = to_ioapic(this);  	u32 result; @@ -541,8 +538,8 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,  	return 0;  } -static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, -			     const void *val) +static int ioapic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, +				 gpa_t addr, int len, const void *val)  {  	struct kvm_ioapic *ioapic = to_ioapic(this);  	u32 data; @@ -597,6 +594,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic)  	ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;  	ioapic->ioregsel = 0;  	ioapic->irr = 0; +	ioapic->irr_delivered = 0;  	ioapic->id = 0;  	memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);  	rtc_irq_eoi_tracking_reset(ioapic); @@ -654,6 +652,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)  	spin_lock(&ioapic->lock);  	memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); +	state->irr &= ~ioapic->irr_delivered;  	spin_unlock(&ioapic->lock);  	return 0;  } @@ -667,6 +666,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)  	spin_lock(&ioapic->lock);  	memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));  	ioapic->irr = 0; +	ioapic->irr_delivered = 0;  	update_handled_vectors(ioapic);  	kvm_vcpu_request_scan_ioapic(kvm);  	kvm_ioapic_inject_all(ioapic, state->irr);  |