KVM: x86: detect LVTT changes under APICv
APIC-write VM exits are "trap-like": they save CS:RIP values for the instruction after the write, and more importantly, the handler will already see the new value in the virtual-APIC page. This means that apic_reg_write cannot use kvm_apic_get_reg to omit timer cancelation when mode changes. timer_mode_mask shouldn't be changing as it depends on cpuid. Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									e462755cae
								
							
						
					
					
						commit
						a323b40982
					
				| @ -1242,17 +1242,20 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | ||||
| 
 | ||||
| 		break; | ||||
| 
 | ||||
| 	case APIC_LVTT: | ||||
| 		if ((kvm_apic_get_reg(apic, APIC_LVTT) & | ||||
| 		    apic->lapic_timer.timer_mode_mask) != | ||||
| 		   (val & apic->lapic_timer.timer_mode_mask)) | ||||
| 	case APIC_LVTT: { | ||||
| 		u32 timer_mode = val & apic->lapic_timer.timer_mode_mask; | ||||
| 
 | ||||
| 		if (apic->lapic_timer.timer_mode != timer_mode) { | ||||
| 			apic->lapic_timer.timer_mode = timer_mode; | ||||
| 			hrtimer_cancel(&apic->lapic_timer.timer); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!kvm_apic_sw_enabled(apic)) | ||||
| 			val |= APIC_LVT_MASKED; | ||||
| 		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); | ||||
| 		apic_set_reg(apic, APIC_LVTT, val); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case APIC_TMICT: | ||||
| 		if (apic_lvtt_tscdeadline(apic)) | ||||
| @ -1483,6 +1486,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | ||||
| 
 | ||||
| 	for (i = 0; i < APIC_LVT_NUM; i++) | ||||
| 		apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); | ||||
| 	apic->lapic_timer.timer_mode = 0; | ||||
| 	apic_set_reg(apic, APIC_LVT0, | ||||
| 		     SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,7 @@ | ||||
| struct kvm_timer { | ||||
| 	struct hrtimer timer; | ||||
| 	s64 period; 				/* unit: ns */ | ||||
| 	u32 timer_mode; | ||||
| 	u32 timer_mode_mask; | ||||
| 	u64 tscdeadline; | ||||
| 	atomic_t pending;			/* accumulated triggered timers */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user