diff mbox series

[v3] powerpc/sstep: Check ISA 3.0 instruction validity before emulation

Message ID 161114113785.214433.12934683302522893921.stgit@thinktux.local (mailing list archive)
State Superseded
Headers show
Series [v3] powerpc/sstep: Check ISA 3.0 instruction validity before emulation | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch powerpc/merge (41d8cb7ece7c81e4eb897ed7ec7d3c3d72fd0af4)
snowpatch_ozlabs/build-ppc64le success Build succeeded
snowpatch_ozlabs/build-ppc64be success Build succeeded
snowpatch_ozlabs/build-ppc64e success Build succeeded
snowpatch_ozlabs/build-pmac32 success Build succeeded
snowpatch_ozlabs/checkpatch warning total: 0 errors, 0 warnings, 1 checks, 173 lines checked
snowpatch_ozlabs/needsstable success Patch has no Fixes tags

Commit Message

Ananth N Mavinakayanahalli Jan. 20, 2021, 11:13 a.m. UTC
We currently unconditionally try to emulate newer instructions on older
Power versions that could cause issues. Gate it.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
---

[v3] Addressed Naveen's comments on scv and addpcis
[v2] Fixed description

 arch/powerpc/lib/sstep.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

Comments

Naveen N. Rao Jan. 20, 2021, 1:50 p.m. UTC | #1
On 2021/01/20 04:43PM, Ananth N Mavinakayanahalli wrote:
> We currently unconditionally try to emulate newer instructions on older
> Power versions that could cause issues. Gate it.
> 
> Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
> ---
> 
> [v3] Addressed Naveen's comments on scv and addpcis
> [v2] Fixed description
> 
>  arch/powerpc/lib/sstep.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 44 insertions(+), 2 deletions(-)

Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>

- Naveen
Michal Suchánek Jan. 20, 2021, 4:09 p.m. UTC | #2
On Wed, Jan 20, 2021 at 04:43:14PM +0530, Ananth N Mavinakayanahalli wrote:
> We currently unconditionally try to emulate newer instructions on older
> Power versions that could cause issues. Gate it.
Fixes: 350779a29f11 ("powerpc: Handle most loads and stores in instruction emulation code")

There are more that would apply but most of the checks land in code
added by the above.

Thanks

Michal
> 
> Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
> ---
> 
> [v3] Addressed Naveen's comments on scv and addpcis
> [v2] Fixed description
> 
>  arch/powerpc/lib/sstep.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 44 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index bf7a7d62ae8b..5a425a4a1d88 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1304,9 +1304,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  		if ((word & 0xfe2) == 2)
>  			op->type = SYSCALL;
>  		else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
> -				(word & 0xfe3) == 1)
> +				(word & 0xfe3) == 1) {	/* scv */
>  			op->type = SYSCALL_VECTORED_0;
> -		else
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
> +		} else
>  			op->type = UNKNOWN;
>  		return 0;
>  #endif
> @@ -1530,6 +1532,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  	case 19:
>  		if (((word >> 1) & 0x1f) == 2) {
>  			/* addpcis */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			imm = (short) (word & 0xffc1);	/* d0 + d2 fields */
>  			imm |= (word >> 15) & 0x3e;	/* d1 field */
>  			op->val = regs->nip + (imm << 16) + 4;
> @@ -2439,6 +2443,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 268:	/* lxvx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 16);
>  			op->element_size = 16;
> @@ -2448,6 +2454,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  		case 269:	/* lxvl */
>  		case 301: {	/* lxvll */
>  			int nb;
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->ea = ra ? regs->gpr[ra] : 0;
>  			nb = regs->gpr[rb] & 0xff;
> @@ -2475,6 +2483,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 364:	/* lxvwsx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 4);
>  			op->element_size = 4;
> @@ -2482,6 +2492,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 396:	/* stxvx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(STORE_VSX, 0, 16);
>  			op->element_size = 16;
> @@ -2491,6 +2503,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  		case 397:	/* stxvl */
>  		case 429: {	/* stxvll */
>  			int nb;
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->ea = ra ? regs->gpr[ra] : 0;
>  			nb = regs->gpr[rb] & 0xff;
> @@ -2542,6 +2556,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 781:	/* lxsibzx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 1);
>  			op->element_size = 8;
> @@ -2549,6 +2565,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 812:	/* lxvh8x */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 16);
>  			op->element_size = 2;
> @@ -2556,6 +2574,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 813:	/* lxsihzx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 2);
>  			op->element_size = 8;
> @@ -2569,6 +2589,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 876:	/* lxvb16x */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(LOAD_VSX, 0, 16);
>  			op->element_size = 1;
> @@ -2582,6 +2604,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 909:	/* stxsibx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(STORE_VSX, 0, 1);
>  			op->element_size = 8;
> @@ -2589,6 +2613,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 940:	/* stxvh8x */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(STORE_VSX, 0, 16);
>  			op->element_size = 2;
> @@ -2596,6 +2622,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 941:	/* stxsihx */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(STORE_VSX, 0, 2);
>  			op->element_size = 8;
> @@ -2609,6 +2637,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 1004:	/* stxvb16x */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd | ((word & 1) << 5);
>  			op->type = MKOP(STORE_VSX, 0, 16);
>  			op->element_size = 1;
> @@ -2717,12 +2747,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			op->type = MKOP(LOAD_FP, 0, 16);
>  			break;
>  		case 2:		/* lxsd */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd + 32;
>  			op->type = MKOP(LOAD_VSX, 0, 8);
>  			op->element_size = 8;
>  			op->vsx_flags = VSX_CHECK_VEC;
>  			break;
>  		case 3:		/* lxssp */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->reg = rd + 32;
>  			op->type = MKOP(LOAD_VSX, 0, 4);
>  			op->element_size = 8;
> @@ -2775,6 +2809,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 1:		/* lxv */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->ea = dqform_ea(word, regs);
>  			if (word & 8)
>  				op->reg = rd + 32;
> @@ -2785,6 +2821,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  
>  		case 2:		/* stxsd with LSB of DS field = 0 */
>  		case 6:		/* stxsd with LSB of DS field = 1 */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->ea = dsform_ea(word, regs);
>  			op->reg = rd + 32;
>  			op->type = MKOP(STORE_VSX, 0, 8);
> @@ -2794,6 +2832,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  
>  		case 3:		/* stxssp with LSB of DS field = 0 */
>  		case 7:		/* stxssp with LSB of DS field = 1 */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->ea = dsform_ea(word, regs);
>  			op->reg = rd + 32;
>  			op->type = MKOP(STORE_VSX, 0, 4);
> @@ -2802,6 +2842,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			break;
>  
>  		case 5:		/* stxv */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
>  			op->ea = dqform_ea(word, regs);
>  			if (word & 8)
>  				op->reg = rd + 32;
> 
>
Sandipan Das Jan. 21, 2021, 4:36 a.m. UTC | #3
On 20/01/21 4:43 pm, Ananth N Mavinakayanahalli wrote:
> We currently unconditionally try to emulate newer instructions on older
> Power versions that could cause issues. Gate it.
> 
> Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
> ---
> 
> [v3] Addressed Naveen's comments on scv and addpcis
> [v2] Fixed description
> 
>  arch/powerpc/lib/sstep.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 44 insertions(+), 2 deletions(-)
> 

Reviewed-by: Sandipan Das <sandipan@linux.ibm.com>
diff mbox series

Patch

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index bf7a7d62ae8b..5a425a4a1d88 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1304,9 +1304,11 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 		if ((word & 0xfe2) == 2)
 			op->type = SYSCALL;
 		else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
-				(word & 0xfe3) == 1)
+				(word & 0xfe3) == 1) {	/* scv */
 			op->type = SYSCALL_VECTORED_0;
-		else
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
+		} else
 			op->type = UNKNOWN;
 		return 0;
 #endif
@@ -1530,6 +1532,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 	case 19:
 		if (((word >> 1) & 0x1f) == 2) {
 			/* addpcis */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			imm = (short) (word & 0xffc1);	/* d0 + d2 fields */
 			imm |= (word >> 15) & 0x3e;	/* d1 field */
 			op->val = regs->nip + (imm << 16) + 4;
@@ -2439,6 +2443,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 268:	/* lxvx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 16);
 			op->element_size = 16;
@@ -2448,6 +2454,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 		case 269:	/* lxvl */
 		case 301: {	/* lxvll */
 			int nb;
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->ea = ra ? regs->gpr[ra] : 0;
 			nb = regs->gpr[rb] & 0xff;
@@ -2475,6 +2483,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 364:	/* lxvwsx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 4);
 			op->element_size = 4;
@@ -2482,6 +2492,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 396:	/* stxvx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(STORE_VSX, 0, 16);
 			op->element_size = 16;
@@ -2491,6 +2503,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 		case 397:	/* stxvl */
 		case 429: {	/* stxvll */
 			int nb;
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->ea = ra ? regs->gpr[ra] : 0;
 			nb = regs->gpr[rb] & 0xff;
@@ -2542,6 +2556,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 781:	/* lxsibzx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 1);
 			op->element_size = 8;
@@ -2549,6 +2565,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 812:	/* lxvh8x */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 16);
 			op->element_size = 2;
@@ -2556,6 +2574,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 813:	/* lxsihzx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 2);
 			op->element_size = 8;
@@ -2569,6 +2589,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 876:	/* lxvb16x */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(LOAD_VSX, 0, 16);
 			op->element_size = 1;
@@ -2582,6 +2604,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 909:	/* stxsibx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(STORE_VSX, 0, 1);
 			op->element_size = 8;
@@ -2589,6 +2613,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 940:	/* stxvh8x */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(STORE_VSX, 0, 16);
 			op->element_size = 2;
@@ -2596,6 +2622,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 941:	/* stxsihx */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(STORE_VSX, 0, 2);
 			op->element_size = 8;
@@ -2609,6 +2637,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 1004:	/* stxvb16x */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd | ((word & 1) << 5);
 			op->type = MKOP(STORE_VSX, 0, 16);
 			op->element_size = 1;
@@ -2717,12 +2747,16 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			op->type = MKOP(LOAD_FP, 0, 16);
 			break;
 		case 2:		/* lxsd */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd + 32;
 			op->type = MKOP(LOAD_VSX, 0, 8);
 			op->element_size = 8;
 			op->vsx_flags = VSX_CHECK_VEC;
 			break;
 		case 3:		/* lxssp */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->reg = rd + 32;
 			op->type = MKOP(LOAD_VSX, 0, 4);
 			op->element_size = 8;
@@ -2775,6 +2809,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 1:		/* lxv */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->ea = dqform_ea(word, regs);
 			if (word & 8)
 				op->reg = rd + 32;
@@ -2785,6 +2821,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
 		case 2:		/* stxsd with LSB of DS field = 0 */
 		case 6:		/* stxsd with LSB of DS field = 1 */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->ea = dsform_ea(word, regs);
 			op->reg = rd + 32;
 			op->type = MKOP(STORE_VSX, 0, 8);
@@ -2794,6 +2832,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
 		case 3:		/* stxssp with LSB of DS field = 0 */
 		case 7:		/* stxssp with LSB of DS field = 1 */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->ea = dsform_ea(word, regs);
 			op->reg = rd + 32;
 			op->type = MKOP(STORE_VSX, 0, 4);
@@ -2802,6 +2842,8 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			break;
 
 		case 5:		/* stxv */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
 			op->ea = dqform_ea(word, regs);
 			if (word & 8)
 				op->reg = rd + 32;