16ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz/* The fake debug assert instructions 26ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz * 36ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz * Copyright 2010 Analog Devices Inc. 46ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz * 56ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz * Licensed under the GPL-2 or later 66ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz */ 76ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 86ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#include <linux/types.h> 96ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#include <linux/kernel.h> 106ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#include <linux/ptrace.h> 116ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 125a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getzconst char * const greg_names[] = { 135a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", 145a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP", 155a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3", 165a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3", 175a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS", 185a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", 195a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2", 205a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT", 215a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz}; 225a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz 235a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getzstatic const char *get_allreg_name(int grp, int reg) 245a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz{ 255a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz return greg_names[(grp << 3) | reg]; 265a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz} 275a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz 28dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz/* 29dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz * Unfortunately, the pt_regs structure is not laid out the same way as the 30dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz * hardware register file, so we need to do some fix ups. 315a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * 325a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * CYCLES is not stored in the pt_regs structure - so, we just read it from 335a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * the hardware. 345a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * 355a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * Don't support: 365a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * - All reserved registers 375a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz * - All in group 7 are (supervisors only) 38dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz */ 395a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz 40dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getzstatic bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg) 41dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz{ 42dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz long *val = &fp->r0; 435a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz unsigned long tmp; 44dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 45dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz /* Only do Dregs and Pregs for now */ 465a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz if (grp == 5 || 475a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz (grp == 4 && (reg == 4 || reg == 5)) || 485a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz (grp == 7)) 49dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz return false; 50dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 51dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz if (grp == 0 || (grp == 1 && reg < 6)) 52dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz val -= (reg + 8 * grp); 53dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz else if (grp == 1 && reg == 6) 54dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz val = &fp->usp; 55dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz else if (grp == 1 && reg == 7) 56dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz val = &fp->fp; 575a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz else if (grp == 2) { 585a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->i0; 595a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val -= reg; 605a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 3 && reg >= 4) { 615a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->l0; 625a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val -= (reg - 4); 635a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 3 && reg < 4) { 645a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->b0; 655a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val -= reg; 665a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 4 && reg < 4) { 675a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->a0x; 685a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val -= reg; 695a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 4 && reg == 6) 705a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->astat; 715a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz else if (grp == 4 && reg == 7) 725a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->rets; 735a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz else if (grp == 6 && reg < 6) { 745a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &fp->lc0; 755a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val -= reg; 765a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 6 && reg == 6) { 775a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz __asm__ __volatile__("%0 = cycles;\n" : "=d"(tmp)); 785a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &tmp; 795a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } else if (grp == 6 && reg == 7) { 805a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz __asm__ __volatile__("%0 = cycles2;\n" : "=d"(tmp)); 815a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz val = &tmp; 825a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz } 83dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 84dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz *value = *val; 85dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz return true; 86dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 87dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz} 88dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 896ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_opcode 0xf0000000 906ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_expected_bits 0 916ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_expected_mask 0xffff 926ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_regtest_bits 16 936ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_regtest_mask 0x7 946ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_grp_bits 19 956ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_grp_mask 0x7 966ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_dbgop_bits 22 976ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_dbgop_mask 0x3 986ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_dontcare_bits 24 996ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_dontcare_mask 0x7 1006ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_code_bits 27 1016ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz#define PseudoDbg_Assert_code_mask 0x1f 1026ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 103dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz/* 104dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz * DBGA - debug assert 105dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz */ 1066ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getzbool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode) 1076ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz{ 1086ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask); 1096ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz int dbgop = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask); 1106ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz int grp = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask); 1116ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz int regtest = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask); 112dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz long value; 1136ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 1146ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode) 1156ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz return false; 1166ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 117dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz if (!fix_up_reg(fp, &value, grp, regtest)) 1186ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz return false; 1196ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 1206ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz if (dbgop == 0 || dbgop == 2) { 1216ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz /* DBGA ( regs_lo , uimm16 ) */ 1226ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz /* DBGAL ( regs , uimm16 ) */ 123dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz if (expected != (value & 0xFFFF)) { 1245a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz pr_notice("DBGA (%s.L,0x%x) failure, got 0x%x\n", 1255a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz get_allreg_name(grp, regtest), 1265a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz expected, (unsigned int)(value & 0xFFFF)); 1276ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz return false; 1286ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz } 1296ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 1306ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz } else if (dbgop == 1 || dbgop == 3) { 1316ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz /* DBGA ( regs_hi , uimm16 ) */ 1326ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz /* DBGAH ( regs , uimm16 ) */ 133dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz if (expected != ((value >> 16) & 0xFFFF)) { 1345a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz pr_notice("DBGA (%s.H,0x%x) failure, got 0x%x\n", 1355a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz get_allreg_name(grp, regtest), 1365a132f7aeba772e1e1f9ccbad14a6779cd40cdfbRobin Getz expected, (unsigned int)((value >> 16) & 0xFFFF)); 1376ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz return false; 1386ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz } 1396ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz } 1406ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz 1416ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz fp->pc += 4; 1426ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz return true; 1436ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13fRobin Getz} 144dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 145dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_opcode 0xf8000000 146dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_reg_bits 0 147dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_reg_mask 0x7 148dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_grp_bits 3 149dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_grp_mask 0x7 150dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_fn_bits 6 151dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_fn_mask 0x3 152dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_code_bits 8 153dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz#define PseudoDbg_code_mask 0xff 154dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 155dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz/* 156dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz * DBG - debug (dump a register value out) 157dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz */ 158dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getzbool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode) 159dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz{ 160dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz int grp, fn, reg; 161a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz long value, value1; 162dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 163dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz if ((opcode & 0xFF000000) != PseudoDbg_opcode) 164dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz return false; 165dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 166dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz opcode >>= 16; 167dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz grp = ((opcode >> PseudoDbg_grp_bits) & PseudoDbg_reg_mask); 168dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz fn = ((opcode >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask); 169dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz reg = ((opcode >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask); 170dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 171a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz if (fn == 3 && (reg == 0 || reg == 1)) { 172a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz if (!fix_up_reg(fp, &value, 4, 2 * reg)) 173a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return false; 174a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz if (!fix_up_reg(fp, &value1, 4, 2 * reg + 1)) 175a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return false; 176dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 177a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz pr_notice("DBG A%i = %02lx%08lx\n", reg, value & 0xFF, value1); 178a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz fp->pc += 2; 179a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return true; 180dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz 181a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz } else if (fn == 0) { 182a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz if (!fix_up_reg(fp, &value, grp, reg)) 183a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return false; 184a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz 185a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz pr_notice("DBG %s = %08lx\n", get_allreg_name(grp, reg), value); 186a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz fp->pc += 2; 187a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return true; 188a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz } 189a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz 190a6d9dbf5e4daaf21b33917a809a5ac1e7bce9e05Robin Getz return false; 191dc89d97fc73176c883b32ff21ae6f1164ca20d05Robin Getz} 192