PageRenderTime 22ms CodeModel.GetById 13ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/ppc64/lib/sstep.c

https://bitbucket.org/evzijst/gittest
C | 141 lines | 105 code | 6 blank | 30 comment | 35 complexity | 639df0b67f846c43feb94ff7cbe06560 MD5 | raw file
  1/*
  2 * Single-step support.
  3 *
  4 * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the License, or (at your option) any later version.
 10 */
 11#include <linux/kernel.h>
 12#include <linux/ptrace.h>
 13#include <asm/sstep.h>
 14#include <asm/processor.h>
 15
 16extern char system_call_common[];
 17
 18/* Bits in SRR1 that are copied from MSR */
 19#define MSR_MASK	0xffffffff87c0ffff
 20
 21/*
 22 * Determine whether a conditional branch instruction would branch.
 23 */
 24static int branch_taken(unsigned int instr, struct pt_regs *regs)
 25{
 26	unsigned int bo = (instr >> 21) & 0x1f;
 27	unsigned int bi;
 28
 29	if ((bo & 4) == 0) {
 30		/* decrement counter */
 31		--regs->ctr;
 32		if (((bo >> 1) & 1) ^ (regs->ctr == 0))
 33			return 0;
 34	}
 35	if ((bo & 0x10) == 0) {
 36		/* check bit from CR */
 37		bi = (instr >> 16) & 0x1f;
 38		if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
 39			return 0;
 40	}
 41	return 1;
 42}
 43
 44/*
 45 * Emulate instructions that cause a transfer of control.
 46 * Returns 1 if the step was emulated, 0 if not,
 47 * or -1 if the instruction is one that should not be stepped,
 48 * such as an rfid, or a mtmsrd that would clear MSR_RI.
 49 */
 50int emulate_step(struct pt_regs *regs, unsigned int instr)
 51{
 52	unsigned int opcode, rd;
 53	unsigned long int imm;
 54
 55	opcode = instr >> 26;
 56	switch (opcode) {
 57	case 16:	/* bc */
 58		imm = (signed short)(instr & 0xfffc);
 59		if ((instr & 2) == 0)
 60			imm += regs->nip;
 61		regs->nip += 4;
 62		if ((regs->msr & MSR_SF) == 0)
 63			regs->nip &= 0xffffffffUL;
 64		if (instr & 1)
 65			regs->link = regs->nip;
 66		if (branch_taken(instr, regs))
 67			regs->nip = imm;
 68		return 1;
 69	case 17:	/* sc */
 70		/*
 71		 * N.B. this uses knowledge about how the syscall
 72		 * entry code works.  If that is changed, this will
 73		 * need to be changed also.
 74		 */
 75		regs->gpr[9] = regs->gpr[13];
 76		regs->gpr[11] = regs->nip + 4;
 77		regs->gpr[12] = regs->msr & MSR_MASK;
 78		regs->gpr[13] = (unsigned long) get_paca();
 79		regs->nip = (unsigned long) &system_call_common;
 80		regs->msr = MSR_KERNEL;
 81		return 1;
 82	case 18:	/* b */
 83		imm = instr & 0x03fffffc;
 84		if (imm & 0x02000000)
 85			imm -= 0x04000000;
 86		if ((instr & 2) == 0)
 87			imm += regs->nip;
 88		if (instr & 1) {
 89			regs->link = regs->nip + 4;
 90			if ((regs->msr & MSR_SF) == 0)
 91				regs->link &= 0xffffffffUL;
 92		}
 93		if ((regs->msr & MSR_SF) == 0)
 94			imm &= 0xffffffffUL;
 95		regs->nip = imm;
 96		return 1;
 97	case 19:
 98		switch (instr & 0x7fe) {
 99		case 0x20:	/* bclr */
100		case 0x420:	/* bcctr */
101			imm = (instr & 0x400)? regs->ctr: regs->link;
102			regs->nip += 4;
103			if ((regs->msr & MSR_SF) == 0) {
104				regs->nip &= 0xffffffffUL;
105				imm &= 0xffffffffUL;
106			}
107			if (instr & 1)
108				regs->link = regs->nip;
109			if (branch_taken(instr, regs))
110				regs->nip = imm;
111			return 1;
112		case 0x24:	/* rfid, scary */
113			return -1;
114		}
115	case 31:
116		rd = (instr >> 21) & 0x1f;
117		switch (instr & 0x7fe) {
118		case 0xa6:	/* mfmsr */
119			regs->gpr[rd] = regs->msr & MSR_MASK;
120			regs->nip += 4;
121			if ((regs->msr & MSR_SF) == 0)
122				regs->nip &= 0xffffffffUL;
123			return 1;
124		case 0x164:	/* mtmsrd */
125			/* only MSR_EE and MSR_RI get changed if bit 15 set */
126			/* mtmsrd doesn't change MSR_HV and MSR_ME */
127			imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
128			imm = (regs->msr & MSR_MASK & ~imm)
129				| (regs->gpr[rd] & imm);
130			if ((imm & MSR_RI) == 0)
131				/* can't step mtmsrd that would clear MSR_RI */
132				return -1;
133			regs->msr = imm;
134			regs->nip += 4;
135			if ((imm & MSR_SF) == 0)
136				regs->nip &= 0xffffffffUL;
137			return 1;
138		}
139	}
140	return 0;
141}