[PATCH 24/30] KVM: PPC: booke: call resched after every exit

Alexander Graf agraf at suse.de
Tue Feb 21 00:17:22 EST 2012


On 18.02.2012, at 00:00, Scott Wood wrote:

> On 02/17/2012 11:13 AM, Alexander Graf wrote:
>> Instead of checking whether we should reschedule only when we exited
>> due to an interrupt, let's always check before entering the guest back
>> again. This gets the target more in line with the other archs.
>> 
>> Signed-off-by: Alexander Graf <agraf at suse.de>
>> ---
>> arch/powerpc/kvm/booke.c |   15 ++++++++++-----
>> 1 files changed, 10 insertions(+), 5 deletions(-)
>> 
>> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
>> index bfb2092..de30b6d 100644
>> --- a/arch/powerpc/kvm/booke.c
>> +++ b/arch/powerpc/kvm/booke.c
>> @@ -572,6 +572,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
>>                        unsigned int exit_nr)
>> {
>> 	int r = RESUME_HOST;
>> +	int resched_needed = 1;
>> 
>> 	/* update before a new last_exit_type is rewritten */
>> 	kvmppc_update_timing_stats(vcpu);
>> @@ -602,25 +603,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
>> 
>> 	switch (exit_nr) {
>> 	case BOOKE_INTERRUPT_MACHINE_CHECK:
>> -		kvm_resched(vcpu);
>> 		r = RESUME_GUEST;
>> 		break;
>> 
>> 	case BOOKE_INTERRUPT_EXTERNAL:
>> 		kvmppc_account_exit(vcpu, EXT_INTR_EXITS);
>> -		kvm_resched(vcpu);
>> 		r = RESUME_GUEST;
>> 		break;
>> 
>> 	case BOOKE_INTERRUPT_DECREMENTER:
>> 		kvmppc_account_exit(vcpu, DEC_EXITS);
>> -		kvm_resched(vcpu);
>> 		r = RESUME_GUEST;
>> 		break;
>> 
>> 	case BOOKE_INTERRUPT_DOORBELL:
>> 		kvmppc_account_exit(vcpu, DBELL_EXITS);
>> -		kvm_resched(vcpu);
>> 		r = RESUME_GUEST;
>> 		break;
>> 
>> @@ -869,8 +866,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
>> 		BUG();
>> 	}
>> 
>> -	local_irq_disable();
>> +	/* make sure we reschedule if we need to */
>> +	while (resched_needed) {
>> +		local_irq_disable();
>> 
>> +		resched_needed = need_resched();
>> +		if (resched_needed) {
>> +			local_irq_enable();
>> +			cond_resched();
>> +		}
>> +	}
>> 	kvmppc_core_prepare_to_enter(vcpu);
>> 
>> 	if (!(r & RESUME_HOST)) {
> 
> kvmppc_core_prepare_to_enter can enable interrupts (and block) if guest
> MSR_WE is set.  We may take an interrupt that wants a resched after
> waking but before interrupts are disabled again.
> 
> We also want to check for a resched in kvmppc_vcpu_run.  So, the resched
> check belongs in kvmppc_core_prepare_to_enter, something like:
> 
> /* Check pending exceptions and deliver one, if possible. */
> void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
> {
> 	WARN_ON_ONCE(!irqs_disabled());
> 
> 	while (true) {
> 		if (signal_pending(current))
> 			break;
> 
> 		if (need_resched()) {
> 			local_irq_enable();
> 			cond_resched();
> 			local_irq_disable();
> 			continue;
> 		}
> 
> 		kvmppc_core_check_exceptions(vcpu);
> 
> 		if (vcpu->arch.shared->msr & MSR_WE) {
> 			local_irq_enable();
> 			kvm_vcpu_block(vcpu);
> 			local_irq_disable();
> 	
> 			kvmppc_set_exit_type(vcpu,
> 				EMULATED_MTMSRWE_EXITS);
> 			continue;
> 		}
> 
> 		break;
> 	}
> }
> 
> It would be simpler (both here and in the idle hcall) if we could just
> drop support for CONFIG_PREEMPT=n. :-P

When running with CONFIG_PREEMPT=n we don't have to worry about interrupts being enabled though, since we only preempt on known good checkpoints, right? While for CONFIG_PREEMPT=y we can always get preempted, rendering most of these checks void.

So essentially we could just be lazy and do a "best effort" resched check, but not worry about races wrt guest entry/exit, right? And for real preemption modes we don't have to worry about any of the resched stuff IIUC, correct?


Alex



More information about the Linuxppc-dev mailing list