Commit d955189a authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman

powerpc: Handle opposite-endian processes in emulation code

This adds code to the load and store emulation code to byte-swap
the data appropriately when the process being emulated is set to
the opposite endianness to that of the kernel.

This also enables the emulation for the multiple-register loads
and stores (lmw, stmw, lswi, stswi, lswx, stswx) to work for
little-endian.  In little-endian mode, the partial word at the
end of a transfer for lsw*/stsw* (when the byte count is not a
multiple of 4) is loaded/stored at the least-significant end of
the register.  Additionally, this fixes a bug in the previous
code in that it could call read_mem/write_mem with a byte count
that was not 1, 2, 4 or 8.

Note that this only works correctly on processors with "true"
little-endian mode, such as IBM POWER processors from POWER6 on, not
the so-called "PowerPC" little-endian mode that uses address swizzling
as implemented on the old 32-bit 603, 604, 740/750, 74xx CPUs.
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent b9da9c8a
...@@ -153,7 +153,8 @@ void emulate_update_regs(struct pt_regs *reg, struct instruction_op *op); ...@@ -153,7 +153,8 @@ void emulate_update_regs(struct pt_regs *reg, struct instruction_op *op);
extern int emulate_step(struct pt_regs *regs, unsigned int instr); extern int emulate_step(struct pt_regs *regs, unsigned int instr);
extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg, extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
const void *mem); const void *mem, bool cross_endian);
extern void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg, extern void emulate_vsx_store(struct instruction_op *op,
void *mem); const union vsx_reg *reg, void *mem,
bool cross_endian);
extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs); extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs);
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment