1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved. 3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is free software; you can redistribute it and/or 5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * modify it under the terms of the GNU General Public License 6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * as published by the Free Software Foundation, version 2. 7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is distributed in the hope that it will be useful, but 9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * WITHOUT ANY WARRANTY; without even the implied warranty of 10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * NON INFRINGEMENT. See the GNU General Public License for 12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * more details. 13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * A code-rewriter that enables instruction single-stepping. 15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Derived from iLib's single-stepping code. 16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 18233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#ifndef __tilegx__ /* Hardware support for single step unavailable. */ 19867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* These functions are only used on the TILE platform */ 21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/slab.h> 22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/thread_info.h> 23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/uaccess.h> 24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/mman.h> 25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/types.h> 260707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#include <linux/err.h> 27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/cacheflush.h> 28bd119c69239322caafdb64517a806037d0d0c70aDavid Howells#include <asm/unaligned.h> 29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <arch/abi.h> 30eb7c792da5afa3b9ec3e802c30952f82d2e9722bChris Metcalf#include <arch/opcode.h> 31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define signExtend17(val) sign_extend((val), 17) 33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define TILE_X1_MASK (0xffffffffULL << 31) 34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfint unaligned_printk; 36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic int __init setup_unaligned_printk(char *str) 38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf long val; 40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (strict_strtol(str, 0, &val) != 0) 41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return 0; 42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unaligned_printk = val; 430707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_info("Printk for each unaligned data accesses is %s\n", 440707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf unaligned_printk ? "enabled" : "disabled"); 45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return 1; 46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf__setup("unaligned_printk=", setup_unaligned_printk); 48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfunsigned int unaligned_fixup_count; 50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfenum mem_op { 52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MEMOP_NONE, 53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MEMOP_LOAD, 54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MEMOP_STORE, 55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MEMOP_LOAD_POSTINCR, 56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MEMOP_STORE_POSTINCR 57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}; 58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 5904f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalfstatic inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset) 60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits result; 62867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* mask out the old offset */ 64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits mask = create_BrOff_X1(-1); 65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf result = n & (~mask); 66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* or in the new offset */ 68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf result |= create_BrOff_X1(offset); 69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return result; 71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline tile_bundle_bits move_X1(tile_bundle_bits n, int dest, int src) 74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits result; 76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits op; 77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf result = n & (~TILE_X1_MASK); 79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf op = create_Opcode_X1(SPECIAL_0_OPCODE_X1) | 81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_RRROpcodeExtension_X1(OR_SPECIAL_0_OPCODE_X1) | 82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Dest_X1(dest) | 83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_SrcB_X1(TREG_ZERO) | 84867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_SrcA_X1(src) ; 85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf result |= op; 87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return result; 88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline tile_bundle_bits nop_X1(tile_bundle_bits n) 91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return move_X1(n, TREG_ZERO, TREG_ZERO); 93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline tile_bundle_bits addi_X1( 96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits n, int dest, int src, int imm) 97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf n &= ~TILE_X1_MASK; 99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf n |= (create_SrcA_X1(src) | 101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Dest_X1(dest) | 102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Imm8_X1(imm) | 103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_S_X1(0) | 104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Opcode_X1(IMM_0_OPCODE_X1) | 105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_ImmOpcodeExtension_X1(ADDI_IMM_0_OPCODE_X1)); 106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return n; 108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic tile_bundle_bits rewrite_load_store_unaligned( 111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct single_step_state *state, 112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits bundle, 113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct pt_regs *regs, 114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf enum mem_op mem_op, 115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int size, int sign_ext) 116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 1170707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf unsigned char __user *addr; 118867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int val_reg, addr_reg, err, val; 119867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 120867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Get address and value registers */ 121eb7c792da5afa3b9ec3e802c30952f82d2e9722bChris Metcalf if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) { 122867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr_reg = get_SrcA_Y2(bundle); 123867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val_reg = get_SrcBDest_Y2(bundle); 124867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { 125867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr_reg = get_SrcA_X1(bundle); 126867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val_reg = get_Dest_X1(bundle); 127867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 128867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr_reg = get_SrcA_X1(bundle); 129867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val_reg = get_SrcB_X1(bundle); 130867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 131867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 132867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 133867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If registers are not GPRs, don't try to handle it. 134867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 135867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * FIXME: we could handle non-GPR loads by getting the real value 136867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * from memory, writing it to the single step buffer, using a 137867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * temp_reg to hold a pointer to that memory, then executing that 138867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * instruction and resetting temp_reg. For non-GPR stores, it's a 139867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * little trickier; we could use the single step buffer for that 140867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * too, but we'd have to add some more state bits so that we could 141867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * call back in here to copy that value to the real target. For 142867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * now, we just handle the simple case. 143867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 144867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if ((val_reg >= PTREGS_NR_GPRS && 145867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (val_reg != TREG_ZERO || 146867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op == MEMOP_LOAD || 147867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op == MEMOP_LOAD_POSTINCR)) || 148867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr_reg >= PTREGS_NR_GPRS) 149867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return bundle; 150867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 151867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* If it's aligned, don't handle it specially */ 1520707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf addr = (void __user *)regs->regs[addr_reg]; 153867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (((unsigned long)addr % size) == 0) 154867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return bundle; 155867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 156cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf /* 157cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf * Return SIGBUS with the unaligned address, if requested. 158cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf * Note that we return SIGBUS even for completely invalid addresses 159cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf * as long as they are in fact unaligned; this matches what the 160cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf * tilepro hardware would be doing, if it could provide us with the 161cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf * actual bad address in an SPR, which it doesn't. 162cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf */ 163cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf if (unaligned_fixup == 0) { 164cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf siginfo_t info = { 165cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf .si_signo = SIGBUS, 166cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf .si_code = BUS_ADRALN, 167cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf .si_addr = addr 168cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf }; 169cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf trace_unhandled_signal("unaligned trap", regs, 170cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf (unsigned long)addr, SIGBUS); 171cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf force_sig_info(info.si_signo, &info, current); 172cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf return (tilepro_bundle_bits) 0; 173cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf } 174cdd8e16feba87a3fc2bb1885d36f895a2a3288bfChris Metcalf 175867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifndef __LITTLE_ENDIAN 176867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf# error We assume little-endian representation with copy_xx_user size 2 here 177867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 178867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Handle unaligned load/store */ 179867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { 180867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned short val_16; 181867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (size) { 182867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case 2: 183867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_from_user(&val_16, addr, sizeof(val_16)); 184867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val = sign_ext ? ((short)val_16) : val_16; 185867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 186867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case 4: 187867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_from_user(&val, addr, sizeof(val)); 188867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 189867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf default: 190867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG(); 191867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 192867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err == 0) { 193867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_reg = val_reg; 194867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_value = val; 195867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 196867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 197867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 198867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg]; 199867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_to_user(addr, &val, size); 200867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 201867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 202867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err) { 203867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf siginfo_t info = { 204867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_signo = SIGSEGV, 205867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_code = SEGV_MAPERR, 2060707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf .si_addr = addr 207867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf }; 208571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf trace_unhandled_signal("segfault", regs, 209571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf (unsigned long)addr, SIGSEGV); 210867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf force_sig_info(info.si_signo, &info, current); 211867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return (tile_bundle_bits) 0; 212867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 213867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 214867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (unaligned_printk || unaligned_fixup_count == 0) { 2150707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_info("Process %d/%s: PC %#lx: Fixup of" 2160707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf " unaligned %s at %#lx.\n", 2170707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf current->pid, current->comm, regs->pc, 2180707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (mem_op == MEMOP_LOAD || 2190707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf mem_op == MEMOP_LOAD_POSTINCR) ? 2200707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf "load" : "store", 2210707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (unsigned long)addr); 222867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (!unaligned_printk) { 2230707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#define P pr_info 2240707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("\n"); 2250707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("Unaligned fixups in the kernel will slow your application considerably.\n"); 2260707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("To find them, write a \"1\" to /proc/sys/tile/unaligned_fixup/printk,\n"); 2270707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("which requests the kernel show all unaligned fixups, or write a \"0\"\n"); 2280707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("to /proc/sys/tile/unaligned_fixup/enabled, in which case each unaligned\n"); 2290707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("access will become a SIGBUS you can debug. No further warnings will be\n"); 2300707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("shown so as to avoid additional slowdown, but you can track the number\n"); 2310707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("of fixups performed via /proc/sys/tile/unaligned_fixup/count.\n"); 2320707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("Use the tile-addr2line command (see \"info addr2line\") to decode PCs.\n"); 2330707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("\n"); 2340707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#undef P 235867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 236867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 237867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ++unaligned_fixup_count; 238867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 239eb7c792da5afa3b9ec3e802c30952f82d2e9722bChris Metcalf if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) { 240867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Convert the Y2 instruction to a prefetch. */ 241867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle &= ~(create_SrcBDest_Y2(-1) | 242867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Opcode_Y2(-1)); 243867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= (create_SrcBDest_Y2(TREG_ZERO) | 244867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Opcode_Y2(LW_OPCODE_Y2)); 245867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Replace the load postincr with an addi */ 246867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (mem_op == MEMOP_LOAD_POSTINCR) { 247867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = addi_X1(bundle, addr_reg, addr_reg, 248867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf get_Imm8_X1(bundle)); 249867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Replace the store postincr with an addi */ 250867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (mem_op == MEMOP_STORE_POSTINCR) { 251867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = addi_X1(bundle, addr_reg, addr_reg, 252867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf get_Dest_Imm8_X1(bundle)); 253867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 254867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Convert the X1 instruction to a nop. */ 255867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle &= ~(create_Opcode_X1(-1) | 256867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnShOpcodeExtension_X1(-1) | 257867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnOpcodeExtension_X1(-1)); 258867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= (create_Opcode_X1(SHUN_0_OPCODE_X1) | 259867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnShOpcodeExtension_X1( 260867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf UN_0_SHUN_0_OPCODE_X1) | 261867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnOpcodeExtension_X1( 262867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf NOP_UN_0_SHUN_0_OPCODE_X1)); 263867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 264867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 265867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return bundle; 266867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 267867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 26804f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf/* 26904f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * Called after execve() has started the new image. This allows us 27004f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * to reset the info state. Note that the the mmap'ed memory, if there 27104f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * was any, has already been unmapped by the exec. 27204f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf */ 27304f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalfvoid single_step_execve(void) 27404f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf{ 27504f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf struct thread_info *ti = current_thread_info(); 27604f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf kfree(ti->step_state); 27704f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf ti->step_state = NULL; 27804f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf} 27904f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf 280867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/** 281867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * single_step_once() - entry point when single stepping has been triggered. 282867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @regs: The machine register state 283867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 284867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * When we arrive at this routine via a trampoline, the single step 285867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * engine copies the executing bundle to the single step buffer. 286867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If the instruction is a condition branch, then the target is 287867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * reset to one past the next instruction. If the instruction 288867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * sets the lr, then that is noted. If the instruction is a jump 289867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * or call, then the new target pc is preserved and the current 290867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * bundle instruction set to null. 291867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 292867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * The necessary post-single-step rewriting information is stored in 293867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * single_step_state-> We use data segment values because the 294867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * stack will be rewound when we run the rewritten single-stepped 295867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * instruction. 296867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 297867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid single_step_once(struct pt_regs *regs) 298867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 299867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_ill_insn; 300867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_j_insn; 301867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_addli_insn; 302867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_auli_insn; 303867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct thread_info *info = (void *)current_thread_info(); 304867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct single_step_state *state = info->step_state; 305867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); 3060707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf tile_bundle_bits __user *buffer, *pc; 307867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits bundle; 308867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int temp_reg; 309867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int target_reg = TREG_LR; 310867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int err; 311867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf enum mem_op mem_op = MEMOP_NONE; 312867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int size = 0, sign_ext = 0; /* happy compiler */ 313867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 314867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf asm( 315867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .pushsection .rodata.single_step\n" 316867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .align 8\n" 317867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_ill_insn\n" 318867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_ill_insn:\n" 319867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" ill\n" 320867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_addli_insn\n" 321867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_addli_insn:\n" 322867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" { nop; addli r0, zero, 0 }\n" 323867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_auli_insn\n" 324867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_auli_insn:\n" 325867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" { nop; auli r0, r0, 0 }\n" 326867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_j_insn\n" 327867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_j_insn:\n" 328867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" j .\n" 329867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .popsection\n" 330867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ); 331867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 332313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf /* 333313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * Enable interrupts here to allow touching userspace and the like. 334313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * The callers expect this: do_trap() already has interrupts 335313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * enabled, and do_work_pending() handles functions that enable 336313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * interrupts internally. 337313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf */ 338313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf local_irq_enable(); 339313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf 340867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state == NULL) { 341867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* allocate a page of writable, executable memory */ 342867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); 343867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state == NULL) { 3440707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Out of kernel memory trying to single-step\n"); 345867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 346867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 347867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 348867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* allocate a cache line of writable, executable memory */ 3496be5ceb02e98eaf6cfc4f8b12a896d04023f340dLinus Torvalds buffer = (void __user *) vm_mmap(NULL, 0, 64, 350867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf PROT_EXEC | PROT_READ | PROT_WRITE, 351867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MAP_PRIVATE | MAP_ANONYMOUS, 352867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 0); 353867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 3540707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf if (IS_ERR((void __force *)buffer)) { 355867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf kfree(state); 3560707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Out of kernel pages trying to single-step\n"); 357867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 358867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 359867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 360867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->buffer = buffer; 361867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->is_enabled = 0; 362867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 363867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf info->step_state = state; 364867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 365867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Validate our stored instruction patterns */ 366867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Opcode_X1(__single_step_addli_insn) != 367867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ADDLI_OPCODE_X1); 368867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Opcode_X1(__single_step_auli_insn) != 369867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf AULI_OPCODE_X1); 370867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_SrcA_X1(__single_step_addli_insn) != TREG_ZERO); 371867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Dest_X1(__single_step_addli_insn) != 0); 372867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_JOffLong_X1(__single_step_j_insn) != 0); 373867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 374867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 375867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 376867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we are returning from a syscall, we still haven't hit the 377867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * "ill" for the swint1 instruction. So back the PC up to be 378867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pointing at the swint1, but we'll actually return directly 379867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * back to the "ill" so we come back in via SIGILL as if we 380867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * had "executed" the swint1 without ever being in kernel space. 381867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 382867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (regs->faultnum == INT_SWINT_1) 383867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->pc -= 8; 384867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 3850707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pc = (tile_bundle_bits __user *)(regs->pc); 3860707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf if (get_user(bundle, pc) != 0) { 3870707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Couldn't read instruction at %p trying to step\n", pc); 3880707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf return; 3890707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf } 390867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 391867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* We'll follow the instruction with 2 ill op bundles */ 3920707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf state->orig_pc = (unsigned long)pc; 393867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = (unsigned long)(pc + 1); 394867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->branch_next_pc = 0; 395867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 0; 396867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 397eb7c792da5afa3b9ec3e802c30952f82d2e9722bChris Metcalf if (!(bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)) { 398867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* two wide, check for control flow */ 399867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int opcode = get_Opcode_X1(bundle); 400867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 401867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (opcode) { 402867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* branches */ 403867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case BRANCH_OPCODE_X1: 404867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 40504f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf s32 offset = signExtend17(get_BrOff_X1(bundle)); 406867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 407867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 408867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * For branches, we use a rewriting trick to let the 409867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * hardware evaluate whether the branch is taken or 410867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * untaken. We record the target offset and then 411867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * rewrite the branch instruction to target 1 insn 412867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * ahead if the branch is taken. We then follow the 413867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * rewritten branch with two bundles, each containing 414867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * an "ill" instruction. The supervisor examines the 415867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pc after the single step code is executed, and if 416867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * the pc is the first ill instruction, then the 417867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * branch (if any) was not taken. If the pc is the 418867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * second ill instruction, then the branch was 419867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * taken. The new pc is computed for these cases, and 420867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * inserted into the registers for the thread. If 421867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * the pc is the start of the single step code, then 422867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * an exception or interrupt was taken before the 423867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * code started processing, and the same "original" 424867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pc is restored. This change, different from the 425867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * original implementation, has the advantage of 426867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * executing a single user instruction. 427867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 428867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->branch_next_pc = (unsigned long)(pc + offset); 429867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 430867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* rewrite branch offset to go forward one bundle */ 431867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = set_BrOff_X1(bundle, 2); 432867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 433867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 434867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 435867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* jumps */ 436867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALB_OPCODE_X1: 437867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALF_OPCODE_X1: 438867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 439867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 440867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long) (pc + get_JOffLong_X1(bundle)); 441867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 442867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 443867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JB_OPCODE_X1: 444867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JF_OPCODE_X1: 445867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 446867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long) (pc + get_JOffLong_X1(bundle)); 447867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 448867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 449867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 450867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SPECIAL_0_OPCODE_X1: 451867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_RRROpcodeExtension_X1(bundle)) { 452867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* jump-register */ 453867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALRP_SPECIAL_0_OPCODE_X1: 454867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALR_SPECIAL_0_OPCODE_X1: 455867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 456867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 457867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[get_SrcA_X1(bundle)]; 458867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 459867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 460867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JRP_SPECIAL_0_OPCODE_X1: 461867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JR_SPECIAL_0_OPCODE_X1: 462867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 463867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[get_SrcA_X1(bundle)]; 464867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 465867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 466867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 467867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LNK_SPECIAL_0_OPCODE_X1: 468867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 469867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf target_reg = get_Dest_X1(bundle); 470867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 471867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 472867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* stores */ 473867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SH_SPECIAL_0_OPCODE_X1: 474867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 475867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 476867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 477867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 478867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SW_SPECIAL_0_OPCODE_X1: 479867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 480867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 481867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 482867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 483867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 484867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 485867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* loads and iret */ 486867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SHUN_0_OPCODE_X1: 487867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (get_UnShOpcodeExtension_X1(bundle) == 488867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf UN_0_SHUN_0_OPCODE_X1) { 489867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_UnOpcodeExtension_X1(bundle)) { 490867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_UN_0_SHUN_0_OPCODE_X1: 491867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 492867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 493867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 494867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 495867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 496867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_U_UN_0_SHUN_0_OPCODE_X1: 497867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 498867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 499867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 500867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 501867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 502867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LW_UN_0_SHUN_0_OPCODE_X1: 503867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 504867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 505867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 506867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 507867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case IRET_UN_0_SHUN_0_OPCODE_X1: 508867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 509867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long ex0_0 = __insn_mfspr( 510867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf SPR_EX_CONTEXT_0_0); 511867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long ex0_1 = __insn_mfspr( 512867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf SPR_EX_CONTEXT_0_1); 513867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 514867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Special-case it if we're iret'ing 515867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * to PL0 again. Otherwise just let 516867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * it run and it will generate SIGILL. 517867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 518867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (EX1_PL(ex0_1) == USER_PL) { 519867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = ex0_0; 520867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->ex1 = ex0_1; 521867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 522867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 523867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 524867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 525867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 526867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 527867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 528867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#if CHIP_HAS_WH64() 529867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* postincrement operations */ 530867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case IMM_0_OPCODE_X1: 531867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_ImmOpcodeExtension_X1(bundle)) { 532867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LWADD_IMM_0_OPCODE_X1: 533867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 534867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 535867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 536867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 537867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LHADD_IMM_0_OPCODE_X1: 538867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 539867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 540867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 541867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 542867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 543867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LHADD_U_IMM_0_OPCODE_X1: 544867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 545867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 546867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 547867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 548867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 549867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SWADD_IMM_0_OPCODE_X1: 550867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE_POSTINCR; 551867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 552867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 553867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 554867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SHADD_IMM_0_OPCODE_X1: 555867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE_POSTINCR; 556867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 557867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 558867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 559867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf default: 560867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 561867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 562867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 563867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* CHIP_HAS_WH64() */ 564867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 565867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 566867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state->update) { 567867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 568867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Get an available register. We start with a 569867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * bitmask with 1's for available registers. 570867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We truncate to the low 32 registers since 571867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * we are guaranteed to have set bits in the 572867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * low 32 bits, then use ctz to pick the first. 573867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 574867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf u32 mask = (u32) ~((1ULL << get_Dest_X0(bundle)) | 575867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << get_SrcA_X0(bundle)) | 576867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << get_SrcB_X0(bundle)) | 577867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << target_reg)); 578867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf temp_reg = __builtin_ctz(mask); 579867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_reg = temp_reg; 580867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_value = regs->regs[temp_reg]; 581867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[temp_reg] = (unsigned long) (pc+1); 582867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->flags |= PT_FLAGS_RESTORE_REGS; 583867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = move_X1(bundle, target_reg, temp_reg); 584867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 585867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 586867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int opcode = get_Opcode_Y2(bundle); 587867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 588867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (opcode) { 589867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* loads */ 590867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_OPCODE_Y2: 591867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 592867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 593867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 594867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 595867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 596867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_U_OPCODE_Y2: 597867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 598867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 599867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 600867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 601867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 602867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LW_OPCODE_Y2: 603867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 604867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 605867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 606867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 607867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* stores */ 608867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SH_OPCODE_Y2: 609867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 610867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 611867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 612867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 613867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SW_OPCODE_Y2: 614867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 615867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 616867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 617867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 618867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 619867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 620867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 621867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Check if we need to rewrite an unaligned load/store. 622867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Returning zero is a special value meaning we need to SIGSEGV. 623867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 624867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (mem_op != MEMOP_NONE && unaligned_fixup >= 0) { 625867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = rewrite_load_store_unaligned(state, bundle, regs, 626867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op, size, sign_ext); 627867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (bundle == 0) 628867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 629867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 630867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 631867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* write the bundle to our execution area */ 632867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf buffer = state->buffer; 633867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = __put_user(bundle, buffer++); 634867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 635867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 636867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we're really single-stepping, we take an INT_ILL after. 637867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we're just handling an unaligned access, we can just 638867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * jump directly back to where we were in user code. 639867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 640867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (is_single_step) { 641867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(__single_step_ill_insn, buffer++); 642867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(__single_step_ill_insn, buffer++); 643867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 644867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf long delta; 645867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 646867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state->update) { 647867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* We have some state to update; do it inline */ 648867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int ha16; 649867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_addli_insn; 650867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Dest_X1(state->update_reg); 651867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Imm16_X1(state->update_value); 652867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 653867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_auli_insn; 654867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Dest_X1(state->update_reg); 655867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_SrcA_X1(state->update_reg); 656867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ha16 = (state->update_value + 0x8000) >> 16; 657867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Imm16_X1(ha16); 658867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 659867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 0; 660867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 661867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 662867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* End with a jump back to the next instruction */ 663867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf delta = ((regs->pc + TILE_BUNDLE_SIZE_IN_BYTES) - 664867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long)buffer) >> 665867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES; 666867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_j_insn; 667867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_JOffLong_X1(delta); 668867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 669867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 670867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 671867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err) { 6720707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Fault when writing to single-step buffer\n"); 673867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 674867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 675867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 676867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 677867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Flush the buffer. 678867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We do a local flush only, since this is a thread-specific buffer. 679867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 6800707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf __flush_icache_range((unsigned long)state->buffer, 6810707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (unsigned long)buffer); 682867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 683867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Indicate enabled */ 684867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->is_enabled = is_single_step; 6850707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf regs->pc = (unsigned long)state->buffer; 686867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 687867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Fault immediately if we are coming back from a syscall. */ 688867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (regs->faultnum == INT_SWINT_1) 689867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->pc += 8; 690867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 691867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 692233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#else 693233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <linux/smp.h> 694233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <linux/ptrace.h> 695233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <arch/spr_def.h> 696233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 697233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfstatic DEFINE_PER_CPU(unsigned long, ss_saved_pc); 698233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 699233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 700233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf/* 701233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * Called directly on the occasion of an interrupt. 702233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 703233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If the process doesn't have single step set, then we use this as an 704233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * opportunity to turn single step off. 705233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 706233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * It has been mentioned that we could conditionally turn off single stepping 707233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on each entry into the kernel and rely on single_step_once to turn it 708233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on for the processes that matter (as we already do), but this 709233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * implementation is somewhat more efficient in that we muck with registers 710233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * once on a bum interrupt rather than on every entry into the kernel. 711233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 712233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred, 713233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * so we have to run through this process again before we can say that an 714233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * instruction has executed. 715233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 716233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * swint will set CANCELED, but it's a legitimate instruction. Fortunately 717233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * it changes the PC. If it hasn't changed, then we know that the interrupt 718233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * wasn't generated by swint and we'll need to run this process again before 719233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * we can say an instruction has executed. 720233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 721233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get 722233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on with our lives. 723233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf */ 724233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 725233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfvoid gx_singlestep_handle(struct pt_regs *regs, int fault_num) 726233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf{ 727233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); 728233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf struct thread_info *info = (void *)current_thread_info(); 729233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); 730233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); 731233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 732233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf if (is_single_step == 0) { 733233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0); 734233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 735233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf } else if ((*ss_pc != regs->pc) || 736233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) { 737233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 738233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf ptrace_notify(SIGTRAP); 739233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; 740233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; 741233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); 742233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf } 743233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf} 744233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 745233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 746233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf/* 747233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * Called from need_singlestep. Set up the control registers and the enable 748233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * register, then return back. 749233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf */ 750233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 751233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfvoid single_step_once(struct pt_regs *regs) 752233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf{ 753233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); 754233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); 755233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 756233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf *ss_pc = regs->pc; 757233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; 758233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; 759233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); 760233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL); 761233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf} 762233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 76304f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalfvoid single_step_execve(void) 76404f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf{ 76504f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf /* Nothing */ 76604f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf} 76704f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf 768867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* !__tilegx__ */ 769