powerpc: Use a datatype for instructions

Currently unsigned ints are used to represent instructions on powerpc.
This has worked well as instructions have always been 4 byte words.

However, ISA v3.1 introduces some changes to instructions that mean
this scheme will no longer work as well. This change is Prefixed
Instructions. A prefixed instruction is made up of a word prefix
followed by a word suffix to make an 8 byte double word instruction.
No matter the endianness of the system the prefix always comes first.
Prefixed instructions are only planned for powerpc64.

Introduce a ppc_inst type to represent both prefixed and word
instructions on powerpc64 while keeping it possible to exclusively
have word instructions on powerpc32.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
[mpe: Fix compile error in emulate_spe()]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200506034050.24806-12-jniethe5@gmail.com
This commit is contained in:
Jordan Niethe
2020-05-06 13:40:31 +10:00
committed by Michael Ellerman
parent 217862d9b9
commit 94afd069d9
26 changed files with 237 additions and 214 deletions

View File

@@ -100,7 +100,7 @@ static long *xmon_fault_jmp[NR_CPUS];
/* Breakpoint stuff */
struct bpt {
unsigned long address;
unsigned int *instr;
struct ppc_inst *instr;
atomic_t ref_count;
int enabled;
unsigned long pad;
@@ -876,8 +876,8 @@ static struct bpt *new_breakpoint(unsigned long a)
for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
bp->address = a;
bp->instr = bpt_table + ((bp - bpts) * BPT_WORDS);
patch_instruction(bp->instr + 1, bpinstr);
bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
patch_instruction(bp->instr + 1, ppc_inst(bpinstr));
return bp;
}
}
@@ -889,7 +889,7 @@ static struct bpt *new_breakpoint(unsigned long a)
static void insert_bpts(void)
{
int i;
unsigned int instr;
struct ppc_inst instr;
struct bpt *bp;
bp = bpts;
@@ -911,8 +911,8 @@ static void insert_bpts(void)
patch_instruction(bp->instr, instr);
if (bp->enabled & BP_CIABR)
continue;
if (patch_instruction((unsigned int *)bp->address,
bpinstr) != 0) {
if (patch_instruction((struct ppc_inst *)bp->address,
ppc_inst(bpinstr)) != 0) {
printf("Couldn't write instruction at %lx, "
"disabling breakpoint there\n", bp->address);
bp->enabled &= ~BP_TRAP;
@@ -940,7 +940,7 @@ static void remove_bpts(void)
{
int i;
struct bpt *bp;
unsigned instr;
struct ppc_inst instr;
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
@@ -949,7 +949,7 @@ static void remove_bpts(void)
if (mread(bp->address, &instr, 4) == 4
&& ppc_inst_equal(instr, ppc_inst(bpinstr))
&& patch_instruction(
(unsigned int *)bp->address, bp->instr[0]) != 0)
(struct ppc_inst *)bp->address, bp->instr[0]) != 0)
printf("Couldn't remove breakpoint at %lx\n",
bp->address);
}
@@ -1156,7 +1156,7 @@ static int do_step(struct pt_regs *regs)
*/
static int do_step(struct pt_regs *regs)
{
unsigned int instr;
struct ppc_inst instr;
int stepped;
force_enable_xmon();
@@ -1322,7 +1322,7 @@ csum(void)
*/
static long check_bp_loc(unsigned long addr)
{
unsigned int instr;
struct ppc_inst instr;
addr &= ~3;
if (!is_kernel_addr(addr)) {
@@ -2848,7 +2848,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
{
int nr, dotted;
unsigned long first_adr;
unsigned int inst, last_inst = ppc_inst(0);
struct ppc_inst inst, last_inst = ppc_inst(0);
unsigned char val[4];
dotted = 0;