Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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")
Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/161157995977.64773.13794501093457185080.stgit@thinktux.local

authored by

Ananth N Mavinakayanahalli and committed by
Michael Ellerman
8813ff49 4eeef098

+62 -16
+62 -16
arch/powerpc/lib/sstep.c
··· 1304 1304 if ((word & 0xfe2) == 2) 1305 1305 op->type = SYSCALL; 1306 1306 else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && 1307 - (word & 0xfe3) == 1) 1307 + (word & 0xfe3) == 1) { /* scv */ 1308 1308 op->type = SYSCALL_VECTORED_0; 1309 - else 1309 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1310 + goto unknown_opcode; 1311 + } else 1310 1312 op->type = UNKNOWN; 1311 1313 return 0; 1312 1314 #endif ··· 1412 1410 #ifdef __powerpc64__ 1413 1411 case 1: 1414 1412 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 1415 - return -1; 1413 + goto unknown_opcode; 1416 1414 1417 1415 prefix_r = GET_PREFIX_R(word); 1418 1416 ra = GET_PREFIX_RA(suffix); ··· 1446 1444 #ifdef __powerpc64__ 1447 1445 case 4: 1448 1446 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1449 - return -1; 1447 + goto unknown_opcode; 1450 1448 1451 1449 switch (word & 0x3f) { 1452 1450 case 48: /* maddhd */ ··· 1532 1530 case 19: 1533 1531 if (((word >> 1) & 0x1f) == 2) { 1534 1532 /* addpcis */ 1533 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1534 + goto unknown_opcode; 1535 1535 imm = (short) (word & 0xffc1); /* d0 + d2 fields */ 1536 1536 imm |= (word >> 15) & 0x3e; /* d1 field */ 1537 1537 op->val = regs->nip + (imm << 16) + 4; ··· 1846 1842 #ifdef __powerpc64__ 1847 1843 case 265: /* modud */ 1848 1844 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1849 - return -1; 1845 + goto unknown_opcode; 1850 1846 op->val = regs->gpr[ra] % regs->gpr[rb]; 1851 1847 goto compute_done; 1852 1848 #endif ··· 1856 1852 1857 1853 case 267: /* moduw */ 1858 1854 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1859 - return -1; 1855 + goto unknown_opcode; 1860 1856 op->val = (unsigned int) regs->gpr[ra] % 1861 1857 (unsigned int) regs->gpr[rb]; 1862 1858 goto compute_done; ··· 1893 1889 #endif 1894 1890 case 755: /* darn */ 1895 1891 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1896 - return -1; 1892 + goto unknown_opcode; 1897 1893 switch (ra & 0x3) { 1898 1894 case 0: 1899 1895 /* 32-bit conditioned */ ··· 1915 1911 #ifdef __powerpc64__ 1916 1912 case 777: /* modsd */ 1917 1913 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1918 - return -1; 1914 + goto unknown_opcode; 1919 1915 op->val = (long int) regs->gpr[ra] % 1920 1916 (long int) regs->gpr[rb]; 1921 1917 goto compute_done; 1922 1918 #endif 1923 1919 case 779: /* modsw */ 1924 1920 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 1925 - return -1; 1921 + goto unknown_opcode; 1926 1922 op->val = (int) regs->gpr[ra] % 1927 1923 (int) regs->gpr[rb]; 1928 1924 goto compute_done; ··· 1999 1995 #endif 2000 1996 case 538: /* cnttzw */ 2001 1997 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2002 - return -1; 1998 + goto unknown_opcode; 2003 1999 val = (unsigned int) regs->gpr[rd]; 2004 2000 op->val = (val ? __builtin_ctz(val) : 32); 2005 2001 goto logical_done; 2006 2002 #ifdef __powerpc64__ 2007 2003 case 570: /* cnttzd */ 2008 2004 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2009 - return -1; 2005 + goto unknown_opcode; 2010 2006 val = regs->gpr[rd]; 2011 2007 op->val = (val ? __builtin_ctzl(val) : 64); 2012 2008 goto logical_done; ··· 2116 2112 case 890: /* extswsli with sh_5 = 0 */ 2117 2113 case 891: /* extswsli with sh_5 = 1 */ 2118 2114 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2119 - return -1; 2115 + goto unknown_opcode; 2120 2116 op->type = COMPUTE + SETREG; 2121 2117 sh = rb | ((word & 2) << 4); 2122 2118 val = (signed int) regs->gpr[rd]; ··· 2443 2439 break; 2444 2440 2445 2441 case 268: /* lxvx */ 2442 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2443 + goto unknown_opcode; 2446 2444 op->reg = rd | ((word & 1) << 5); 2447 2445 op->type = MKOP(LOAD_VSX, 0, 16); 2448 2446 op->element_size = 16; ··· 2454 2448 case 269: /* lxvl */ 2455 2449 case 301: { /* lxvll */ 2456 2450 int nb; 2451 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2452 + goto unknown_opcode; 2457 2453 op->reg = rd | ((word & 1) << 5); 2458 2454 op->ea = ra ? regs->gpr[ra] : 0; 2459 2455 nb = regs->gpr[rb] & 0xff; ··· 2476 2468 2477 2469 case 333: /* lxvpx */ 2478 2470 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 2479 - return -1; 2471 + goto unknown_opcode; 2480 2472 op->reg = VSX_REGISTER_XTP(rd); 2481 2473 op->type = MKOP(LOAD_VSX, 0, 32); 2482 2474 op->element_size = 32; 2483 2475 break; 2484 2476 2485 2477 case 364: /* lxvwsx */ 2478 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2479 + goto unknown_opcode; 2486 2480 op->reg = rd | ((word & 1) << 5); 2487 2481 op->type = MKOP(LOAD_VSX, 0, 4); 2488 2482 op->element_size = 4; ··· 2492 2482 break; 2493 2483 2494 2484 case 396: /* stxvx */ 2485 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2486 + goto unknown_opcode; 2495 2487 op->reg = rd | ((word & 1) << 5); 2496 2488 op->type = MKOP(STORE_VSX, 0, 16); 2497 2489 op->element_size = 16; ··· 2503 2491 case 397: /* stxvl */ 2504 2492 case 429: { /* stxvll */ 2505 2493 int nb; 2494 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2495 + goto unknown_opcode; 2506 2496 op->reg = rd | ((word & 1) << 5); 2507 2497 op->ea = ra ? regs->gpr[ra] : 0; 2508 2498 nb = regs->gpr[rb] & 0xff; ··· 2518 2504 } 2519 2505 case 461: /* stxvpx */ 2520 2506 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 2521 - return -1; 2507 + goto unknown_opcode; 2522 2508 op->reg = VSX_REGISTER_XTP(rd); 2523 2509 op->type = MKOP(STORE_VSX, 0, 32); 2524 2510 op->element_size = 32; ··· 2556 2542 break; 2557 2543 2558 2544 case 781: /* lxsibzx */ 2545 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2546 + goto unknown_opcode; 2559 2547 op->reg = rd | ((word & 1) << 5); 2560 2548 op->type = MKOP(LOAD_VSX, 0, 1); 2561 2549 op->element_size = 8; ··· 2565 2549 break; 2566 2550 2567 2551 case 812: /* lxvh8x */ 2552 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2553 + goto unknown_opcode; 2568 2554 op->reg = rd | ((word & 1) << 5); 2569 2555 op->type = MKOP(LOAD_VSX, 0, 16); 2570 2556 op->element_size = 2; ··· 2574 2556 break; 2575 2557 2576 2558 case 813: /* lxsihzx */ 2559 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2560 + goto unknown_opcode; 2577 2561 op->reg = rd | ((word & 1) << 5); 2578 2562 op->type = MKOP(LOAD_VSX, 0, 2); 2579 2563 op->element_size = 8; ··· 2589 2569 break; 2590 2570 2591 2571 case 876: /* lxvb16x */ 2572 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2573 + goto unknown_opcode; 2592 2574 op->reg = rd | ((word & 1) << 5); 2593 2575 op->type = MKOP(LOAD_VSX, 0, 16); 2594 2576 op->element_size = 1; ··· 2604 2582 break; 2605 2583 2606 2584 case 909: /* stxsibx */ 2585 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2586 + goto unknown_opcode; 2607 2587 op->reg = rd | ((word & 1) << 5); 2608 2588 op->type = MKOP(STORE_VSX, 0, 1); 2609 2589 op->element_size = 8; ··· 2613 2589 break; 2614 2590 2615 2591 case 940: /* stxvh8x */ 2592 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2593 + goto unknown_opcode; 2616 2594 op->reg = rd | ((word & 1) << 5); 2617 2595 op->type = MKOP(STORE_VSX, 0, 16); 2618 2596 op->element_size = 2; ··· 2622 2596 break; 2623 2597 2624 2598 case 941: /* stxsihx */ 2599 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2600 + goto unknown_opcode; 2625 2601 op->reg = rd | ((word & 1) << 5); 2626 2602 op->type = MKOP(STORE_VSX, 0, 2); 2627 2603 op->element_size = 8; ··· 2637 2609 break; 2638 2610 2639 2611 case 1004: /* stxvb16x */ 2612 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2613 + goto unknown_opcode; 2640 2614 op->reg = rd | ((word & 1) << 5); 2641 2615 op->type = MKOP(STORE_VSX, 0, 16); 2642 2616 op->element_size = 1; ··· 2747 2717 op->type = MKOP(LOAD_FP, 0, 16); 2748 2718 break; 2749 2719 case 2: /* lxsd */ 2720 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2721 + goto unknown_opcode; 2750 2722 op->reg = rd + 32; 2751 2723 op->type = MKOP(LOAD_VSX, 0, 8); 2752 2724 op->element_size = 8; 2753 2725 op->vsx_flags = VSX_CHECK_VEC; 2754 2726 break; 2755 2727 case 3: /* lxssp */ 2728 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2729 + goto unknown_opcode; 2756 2730 op->reg = rd + 32; 2757 2731 op->type = MKOP(LOAD_VSX, 0, 4); 2758 2732 op->element_size = 8; ··· 2786 2752 #ifdef CONFIG_VSX 2787 2753 case 6: 2788 2754 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 2789 - return -1; 2755 + goto unknown_opcode; 2790 2756 op->ea = dqform_ea(word, regs); 2791 2757 op->reg = VSX_REGISTER_XTP(rd); 2792 2758 op->element_size = 32; ··· 2809 2775 break; 2810 2776 2811 2777 case 1: /* lxv */ 2778 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2779 + goto unknown_opcode; 2812 2780 op->ea = dqform_ea(word, regs); 2813 2781 if (word & 8) 2814 2782 op->reg = rd + 32; ··· 2821 2785 2822 2786 case 2: /* stxsd with LSB of DS field = 0 */ 2823 2787 case 6: /* stxsd with LSB of DS field = 1 */ 2788 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2789 + goto unknown_opcode; 2824 2790 op->ea = dsform_ea(word, regs); 2825 2791 op->reg = rd + 32; 2826 2792 op->type = MKOP(STORE_VSX, 0, 8); ··· 2832 2794 2833 2795 case 3: /* stxssp with LSB of DS field = 0 */ 2834 2796 case 7: /* stxssp with LSB of DS field = 1 */ 2797 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2798 + goto unknown_opcode; 2835 2799 op->ea = dsform_ea(word, regs); 2836 2800 op->reg = rd + 32; 2837 2801 op->type = MKOP(STORE_VSX, 0, 4); ··· 2842 2802 break; 2843 2803 2844 2804 case 5: /* stxv */ 2805 + if (!cpu_has_feature(CPU_FTR_ARCH_300)) 2806 + goto unknown_opcode; 2845 2807 op->ea = dqform_ea(word, regs); 2846 2808 if (word & 8) 2847 2809 op->reg = rd + 32; ··· 2873 2831 break; 2874 2832 case 1: /* Prefixed instructions */ 2875 2833 if (!cpu_has_feature(CPU_FTR_ARCH_31)) 2876 - return -1; 2834 + goto unknown_opcode; 2877 2835 2878 2836 prefix_r = GET_PREFIX_R(word); 2879 2837 ra = GET_PREFIX_RA(suffix); ··· 3020 2978 } 3021 2979 #endif /* CONFIG_VSX */ 3022 2980 2981 + return 0; 2982 + 2983 + unknown_opcode: 2984 + op->type = UNKNOWN; 3023 2985 return 0; 3024 2986 3025 2987 logical_done: