We currently unconditionally try to emulate newer instructions on older
Power versions that could cause issues. Gate it.

Signed-off-by: Ananth N Mavinakayanahalli <ana...@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;


Reply via email to