Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cdfcbfd authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman
Browse files

powerpc: Change analyse_instr so it doesn't modify *regs



The analyse_instr function currently doesn't just work out what an
instruction does, it also executes those instructions whose effect
is only to update CPU registers that are stored in struct pt_regs.
This is undesirable because optprobes uses analyse_instr to work out
if an instruction could be successfully emulated in future.

This changes analyse_instr so it doesn't modify *regs; instead it
stores information in the instruction_op structure to indicate what
registers (GPRs, CR, XER, LR) would be set and what value they would
be set to.  A companion function called emulate_update_regs() can
then use that information to update a pt_regs struct appropriately.

As a minor cleanup, this replaces inline asm using the cntlzw and
cntlzd instructions with calls to __builtin_clz() and __builtin_clzl().

Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 93b2d3cf
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -23,9 +23,6 @@ struct pt_regs;
#define IS_RFID(instr)		(((instr) & 0xfc0007fe) == 0x4c000024)
#define IS_RFI(instr)		(((instr) & 0xfc0007fe) == 0x4c000064)

/* Emulate instructions that cause a transfer of control. */
extern int emulate_step(struct pt_regs *regs, unsigned int instr);

enum instruction_type {
	COMPUTE,		/* arith/logical/CR op, etc. */
	LOAD,
@@ -55,11 +52,29 @@ enum instruction_type {

#define INSTR_TYPE_MASK	0x1f

/* Compute flags, ORed in with type */
#define SETREG		0x20
#define SETCC		0x40
#define SETXER		0x80

/* Branch flags, ORed in with type */
#define SETLK		0x20
#define BRTAKEN		0x40
#define DECCTR		0x80

/* Load/store flags, ORed in with type */
#define SIGNEXT		0x20
#define UPDATE		0x40	/* matches bit in opcode 31 instructions */
#define BYTEREV		0x80

/* Barrier type field, ORed in with type */
#define BARRIER_MASK	0xe0
#define BARRIER_SYNC	0x00
#define BARRIER_ISYNC	0x20
#define BARRIER_EIEIO	0x40
#define BARRIER_LWSYNC	0x60
#define BARRIER_PTESYNC	0x80

/* Cacheop values, ORed in with type */
#define CACHEOP_MASK	0x700
#define DCBST		0
@@ -83,7 +98,36 @@ struct instruction_op {
	int update_reg;
	/* For MFSPR */
	int spr;
	u32 ccval;
	u32 xerval;
};

extern int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
/*
 * Decode an instruction, and return information about it in *op
 * without changing *regs.
 *
 * Return value is 1 if the instruction can be emulated just by
 * updating *regs with the information in *op, -1 if we need the
 * GPRs but *regs doesn't contain the full register set, or 0
 * otherwise.
 */
extern int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
			 unsigned int instr);

/*
 * Emulate an instruction that can be executed just by updating
 * fields in *regs.
 */
void emulate_update_regs(struct pt_regs *reg, struct instruction_op *op);

/*
 * Emulate instructions that cause a transfer of control,
 * arithmetic/logical instructions, loads and stores,
 * cache operations and barriers.
 *
 * Returns 1 if the instruction was emulated successfully,
 * 0 if it could not be emulated, or -1 for an instruction that
 * should not be emulated (rfid, mtmsrd clearing MSR_RI, etc.).
 */
extern int emulate_step(struct pt_regs *regs, unsigned int instr);
+348 −253

File changed.

Preview size limit exceeded, changes collapsed.