提交 e4c0a635 编写于 作者: A Ananth N Mavinakayanahalli 提交者: Zheng Zengkai

powerpc/sstep: Check instruction validity against ISA version before emulation

stable inclusion
from stable-5.10.21
commit 20d323c8cf5730eb1693ef3fcf0919b35a20e6ad
bugzilla: 50609

--------------------------------

commit 8813ff49 upstream.

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

Fixes: 350779a2 ("powerpc: Handle most loads and stores in instruction emulation code")
Signed-off-by: NAnanth N Mavinakayanahalli <ananth@linux.ibm.com>
Signed-off-by: NMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/161157995977.64773.13794501093457185080.stgit@thinktux.local
[Dropped a few missing hunks for the backport to v5.10]
Signed-off-by: NNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 2388b274
...@@ -1241,9 +1241,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1241,9 +1241,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
if ((word & 0xfe2) == 2) if ((word & 0xfe2) == 2)
op->type = SYSCALL; op->type = SYSCALL;
else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
(word & 0xfe3) == 1) (word & 0xfe3) == 1) { /* scv */
op->type = SYSCALL_VECTORED_0; op->type = SYSCALL_VECTORED_0;
else if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
} else
op->type = UNKNOWN; op->type = UNKNOWN;
return 0; return 0;
#endif #endif
...@@ -1347,7 +1349,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1347,7 +1349,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__ #ifdef __powerpc64__
case 1: case 1:
if (!cpu_has_feature(CPU_FTR_ARCH_31)) if (!cpu_has_feature(CPU_FTR_ARCH_31))
return -1; goto unknown_opcode;
prefix_r = GET_PREFIX_R(word); prefix_r = GET_PREFIX_R(word);
ra = GET_PREFIX_RA(suffix); ra = GET_PREFIX_RA(suffix);
...@@ -1381,7 +1383,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1381,7 +1383,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__ #ifdef __powerpc64__
case 4: case 4:
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
switch (word & 0x3f) { switch (word & 0x3f) {
case 48: /* maddhd */ case 48: /* maddhd */
...@@ -1467,6 +1469,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1467,6 +1469,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 19: case 19:
if (((word >> 1) & 0x1f) == 2) { if (((word >> 1) & 0x1f) == 2) {
/* addpcis */ /* addpcis */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
imm = (short) (word & 0xffc1); /* d0 + d2 fields */ imm = (short) (word & 0xffc1); /* d0 + d2 fields */
imm |= (word >> 15) & 0x3e; /* d1 field */ imm |= (word >> 15) & 0x3e; /* d1 field */
op->val = regs->nip + (imm << 16) + 4; op->val = regs->nip + (imm << 16) + 4;
...@@ -1779,7 +1783,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1779,7 +1783,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__ #ifdef __powerpc64__
case 265: /* modud */ case 265: /* modud */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
op->val = regs->gpr[ra] % regs->gpr[rb]; op->val = regs->gpr[ra] % regs->gpr[rb];
goto compute_done; goto compute_done;
#endif #endif
...@@ -1789,7 +1793,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1789,7 +1793,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 267: /* moduw */ case 267: /* moduw */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
op->val = (unsigned int) regs->gpr[ra] % op->val = (unsigned int) regs->gpr[ra] %
(unsigned int) regs->gpr[rb]; (unsigned int) regs->gpr[rb];
goto compute_done; goto compute_done;
...@@ -1826,7 +1830,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1826,7 +1830,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#endif #endif
case 755: /* darn */ case 755: /* darn */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
switch (ra & 0x3) { switch (ra & 0x3) {
case 0: case 0:
/* 32-bit conditioned */ /* 32-bit conditioned */
...@@ -1848,14 +1852,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1848,14 +1852,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__ #ifdef __powerpc64__
case 777: /* modsd */ case 777: /* modsd */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
op->val = (long int) regs->gpr[ra] % op->val = (long int) regs->gpr[ra] %
(long int) regs->gpr[rb]; (long int) regs->gpr[rb];
goto compute_done; goto compute_done;
#endif #endif
case 779: /* modsw */ case 779: /* modsw */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
op->val = (int) regs->gpr[ra] % op->val = (int) regs->gpr[ra] %
(int) regs->gpr[rb]; (int) regs->gpr[rb];
goto compute_done; goto compute_done;
...@@ -1932,14 +1936,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1932,14 +1936,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#endif #endif
case 538: /* cnttzw */ case 538: /* cnttzw */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
val = (unsigned int) regs->gpr[rd]; val = (unsigned int) regs->gpr[rd];
op->val = (val ? __builtin_ctz(val) : 32); op->val = (val ? __builtin_ctz(val) : 32);
goto logical_done; goto logical_done;
#ifdef __powerpc64__ #ifdef __powerpc64__
case 570: /* cnttzd */ case 570: /* cnttzd */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
val = regs->gpr[rd]; val = regs->gpr[rd];
op->val = (val ? __builtin_ctzl(val) : 64); op->val = (val ? __builtin_ctzl(val) : 64);
goto logical_done; goto logical_done;
...@@ -2049,7 +2053,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2049,7 +2053,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 890: /* extswsli with sh_5 = 0 */ case 890: /* extswsli with sh_5 = 0 */
case 891: /* extswsli with sh_5 = 1 */ case 891: /* extswsli with sh_5 = 1 */
if (!cpu_has_feature(CPU_FTR_ARCH_300)) if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1; goto unknown_opcode;
op->type = COMPUTE + SETREG; op->type = COMPUTE + SETREG;
sh = rb | ((word & 2) << 4); sh = rb | ((word & 2) << 4);
val = (signed int) regs->gpr[rd]; val = (signed int) regs->gpr[rd];
...@@ -2376,6 +2380,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2376,6 +2380,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 268: /* lxvx */ case 268: /* lxvx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16); op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 16; op->element_size = 16;
...@@ -2385,6 +2391,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2385,6 +2391,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 269: /* lxvl */ case 269: /* lxvl */
case 301: { /* lxvll */ case 301: { /* lxvll */
int nb; int nb;
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->ea = ra ? regs->gpr[ra] : 0; op->ea = ra ? regs->gpr[ra] : 0;
nb = regs->gpr[rb] & 0xff; nb = regs->gpr[rb] & 0xff;
...@@ -2404,6 +2412,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2404,6 +2412,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 364: /* lxvwsx */ case 364: /* lxvwsx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4); op->type = MKOP(LOAD_VSX, 0, 4);
op->element_size = 4; op->element_size = 4;
...@@ -2411,6 +2421,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2411,6 +2421,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 396: /* stxvx */ case 396: /* stxvx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16); op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 16; op->element_size = 16;
...@@ -2420,6 +2432,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2420,6 +2432,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 397: /* stxvl */ case 397: /* stxvl */
case 429: { /* stxvll */ case 429: { /* stxvll */
int nb; int nb;
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->ea = ra ? regs->gpr[ra] : 0; op->ea = ra ? regs->gpr[ra] : 0;
nb = regs->gpr[rb] & 0xff; nb = regs->gpr[rb] & 0xff;
...@@ -2464,6 +2478,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2464,6 +2478,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 781: /* lxsibzx */ case 781: /* lxsibzx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 1); op->type = MKOP(LOAD_VSX, 0, 1);
op->element_size = 8; op->element_size = 8;
...@@ -2471,6 +2487,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2471,6 +2487,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 812: /* lxvh8x */ case 812: /* lxvh8x */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16); op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 2; op->element_size = 2;
...@@ -2478,6 +2496,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2478,6 +2496,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 813: /* lxsihzx */ case 813: /* lxsihzx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 2); op->type = MKOP(LOAD_VSX, 0, 2);
op->element_size = 8; op->element_size = 8;
...@@ -2491,6 +2511,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2491,6 +2511,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 876: /* lxvb16x */ case 876: /* lxvb16x */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 16); op->type = MKOP(LOAD_VSX, 0, 16);
op->element_size = 1; op->element_size = 1;
...@@ -2504,6 +2526,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2504,6 +2526,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 909: /* stxsibx */ case 909: /* stxsibx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 1); op->type = MKOP(STORE_VSX, 0, 1);
op->element_size = 8; op->element_size = 8;
...@@ -2511,6 +2535,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2511,6 +2535,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 940: /* stxvh8x */ case 940: /* stxvh8x */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16); op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 2; op->element_size = 2;
...@@ -2518,6 +2544,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2518,6 +2544,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 941: /* stxsihx */ case 941: /* stxsihx */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 2); op->type = MKOP(STORE_VSX, 0, 2);
op->element_size = 8; op->element_size = 8;
...@@ -2531,6 +2559,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2531,6 +2559,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 1004: /* stxvb16x */ case 1004: /* stxvb16x */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd | ((word & 1) << 5); op->reg = rd | ((word & 1) << 5);
op->type = MKOP(STORE_VSX, 0, 16); op->type = MKOP(STORE_VSX, 0, 16);
op->element_size = 1; op->element_size = 1;
...@@ -2639,12 +2669,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2639,12 +2669,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
op->type = MKOP(LOAD_FP, 0, 16); op->type = MKOP(LOAD_FP, 0, 16);
break; break;
case 2: /* lxsd */ case 2: /* lxsd */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd + 32; op->reg = rd + 32;
op->type = MKOP(LOAD_VSX, 0, 8); op->type = MKOP(LOAD_VSX, 0, 8);
op->element_size = 8; op->element_size = 8;
op->vsx_flags = VSX_CHECK_VEC; op->vsx_flags = VSX_CHECK_VEC;
break; break;
case 3: /* lxssp */ case 3: /* lxssp */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->reg = rd + 32; op->reg = rd + 32;
op->type = MKOP(LOAD_VSX, 0, 4); op->type = MKOP(LOAD_VSX, 0, 4);
op->element_size = 8; op->element_size = 8;
...@@ -2681,6 +2715,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2681,6 +2715,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 1: /* lxv */ case 1: /* lxv */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->ea = dqform_ea(word, regs); op->ea = dqform_ea(word, regs);
if (word & 8) if (word & 8)
op->reg = rd + 32; op->reg = rd + 32;
...@@ -2691,6 +2727,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2691,6 +2727,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 2: /* stxsd with LSB of DS field = 0 */ case 2: /* stxsd with LSB of DS field = 0 */
case 6: /* stxsd with LSB of DS field = 1 */ case 6: /* stxsd with LSB of DS field = 1 */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->ea = dsform_ea(word, regs); op->ea = dsform_ea(word, regs);
op->reg = rd + 32; op->reg = rd + 32;
op->type = MKOP(STORE_VSX, 0, 8); op->type = MKOP(STORE_VSX, 0, 8);
...@@ -2700,6 +2738,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2700,6 +2738,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 3: /* stxssp with LSB of DS field = 0 */ case 3: /* stxssp with LSB of DS field = 0 */
case 7: /* stxssp with LSB of DS field = 1 */ case 7: /* stxssp with LSB of DS field = 1 */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->ea = dsform_ea(word, regs); op->ea = dsform_ea(word, regs);
op->reg = rd + 32; op->reg = rd + 32;
op->type = MKOP(STORE_VSX, 0, 4); op->type = MKOP(STORE_VSX, 0, 4);
...@@ -2708,6 +2748,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2708,6 +2748,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 5: /* stxv */ case 5: /* stxv */
if (!cpu_has_feature(CPU_FTR_ARCH_300))
goto unknown_opcode;
op->ea = dqform_ea(word, regs); op->ea = dqform_ea(word, regs);
if (word & 8) if (word & 8)
op->reg = rd + 32; op->reg = rd + 32;
...@@ -2737,7 +2779,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2737,7 +2779,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
case 1: /* Prefixed instructions */ case 1: /* Prefixed instructions */
if (!cpu_has_feature(CPU_FTR_ARCH_31)) if (!cpu_has_feature(CPU_FTR_ARCH_31))
return -1; goto unknown_opcode;
prefix_r = GET_PREFIX_R(word); prefix_r = GET_PREFIX_R(word);
ra = GET_PREFIX_RA(suffix); ra = GET_PREFIX_RA(suffix);
...@@ -2872,6 +2914,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -2872,6 +2914,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0; return 0;
unknown_opcode:
op->type = UNKNOWN;
return 0;
logical_done: logical_done:
if (word & 1) if (word & 1)
set_cr0(regs, op); set_cr0(regs, op);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册