single_step.c revision 313ce674d3cbc2d48ed34a9462427920ac54f4ad
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> 28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/opcode-tile.h> 29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/opcode_constants.h> 30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <arch/abi.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 */ 121867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (bundle & TILE_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 156867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifndef __LITTLE_ENDIAN 157867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf# error We assume little-endian representation with copy_xx_user size 2 here 158867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 159867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Handle unaligned load/store */ 160867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { 161867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned short val_16; 162867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (size) { 163867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case 2: 164867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_from_user(&val_16, addr, sizeof(val_16)); 165867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val = sign_ext ? ((short)val_16) : val_16; 166867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 167867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case 4: 168867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_from_user(&val, addr, sizeof(val)); 169867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 170867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf default: 171867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG(); 172867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 173867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err == 0) { 174867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_reg = val_reg; 175867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_value = val; 176867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 177867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 178867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 179867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg]; 180867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = copy_to_user(addr, &val, size); 181867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 182867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 183867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err) { 184867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf siginfo_t info = { 185867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_signo = SIGSEGV, 186867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_code = SEGV_MAPERR, 1870707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf .si_addr = addr 188867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf }; 189867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf force_sig_info(info.si_signo, &info, current); 190867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return (tile_bundle_bits) 0; 191867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 192867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 193867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (unaligned_fixup == 0) { 194867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf siginfo_t info = { 195867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_signo = SIGBUS, 196867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf .si_code = BUS_ADRALN, 1970707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf .si_addr = addr 198867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf }; 199867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf force_sig_info(info.si_signo, &info, current); 200867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return (tile_bundle_bits) 0; 201867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 202867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 203867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (unaligned_printk || unaligned_fixup_count == 0) { 2040707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_info("Process %d/%s: PC %#lx: Fixup of" 2050707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf " unaligned %s at %#lx.\n", 2060707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf current->pid, current->comm, regs->pc, 2070707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (mem_op == MEMOP_LOAD || 2080707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf mem_op == MEMOP_LOAD_POSTINCR) ? 2090707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf "load" : "store", 2100707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (unsigned long)addr); 211867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (!unaligned_printk) { 2120707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#define P pr_info 2130707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("\n"); 2140707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("Unaligned fixups in the kernel will slow your application considerably.\n"); 2150707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("To find them, write a \"1\" to /proc/sys/tile/unaligned_fixup/printk,\n"); 2160707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("which requests the kernel show all unaligned fixups, or write a \"0\"\n"); 2170707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("to /proc/sys/tile/unaligned_fixup/enabled, in which case each unaligned\n"); 2180707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("access will become a SIGBUS you can debug. No further warnings will be\n"); 2190707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("shown so as to avoid additional slowdown, but you can track the number\n"); 2200707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("of fixups performed via /proc/sys/tile/unaligned_fixup/count.\n"); 2210707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("Use the tile-addr2line command (see \"info addr2line\") to decode PCs.\n"); 2220707ad30d10110aebc01a5a64fb63f4b32d20b73Chris MetcalfP("\n"); 2230707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#undef P 224867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 225867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 226867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ++unaligned_fixup_count; 227867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 228867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) { 229867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Convert the Y2 instruction to a prefetch. */ 230867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle &= ~(create_SrcBDest_Y2(-1) | 231867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Opcode_Y2(-1)); 232867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= (create_SrcBDest_Y2(TREG_ZERO) | 233867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_Opcode_Y2(LW_OPCODE_Y2)); 234867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Replace the load postincr with an addi */ 235867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (mem_op == MEMOP_LOAD_POSTINCR) { 236867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = addi_X1(bundle, addr_reg, addr_reg, 237867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf get_Imm8_X1(bundle)); 238867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Replace the store postincr with an addi */ 239867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (mem_op == MEMOP_STORE_POSTINCR) { 240867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = addi_X1(bundle, addr_reg, addr_reg, 241867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf get_Dest_Imm8_X1(bundle)); 242867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 243867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Convert the X1 instruction to a nop. */ 244867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle &= ~(create_Opcode_X1(-1) | 245867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnShOpcodeExtension_X1(-1) | 246867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnOpcodeExtension_X1(-1)); 247867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= (create_Opcode_X1(SHUN_0_OPCODE_X1) | 248867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnShOpcodeExtension_X1( 249867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf UN_0_SHUN_0_OPCODE_X1) | 250867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf create_UnOpcodeExtension_X1( 251867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf NOP_UN_0_SHUN_0_OPCODE_X1)); 252867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 253867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 254867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return bundle; 255867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 256867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 25704f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf/* 25804f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * Called after execve() has started the new image. This allows us 25904f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * to reset the info state. Note that the the mmap'ed memory, if there 26004f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf * was any, has already been unmapped by the exec. 26104f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf */ 26204f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalfvoid single_step_execve(void) 26304f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf{ 26404f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf struct thread_info *ti = current_thread_info(); 26504f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf kfree(ti->step_state); 26604f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf ti->step_state = NULL; 26704f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf} 26804f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf 269867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/** 270867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * single_step_once() - entry point when single stepping has been triggered. 271867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @regs: The machine register state 272867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 273867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * When we arrive at this routine via a trampoline, the single step 274867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * engine copies the executing bundle to the single step buffer. 275867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If the instruction is a condition branch, then the target is 276867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * reset to one past the next instruction. If the instruction 277867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * sets the lr, then that is noted. If the instruction is a jump 278867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * or call, then the new target pc is preserved and the current 279867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * bundle instruction set to null. 280867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 281867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * The necessary post-single-step rewriting information is stored in 282867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * single_step_state-> We use data segment values because the 283867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * stack will be rewound when we run the rewritten single-stepped 284867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * instruction. 285867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 286867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid single_step_once(struct pt_regs *regs) 287867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 288867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_ill_insn; 289867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_j_insn; 290867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_addli_insn; 291867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf extern tile_bundle_bits __single_step_auli_insn; 292867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct thread_info *info = (void *)current_thread_info(); 293867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct single_step_state *state = info->step_state; 294867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); 2950707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf tile_bundle_bits __user *buffer, *pc; 296867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tile_bundle_bits bundle; 297867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int temp_reg; 298867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int target_reg = TREG_LR; 299867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int err; 300867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf enum mem_op mem_op = MEMOP_NONE; 301867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int size = 0, sign_ext = 0; /* happy compiler */ 302867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 303867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf asm( 304867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .pushsection .rodata.single_step\n" 305867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .align 8\n" 306867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_ill_insn\n" 307867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_ill_insn:\n" 308867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" ill\n" 309867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_addli_insn\n" 310867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_addli_insn:\n" 311867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" { nop; addli r0, zero, 0 }\n" 312867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_auli_insn\n" 313867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_auli_insn:\n" 314867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" { nop; auli r0, r0, 0 }\n" 315867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .globl __single_step_j_insn\n" 316867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf"__single_step_j_insn:\n" 317867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" j .\n" 318867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf" .popsection\n" 319867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ); 320867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 321313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf /* 322313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * Enable interrupts here to allow touching userspace and the like. 323313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * The callers expect this: do_trap() already has interrupts 324313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * enabled, and do_work_pending() handles functions that enable 325313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf * interrupts internally. 326313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf */ 327313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf local_irq_enable(); 328313ce674d3cbc2d48ed34a9462427920ac54f4adChris Metcalf 329867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state == NULL) { 330867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* allocate a page of writable, executable memory */ 331867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); 332867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state == NULL) { 3330707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Out of kernel memory trying to single-step\n"); 334867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 335867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 336867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 337867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* allocate a cache line of writable, executable memory */ 338867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf down_write(¤t->mm->mmap_sem); 3390707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf buffer = (void __user *) do_mmap(NULL, 0, 64, 340867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf PROT_EXEC | PROT_READ | PROT_WRITE, 341867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf MAP_PRIVATE | MAP_ANONYMOUS, 342867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 0); 343867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf up_write(¤t->mm->mmap_sem); 344867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 3450707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf if (IS_ERR((void __force *)buffer)) { 346867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf kfree(state); 3470707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Out of kernel pages trying to single-step\n"); 348867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 349867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 350867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 351867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->buffer = buffer; 352867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->is_enabled = 0; 353867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 354867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf info->step_state = state; 355867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 356867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Validate our stored instruction patterns */ 357867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Opcode_X1(__single_step_addli_insn) != 358867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ADDLI_OPCODE_X1); 359867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Opcode_X1(__single_step_auli_insn) != 360867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf AULI_OPCODE_X1); 361867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_SrcA_X1(__single_step_addli_insn) != TREG_ZERO); 362867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_Dest_X1(__single_step_addli_insn) != 0); 363867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(get_JOffLong_X1(__single_step_j_insn) != 0); 364867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 365867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 366867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 367867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we are returning from a syscall, we still haven't hit the 368867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * "ill" for the swint1 instruction. So back the PC up to be 369867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pointing at the swint1, but we'll actually return directly 370867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * back to the "ill" so we come back in via SIGILL as if we 371867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * had "executed" the swint1 without ever being in kernel space. 372867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 373867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (regs->faultnum == INT_SWINT_1) 374867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->pc -= 8; 375867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 3760707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pc = (tile_bundle_bits __user *)(regs->pc); 3770707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf if (get_user(bundle, pc) != 0) { 3780707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Couldn't read instruction at %p trying to step\n", pc); 3790707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf return; 3800707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf } 381867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 382867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* We'll follow the instruction with 2 ill op bundles */ 3830707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf state->orig_pc = (unsigned long)pc; 384867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = (unsigned long)(pc + 1); 385867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->branch_next_pc = 0; 386867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 0; 387867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 388867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (!(bundle & TILE_BUNDLE_Y_ENCODING_MASK)) { 389867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* two wide, check for control flow */ 390867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int opcode = get_Opcode_X1(bundle); 391867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 392867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (opcode) { 393867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* branches */ 394867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case BRANCH_OPCODE_X1: 395867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 39604f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf s32 offset = signExtend17(get_BrOff_X1(bundle)); 397867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 398867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 399867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * For branches, we use a rewriting trick to let the 400867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * hardware evaluate whether the branch is taken or 401867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * untaken. We record the target offset and then 402867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * rewrite the branch instruction to target 1 insn 403867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * ahead if the branch is taken. We then follow the 404867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * rewritten branch with two bundles, each containing 405867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * an "ill" instruction. The supervisor examines the 406867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pc after the single step code is executed, and if 407867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * the pc is the first ill instruction, then the 408867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * branch (if any) was not taken. If the pc is the 409867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * second ill instruction, then the branch was 410867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * taken. The new pc is computed for these cases, and 411867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * inserted into the registers for the thread. If 412867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * the pc is the start of the single step code, then 413867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * an exception or interrupt was taken before the 414867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * code started processing, and the same "original" 415867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * pc is restored. This change, different from the 416867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * original implementation, has the advantage of 417867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * executing a single user instruction. 418867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 419867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->branch_next_pc = (unsigned long)(pc + offset); 420867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 421867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* rewrite branch offset to go forward one bundle */ 422867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = set_BrOff_X1(bundle, 2); 423867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 424867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 425867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 426867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* jumps */ 427867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALB_OPCODE_X1: 428867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALF_OPCODE_X1: 429867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 430867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 431867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long) (pc + get_JOffLong_X1(bundle)); 432867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 433867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 434867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JB_OPCODE_X1: 435867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JF_OPCODE_X1: 436867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 437867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long) (pc + get_JOffLong_X1(bundle)); 438867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 439867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 440867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 441867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SPECIAL_0_OPCODE_X1: 442867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_RRROpcodeExtension_X1(bundle)) { 443867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* jump-register */ 444867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALRP_SPECIAL_0_OPCODE_X1: 445867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JALR_SPECIAL_0_OPCODE_X1: 446867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 447867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 448867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[get_SrcA_X1(bundle)]; 449867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 450867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 451867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JRP_SPECIAL_0_OPCODE_X1: 452867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case JR_SPECIAL_0_OPCODE_X1: 453867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = 454867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[get_SrcA_X1(bundle)]; 455867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 456867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 457867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 458867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LNK_SPECIAL_0_OPCODE_X1: 459867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 1; 460867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf target_reg = get_Dest_X1(bundle); 461867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 462867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 463867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* stores */ 464867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SH_SPECIAL_0_OPCODE_X1: 465867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 466867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 467867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 468867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 469867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SW_SPECIAL_0_OPCODE_X1: 470867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 471867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 472867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 473867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 474867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 475867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 476867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* loads and iret */ 477867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SHUN_0_OPCODE_X1: 478867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (get_UnShOpcodeExtension_X1(bundle) == 479867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf UN_0_SHUN_0_OPCODE_X1) { 480867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_UnOpcodeExtension_X1(bundle)) { 481867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_UN_0_SHUN_0_OPCODE_X1: 482867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 483867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 484867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 485867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 486867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 487867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_U_UN_0_SHUN_0_OPCODE_X1: 488867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 489867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 490867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 491867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 492867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 493867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LW_UN_0_SHUN_0_OPCODE_X1: 494867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 495867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 496867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 497867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 498867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case IRET_UN_0_SHUN_0_OPCODE_X1: 499867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 500867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long ex0_0 = __insn_mfspr( 501867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf SPR_EX_CONTEXT_0_0); 502867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long ex0_1 = __insn_mfspr( 503867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf SPR_EX_CONTEXT_0_1); 504867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 505867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Special-case it if we're iret'ing 506867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * to PL0 again. Otherwise just let 507867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * it run and it will generate SIGILL. 508867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 509867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (EX1_PL(ex0_1) == USER_PL) { 510867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->next_pc = ex0_0; 511867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->ex1 = ex0_1; 512867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = nop_X1(bundle); 513867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 514867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 515867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 516867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 517867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 518867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 519867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#if CHIP_HAS_WH64() 520867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* postincrement operations */ 521867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case IMM_0_OPCODE_X1: 522867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (get_ImmOpcodeExtension_X1(bundle)) { 523867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LWADD_IMM_0_OPCODE_X1: 524867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 525867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 526867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 527867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 528867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LHADD_IMM_0_OPCODE_X1: 529867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 530867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 531867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 532867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 533867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 534867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LHADD_U_IMM_0_OPCODE_X1: 535867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD_POSTINCR; 536867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 537867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 538867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 539867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 540867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SWADD_IMM_0_OPCODE_X1: 541867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE_POSTINCR; 542867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 543867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 544867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 545867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SHADD_IMM_0_OPCODE_X1: 546867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE_POSTINCR; 547867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 548867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 549867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 550867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf default: 551867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 552867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 553867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 554867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* CHIP_HAS_WH64() */ 555867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 556867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 557867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state->update) { 558867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 559867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Get an available register. We start with a 560867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * bitmask with 1's for available registers. 561867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We truncate to the low 32 registers since 562867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * we are guaranteed to have set bits in the 563867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * low 32 bits, then use ctz to pick the first. 564867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 565867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf u32 mask = (u32) ~((1ULL << get_Dest_X0(bundle)) | 566867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << get_SrcA_X0(bundle)) | 567867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << get_SrcB_X0(bundle)) | 568867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (1ULL << target_reg)); 569867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf temp_reg = __builtin_ctz(mask); 570867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_reg = temp_reg; 571867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update_value = regs->regs[temp_reg]; 572867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->regs[temp_reg] = (unsigned long) (pc+1); 573867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->flags |= PT_FLAGS_RESTORE_REGS; 574867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = move_X1(bundle, target_reg, temp_reg); 575867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 576867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 577867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int opcode = get_Opcode_Y2(bundle); 578867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 579867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf switch (opcode) { 580867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* loads */ 581867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_OPCODE_Y2: 582867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 583867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 584867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 1; 585867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 586867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 587867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LH_U_OPCODE_Y2: 588867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 589867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 590867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sign_ext = 0; 591867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 592867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 593867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case LW_OPCODE_Y2: 594867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_LOAD; 595867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 596867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 597867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 598867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* stores */ 599867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SH_OPCODE_Y2: 600867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 601867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 2; 602867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 603867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 604867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf case SW_OPCODE_Y2: 605867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op = MEMOP_STORE; 606867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf size = 4; 607867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 608867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 609867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 610867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 611867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 612867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Check if we need to rewrite an unaligned load/store. 613867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Returning zero is a special value meaning we need to SIGSEGV. 614867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 615867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (mem_op != MEMOP_NONE && unaligned_fixup >= 0) { 616867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = rewrite_load_store_unaligned(state, bundle, regs, 617867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf mem_op, size, sign_ext); 618867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (bundle == 0) 619867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 620867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 621867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 622867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* write the bundle to our execution area */ 623867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf buffer = state->buffer; 624867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err = __put_user(bundle, buffer++); 625867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 626867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 627867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we're really single-stepping, we take an INT_ILL after. 628867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we're just handling an unaligned access, we can just 629867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * jump directly back to where we were in user code. 630867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 631867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (is_single_step) { 632867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(__single_step_ill_insn, buffer++); 633867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(__single_step_ill_insn, buffer++); 634867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else { 635867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf long delta; 636867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 637867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (state->update) { 638867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* We have some state to update; do it inline */ 639867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int ha16; 640867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_addli_insn; 641867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Dest_X1(state->update_reg); 642867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Imm16_X1(state->update_value); 643867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 644867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_auli_insn; 645867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Dest_X1(state->update_reg); 646867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_SrcA_X1(state->update_reg); 647867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ha16 = (state->update_value + 0x8000) >> 16; 648867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_Imm16_X1(ha16); 649867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 650867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->update = 0; 651867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 652867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 653867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* End with a jump back to the next instruction */ 654867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf delta = ((regs->pc + TILE_BUNDLE_SIZE_IN_BYTES) - 655867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (unsigned long)buffer) >> 656867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES; 657867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle = __single_step_j_insn; 658867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf bundle |= create_JOffLong_X1(delta); 659867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf err |= __put_user(bundle, buffer++); 660867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 661867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 662867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (err) { 6630707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_err("Fault when writing to single-step buffer\n"); 664867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return; 665867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 666867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 667867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 668867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Flush the buffer. 669867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We do a local flush only, since this is a thread-specific buffer. 670867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 6710707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf __flush_icache_range((unsigned long)state->buffer, 6720707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf (unsigned long)buffer); 673867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 674867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Indicate enabled */ 675867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf state->is_enabled = is_single_step; 6760707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf regs->pc = (unsigned long)state->buffer; 677867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 678867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Fault immediately if we are coming back from a syscall. */ 679867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (regs->faultnum == INT_SWINT_1) 680867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf regs->pc += 8; 681867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 682867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 683233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#else 684233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <linux/smp.h> 685233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <linux/ptrace.h> 686233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf#include <arch/spr_def.h> 687233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 688233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfstatic DEFINE_PER_CPU(unsigned long, ss_saved_pc); 689233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 690233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 691233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf/* 692233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * Called directly on the occasion of an interrupt. 693233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 694233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If the process doesn't have single step set, then we use this as an 695233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * opportunity to turn single step off. 696233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 697233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * It has been mentioned that we could conditionally turn off single stepping 698233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on each entry into the kernel and rely on single_step_once to turn it 699233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on for the processes that matter (as we already do), but this 700233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * implementation is somewhat more efficient in that we muck with registers 701233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * once on a bum interrupt rather than on every entry into the kernel. 702233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 703233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred, 704233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * so we have to run through this process again before we can say that an 705233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * instruction has executed. 706233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 707233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * swint will set CANCELED, but it's a legitimate instruction. Fortunately 708233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * it changes the PC. If it hasn't changed, then we know that the interrupt 709233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * wasn't generated by swint and we'll need to run this process again before 710233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * we can say an instruction has executed. 711233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * 712233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get 713233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * on with our lives. 714233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf */ 715233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 716233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfvoid gx_singlestep_handle(struct pt_regs *regs, int fault_num) 717233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf{ 718233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); 719233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf struct thread_info *info = (void *)current_thread_info(); 720233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); 721233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); 722233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 723233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf if (is_single_step == 0) { 724233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0); 725233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 726233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf } else if ((*ss_pc != regs->pc) || 727233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) { 728233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 729233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf ptrace_notify(SIGTRAP); 730233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; 731233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; 732233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); 733233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf } 734233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf} 735233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 736233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 737233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf/* 738233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * Called from need_singlestep. Set up the control registers and the enable 739233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf * register, then return back. 740233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf */ 741233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 742233325b94999d4bb8df227bb39904a57509e4995Chris Metcalfvoid single_step_once(struct pt_regs *regs) 743233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf{ 744233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); 745233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); 746233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 747233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf *ss_pc = regs->pc; 748233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; 749233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; 750233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); 751233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL); 752233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf} 753233325b94999d4bb8df227bb39904a57509e4995Chris Metcalf 75404f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalfvoid single_step_execve(void) 75504f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf{ 75604f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf /* Nothing */ 75704f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf} 75804f7a3f12e10032ee3d44df1a509dbf5b2001fceChris Metcalf 759867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* !__tilegx__ */ 760