Re: [PATCH 14/23] KVM: PPC: Book3S PR: Delay disabling relocation-on interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06.08.2013, at 06:23, Paul Mackerras wrote:

> When we are running a PR KVM guest on POWER8, we have to disable the
> new POWER8 feature of taking interrupts with relocation on, that is,
> of taking interrupts without disabling the MMU, because the SLB does
> not contain the normal kernel SLB entries while in the guest.
> Currently we disable relocation-on interrupts when a PR guest is
> created, and leave it disabled until there are no more PR guests in
> existence.
> 
> This defers the disabling of relocation-on interrupts until the first

It would've been nice to see the original patch on kvm-ppc@vger.

> time a PR KVM guest vcpu is run.  The reason is that in future we will
> support both PR and HV guests in the same kernel, and this will avoid
> disabling relocation-on interrupts unnecessarily for guests which turn
> out to be HV guests, as we will not know at VM creation time whether
> it will be a PR or a HV guest.
> 
> Signed-off-by: Paul Mackerras <paulus@xxxxxxxxx>
> ---
> arch/powerpc/include/asm/kvm_host.h |  1 +
> arch/powerpc/kvm/book3s_pr.c        | 71 ++++++++++++++++++++++++++-----------
> 2 files changed, 52 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index 4d83972..c012db2 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -264,6 +264,7 @@ struct kvm_arch {
> #endif /* CONFIG_KVM_BOOK3S_64_HV */
> #ifdef CONFIG_KVM_BOOK3S_PR
> 	struct mutex hpt_mutex;
> +	bool relon_disabled;
> #endif
> #ifdef CONFIG_PPC_BOOK3S_64
> 	struct list_head spapr_tce_tables;
> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
> index 5b06a70..2759ddc 100644
> --- a/arch/powerpc/kvm/book3s_pr.c
> +++ b/arch/powerpc/kvm/book3s_pr.c
> @@ -1197,6 +1197,47 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
> 	kmem_cache_free(kvm_vcpu_cache, vcpu);
> }
> 
> +/*
> + * On POWER8, we have to disable relocation-on interrupts while
> + * we are in the guest, since the guest doesn't have the normal
> + * kernel SLB contents.  Since disabling relocation-on interrupts
> + * is a fairly heavy-weight operation, we do it once when starting
> + * the first guest vcpu and leave it disabled until the last guest
> + * has been destroyed.
> + */
> +static unsigned int kvm_global_user_count = 0;
> +static DEFINE_SPINLOCK(kvm_global_user_count_lock);
> +
> +static void disable_relon_interrupts(struct kvm *kvm)
> +{
> +	mutex_lock(&kvm->lock);
> +	if (!kvm->arch.relon_disabled) {
> +		if (firmware_has_feature(FW_FEATURE_SET_MODE)) {

Is this the same as the endianness setting rtas call? If so, would a PR guest in an HV guest that provides only endianness setting but no relocation-on setting confuse any of this code?


Alex

> +			spin_lock(&kvm_global_user_count_lock);
> +			if (++kvm_global_user_count == 1)
> +				pSeries_disable_reloc_on_exc();
> +			spin_unlock(&kvm_global_user_count_lock);
> +		}
> +		/* order disabling above with setting relon_disabled */
> +		smp_mb();
> +		kvm->arch.relon_disabled = true;
> +	}
> +	mutex_unlock(&kvm->lock);
> +}
> +
> +static void enable_relon_interrupts(struct kvm *kvm)
> +{
> +	if (kvm->arch.relon_disabled &&
> +	    firmware_has_feature(FW_FEATURE_SET_MODE)) {
> +		spin_lock(&kvm_global_user_count_lock);
> +		BUG_ON(kvm_global_user_count == 0);
> +		if (--kvm_global_user_count == 0)
> +			pSeries_enable_reloc_on_exc();
> +		spin_unlock(&kvm_global_user_count_lock);
> +	}
> +	kvm->arch.relon_disabled = false;
> +}
> +
> int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
> {
> 	int ret;
> @@ -1234,6 +1275,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
> 		goto out;
> 	}
> 
> +	if (!vcpu->kvm->arch.relon_disabled)
> +		disable_relon_interrupts(vcpu->kvm);
> +
> 	/* Save FPU state in stack */
> 	if (current->thread.regs->msr & MSR_FP)
> 		giveup_fpu(current);
> @@ -1400,9 +1444,6 @@ void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
> {
> }
> 
> -static unsigned int kvm_global_user_count = 0;
> -static DEFINE_SPINLOCK(kvm_global_user_count_lock);
> -
> int kvmppc_core_init_vm(struct kvm *kvm)
> {
> #ifdef CONFIG_PPC64
> @@ -1411,28 +1452,18 @@ int kvmppc_core_init_vm(struct kvm *kvm)
> #endif
> 	mutex_init(&kvm->arch.hpt_mutex);
> 
> -	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
> -		spin_lock(&kvm_global_user_count_lock);
> -		if (++kvm_global_user_count == 1)
> -			pSeries_disable_reloc_on_exc();
> -		spin_unlock(&kvm_global_user_count_lock);
> -	}
> +	/*
> +	 * If we don't have relocation-on interrupts at all,
> +	 * then we can consider them to be already disabled.
> +	 */
> +	kvm->arch.relon_disabled = !firmware_has_feature(FW_FEATURE_SET_MODE);
> +
> 	return 0;
> }
> 
> void kvmppc_core_destroy_vm(struct kvm *kvm)
> {
> -#ifdef CONFIG_PPC64
> -	WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
> -#endif
> -
> -	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
> -		spin_lock(&kvm_global_user_count_lock);
> -		BUG_ON(kvm_global_user_count == 0);
> -		if (--kvm_global_user_count == 0)
> -			pSeries_enable_reloc_on_exc();
> -		spin_unlock(&kvm_global_user_count_lock);
> -	}
> +	enable_relon_interrupts(kvm);
> }
> 
> static int kvmppc_book3s_init(void)
> -- 
> 1.8.3.1
> 

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux