^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2011-2012 Synopsys (www.synopsys.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * vineetg : May 2011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * -Adapted (from .26 to .35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * -original contribution by Tim.yao@amlogic.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/disasm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #ifdef CONFIG_CPU_BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define BE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define FIRST_BYTE_16 "swap %1, %1\n swape %1, %1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define FIRST_BYTE_32 "swape %1, %1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define BE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define FIRST_BYTE_16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define FIRST_BYTE_32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define __get8_unaligned_check(val, addr, err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) __asm__( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) "1: ldb.ab %1, [%2, 1]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) "2:\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) " .section .fixup,\"ax\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) "3: mov %0, 1\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) " j 2b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) " .section __ex_table,\"a\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) " .long 1b, 3b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) : "=r" (err), "=&r" (val), "=r" (addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) : "0" (err), "2" (addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define get16_unaligned_check(val, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int err = 0, v, a = addr; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) val = v << ((BE) ? 8 : 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) val |= v << ((BE) ? 0 : 8); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) goto fault; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define get32_unaligned_check(val, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned int err = 0, v, a = addr; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) val = v << ((BE) ? 24 : 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) val |= v << ((BE) ? 16 : 8); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) val |= v << ((BE) ? 8 : 16); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) __get8_unaligned_check(v, a, err); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) val |= v << ((BE) ? 0 : 24); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) goto fault; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define put16_unaligned_check(val, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int err = 0, v = val, a = addr;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __asm__( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) FIRST_BYTE_16 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "1: stb.ab %1, [%2, 1]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) " lsr %1, %1, 8\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "2: stb %1, [%2]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) "3:\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) " .section .fixup,\"ax\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "4: mov %0, 1\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) " j 3b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) " .section __ex_table,\"a\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) " .long 1b, 4b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) " .long 2b, 4b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) : "=r" (err), "=&r" (v), "=&r" (a) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) : "0" (err), "1" (v), "2" (a)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) goto fault; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define put32_unaligned_check(val, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int err = 0, v = val, a = addr;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) __asm__( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) FIRST_BYTE_32 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) "1: stb.ab %1, [%2, 1]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) " lsr %1, %1, 8\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) "2: stb.ab %1, [%2, 1]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) " lsr %1, %1, 8\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "3: stb.ab %1, [%2, 1]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) " lsr %1, %1, 8\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) "4: stb %1, [%2]\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) "5:\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) " .section .fixup,\"ax\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "6: mov %0, 1\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) " j 5b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) " .section __ex_table,\"a\"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) " .align 4\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) " .long 1b, 6b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) " .long 2b, 6b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) " .long 3b, 6b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) " .long 4b, 6b\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) " .previous\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) : "=r" (err), "=&r" (v), "=&r" (a) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) : "0" (err), "1" (v), "2" (a)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto fault; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* sysctl hooks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int unaligned_enabled __read_mostly = 1; /* Enabled by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int no_unaligned_warning __read_mostly = 1; /* Only 1 warning by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void fixup_load(struct disasm_state *state, struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct callee_regs *cregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* register write back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if ((state->aa == 1) || (state->aa == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) set_reg(state->wb_reg, state->src1 + state->src2, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (state->aa == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) state->src2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (state->zz == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) get32_unaligned_check(val, state->src1 + state->src2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) get16_unaligned_check(val, state->src1 + state->src2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (state->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) val = (val << 16) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (state->pref == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) set_reg(state->dest, val, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) fault: state->fault = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void fixup_store(struct disasm_state *state, struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct callee_regs *cregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* register write back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if ((state->aa == 1) || (state->aa == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) set_reg(state->wb_reg, state->src2 + state->src3, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (state->aa == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) state->src3 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) } else if (state->aa == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (state->zz == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) set_reg(state->wb_reg, state->src2 + (state->src3 << 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) } else if (!state->zz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) set_reg(state->wb_reg, state->src2 + (state->src3 << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* write fix-up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!state->zz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) put32_unaligned_check(state->src1, state->src2 + state->src3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) put16_unaligned_check(state->src1, state->src2 + state->src3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) fault: state->fault = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Handle an unaligned access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Returns 0 if successfully handled, 1 if some error happened
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int misaligned_fixup(unsigned long address, struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct callee_regs *cregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct disasm_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) char buf[TASK_COMM_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* handle user mode only and only if enabled by sysadmin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!user_mode(regs) || !unaligned_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (no_unaligned_warning) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) pr_warn_once("%s(%d) made unaligned access which was emulated"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) " by kernel assist\n. This can degrade application"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) " performance significantly\n. To enable further"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) " logging of such instances, please \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) " echo 0 > /proc/sys/kernel/ignore-unaligned-usertrap\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) get_task_comm(buf, current), task_pid_nr(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* Add rate limiting if it gets down to it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) pr_warn("%s(%d): unaligned access to/from 0x%lx by PC: 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) get_task_comm(buf, current), task_pid_nr(current),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) address, regs->ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) disasm_instr(regs->ret, &state, 1, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (state.fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* ldb/stb should not have unaligned exception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if ((state.zz == 1) || (state.di))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!state.write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) fixup_load(&state, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) fixup_store(&state, regs, cregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (state.fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* clear any remanants of delay slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (delay_mode(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) regs->ret = regs->bta & ~1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) regs->status32 &= ~STATUS_DE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) regs->ret += state.instr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* handle zero-overhead-loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ((regs->ret == regs->lp_end) && (regs->lp_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) regs->ret = regs->lp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) regs->lp_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pr_err("Alignment trap: fault in fix-up %08lx at [<%08lx>]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) state.words[0], address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }