diff mbox

[2/3] KVM: PPC: booke: Allow multiple exception types

Message ID 1343977723-25341-2-git-send-email-Bharat.Bhushan@freescale.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bharat Bhushan Aug. 3, 2012, 7:08 a.m. UTC
Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
all handlers are considered to be the same size. This will not be
the case if we want to use different macros for different handlers.

This patch improves the kvmppc_booke_handler so that it can
support different macros for different handlers.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
[bharat.bhushan@freescale.com: Substantial changes]
Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
 arch/powerpc/include/asm/kvm_ppc.h  |    2 -
 arch/powerpc/kvm/booke.c            |    9 ++++---
 arch/powerpc/kvm/booke.h            |    1 +
 arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++--
 arch/powerpc/kvm/e500.c             |   13 +++++++----
 5 files changed, 48 insertions(+), 14 deletions(-)

Comments

Alexander Graf Aug. 7, 2012, 10:46 a.m. UTC | #1
On 03.08.2012, at 09:08, Bharat Bhushan wrote:

> Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
> all handlers are considered to be the same size. This will not be
> the case if we want to use different macros for different handlers.
> 
> This patch improves the kvmppc_booke_handler so that it can
> support different macros for different handlers.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> [bharat.bhushan@freescale.com: Substantial changes]
> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> ---
> arch/powerpc/include/asm/kvm_ppc.h  |    2 -
> arch/powerpc/kvm/booke.c            |    9 ++++---
> arch/powerpc/kvm/booke.h            |    1 +
> arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++--
> arch/powerpc/kvm/e500.c             |   13 +++++++----
> 5 files changed, 48 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> index 1438a5e..deb55bd 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -47,8 +47,6 @@ enum emulation_result {
> 
> extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
> extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
> -extern char kvmppc_handlers_start[];
> -extern unsigned long kvmppc_handler_len;
> extern void kvmppc_handler_highmem(void);
> 
> extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index aebbb8b..1338233 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void)
> {
> #ifndef CONFIG_KVM_BOOKE_HV
> 	unsigned long ivor[16];
> +	unsigned long *handler = kvmppc_booke_handler_addr;
> 	unsigned long max_ivor = 0;
> 	int i;
> 
> @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
> 
> 	for (i = 0; i < 16; i++) {
> 		if (ivor[i] > max_ivor)
> -			max_ivor = ivor[i];
> +			max_ivor = i;
> 
> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> -		       kvmppc_handlers_start + i * kvmppc_handler_len,
> -		       kvmppc_handler_len);
> +		       (void *)handler[i], handler[i + 1] - handler[i]);
> 	}
> 	flush_icache_range(kvmppc_booke_handlers,
> -	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> +                               handler[max_ivor + 1] - handler[max_ivor]);
> #endif /* !BOOKE_HV */
> 	return 0;
> }
> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> index ba61974..de9e526 100644
> --- a/arch/powerpc/kvm/booke.h
> +++ b/arch/powerpc/kvm/booke.h
> @@ -65,6 +65,7 @@
> 			  (1 << BOOKE_IRQPRIO_CRITICAL))
> 
> extern unsigned long kvmppc_booke_handlers;
> +extern unsigned long kvmppc_booke_handler_addr[];
> 
> void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
> void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
> diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
> index bb46b32..3539805 100644
> --- a/arch/powerpc/kvm/booke_interrupts.S
> +++ b/arch/powerpc/kvm/booke_interrupts.S
> @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
> 	bctr
> .endm
> 
> +.macro KVM_HANDLER_ADDR ivor_nr
> +	.long	kvmppc_handler_\ivor_nr
> +.endm
> +
> +.macro KVM_HANDLER_END
> +	.long	kvmppc_handlers_end
> +.endm
> +
> _GLOBAL(kvmppc_handlers_start)
> KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
> KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK  SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
> @@ -93,9 +101,7 @@ KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
> KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> -
> -_GLOBAL(kvmppc_handler_len)
> -	.long kvmppc_handler_1 - kvmppc_handler_0
> +_GLOBAL(kvmppc_handlers_end)
> 
> /* Registers:
>  *  SPRG_SCRATCH0: guest r4
> @@ -463,6 +469,31 @@ lightweight_exit:
> 	lwz	r4, VCPU_GPR(R4)(r4)
> 	rfi
> 
> +	.data
> +	.align	4
> +	.globl	kvmppc_booke_handler_addr
> +kvmppc_booke_handler_addr:
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_MACHINE_CHECK
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DATA_STORAGE
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_INST_STORAGE
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_EXTERNAL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FP_UNAVAIL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DECREMENTER
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DTLB_MISS
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ITLB_MISS
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_DATA
> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_ROUND
> +KVM_HANDLER_END /*Always keep this in end*/
> +
> #ifdef CONFIG_SPE
> _GLOBAL(kvmppc_save_guest_spe)
> 	cmpi	0,r3,0
> diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
> index b479ed7..cb7a5e7 100644
> --- a/arch/powerpc/kvm/e500.c
> +++ b/arch/powerpc/kvm/e500.c
> @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void)
> {
> 	int r, i;
> 	unsigned long ivor[3];
> +	unsigned long *handler = kvmppc_booke_handler_addr;

/* Process remaining handlers above the generic first 16 */
unsigned long *handler = &kvmppc_booke_handler_addr[16];

> 	unsigned long max_ivor = 0;
> 
> 	r = kvmppc_core_check_processor_compat();
> 	if (r)
> 		return r;
> 
> +	handler += 16;
> +
> 	r = kvmppc_booke_init();
> 	if (r)
> 		return r;
> @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
> 	ivor[1] = mfspr(SPRN_IVOR33);
> 	ivor[2] = mfspr(SPRN_IVOR34);
> 	for (i = 0; i < 3; i++) {
> -		if (ivor[i] > max_ivor)
> -			max_ivor = ivor[i];
> +		if (ivor[i] > ivor[max_ivor])
> +			max_ivor = i;
> 
> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> -		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
> -		       kvmppc_handler_len);
> +		       (void *)handler[i], handler[i + 1] - handler[i]);

handler_len = handler[i + 1] - handler[i];
handler_end = max(handler_end, handler[i] + handler_len);

> 	}
> 	flush_icache_range(kvmppc_booke_handlers,
> -			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> +	                       handler[max_ivor + 1] - handler[max_ivor]);

handler_end


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bharat Bhushan Aug. 10, 2012, 6:38 a.m. UTC | #2
> -----Original Message-----
> From: kvm-ppc-owner@vger.kernel.org [mailto:kvm-ppc-owner@vger.kernel.org] On
> Behalf Of Alexander Graf
> Sent: Tuesday, August 07, 2012 4:16 PM
> To: Bhushan Bharat-R65777
> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; Bhushan Bharat-R65777
> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception types
> 
> 
> On 03.08.2012, at 09:08, Bharat Bhushan wrote:
> 
> > Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
> > all handlers are considered to be the same size. This will not be
> > the case if we want to use different macros for different handlers.
> >
> > This patch improves the kvmppc_booke_handler so that it can
> > support different macros for different handlers.
> >
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
> > [bharat.bhushan@freescale.com: Substantial changes]
> > Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> > ---
> > arch/powerpc/include/asm/kvm_ppc.h  |    2 -
> > arch/powerpc/kvm/booke.c            |    9 ++++---
> > arch/powerpc/kvm/booke.h            |    1 +
> > arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++--
> > arch/powerpc/kvm/e500.c             |   13 +++++++----
> > 5 files changed, 48 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/kvm_ppc.h
> b/arch/powerpc/include/asm/kvm_ppc.h
> > index 1438a5e..deb55bd 100644
> > --- a/arch/powerpc/include/asm/kvm_ppc.h
> > +++ b/arch/powerpc/include/asm/kvm_ppc.h
> > @@ -47,8 +47,6 @@ enum emulation_result {
> >
> > extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
> > extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
> > -extern char kvmppc_handlers_start[];
> > -extern unsigned long kvmppc_handler_len;
> > extern void kvmppc_handler_highmem(void);
> >
> > extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > index aebbb8b..1338233 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void)
> > {
> > #ifndef CONFIG_KVM_BOOKE_HV
> > 	unsigned long ivor[16];
> > +	unsigned long *handler = kvmppc_booke_handler_addr;
> > 	unsigned long max_ivor = 0;
> > 	int i;
> >
> > @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
> >
> > 	for (i = 0; i < 16; i++) {
> > 		if (ivor[i] > max_ivor)
> > -			max_ivor = ivor[i];
> > +			max_ivor = i;
> >
> > 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> > -		       kvmppc_handlers_start + i * kvmppc_handler_len,
> > -		       kvmppc_handler_len);
> > +		       (void *)handler[i], handler[i + 1] - handler[i]);
> > 	}
> > 	flush_icache_range(kvmppc_booke_handlers,
> > -	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> > +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> > +                               handler[max_ivor + 1] - handler[max_ivor]);
> > #endif /* !BOOKE_HV */
> > 	return 0;
> > }
> > diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> > index ba61974..de9e526 100644
> > --- a/arch/powerpc/kvm/booke.h
> > +++ b/arch/powerpc/kvm/booke.h
> > @@ -65,6 +65,7 @@
> > 			  (1 << BOOKE_IRQPRIO_CRITICAL))
> >
> > extern unsigned long kvmppc_booke_handlers;
> > +extern unsigned long kvmppc_booke_handler_addr[];
> >
> > void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
> > void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
> > diff --git a/arch/powerpc/kvm/booke_interrupts.S
> b/arch/powerpc/kvm/booke_interrupts.S
> > index bb46b32..3539805 100644
> > --- a/arch/powerpc/kvm/booke_interrupts.S
> > +++ b/arch/powerpc/kvm/booke_interrupts.S
> > @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
> > 	bctr
> > .endm
> >
> > +.macro KVM_HANDLER_ADDR ivor_nr
> > +	.long	kvmppc_handler_\ivor_nr
> > +.endm
> > +
> > +.macro KVM_HANDLER_END
> > +	.long	kvmppc_handlers_end
> > +.endm
> > +
> > _GLOBAL(kvmppc_handlers_start)
> > KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
> > KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK  SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
> > @@ -93,9 +101,7 @@ KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT
> SPRN_CSRR0
> > KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> > KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> > KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> > -
> > -_GLOBAL(kvmppc_handler_len)
> > -	.long kvmppc_handler_1 - kvmppc_handler_0
> > +_GLOBAL(kvmppc_handlers_end)
> >
> > /* Registers:
> >  *  SPRG_SCRATCH0: guest r4
> > @@ -463,6 +469,31 @@ lightweight_exit:
> > 	lwz	r4, VCPU_GPR(R4)(r4)
> > 	rfi
> >
> > +	.data
> > +	.align	4
> > +	.globl	kvmppc_booke_handler_addr
> > +kvmppc_booke_handler_addr:
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_MACHINE_CHECK
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DATA_STORAGE
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_INST_STORAGE
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_EXTERNAL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FP_UNAVAIL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DECREMENTER
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DTLB_MISS
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ITLB_MISS
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_DATA
> > +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_ROUND
> > +KVM_HANDLER_END /*Always keep this in end*/
> > +
> > #ifdef CONFIG_SPE
> > _GLOBAL(kvmppc_save_guest_spe)
> > 	cmpi	0,r3,0
> > diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
> > index b479ed7..cb7a5e7 100644
> > --- a/arch/powerpc/kvm/e500.c
> > +++ b/arch/powerpc/kvm/e500.c
> > @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void)
> > {
> > 	int r, i;
> > 	unsigned long ivor[3];
> > +	unsigned long *handler = kvmppc_booke_handler_addr;
> 
> /* Process remaining handlers above the generic first 16 */
> unsigned long *handler = &kvmppc_booke_handler_addr[16];
> 
> > 	unsigned long max_ivor = 0;
> >
> > 	r = kvmppc_core_check_processor_compat();
> > 	if (r)
> > 		return r;
> >
> > +	handler += 16;
> > +
> > 	r = kvmppc_booke_init();
> > 	if (r)
> > 		return r;
> > @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
> > 	ivor[1] = mfspr(SPRN_IVOR33);
> > 	ivor[2] = mfspr(SPRN_IVOR34);
> > 	for (i = 0; i < 3; i++) {
> > -		if (ivor[i] > max_ivor)
> > -			max_ivor = ivor[i];
> > +		if (ivor[i] > ivor[max_ivor])
> > +			max_ivor = i;
> >
> > 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> > -		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
> > -		       kvmppc_handler_len);
> > +		       (void *)handler[i], handler[i + 1] - handler[i]);
> 
> handler_len = handler[i + 1] - handler[i];
> handler_end = max(handler_end, handler[i] + handler_len);

Ok .

> 
> > 	}
> > 	flush_icache_range(kvmppc_booke_handlers,
> > -			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> > +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> > +	                       handler[max_ivor + 1] - handler[max_ivor]);
> 
> handler_end

I do not get how this logic will work and simple. Can you please explain ?

The end address here is calculated by IVOR offset (same as host ivor offset) where KVM handler[last] is copied in kvmppc_booke_handlers and length by handler[last + 1] - handler[last];

Thanks
-Bharat

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf Aug. 10, 2012, 9:19 a.m. UTC | #3
On 10.08.2012, at 08:38, Bhushan Bharat-R65777 wrote:

> 
> 
>> -----Original Message-----
>> From: kvm-ppc-owner@vger.kernel.org [mailto:kvm-ppc-owner@vger.kernel.org] On
>> Behalf Of Alexander Graf
>> Sent: Tuesday, August 07, 2012 4:16 PM
>> To: Bhushan Bharat-R65777
>> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; Bhushan Bharat-R65777
>> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception types
>> 
>> 
>> On 03.08.2012, at 09:08, Bharat Bhushan wrote:
>> 
>>> Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
>>> all handlers are considered to be the same size. This will not be
>>> the case if we want to use different macros for different handlers.
>>> 
>>> This patch improves the kvmppc_booke_handler so that it can
>>> support different macros for different handlers.
>>> 
>>> Signed-off-by: Liu Yu <yu.liu@freescale.com>
>>> [bharat.bhushan@freescale.com: Substantial changes]
>>> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
>>> ---
>>> arch/powerpc/include/asm/kvm_ppc.h  |    2 -
>>> arch/powerpc/kvm/booke.c            |    9 ++++---
>>> arch/powerpc/kvm/booke.h            |    1 +
>>> arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++--
>>> arch/powerpc/kvm/e500.c             |   13 +++++++----
>>> 5 files changed, 48 insertions(+), 14 deletions(-)
>>> 
>>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h
>> b/arch/powerpc/include/asm/kvm_ppc.h
>>> index 1438a5e..deb55bd 100644
>>> --- a/arch/powerpc/include/asm/kvm_ppc.h
>>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
>>> @@ -47,8 +47,6 @@ enum emulation_result {
>>> 
>>> extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
>>> extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
>>> -extern char kvmppc_handlers_start[];
>>> -extern unsigned long kvmppc_handler_len;
>>> extern void kvmppc_handler_highmem(void);
>>> 
>>> extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
>>> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
>>> index aebbb8b..1338233 100644
>>> --- a/arch/powerpc/kvm/booke.c
>>> +++ b/arch/powerpc/kvm/booke.c
>>> @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void)
>>> {
>>> #ifndef CONFIG_KVM_BOOKE_HV
>>> 	unsigned long ivor[16];
>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
>>> 	unsigned long max_ivor = 0;
>>> 	int i;
>>> 
>>> @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
>>> 
>>> 	for (i = 0; i < 16; i++) {
>>> 		if (ivor[i] > max_ivor)
>>> -			max_ivor = ivor[i];
>>> +			max_ivor = i;
>>> 
>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
>>> -		       kvmppc_handlers_start + i * kvmppc_handler_len,
>>> -		       kvmppc_handler_len);
>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
>>> 	}
>>> 	flush_icache_range(kvmppc_booke_handlers,
>>> -	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
>>> +                               handler[max_ivor + 1] - handler[max_ivor]);
>>> #endif /* !BOOKE_HV */
>>> 	return 0;
>>> }
>>> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
>>> index ba61974..de9e526 100644
>>> --- a/arch/powerpc/kvm/booke.h
>>> +++ b/arch/powerpc/kvm/booke.h
>>> @@ -65,6 +65,7 @@
>>> 			  (1 << BOOKE_IRQPRIO_CRITICAL))
>>> 
>>> extern unsigned long kvmppc_booke_handlers;
>>> +extern unsigned long kvmppc_booke_handler_addr[];
>>> 
>>> void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
>>> void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
>>> diff --git a/arch/powerpc/kvm/booke_interrupts.S
>> b/arch/powerpc/kvm/booke_interrupts.S
>>> index bb46b32..3539805 100644
>>> --- a/arch/powerpc/kvm/booke_interrupts.S
>>> +++ b/arch/powerpc/kvm/booke_interrupts.S
>>> @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
>>> 	bctr
>>> .endm
>>> 
>>> +.macro KVM_HANDLER_ADDR ivor_nr
>>> +	.long	kvmppc_handler_\ivor_nr
>>> +.endm
>>> +
>>> +.macro KVM_HANDLER_END
>>> +	.long	kvmppc_handlers_end
>>> +.endm
>>> +
>>> _GLOBAL(kvmppc_handlers_start)
>>> KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
>>> KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK  SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
>>> @@ -93,9 +101,7 @@ KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT
>> SPRN_CSRR0
>>> KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
>>> KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
>>> KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
>>> -
>>> -_GLOBAL(kvmppc_handler_len)
>>> -	.long kvmppc_handler_1 - kvmppc_handler_0
>>> +_GLOBAL(kvmppc_handlers_end)
>>> 
>>> /* Registers:
>>> *  SPRG_SCRATCH0: guest r4
>>> @@ -463,6 +469,31 @@ lightweight_exit:
>>> 	lwz	r4, VCPU_GPR(R4)(r4)
>>> 	rfi
>>> 
>>> +	.data
>>> +	.align	4
>>> +	.globl	kvmppc_booke_handler_addr
>>> +kvmppc_booke_handler_addr:
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_MACHINE_CHECK
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DATA_STORAGE
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_INST_STORAGE
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_EXTERNAL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FP_UNAVAIL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DECREMENTER
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DTLB_MISS
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_ITLB_MISS
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_DATA
>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_ROUND
>>> +KVM_HANDLER_END /*Always keep this in end*/
>>> +
>>> #ifdef CONFIG_SPE
>>> _GLOBAL(kvmppc_save_guest_spe)
>>> 	cmpi	0,r3,0
>>> diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
>>> index b479ed7..cb7a5e7 100644
>>> --- a/arch/powerpc/kvm/e500.c
>>> +++ b/arch/powerpc/kvm/e500.c
>>> @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void)
>>> {
>>> 	int r, i;
>>> 	unsigned long ivor[3];
>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
>> 
>> /* Process remaining handlers above the generic first 16 */
>> unsigned long *handler = &kvmppc_booke_handler_addr[16];
>> 
>>> 	unsigned long max_ivor = 0;
>>> 
>>> 	r = kvmppc_core_check_processor_compat();
>>> 	if (r)
>>> 		return r;
>>> 
>>> +	handler += 16;
>>> +
>>> 	r = kvmppc_booke_init();
>>> 	if (r)
>>> 		return r;
>>> @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
>>> 	ivor[1] = mfspr(SPRN_IVOR33);
>>> 	ivor[2] = mfspr(SPRN_IVOR34);
>>> 	for (i = 0; i < 3; i++) {
>>> -		if (ivor[i] > max_ivor)
>>> -			max_ivor = ivor[i];
>>> +		if (ivor[i] > ivor[max_ivor])
>>> +			max_ivor = i;
>>> 
>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
>>> -		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
>>> -		       kvmppc_handler_len);
>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
>> 
>> handler_len = handler[i + 1] - handler[i];
>> handler_end = max(handler_end, handler[i] + handler_len);
> 
> Ok .
> 
>> 
>>> 	}
>>> 	flush_icache_range(kvmppc_booke_handlers,
>>> -			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
>>> +	                       handler[max_ivor + 1] - handler[max_ivor]);
>> 
>> handler_end
> 
> I do not get how this logic will work and simple. Can you please explain ?
> 
> The end address here is calculated by IVOR offset (same as host ivor offset) where KVM handler[last] is copied in kvmppc_booke_handlers and length by handler[last + 1] - handler[last];

Hrm. You want to flush from [ kvmppc_booke_handlers ; kvmppc_booke_handlers + handlers_len ].

handlers_len = handler[0] - handler_end;


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bharat Bhushan Aug. 10, 2012, 10:41 a.m. UTC | #4
> -----Original Message-----
> From: kvm-owner@vger.kernel.org [mailto:kvm-owner@vger.kernel.org] On Behalf Of
> Alexander Graf
> Sent: Friday, August 10, 2012 2:49 PM
> To: Bhushan Bharat-R65777
> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org
> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception types
> 
> 
> On 10.08.2012, at 08:38, Bhushan Bharat-R65777 wrote:
> 
> >
> >
> >> -----Original Message-----
> >> From: kvm-ppc-owner@vger.kernel.org
> >> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Alexander Graf
> >> Sent: Tuesday, August 07, 2012 4:16 PM
> >> To: Bhushan Bharat-R65777
> >> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; Bhushan
> >> Bharat-R65777
> >> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception
> >> types
> >>
> >>
> >> On 03.08.2012, at 09:08, Bharat Bhushan wrote:
> >>
> >>> Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
> >>> all handlers are considered to be the same size. This will not be
> >>> the case if we want to use different macros for different handlers.
> >>>
> >>> This patch improves the kvmppc_booke_handler so that it can support
> >>> different macros for different handlers.
> >>>
> >>> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> >>> [bharat.bhushan@freescale.com: Substantial changes]
> >>> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> >>> ---
> >>> arch/powerpc/include/asm/kvm_ppc.h  |    2 -
> >>> arch/powerpc/kvm/booke.c            |    9 ++++---
> >>> arch/powerpc/kvm/booke.h            |    1 +
> >>> arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++-
> -
> >>> arch/powerpc/kvm/e500.c             |   13 +++++++----
> >>> 5 files changed, 48 insertions(+), 14 deletions(-)
> >>>
> >>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h
> >> b/arch/powerpc/include/asm/kvm_ppc.h
> >>> index 1438a5e..deb55bd 100644
> >>> --- a/arch/powerpc/include/asm/kvm_ppc.h
> >>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> >>> @@ -47,8 +47,6 @@ enum emulation_result {
> >>>
> >>> extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu
> >>> *vcpu); extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct
> >>> kvm_vcpu *vcpu); -extern char kvmppc_handlers_start[]; -extern
> >>> unsigned long kvmppc_handler_len; extern void
> >>> kvmppc_handler_highmem(void);
> >>>
> >>> extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); diff --git
> >>> a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
> >>> aebbb8b..1338233 100644
> >>> --- a/arch/powerpc/kvm/booke.c
> >>> +++ b/arch/powerpc/kvm/booke.c
> >>> @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void) { #ifndef
> >>> CONFIG_KVM_BOOKE_HV
> >>> 	unsigned long ivor[16];
> >>> +	unsigned long *handler = kvmppc_booke_handler_addr;
> >>> 	unsigned long max_ivor = 0;
> >>> 	int i;
> >>>
> >>> @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
> >>>
> >>> 	for (i = 0; i < 16; i++) {
> >>> 		if (ivor[i] > max_ivor)
> >>> -			max_ivor = ivor[i];
> >>> +			max_ivor = i;
> >>>
> >>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> >>> -		       kvmppc_handlers_start + i * kvmppc_handler_len,
> >>> -		       kvmppc_handler_len);
> >>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
> >>> 	}
> >>> 	flush_icache_range(kvmppc_booke_handlers,
> >>> -	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> >>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> >>> +                               handler[max_ivor + 1] -
> >>> +handler[max_ivor]);
> >>> #endif /* !BOOKE_HV */
> >>> 	return 0;
> >>> }
> >>> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> >>> index ba61974..de9e526 100644
> >>> --- a/arch/powerpc/kvm/booke.h
> >>> +++ b/arch/powerpc/kvm/booke.h
> >>> @@ -65,6 +65,7 @@
> >>> 			  (1 << BOOKE_IRQPRIO_CRITICAL))
> >>>
> >>> extern unsigned long kvmppc_booke_handlers;
> >>> +extern unsigned long kvmppc_booke_handler_addr[];
> >>>
> >>> void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr); void
> >>> kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr); diff
> >>> --git a/arch/powerpc/kvm/booke_interrupts.S
> >> b/arch/powerpc/kvm/booke_interrupts.S
> >>> index bb46b32..3539805 100644
> >>> --- a/arch/powerpc/kvm/booke_interrupts.S
> >>> +++ b/arch/powerpc/kvm/booke_interrupts.S
> >>> @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
> >>> 	bctr
> >>> .endm
> >>>
> >>> +.macro KVM_HANDLER_ADDR ivor_nr
> >>> +	.long	kvmppc_handler_\ivor_nr
> >>> +.endm
> >>> +
> >>> +.macro KVM_HANDLER_END
> >>> +	.long	kvmppc_handlers_end
> >>> +.endm
> >>> +
> >>> _GLOBAL(kvmppc_handlers_start)
> >>> KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT
> >>> SPRN_CSRR0 KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK
> >>> SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0 @@ -93,9 +101,7 @@ KVM_HANDLER
> >>> BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT
> >> SPRN_CSRR0
> >>> KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0
> >>> SPRN_SRR0 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA
> >>> SPRN_SPRG_RSCRATCH0 SPRN_SRR0 KVM_HANDLER
> >>> BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> >>> -
> >>> -_GLOBAL(kvmppc_handler_len)
> >>> -	.long kvmppc_handler_1 - kvmppc_handler_0
> >>> +_GLOBAL(kvmppc_handlers_end)
> >>>
> >>> /* Registers:
> >>> *  SPRG_SCRATCH0: guest r4
> >>> @@ -463,6 +469,31 @@ lightweight_exit:
> >>> 	lwz	r4, VCPU_GPR(R4)(r4)
> >>> 	rfi
> >>>
> >>> +	.data
> >>> +	.align	4
> >>> +	.globl	kvmppc_booke_handler_addr
> >>> +kvmppc_booke_handler_addr:
> >>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_MACHINE_CHECK KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_DATA_STORAGE KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_INST_STORAGE KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_EXTERNAL KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
> >>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_FP_UNAVAIL KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
> >>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_DECREMENTER KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
> >>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_DTLB_MISS KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_ITLB_MISS KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
> >>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_SPE_FP_DATA KVM_HANDLER_ADDR
> >>> +BOOKE_INTERRUPT_SPE_FP_ROUND KVM_HANDLER_END /*Always keep this in
> >>> +end*/
> >>> +
> >>> #ifdef CONFIG_SPE
> >>> _GLOBAL(kvmppc_save_guest_spe)
> >>> 	cmpi	0,r3,0
> >>> diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index
> >>> b479ed7..cb7a5e7 100644
> >>> --- a/arch/powerpc/kvm/e500.c
> >>> +++ b/arch/powerpc/kvm/e500.c
> >>> @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void) {
> >>> 	int r, i;
> >>> 	unsigned long ivor[3];
> >>> +	unsigned long *handler = kvmppc_booke_handler_addr;
> >>
> >> /* Process remaining handlers above the generic first 16 */
> >> unsigned long *handler = &kvmppc_booke_handler_addr[16];
> >>
> >>> 	unsigned long max_ivor = 0;
> >>>
> >>> 	r = kvmppc_core_check_processor_compat();
> >>> 	if (r)
> >>> 		return r;
> >>>
> >>> +	handler += 16;
> >>> +
> >>> 	r = kvmppc_booke_init();
> >>> 	if (r)
> >>> 		return r;
> >>> @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
> >>> 	ivor[1] = mfspr(SPRN_IVOR33);
> >>> 	ivor[2] = mfspr(SPRN_IVOR34);
> >>> 	for (i = 0; i < 3; i++) {
> >>> -		if (ivor[i] > max_ivor)
> >>> -			max_ivor = ivor[i];
> >>> +		if (ivor[i] > ivor[max_ivor])
> >>> +			max_ivor = i;
> >>>
> >>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> >>> -		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
> >>> -		       kvmppc_handler_len);
> >>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
> >>
> >> handler_len = handler[i + 1] - handler[i];
> >> handler_end = max(handler_end, handler[i] + handler_len);
> >
> > Ok .
> >
> >>
> >>> 	}
> >>> 	flush_icache_range(kvmppc_booke_handlers,
> >>> -			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
> >>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> >>> +	                       handler[max_ivor + 1] - handler[max_ivor]);
> >>
> >> handler_end
> >
> > I do not get how this logic will work and simple. Can you please explain ?
> >
> > The end address here is calculated by IVOR offset (same as host ivor offset)
> where KVM handler[last] is copied in kvmppc_booke_handlers and length by
> handler[last + 1] - handler[last];
> 
> Hrm. You want to flush from [ kvmppc_booke_handlers ; kvmppc_booke_handlers +
> handlers_len ].
> 
> handlers_len = handler[0] - handler_end;

You do not know that handler[0] is placed at lowest memory or some other?

Thanks
-Bharat

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


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf Aug. 10, 2012, 10:57 a.m. UTC | #5
On 10.08.2012, at 12:41, Bhushan Bharat-R65777 wrote:

> 
> 
>> -----Original Message-----
>> From: kvm-owner@vger.kernel.org [mailto:kvm-owner@vger.kernel.org] On Behalf Of
>> Alexander Graf
>> Sent: Friday, August 10, 2012 2:49 PM
>> To: Bhushan Bharat-R65777
>> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org
>> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception types
>> 
>> 
>> On 10.08.2012, at 08:38, Bhushan Bharat-R65777 wrote:
>> 
>>> 
>>> 
>>>> -----Original Message-----
>>>> From: kvm-ppc-owner@vger.kernel.org
>>>> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Alexander Graf
>>>> Sent: Tuesday, August 07, 2012 4:16 PM
>>>> To: Bhushan Bharat-R65777
>>>> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; Bhushan
>>>> Bharat-R65777
>>>> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception
>>>> types
>>>> 
>>>> 
>>>> On 03.08.2012, at 09:08, Bharat Bhushan wrote:
>>>> 
>>>>> Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER) and
>>>>> all handlers are considered to be the same size. This will not be
>>>>> the case if we want to use different macros for different handlers.
>>>>> 
>>>>> This patch improves the kvmppc_booke_handler so that it can support
>>>>> different macros for different handlers.
>>>>> 
>>>>> Signed-off-by: Liu Yu <yu.liu@freescale.com>
>>>>> [bharat.bhushan@freescale.com: Substantial changes]
>>>>> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
>>>>> ---
>>>>> arch/powerpc/include/asm/kvm_ppc.h  |    2 -
>>>>> arch/powerpc/kvm/booke.c            |    9 ++++---
>>>>> arch/powerpc/kvm/booke.h            |    1 +
>>>>> arch/powerpc/kvm/booke_interrupts.S |   37 ++++++++++++++++++++++++++++++++-
>> -
>>>>> arch/powerpc/kvm/e500.c             |   13 +++++++----
>>>>> 5 files changed, 48 insertions(+), 14 deletions(-)
>>>>> 
>>>>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h
>>>> b/arch/powerpc/include/asm/kvm_ppc.h
>>>>> index 1438a5e..deb55bd 100644
>>>>> --- a/arch/powerpc/include/asm/kvm_ppc.h
>>>>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
>>>>> @@ -47,8 +47,6 @@ enum emulation_result {
>>>>> 
>>>>> extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu
>>>>> *vcpu); extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct
>>>>> kvm_vcpu *vcpu); -extern char kvmppc_handlers_start[]; -extern
>>>>> unsigned long kvmppc_handler_len; extern void
>>>>> kvmppc_handler_highmem(void);
>>>>> 
>>>>> extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); diff --git
>>>>> a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
>>>>> aebbb8b..1338233 100644
>>>>> --- a/arch/powerpc/kvm/booke.c
>>>>> +++ b/arch/powerpc/kvm/booke.c
>>>>> @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void) { #ifndef
>>>>> CONFIG_KVM_BOOKE_HV
>>>>> 	unsigned long ivor[16];
>>>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
>>>>> 	unsigned long max_ivor = 0;
>>>>> 	int i;
>>>>> 
>>>>> @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
>>>>> 
>>>>> 	for (i = 0; i < 16; i++) {
>>>>> 		if (ivor[i] > max_ivor)
>>>>> -			max_ivor = ivor[i];
>>>>> +			max_ivor = i;
>>>>> 
>>>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
>>>>> -		       kvmppc_handlers_start + i * kvmppc_handler_len,
>>>>> -		       kvmppc_handler_len);
>>>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
>>>>> 	}
>>>>> 	flush_icache_range(kvmppc_booke_handlers,
>>>>> -	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
>>>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
>>>>> +                               handler[max_ivor + 1] -
>>>>> +handler[max_ivor]);
>>>>> #endif /* !BOOKE_HV */
>>>>> 	return 0;
>>>>> }
>>>>> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
>>>>> index ba61974..de9e526 100644
>>>>> --- a/arch/powerpc/kvm/booke.h
>>>>> +++ b/arch/powerpc/kvm/booke.h
>>>>> @@ -65,6 +65,7 @@
>>>>> 			  (1 << BOOKE_IRQPRIO_CRITICAL))
>>>>> 
>>>>> extern unsigned long kvmppc_booke_handlers;
>>>>> +extern unsigned long kvmppc_booke_handler_addr[];
>>>>> 
>>>>> void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr); void
>>>>> kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr); diff
>>>>> --git a/arch/powerpc/kvm/booke_interrupts.S
>>>> b/arch/powerpc/kvm/booke_interrupts.S
>>>>> index bb46b32..3539805 100644
>>>>> --- a/arch/powerpc/kvm/booke_interrupts.S
>>>>> +++ b/arch/powerpc/kvm/booke_interrupts.S
>>>>> @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
>>>>> 	bctr
>>>>> .endm
>>>>> 
>>>>> +.macro KVM_HANDLER_ADDR ivor_nr
>>>>> +	.long	kvmppc_handler_\ivor_nr
>>>>> +.endm
>>>>> +
>>>>> +.macro KVM_HANDLER_END
>>>>> +	.long	kvmppc_handlers_end
>>>>> +.endm
>>>>> +
>>>>> _GLOBAL(kvmppc_handlers_start)
>>>>> KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT
>>>>> SPRN_CSRR0 KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK
>>>>> SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0 @@ -93,9 +101,7 @@ KVM_HANDLER
>>>>> BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT
>>>> SPRN_CSRR0
>>>>> KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0
>>>>> SPRN_SRR0 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA
>>>>> SPRN_SPRG_RSCRATCH0 SPRN_SRR0 KVM_HANDLER
>>>>> BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
>>>>> -
>>>>> -_GLOBAL(kvmppc_handler_len)
>>>>> -	.long kvmppc_handler_1 - kvmppc_handler_0
>>>>> +_GLOBAL(kvmppc_handlers_end)
>>>>> 
>>>>> /* Registers:
>>>>> *  SPRG_SCRATCH0: guest r4
>>>>> @@ -463,6 +469,31 @@ lightweight_exit:
>>>>> 	lwz	r4, VCPU_GPR(R4)(r4)
>>>>> 	rfi
>>>>> 
>>>>> +	.data
>>>>> +	.align	4
>>>>> +	.globl	kvmppc_booke_handler_addr
>>>>> +kvmppc_booke_handler_addr:
>>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_MACHINE_CHECK KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_DATA_STORAGE KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_INST_STORAGE KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_EXTERNAL KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
>>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_FP_UNAVAIL KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
>>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_DECREMENTER KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
>>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_DTLB_MISS KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_ITLB_MISS KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
>>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_SPE_FP_DATA KVM_HANDLER_ADDR
>>>>> +BOOKE_INTERRUPT_SPE_FP_ROUND KVM_HANDLER_END /*Always keep this in
>>>>> +end*/
>>>>> +
>>>>> #ifdef CONFIG_SPE
>>>>> _GLOBAL(kvmppc_save_guest_spe)
>>>>> 	cmpi	0,r3,0
>>>>> diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index
>>>>> b479ed7..cb7a5e7 100644
>>>>> --- a/arch/powerpc/kvm/e500.c
>>>>> +++ b/arch/powerpc/kvm/e500.c
>>>>> @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void) {
>>>>> 	int r, i;
>>>>> 	unsigned long ivor[3];
>>>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
>>>> 
>>>> /* Process remaining handlers above the generic first 16 */
>>>> unsigned long *handler = &kvmppc_booke_handler_addr[16];
>>>> 
>>>>> 	unsigned long max_ivor = 0;
>>>>> 
>>>>> 	r = kvmppc_core_check_processor_compat();
>>>>> 	if (r)
>>>>> 		return r;
>>>>> 
>>>>> +	handler += 16;
>>>>> +
>>>>> 	r = kvmppc_booke_init();
>>>>> 	if (r)
>>>>> 		return r;
>>>>> @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
>>>>> 	ivor[1] = mfspr(SPRN_IVOR33);
>>>>> 	ivor[2] = mfspr(SPRN_IVOR34);
>>>>> 	for (i = 0; i < 3; i++) {
>>>>> -		if (ivor[i] > max_ivor)
>>>>> -			max_ivor = ivor[i];
>>>>> +		if (ivor[i] > ivor[max_ivor])
>>>>> +			max_ivor = i;
>>>>> 
>>>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
>>>>> -		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
>>>>> -		       kvmppc_handler_len);
>>>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
>>>> 
>>>> handler_len = handler[i + 1] - handler[i];
>>>> handler_end = max(handler_end, handler[i] + handler_len);
>>> 
>>> Ok .
>>> 
>>>> 
>>>>> 	}
>>>>> 	flush_icache_range(kvmppc_booke_handlers,
>>>>> -			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
>>>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
>>>>> +	                       handler[max_ivor + 1] - handler[max_ivor]);
>>>> 
>>>> handler_end
>>> 
>>> I do not get how this logic will work and simple. Can you please explain ?
>>> 
>>> The end address here is calculated by IVOR offset (same as host ivor offset)
>> where KVM handler[last] is copied in kvmppc_booke_handlers and length by
>> handler[last + 1] - handler[last];
>> 
>> Hrm. You want to flush from [ kvmppc_booke_handlers ; kvmppc_booke_handlers +
>> handlers_len ].
>> 
>> handlers_len = handler[0] - handler_end;
> 
> You do not know that handler[0] is placed at lowest memory or some other?

I'm mostly concerned about readability here. The icache flush call should make it obvious what we are flushing, without having to trace 5 different variables on their semantics.


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bharat Bhushan Aug. 10, 2012, 10:59 a.m. UTC | #6
> -----Original Message-----
> From: Alexander Graf [mailto:agraf@suse.de]
> Sent: Friday, August 10, 2012 4:27 PM
> To: Bhushan Bharat-R65777
> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org
> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception types
> 
> 
> On 10.08.2012, at 12:41, Bhushan Bharat-R65777 wrote:
> 
> >
> >
> >> -----Original Message-----
> >> From: kvm-owner@vger.kernel.org [mailto:kvm-owner@vger.kernel.org] On
> >> Behalf Of Alexander Graf
> >> Sent: Friday, August 10, 2012 2:49 PM
> >> To: Bhushan Bharat-R65777
> >> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org
> >> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception
> >> types
> >>
> >>
> >> On 10.08.2012, at 08:38, Bhushan Bharat-R65777 wrote:
> >>
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: kvm-ppc-owner@vger.kernel.org
> >>>> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Alexander Graf
> >>>> Sent: Tuesday, August 07, 2012 4:16 PM
> >>>> To: Bhushan Bharat-R65777
> >>>> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; Bhushan
> >>>> Bharat-R65777
> >>>> Subject: Re: [PATCH 2/3] KVM: PPC: booke: Allow multiple exception
> >>>> types
> >>>>
> >>>>
> >>>> On 03.08.2012, at 09:08, Bharat Bhushan wrote:
> >>>>
> >>>>> Current kvmppc_booke_handlers uses the same macro (KVM_HANDLER)
> >>>>> and all handlers are considered to be the same size. This will not
> >>>>> be the case if we want to use different macros for different handlers.
> >>>>>
> >>>>> This patch improves the kvmppc_booke_handler so that it can
> >>>>> support different macros for different handlers.
> >>>>>
> >>>>> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> >>>>> [bharat.bhushan@freescale.com: Substantial changes]
> >>>>> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> >>>>> ---
> >>>>> arch/powerpc/include/asm/kvm_ppc.h  |    2 -
> >>>>> arch/powerpc/kvm/booke.c            |    9 ++++---
> >>>>> arch/powerpc/kvm/booke.h            |    1 +
> >>>>> arch/powerpc/kvm/booke_interrupts.S |   37
> ++++++++++++++++++++++++++++++++-
> >> -
> >>>>> arch/powerpc/kvm/e500.c             |   13 +++++++----
> >>>>> 5 files changed, 48 insertions(+), 14 deletions(-)
> >>>>>
> >>>>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h
> >>>> b/arch/powerpc/include/asm/kvm_ppc.h
> >>>>> index 1438a5e..deb55bd 100644
> >>>>> --- a/arch/powerpc/include/asm/kvm_ppc.h
> >>>>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> >>>>> @@ -47,8 +47,6 @@ enum emulation_result {
> >>>>>
> >>>>> extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct
> >>>>> kvm_vcpu *vcpu); extern int __kvmppc_vcpu_run(struct kvm_run
> >>>>> *kvm_run, struct kvm_vcpu *vcpu); -extern char
> >>>>> kvmppc_handlers_start[]; -extern unsigned long kvmppc_handler_len;
> >>>>> extern void kvmppc_handler_highmem(void);
> >>>>>
> >>>>> extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); diff --git
> >>>>> a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
> >>>>> aebbb8b..1338233 100644
> >>>>> --- a/arch/powerpc/kvm/booke.c
> >>>>> +++ b/arch/powerpc/kvm/booke.c
> >>>>> @@ -1541,6 +1541,7 @@ int __init kvmppc_booke_init(void) { #ifndef
> >>>>> CONFIG_KVM_BOOKE_HV
> >>>>> 	unsigned long ivor[16];
> >>>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
> >>>>> 	unsigned long max_ivor = 0;
> >>>>> 	int i;
> >>>>>
> >>>>> @@ -1574,14 +1575,14 @@ int __init kvmppc_booke_init(void)
> >>>>>
> >>>>> 	for (i = 0; i < 16; i++) {
> >>>>> 		if (ivor[i] > max_ivor)
> >>>>> -			max_ivor = ivor[i];
> >>>>> +			max_ivor = i;
> >>>>>
> >>>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> >>>>> -		       kvmppc_handlers_start + i * kvmppc_handler_len,
> >>>>> -		       kvmppc_handler_len);
> >>>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
> >>>>> 	}
> >>>>> 	flush_icache_range(kvmppc_booke_handlers,
> >>>>> -	                   kvmppc_booke_handlers + max_ivor +
> kvmppc_handler_len);
> >>>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> >>>>> +                               handler[max_ivor + 1] -
> >>>>> +handler[max_ivor]);
> >>>>> #endif /* !BOOKE_HV */
> >>>>> 	return 0;
> >>>>> }
> >>>>> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> >>>>> index ba61974..de9e526 100644
> >>>>> --- a/arch/powerpc/kvm/booke.h
> >>>>> +++ b/arch/powerpc/kvm/booke.h
> >>>>> @@ -65,6 +65,7 @@
> >>>>> 			  (1 << BOOKE_IRQPRIO_CRITICAL))
> >>>>>
> >>>>> extern unsigned long kvmppc_booke_handlers;
> >>>>> +extern unsigned long kvmppc_booke_handler_addr[];
> >>>>>
> >>>>> void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr); void
> >>>>> kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr); diff
> >>>>> --git a/arch/powerpc/kvm/booke_interrupts.S
> >>>> b/arch/powerpc/kvm/booke_interrupts.S
> >>>>> index bb46b32..3539805 100644
> >>>>> --- a/arch/powerpc/kvm/booke_interrupts.S
> >>>>> +++ b/arch/powerpc/kvm/booke_interrupts.S
> >>>>> @@ -73,6 +73,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
> >>>>> 	bctr
> >>>>> .endm
> >>>>>
> >>>>> +.macro KVM_HANDLER_ADDR ivor_nr
> >>>>> +	.long	kvmppc_handler_\ivor_nr
> >>>>> +.endm
> >>>>> +
> >>>>> +.macro KVM_HANDLER_END
> >>>>> +	.long	kvmppc_handlers_end
> >>>>> +.endm
> >>>>> +
> >>>>> _GLOBAL(kvmppc_handlers_start)
> >>>>> KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT
> >>>>> SPRN_CSRR0 KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK
> >>>>> SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0 @@ -93,9 +101,7 @@ KVM_HANDLER
> >>>>> BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT
> >>>> SPRN_CSRR0
> >>>>> KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0
> >>>>> SPRN_SRR0 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA
> >>>>> SPRN_SPRG_RSCRATCH0 SPRN_SRR0 KVM_HANDLER
> >>>>> BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
> >>>>> -
> >>>>> -_GLOBAL(kvmppc_handler_len)
> >>>>> -	.long kvmppc_handler_1 - kvmppc_handler_0
> >>>>> +_GLOBAL(kvmppc_handlers_end)
> >>>>>
> >>>>> /* Registers:
> >>>>> *  SPRG_SCRATCH0: guest r4
> >>>>> @@ -463,6 +469,31 @@ lightweight_exit:
> >>>>> 	lwz	r4, VCPU_GPR(R4)(r4)
> >>>>> 	rfi
> >>>>>
> >>>>> +	.data
> >>>>> +	.align	4
> >>>>> +	.globl	kvmppc_booke_handler_addr
> >>>>> +kvmppc_booke_handler_addr:
> >>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_MACHINE_CHECK KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_DATA_STORAGE KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_INST_STORAGE KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_EXTERNAL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_ALIGNMENT KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_PROGRAM KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_FP_UNAVAIL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_SYSCALL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_AP_UNAVAIL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_DECREMENTER KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
> >>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_DTLB_MISS KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_ITLB_MISS KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
> >>>>> +KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_SPE_FP_DATA KVM_HANDLER_ADDR
> >>>>> +BOOKE_INTERRUPT_SPE_FP_ROUND KVM_HANDLER_END /*Always keep this
> >>>>> +in end*/
> >>>>> +
> >>>>> #ifdef CONFIG_SPE
> >>>>> _GLOBAL(kvmppc_save_guest_spe)
> >>>>> 	cmpi	0,r3,0
> >>>>> diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
> >>>>> index
> >>>>> b479ed7..cb7a5e7 100644
> >>>>> --- a/arch/powerpc/kvm/e500.c
> >>>>> +++ b/arch/powerpc/kvm/e500.c
> >>>>> @@ -491,12 +491,15 @@ static int __init kvmppc_e500_init(void) {
> >>>>> 	int r, i;
> >>>>> 	unsigned long ivor[3];
> >>>>> +	unsigned long *handler = kvmppc_booke_handler_addr;
> >>>>
> >>>> /* Process remaining handlers above the generic first 16 */
> >>>> unsigned long *handler = &kvmppc_booke_handler_addr[16];
> >>>>
> >>>>> 	unsigned long max_ivor = 0;
> >>>>>
> >>>>> 	r = kvmppc_core_check_processor_compat();
> >>>>> 	if (r)
> >>>>> 		return r;
> >>>>>
> >>>>> +	handler += 16;
> >>>>> +
> >>>>> 	r = kvmppc_booke_init();
> >>>>> 	if (r)
> >>>>> 		return r;
> >>>>> @@ -506,15 +509,15 @@ static int __init kvmppc_e500_init(void)
> >>>>> 	ivor[1] = mfspr(SPRN_IVOR33);
> >>>>> 	ivor[2] = mfspr(SPRN_IVOR34);
> >>>>> 	for (i = 0; i < 3; i++) {
> >>>>> -		if (ivor[i] > max_ivor)
> >>>>> -			max_ivor = ivor[i];
> >>>>> +		if (ivor[i] > ivor[max_ivor])
> >>>>> +			max_ivor = i;
> >>>>>
> >>>>> 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
> >>>>> -		       kvmppc_handlers_start + (i + 16) *
> kvmppc_handler_len,
> >>>>> -		       kvmppc_handler_len);
> >>>>> +		       (void *)handler[i], handler[i + 1] - handler[i]);
> >>>>
> >>>> handler_len = handler[i + 1] - handler[i]; handler_end =
> >>>> max(handler_end, handler[i] + handler_len);
> >>>
> >>> Ok .
> >>>
> >>>>
> >>>>> 	}
> >>>>> 	flush_icache_range(kvmppc_booke_handlers,
> >>>>> -			kvmppc_booke_handlers + max_ivor +
> kvmppc_handler_len);
> >>>>> +	                   kvmppc_booke_handlers + ivor[max_ivor] +
> >>>>> +	                       handler[max_ivor + 1] -
> >>>>> +handler[max_ivor]);
> >>>>
> >>>> handler_end
> >>>
> >>> I do not get how this logic will work and simple. Can you please explain ?
> >>>
> >>> The end address here is calculated by IVOR offset (same as host ivor
> >>> offset)
> >> where KVM handler[last] is copied in kvmppc_booke_handlers and length
> >> by handler[last + 1] - handler[last];
> >>
> >> Hrm. You want to flush from [ kvmppc_booke_handlers ;
> >> kvmppc_booke_handlers + handlers_len ].
> >>
> >> handlers_len = handler[0] - handler_end;
> >
> > You do not know that handler[0] is placed at lowest memory or some other?
> 
> I'm mostly concerned about readability here. The icache flush call should make
> it obvious what we are flushing, without having to trace 5 different variables
> on their semantics.

I will try to remove some variable or at least add comment to support readability .

Thanks
-Bharat

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

Patch

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 1438a5e..deb55bd 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -47,8 +47,6 @@  enum emulation_result {
 
 extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
 extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
-extern char kvmppc_handlers_start[];
-extern unsigned long kvmppc_handler_len;
 extern void kvmppc_handler_highmem(void);
 
 extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index aebbb8b..1338233 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1541,6 +1541,7 @@  int __init kvmppc_booke_init(void)
 {
 #ifndef CONFIG_KVM_BOOKE_HV
 	unsigned long ivor[16];
+	unsigned long *handler = kvmppc_booke_handler_addr;
 	unsigned long max_ivor = 0;
 	int i;
 
@@ -1574,14 +1575,14 @@  int __init kvmppc_booke_init(void)
 
 	for (i = 0; i < 16; i++) {
 		if (ivor[i] > max_ivor)
-			max_ivor = ivor[i];
+			max_ivor = i;
 
 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
-		       kvmppc_handlers_start + i * kvmppc_handler_len,
-		       kvmppc_handler_len);
+		       (void *)handler[i], handler[i + 1] - handler[i]);
 	}
 	flush_icache_range(kvmppc_booke_handlers,
-	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
+	                   kvmppc_booke_handlers + ivor[max_ivor] +
+                               handler[max_ivor + 1] - handler[max_ivor]);
 #endif /* !BOOKE_HV */
 	return 0;
 }
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index ba61974..de9e526 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -65,6 +65,7 @@ 
 			  (1 << BOOKE_IRQPRIO_CRITICAL))
 
 extern unsigned long kvmppc_booke_handlers;
+extern unsigned long kvmppc_booke_handler_addr[];
 
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index bb46b32..3539805 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -73,6 +73,14 @@  _GLOBAL(kvmppc_handler_\ivor_nr)
 	bctr
 .endm
 
+.macro KVM_HANDLER_ADDR ivor_nr
+	.long	kvmppc_handler_\ivor_nr
+.endm
+
+.macro KVM_HANDLER_END
+	.long	kvmppc_handlers_end
+.endm
+
 _GLOBAL(kvmppc_handlers_start)
 KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK  SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
@@ -93,9 +101,7 @@  KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
-
-_GLOBAL(kvmppc_handler_len)
-	.long kvmppc_handler_1 - kvmppc_handler_0
+_GLOBAL(kvmppc_handlers_end)
 
 /* Registers:
  *  SPRG_SCRATCH0: guest r4
@@ -463,6 +469,31 @@  lightweight_exit:
 	lwz	r4, VCPU_GPR(R4)(r4)
 	rfi
 
+	.data
+	.align	4
+	.globl	kvmppc_booke_handler_addr
+kvmppc_booke_handler_addr:
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_MACHINE_CHECK
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_DATA_STORAGE
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_INST_STORAGE
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_EXTERNAL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_FP_UNAVAIL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_DECREMENTER
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_DTLB_MISS
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_ITLB_MISS
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_DATA
+KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_ROUND
+KVM_HANDLER_END /*Always keep this in end*/
+
 #ifdef CONFIG_SPE
 _GLOBAL(kvmppc_save_guest_spe)
 	cmpi	0,r3,0
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index b479ed7..cb7a5e7 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -491,12 +491,15 @@  static int __init kvmppc_e500_init(void)
 {
 	int r, i;
 	unsigned long ivor[3];
+	unsigned long *handler = kvmppc_booke_handler_addr;
 	unsigned long max_ivor = 0;
 
 	r = kvmppc_core_check_processor_compat();
 	if (r)
 		return r;
 
+	handler += 16;
+
 	r = kvmppc_booke_init();
 	if (r)
 		return r;
@@ -506,15 +509,15 @@  static int __init kvmppc_e500_init(void)
 	ivor[1] = mfspr(SPRN_IVOR33);
 	ivor[2] = mfspr(SPRN_IVOR34);
 	for (i = 0; i < 3; i++) {
-		if (ivor[i] > max_ivor)
-			max_ivor = ivor[i];
+		if (ivor[i] > ivor[max_ivor])
+			max_ivor = i;
 
 		memcpy((void *)kvmppc_booke_handlers + ivor[i],
-		       kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
-		       kvmppc_handler_len);
+		       (void *)handler[i], handler[i + 1] - handler[i]);
 	}
 	flush_icache_range(kvmppc_booke_handlers,
-			kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
+	                   kvmppc_booke_handlers + ivor[max_ivor] +
+	                       handler[max_ivor + 1] - handler[max_ivor]);
 
 	return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
 }