[RFC PATCH 06/11] kvm: powerpc: book3s: Add is_hv_enabled to kvmppc_ops

Alexander Graf agraf at suse.de
Mon Sep 30 20:09:51 EST 2013


On 27.09.2013, at 15:03, Aneesh Kumar K.V wrote:

> Alexander Graf <agraf at suse.de> writes:
> 
>> On 27.09.2013, at 12:03, Aneesh Kumar K.V wrote:
>> 
>>> From: "Aneesh Kumar K.V" <aneesh.kumar at linux.vnet.ibm.com>
>>> 
>>> This help us to identify whether we are running with hypervisor mode KVM
>>> enabled. The change is needed so that we can have both HV and PR kvm
>>> enabled in the same kernel.
>>> 
>>> If both HV and PR KVM are included, interrupts come in to the HV version
>>> of the kvmppc_interrupt code, which then jumps to the PR handler,
>>> renamed to kvmppc_interrupt_pr, if the guest is a PR guest.
>>> 
>>> Allowing both PR and HV in the same kernel required some changes to
>>> kvm_dev_ioctl_check_extension(), since the values returned now can't
>>> be selected with #ifdefs as much as previously. We look at is_hv_enabled
>>> to return the right value when checking for capabilities.For capabilities that
>>> are only provided by HV KVM, we return the HV value only if
>>> is_hv_enabled is true. For capabilities provided by PR KVM but not HV,
>>> we return the PR value only if is_hv_enabled is false.
>>> 
>>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
>>> ---
>>> arch/powerpc/include/asm/kvm_book3s.h   | 53 --------------------------------
>>> arch/powerpc/include/asm/kvm_ppc.h      |  5 +--
>>> arch/powerpc/kvm/Makefile               |  2 +-
>>> arch/powerpc/kvm/book3s.c               | 44 +++++++++++++++++++++++++++
>>> arch/powerpc/kvm/book3s_hv.c            |  1 +
>>> arch/powerpc/kvm/book3s_hv_rmhandlers.S |  4 +++
>>> arch/powerpc/kvm/book3s_pr.c            |  1 +
>>> arch/powerpc/kvm/book3s_segment.S       |  7 ++++-
>>> arch/powerpc/kvm/book3s_xics.c          |  2 +-
>>> arch/powerpc/kvm/powerpc.c              | 54 ++++++++++++++++++---------------
>>> 10 files changed, 90 insertions(+), 83 deletions(-)
>>> 
>>> diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
>>> index 3efba3c..ba33c49 100644
>>> --- a/arch/powerpc/include/asm/kvm_book3s.h
>>> +++ b/arch/powerpc/include/asm/kvm_book3s.h
>>> @@ -297,59 +297,6 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
>>> 	return vcpu->arch.fault_dar;
>>> }
>>> 
>>> -#ifdef CONFIG_KVM_BOOK3S_PR
>>> -
>>> -static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
>>> -{
>>> -	return to_book3s(vcpu)->hior;
>>> -}
>>> -
>>> -static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
>>> -			unsigned long pending_now, unsigned long old_pending)
>>> -{
>>> -	if (pending_now)
>>> -		vcpu->arch.shared->int_pending = 1;
>>> -	else if (old_pending)
>>> -		vcpu->arch.shared->int_pending = 0;
>>> -}
>>> -
>>> -static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
>>> -{
>>> -	ulong crit_raw = vcpu->arch.shared->critical;
>>> -	ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
>>> -	bool crit;
>>> -
>>> -	/* Truncate crit indicators in 32 bit mode */
>>> -	if (!(vcpu->arch.shared->msr & MSR_SF)) {
>>> -		crit_raw &= 0xffffffff;
>>> -		crit_r1 &= 0xffffffff;
>>> -	}
>>> -
>>> -	/* Critical section when crit == r1 */
>>> -	crit = (crit_raw == crit_r1);
>>> -	/* ... and we're in supervisor mode */
>>> -	crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
>>> -
>>> -	return crit;
>>> -}
>>> -#else /* CONFIG_KVM_BOOK3S_PR */
>>> -
>>> -static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
>>> -{
>>> -	return 0;
>>> -}
>>> -
>>> -static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
>>> -			unsigned long pending_now, unsigned long old_pending)
>>> -{
>>> -}
>>> -
>>> -static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
>>> -{
>>> -	return false;
>>> -}
>>> -#endif
>>> -
>>> /* Magic register values loaded into r3 and r4 before the 'sc' assembly
>>> * instruction for the OSI hypercalls */
>>> #define OSI_SC_MAGIC_R3			0x113724FA
>>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
>>> index 4d9641c..58e732f 100644
>>> --- a/arch/powerpc/include/asm/kvm_ppc.h
>>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
>>> @@ -169,6 +169,7 @@ extern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq);
>>> extern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq);
>>> 
>>> struct kvmppc_ops {
>>> +	bool is_hv_enabled;
>> 
>> This doesn't really belong into an ops struct. Either you compare
>> 
>>  if (kvmppc_ops == kvmppc_ops_pr)
> 
> will do that in the next update. 
> 
>> 
>> against a global known good ops struct or you put the hint somewhere into the kvm struct.
>> 
>>> 	int (*get_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
>>> 	int (*set_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
>>> 	int (*get_one_reg)(struct kvm_vcpu *vcpu, u64 id,
>>> @@ -309,10 +310,10 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
>>> 
>>> static inline u32 kvmppc_get_xics_latch(void)
>>> {
>>> -	u32 xirr = get_paca()->kvm_hstate.saved_xirr;
>>> +	u32 xirr;
>>> 
>>> +	xirr = get_paca()->kvm_hstate.saved_xirr;
>>> 	get_paca()->kvm_hstate.saved_xirr = 0;
>>> -
>> 
>> I don't see any functionality change here?
>> 
>>> 	return xirr;
> 
> Mistake on my side, I had a if condition in there before, which i later
> removed. But forgot to move the assignment back. Will fix. 
> 
>>> }
>>> 
>>> diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
>>> index c343793..a514ecd 100644
>>> --- a/arch/powerpc/kvm/Makefile
>>> +++ b/arch/powerpc/kvm/Makefile
>>> @@ -77,7 +77,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
>>> 	book3s_rmhandlers.o
>>> endif
>>> 
>>> -kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
>>> +kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV)  += \
>> 
>> This change looks unrelated?
>> 
> 
> yes. Will move it to the correct patch
> 
> 
>>> 	book3s_hv.o \
>>> 	book3s_hv_interrupts.o \
>>> 	book3s_64_mmu_hv.o
>>> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
>>> index bdc3f95..12f94bf 100644
>>> --- a/arch/powerpc/kvm/book3s.c
>>> +++ b/arch/powerpc/kvm/book3s.c
>>> @@ -69,6 +69,50 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
>>> {
>>> }
>>> 
>>> +static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
>> 
>> Please drop the "inline" keyword on functions in .c files :). That way
>> the compiler tells us about unused functions.
> 
> ok .
> 
>> 
>>> +{
>>> +	if (!kvmppc_ops->is_hv_enabled)
>>> +		return to_book3s(vcpu)->hior;
>>> +	return 0;
>>> +}
>>> +
>>> +static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
>>> +			unsigned long pending_now, unsigned long old_pending)
>>> +{
>>> +	if (kvmppc_ops->is_hv_enabled)
>>> +		return;
>>> +	if (pending_now)
>>> +		vcpu->arch.shared->int_pending = 1;
>>> +	else if (old_pending)
>>> +		vcpu->arch.shared->int_pending = 0;
>>> +}
>>> +
> 
> ....
> 
>>> diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
>>> index 1abe478..e0229dd 100644
>>> --- a/arch/powerpc/kvm/book3s_segment.S
>>> +++ b/arch/powerpc/kvm/book3s_segment.S
>>> @@ -161,9 +161,14 @@ kvmppc_handler_trampoline_enter_end:
>>> .global kvmppc_handler_trampoline_exit
>>> kvmppc_handler_trampoline_exit:
>>> 
>>> +#if defined(CONFIG_KVM_BOOK3S_HV)
>>> +.global kvmppc_interrupt_pr
>>> +kvmppc_interrupt_pr:
>>> +	ld	r9, HSTATE_SCRATCH2(r13)
>>> +#else
>>> .global kvmppc_interrupt
>>> kvmppc_interrupt:
>> 
>> Just always call it kvmppc_interrupt_pr and thus share at least that
>> part of the code :).
> 
> But if i don't have HV enabled, we don't compile book3s_hv_rmhandlers.S
> Hence don't have the kvmppc_interrupt symbol defined.

Ah, because we're always jumping to kvmppc_interrupt. Can we make this slightly less magical? How about we always call kvmppc_interrupt_hv when CONFIG_KVM_BOOK3S_HV_POSSIBLE and always kvmppc_interrupt_pr when CONFIG_KVM_BOOK3S_PR_POSSIBLE and then branch to kvmppc_interrupt_pr from kvmppc_interrupt_hv?

IMHO that would make the code flow more obvious.

> 
>> 
>>> -
>>> +#endif
>>> 	/* Register usage at this point:
>>> 	 *
>>> 	 * SPRG_SCRATCH0  = guest R13
>>> diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
>>> index f0c732e..fa7625d 100644
>>> --- a/arch/powerpc/kvm/book3s_xics.c
>>> +++ b/arch/powerpc/kvm/book3s_xics.c
>>> @@ -818,7 +818,7 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
>>> 	}
>>> 
>>> 	/* Check for real mode returning too hard */
>>> -	if (xics->real_mode)
>>> +	if (xics->real_mode && kvmppc_ops->is_hv_enabled)
>>> 		return kvmppc_xics_rm_complete(vcpu, req);
>>> 
>>> 	switch (req) {
>>> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
>>> index 69b9305..00a96fc 100644
>>> --- a/arch/powerpc/kvm/powerpc.c
>>> +++ b/arch/powerpc/kvm/powerpc.c
>>> @@ -52,7 +52,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>>> 	return 1;
>>> }
>>> 
>>> -#ifndef CONFIG_KVM_BOOK3S_64_HV
>>> /*
>>> * Common checks before entering the guest world.  Call with interrupts
>>> * disabled.
>>> @@ -127,7 +126,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
>>> 
>>> 	return r;
>>> }
>>> -#endif /* CONFIG_KVM_BOOK3S_64_HV */
>>> 
>>> int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
>>> {
>>> @@ -194,11 +192,9 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
>>> 	if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
>>> 		goto out;
>>> 
>>> -#ifdef CONFIG_KVM_BOOK3S_64_HV
>>> 	/* HV KVM can only do PAPR mode for now */
>>> -	if (!vcpu->arch.papr_enabled)
>>> +	if (!vcpu->arch.papr_enabled && kvmppc_ops->is_hv_enabled)
>>> 		goto out;
>>> -#endif
>>> 
>>> #ifdef CONFIG_KVM_BOOKE_HV
>>> 	if (!cpu_has_feature(CPU_FTR_EMB_HV))
>>> @@ -322,22 +318,26 @@ int kvm_dev_ioctl_check_extension(long ext)
>>> 	case KVM_CAP_DEVICE_CTRL:
>>> 		r = 1;
>>> 		break;
>>> -#ifndef CONFIG_KVM_BOOK3S_64_HV
>>> 	case KVM_CAP_PPC_PAIRED_SINGLES:
>>> 	case KVM_CAP_PPC_OSI:
>>> 	case KVM_CAP_PPC_GET_PVINFO:
>>> #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
>>> 	case KVM_CAP_SW_TLB:
>>> #endif
>>> -#ifdef CONFIG_KVM_MPIC
>>> -	case KVM_CAP_IRQ_MPIC:
>>> -#endif
>>> -		r = 1;
>>> +		/* We support this only for PR */
>>> +		r = !kvmppc_ops->is_hv_enabled;
>> 
>> Reading this, have you test compiled your code against e500 configs?
> 
> 
> Not yet.

Please do so - for every patch in your series. If you like I can give you my example configs I usually use to test compile this.

> 
> 
>> 
>>> 		break;
>>> +#ifdef CONFIG_KVM_MMIO
>>> 	case KVM_CAP_COALESCED_MMIO:
>>> 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
>>> 		break;
>>> #endif
>>> +#ifdef CONFIG_KVM_MPIC
>>> +	case KVM_CAP_IRQ_MPIC:
>>> +		r = 1;
>>> +		break;
>>> +#endif
>>> +
>>> #ifdef CONFIG_PPC_BOOK3S_64
>>> 	case KVM_CAP_SPAPR_TCE:
>>> 	case KVM_CAP_PPC_ALLOC_HTAB:
>>> @@ -348,32 +348,37 @@ int kvm_dev_ioctl_check_extension(long ext)
>>> 		r = 1;
>>> 		break;
>>> #endif /* CONFIG_PPC_BOOK3S_64 */
>>> -#ifdef CONFIG_KVM_BOOK3S_64_HV
>>> +#ifdef CONFIG_KVM_BOOK3S_HV
>>> 	case KVM_CAP_PPC_SMT:
>>> -		r = threads_per_core;
>>> +		if (kvmppc_ops->is_hv_enabled)
>>> +			r = threads_per_core;
>>> +		else
>>> +			r = 0;
>> 
>> 0? Or 1?
>> 
> 
> That check extension was not supported before on PR. So not sure what
> the value should be. May be 1 is better indicating we have one thread.
> Will change.

Ah, the default case (cap unknown) returns 0, so this is fine.


Alex



More information about the Linuxppc-dev mailing list