KVM: Choose better candidate for directed yield
Currently, on a large vcpu guests, there is a high probability of
yielding to the same vcpu who had recently done a pause-loop exit or
cpu relax intercepted. Such a yield can lead to the vcpu spinning
again and hence degrade the performance.
The patchset keeps track of the pause loop exit/cpu relax interception
and gives chance to a vcpu which:
 (a) Has not done pause loop exit or cpu relax intercepted at all
     (probably he is preempted lock-holder)
 (b) Was skipped in last iteration because it did pause loop exit or
     cpu relax intercepted, and probably has become eligible now
     (next eligible lock holder)
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com> # on s390x
Signed-off-by: Avi Kivity <avi@redhat.com>
	
	
This commit is contained in:
		
					parent
					
						
							
								4c088493c8
							
						
					
				
			
			
				commit
				
					
						06e48c510a
					
				
			
		
					 2 changed files with 47 additions and 0 deletions
				
			
		|  | @ -931,6 +931,11 @@ static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val) | |||
| { | ||||
| } | ||||
| 
 | ||||
| static inline bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu) | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -1579,6 +1579,43 @@ bool kvm_vcpu_yield_to(struct kvm_vcpu *target) | |||
| } | ||||
| EXPORT_SYMBOL_GPL(kvm_vcpu_yield_to); | ||||
| 
 | ||||
| #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT | ||||
| /*
 | ||||
|  * Helper that checks whether a VCPU is eligible for directed yield. | ||||
|  * Most eligible candidate to yield is decided by following heuristics: | ||||
|  * | ||||
|  *  (a) VCPU which has not done pl-exit or cpu relax intercepted recently | ||||
|  *  (preempted lock holder), indicated by @in_spin_loop. | ||||
|  *  Set at the beiginning and cleared at the end of interception/PLE handler. | ||||
|  * | ||||
|  *  (b) VCPU which has done pl-exit/ cpu relax intercepted but did not get | ||||
|  *  chance last time (mostly it has become eligible now since we have probably | ||||
|  *  yielded to lockholder in last iteration. This is done by toggling | ||||
|  *  @dy_eligible each time a VCPU checked for eligibility.) | ||||
|  * | ||||
|  *  Yielding to a recently pl-exited/cpu relax intercepted VCPU before yielding | ||||
|  *  to preempted lock-holder could result in wrong VCPU selection and CPU | ||||
|  *  burning. Giving priority for a potential lock-holder increases lock | ||||
|  *  progress. | ||||
|  * | ||||
|  *  Since algorithm is based on heuristics, accessing another VCPU data without | ||||
|  *  locking does not harm. It may result in trying to yield to  same VCPU, fail | ||||
|  *  and continue with next VCPU and so on. | ||||
|  */ | ||||
| bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu) | ||||
| { | ||||
| 	bool eligible; | ||||
| 
 | ||||
| 	eligible = !vcpu->spin_loop.in_spin_loop || | ||||
| 			(vcpu->spin_loop.in_spin_loop && | ||||
| 			 vcpu->spin_loop.dy_eligible); | ||||
| 
 | ||||
| 	if (vcpu->spin_loop.in_spin_loop) | ||||
| 		kvm_vcpu_set_dy_eligible(vcpu, !vcpu->spin_loop.dy_eligible); | ||||
| 
 | ||||
| 	return eligible; | ||||
| } | ||||
| #endif | ||||
| void kvm_vcpu_on_spin(struct kvm_vcpu *me) | ||||
| { | ||||
| 	struct kvm *kvm = me->kvm; | ||||
|  | @ -1607,6 +1644,8 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me) | |||
| 				continue; | ||||
| 			if (waitqueue_active(&vcpu->wq)) | ||||
| 				continue; | ||||
| 			if (!kvm_vcpu_eligible_for_directed_yield(vcpu)) | ||||
| 				continue; | ||||
| 			if (kvm_vcpu_yield_to(vcpu)) { | ||||
| 				kvm->last_boosted_vcpu = i; | ||||
| 				yielded = 1; | ||||
|  | @ -1615,6 +1654,9 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me) | |||
| 		} | ||||
| 	} | ||||
| 	kvm_vcpu_set_in_spin_loop(me, false); | ||||
| 
 | ||||
| 	/* Ensure vcpu is not eligible during next spinloop */ | ||||
| 	kvm_vcpu_set_dy_eligible(me, false); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(kvm_vcpu_on_spin); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Raghavendra K T
				Raghavendra K T