Patchwork [05/12] KVM: PPC: e500: Add emulation helper for getting instruction ea

login
register
mail settings
Submitter Mihai Caraman
Date Oct. 11, 2012, 4:13 p.m.
Message ID <1349972009-23027-6-git-send-email-mihai.caraman@freescale.com>
Download mbox | patch
Permalink /patch/190950/
State Not Applicable
Headers show

Comments

Mihai Caraman - Oct. 11, 2012, 4:13 p.m.
Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v1: use _t_ype instead of _t_arget _r_egister in tlbilx emulation.

 arch/powerpc/include/asm/kvm_ppc.h |   11 +++++++++++
 arch/powerpc/kvm/e500.h            |    6 +++---
 arch/powerpc/kvm/e500_emulate.c    |   15 ++++++++++-----
 arch/powerpc/kvm/e500_tlb.c        |   33 +++++++++++----------------------
 4 files changed, 35 insertions(+), 30 deletions(-)
Alexander Graf - Dec. 1, 2012, 1:28 p.m.
On 11.10.2012, at 18:13, Mihai Caraman wrote:

> Add emulation helper for getting instruction ea and refactor tlb instruction
> emulation to use it.
> 
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> v1: use _t_ype instead of _t_arget _r_egister in tlbilx emulation.
> 
> arch/powerpc/include/asm/kvm_ppc.h |   11 +++++++++++
> arch/powerpc/kvm/e500.h            |    6 +++---
> arch/powerpc/kvm/e500_emulate.c    |   15 ++++++++++-----
> arch/powerpc/kvm/e500_tlb.c        |   33 +++++++++++----------------------
> 4 files changed, 35 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> index 609cca3..a08e756 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -293,4 +293,15 @@ static inline void kvmppc_lazy_ee_enable(void)
> #endif
> }
> 
> +static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
> +{
> +	ulong ea;
> +
> +	ea = kvmppc_get_gpr(vcpu, rb);
> +	if (ra)
> +		ea += kvmppc_get_gpr(vcpu, ra);
> +
> +	return ea;
> +}
> +
> #endif /* __POWERPC_KVM_PPC_H__ */
> diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
> index d162286..32e98a7 100644
> --- a/arch/powerpc/kvm/e500.h
> +++ b/arch/powerpc/kvm/e500.h
> @@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
> 				ulong value);
> int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
> int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
> -int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
> -int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
> -int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
> +int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
> +int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
> +int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
> int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
> void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
> 
> diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
> index e04b0ef..3bf2486 100644
> --- a/arch/powerpc/kvm/e500_emulate.c
> +++ b/arch/powerpc/kvm/e500_emulate.c
> @@ -88,7 +88,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
> 	int emulated = EMULATE_DONE;
> 	int ra = get_ra(inst);
> 	int rb = get_rb(inst);
> -	int rt = get_rt(inst);

The function scope rt variable shouldn't hurt, as the compiler will be smart enough to only calculate it when it's actually used.

> +	gva_t ea;
> 
> 	switch (get_op(inst)) {
> 	case 31:
> @@ -113,15 +113,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
> 			break;
> 
> 		case XOP_TLBSX:
> -			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
> +			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
> +			emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
> 			break;
> 
> -		case XOP_TLBILX:
> -			emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
> +		case XOP_TLBILX: {
> +			int t = (inst >> 21) & 0x3;

so we can remove this

> +			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
> +			emulated = kvmppc_e500_emul_tlbilx(vcpu, t, ea);

and instead here pass rt & 3.

The rest of the patch looks fine, so I'll do the change while applying it.


Alex
Alexander Graf - Dec. 1, 2012, 1:32 p.m.
On 01.12.2012, at 14:28, Alexander Graf wrote:

> 
> On 11.10.2012, at 18:13, Mihai Caraman wrote:
> 
>> Add emulation helper for getting instruction ea and refactor tlb instruction
>> emulation to use it.
>> 
>> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
>> ---
>> v1: use _t_ype instead of _t_arget _r_egister in tlbilx emulation.
>> 
>> arch/powerpc/include/asm/kvm_ppc.h |   11 +++++++++++
>> arch/powerpc/kvm/e500.h            |    6 +++---
>> arch/powerpc/kvm/e500_emulate.c    |   15 ++++++++++-----
>> arch/powerpc/kvm/e500_tlb.c        |   33 +++++++++++----------------------
>> 4 files changed, 35 insertions(+), 30 deletions(-)
>> 
>> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
>> index 609cca3..a08e756 100644
>> --- a/arch/powerpc/include/asm/kvm_ppc.h
>> +++ b/arch/powerpc/include/asm/kvm_ppc.h
>> @@ -293,4 +293,15 @@ static inline void kvmppc_lazy_ee_enable(void)
>> #endif
>> }
>> 
>> +static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
>> +{
>> +	ulong ea;
>> +
>> +	ea = kvmppc_get_gpr(vcpu, rb);
>> +	if (ra)
>> +		ea += kvmppc_get_gpr(vcpu, ra);
>> +
>> +	return ea;
>> +}
>> +
>> #endif /* __POWERPC_KVM_PPC_H__ */
>> diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
>> index d162286..32e98a7 100644
>> --- a/arch/powerpc/kvm/e500.h
>> +++ b/arch/powerpc/kvm/e500.h
>> @@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
>> 				ulong value);
>> int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
>> int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
>> -int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
>> -int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
>> -int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
>> +int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
>> +int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
>> +int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
>> int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
>> void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
>> 
>> diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
>> index e04b0ef..3bf2486 100644
>> --- a/arch/powerpc/kvm/e500_emulate.c
>> +++ b/arch/powerpc/kvm/e500_emulate.c
>> @@ -88,7 +88,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
>> 	int emulated = EMULATE_DONE;
>> 	int ra = get_ra(inst);
>> 	int rb = get_rb(inst);
>> -	int rt = get_rt(inst);
> 
> The function scope rt variable shouldn't hurt, as the compiler will be smart enough to only calculate it when it's actually used.
> 
>> +	gva_t ea;
>> 
>> 	switch (get_op(inst)) {
>> 	case 31:
>> @@ -113,15 +113,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
>> 			break;
>> 
>> 		case XOP_TLBSX:
>> -			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
>> +			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
>> +			emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
>> 			break;
>> 
>> -		case XOP_TLBILX:
>> -			emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
>> +		case XOP_TLBILX: {
>> +			int t = (inst >> 21) & 0x3;
> 
> so we can remove this
> 
>> +			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
>> +			emulated = kvmppc_e500_emul_tlbilx(vcpu, t, ea);
> 
> and instead here pass rt & 3.
> 
> The rest of the patch looks fine, so I'll do the change while applying it.

Reading my old comment on the previous version, I realized that I was slightly too fuzzy in my wording. I meant to make the parameter that gets passed into the functions a variable of a different type (like you did). Calculating that one from rt is fine.


Alex

Patch

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 609cca3..a08e756 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -293,4 +293,15 @@  static inline void kvmppc_lazy_ee_enable(void)
 #endif
 }
 
+static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
+{
+	ulong ea;
+
+	ea = kvmppc_get_gpr(vcpu, rb);
+	if (ra)
+		ea += kvmppc_get_gpr(vcpu, ra);
+
+	return ea;
+}
+
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index d162286..32e98a7 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -129,9 +129,9 @@  int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
 				ulong value);
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
 int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
 
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index e04b0ef..3bf2486 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -88,7 +88,7 @@  int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	int emulated = EMULATE_DONE;
 	int ra = get_ra(inst);
 	int rb = get_rb(inst);
-	int rt = get_rt(inst);
+	gva_t ea;
 
 	switch (get_op(inst)) {
 	case 31:
@@ -113,15 +113,20 @@  int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			break;
 
 		case XOP_TLBSX:
-			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
 			break;
 
-		case XOP_TLBILX:
-			emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
+		case XOP_TLBILX: {
+			int t = (inst >> 21) & 0x3;
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbilx(vcpu, t, ea);
 			break;
+		}
 
 		case XOP_TLBIVAX:
-			emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+			ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+			emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
 			break;
 
 		default:
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 23b3de6..b5a188a 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -689,14 +689,11 @@  int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
 	return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	unsigned int ia;
 	int esel, tlbsel;
-	gva_t ea;
-
-	ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
 
 	ia = (ea >> 2) & 0x1;
 
@@ -723,7 +720,7 @@  int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 }
 
 static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
-		       int pid, int rt)
+		       int pid, int type)
 {
 	struct kvm_book3e_206_tlb_entry *tlbe;
 	int tid, esel;
@@ -732,7 +729,7 @@  static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 	for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
 		tlbe = get_entry(vcpu_e500, tlbsel, esel);
 		tid = get_tlb_tid(tlbe);
-		if (rt == 0 || tid == pid) {
+		if (type == 0 || tid == pid) {
 			inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
 		}
@@ -740,14 +737,9 @@  static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 }
 
 static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
-		       int ra, int rb)
+		       gva_t ea)
 {
 	int tlbsel, esel;
-	gva_t ea;
-
-	ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
-	if (ra)
-		ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
@@ -759,16 +751,16 @@  static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
 	}
 }
 
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	int pid = get_cur_spid(vcpu);
 
-	if (rt == 0 || rt == 1) {
-		tlbilx_all(vcpu_e500, 0, pid, rt);
-		tlbilx_all(vcpu_e500, 1, pid, rt);
-	} else if (rt == 3) {
-		tlbilx_one(vcpu_e500, pid, ra, rb);
+	if (type == 0 || type == 1) {
+		tlbilx_all(vcpu_e500, 0, pid, type);
+		tlbilx_all(vcpu_e500, 1, pid, type);
+	} else if (type == 3) {
+		tlbilx_one(vcpu_e500, pid, ea);
 	}
 
 	return EMULATE_DONE;
@@ -793,16 +785,13 @@  int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 	return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	int as = !!get_cur_sas(vcpu);
 	unsigned int pid = get_cur_spid(vcpu);
 	int esel, tlbsel;
 	struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
-	gva_t ea;
-
-	ea = kvmppc_get_gpr(vcpu, rb);
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);