^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Emulation of the "brl" instruction for IA64 processors that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * don't support it in hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Stephan Zeisset, Intel Corp. <Stephan.Zeisset@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * 02/22/02 D. Mosberger Clear si_flgs, si_isr, and si_imm to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * leaking kernel bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sched/signal.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/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) extern char ia64_set_b1, ia64_set_b2, ia64_set_b3, ia64_set_b4, ia64_set_b5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct illegal_op_return {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) unsigned long fkt, arg1, arg2, arg3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The unimplemented bits of a virtual address must be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * to the value of the most significant implemented bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * unimpl_va_mask includes all unimplemented bits and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * the most significant implemented bit, so the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * of an and operation with the mask must be all 0's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * or all 1's for the address to be valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define unimplemented_virtual_address(va) ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ((va) & local_cpu_data->unimpl_va_mask) != 0 && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ((va) & local_cpu_data->unimpl_va_mask) != local_cpu_data->unimpl_va_mask \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * The unimplemented bits of a physical address must be 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * unimpl_pa_mask includes all unimplemented bits, so the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * of an and operation with the mask must be all 0's for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * address to be valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define unimplemented_physical_address(pa) ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ((pa) & local_cpu_data->unimpl_pa_mask) != 0 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Handle an illegal operation fault that was caused by an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * unimplemented "brl" instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * If we are not successful (e.g because the illegal operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * wasn't caused by a "brl" after all), we return -1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * If we are successful, we return either 0 or the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * of a "fixup" function for manipulating preserved register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct illegal_op_return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long bundle[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long opcode, btype, qp, offset, cpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct illegal_op_return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) long tmp_taken, unimplemented_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) rv.fkt = (unsigned long) -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Decode the instruction bundle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (copy_from_user(bundle, (void *) (regs->cr_iip), sizeof(bundle)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) next_ip = (unsigned long) regs->cr_iip + 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* "brl" must be in slot 2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ia64_psr(regs)->ri != 1) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Must be "mlx" template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if ((bundle[0] & 0x1e) != 0x4) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) opcode = (bundle[1] >> 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) btype = ((bundle[1] >> 29) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) qp = ((bundle[1] >> 23) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) offset = ((bundle[1] & 0x0800000000000000L) << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) | ((bundle[1] & 0x00fffff000000000L) >> 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) | ((bundle[1] & 0x00000000007fffffL) << 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) | ((bundle[0] & 0xffff000000000000L) >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) tmp_taken = regs->pr & (1L << qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) switch(opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case 0xC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Long Branch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (btype != 0) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) rv.fkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!(tmp_taken)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Qualifying predicate is 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Skip instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) regs->cr_iip = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ia64_psr(regs)->ri = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case 0xD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Long Call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) rv.fkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!(tmp_taken)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Qualifying predicate is 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Skip instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) regs->cr_iip = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ia64_psr(regs)->ri = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * BR[btype] = IP+16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) switch(btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) regs->b0 = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rv.fkt = (unsigned long) &ia64_set_b1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) rv.fkt = (unsigned long) &ia64_set_b2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) rv.fkt = (unsigned long) &ia64_set_b3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) rv.fkt = (unsigned long) &ia64_set_b4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) rv.fkt = (unsigned long) &ia64_set_b5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) regs->b6 = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) regs->b7 = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rv.arg1 = next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * AR[PFS].pfm = CFM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * AR[PFS].pec = AR[EC]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * AR[PFS].ppl = PSR.cpl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cpl = ia64_psr(regs)->cpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) regs->ar_pfs = ((regs->cr_ifs & 0x3fffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) | (ar_ec << 52) | (cpl << 62));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * CFM.sof -= CFM.sol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * CFM.sol = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * CFM.sor = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * CFM.rrb.gr = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * CFM.rrb.fr = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * CFM.rrb.pr = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) regs->cr_ifs = ((regs->cr_ifs & 0xffffffc00000007f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) - ((regs->cr_ifs >> 7) & 0x7f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Unknown opcode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) regs->cr_iip += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ia64_psr(regs)->ri = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (ia64_psr(regs)->it == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unimplemented_address = unimplemented_physical_address(regs->cr_iip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unimplemented_address = unimplemented_virtual_address(regs->cr_iip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (unimplemented_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * The target address contains unimplemented bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) printk(KERN_DEBUG "Woah! Unimplemented Instruction Address Trap!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) force_sig_fault(SIGILL, ILL_BADIADDR, (void __user *)NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) } else if (ia64_psr(regs)->tb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * Branch Tracing is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Force a taken branch signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) force_sig_fault(SIGTRAP, TRAP_BRANCH, (void __user *)NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else if (ia64_psr(regs)->ss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Single Step is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Force a trace signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }