]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
powerpc: Unify opcode definitions and support
authorKumar Gala <galak@kernel.crashing.org>
Tue, 10 Feb 2009 20:10:44 +0000 (20:10 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Sun, 22 Feb 2009 23:48:56 +0000 (10:48 +1100)
Create a new header that becomes a single location for defining PowerPC
opcodes used by code that is either generationg instructions
at runtime (fixups, debug, etc.), emulating instructions, or just
compiling instructions old assemblers don't know about.

We currently don't handle the floating point emulation or alignment decode
as both are better handled by the specific decode support they already
have.

Added support for the new dcbzl, dcbal, msgsnd, tlbilx, & wait instructions
since older assemblers don't know about them.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/code-patching.h
arch/powerpc/include/asm/ppc-opcode.h [new file with mode: 0644]
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/ftrace.c
arch/powerpc/kernel/head_booke.h
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/traps.c
arch/powerpc/lib/feature-fixups.c

index 107d9b915e33e9559f14357a2e4f55cf3f857e82..37c32aba79b7f690dc749af1b2c9393719cc27cb 100644 (file)
@@ -11,9 +11,7 @@
  */
 
 #include <asm/types.h>
-
-#define PPC_NOP_INSTR          0x60000000
-#define PPC_LWSYNC_INSTR       0x7c2004ac
+#include <asm/ppc-opcode.h>
 
 /* Flags for create_branch:
  * "b"   == create_branch(addr, target, 0);
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
new file mode 100644 (file)
index 0000000..f4a4db8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Freescale Semicondutor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * provides masks and opcode images for use by code generation, emulation
+ * and for instructions that older assemblers might not know about
+ */
+#ifndef _ASM_POWERPC_PPC_OPCODE_H
+#define _ASM_POWERPC_PPC_OPCODE_H
+
+#include <linux/stringify.h>
+#include <asm/asm-compat.h>
+
+/* sorted alphabetically */
+#define PPC_INST_DCBA                  0x7c0005ec
+#define PPC_INST_DCBA_MASK             0xfc0007fe
+#define PPC_INST_DCBAL                 0x7c2005ec
+#define PPC_INST_DCBZL                 0x7c2007ec
+#define PPC_INST_ISEL                  0x7c00001e
+#define PPC_INST_ISEL_MASK             0xfc00003e
+#define PPC_INST_LSWI                  0x7c0004aa
+#define PPC_INST_LSWX                  0x7c00042a
+#define PPC_INST_LWSYNC                        0x7c2004ac
+#define PPC_INST_MCRXR                 0x7c000400
+#define PPC_INST_MCRXR_MASK            0xfc0007fe
+#define PPC_INST_MFSPR_PVR             0x7c1f42a6
+#define PPC_INST_MFSPR_PVR_MASK                0xfc1fffff
+#define PPC_INST_MSGSND                        0x7c00019c
+#define PPC_INST_NOP                   0x60000000
+#define PPC_INST_POPCNTB               0x7c0000f4
+#define PPC_INST_POPCNTB_MASK          0xfc0007fe
+#define PPC_INST_RFCI                  0x4c000066
+#define PPC_INST_RFDI                  0x4c00004e
+#define PPC_INST_RFMCI                 0x4c00004c
+
+#define PPC_INST_STRING                        0x7c00042a
+#define PPC_INST_STRING_MASK           0xfc0007fe
+#define PPC_INST_STRING_GEN_MASK       0xfc00067e
+
+#define PPC_INST_STSWI                 0x7c0005aa
+#define PPC_INST_STSWX                 0x7c00052a
+#define PPC_INST_TLBILX                        0x7c000626
+#define PPC_INST_WAIT                  0x7c00007c
+
+/* macros to insert fields into opcodes */
+#define __PPC_RA(a)    ((a & 0x1f) << 16)
+#define __PPC_RB(b)    ((b & 0x1f) << 11)
+#define __PPC_T_TLB(t) ((t & 0x3) << 21)
+#define __PPC_WC(w)    ((w & 0x3) << 21)
+
+/* Deal with instructions that older assemblers aren't aware of */
+#define        PPC_DCBAL(a, b)         stringify_in_c(.long PPC_INST_DCBAL | \
+                                       __PPC_RA(a) | __PPC_RB(b))
+#define        PPC_DCBZL(a, b)         stringify_in_c(.long PPC_INST_DCBZL | \
+                                       __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MSGSND(b)          stringify_in_c(.long PPC_INST_MSGSND | \
+                                       __PPC_RB(b))
+#define PPC_RFCI               stringify_in_c(.long PPC_INST_RFCI)
+#define PPC_RFDI               stringify_in_c(.long PPC_INST_RFDI)
+#define PPC_RFMCI              stringify_in_c(.long PPC_INST_RFMCI)
+#define PPC_TLBILX(t, a, b)    stringify_in_c(.long PPC_INST_TLBILX | \
+                                       __PPC_T_TLB(t) | __PPC_RA(a) | __PPC_RB(b))
+#define PPC_TLBILX_ALL(a, b)   PPC_TLBILX(0, a, b)
+#define PPC_TLBILX_PID(a, b)   PPC_TLBILX(1, a, b)
+#define PPC_TLBILX_VA(a, b)    PPC_TLBILX(3, a, b)
+#define PPC_WAIT(w)            stringify_in_c(.long PPC_INST_WAIT | \
+                                       __PPC_WC(w))
+
+#endif /* _ASM_POWERPC_PPC_OPCODE_H */
index 1a0d628eb114bc0f1a6a930ee1a171c91c1eae06..f59a66684aed56ad82d4ecac33696784edab18f7 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/stringify.h>
 #include <asm/asm-compat.h>
 #include <asm/processor.h>
+#include <asm/ppc-opcode.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -167,11 +168,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR);                                       \
 #define HMT_MEDIUM_HIGH or     5,5,5           # medium high priority
 #define HMT_HIGH       or      3,3,3
 
-/* handle instructions that older assemblers may not know */
-#define RFCI           .long 0x4c000066        /* rfci instruction */
-#define RFDI           .long 0x4c00004e        /* rfdi instruction */
-#define RFMCI          .long 0x4c00004c        /* rfmci instruction */
-
 #ifdef __KERNEL__
 #ifdef CONFIG_PPC64
 
index 19671aca659137ca8a6f62ac80585d969203a6f9..5fb667a60894dd6238b51db9c13b1caf93fc0253 100644 (file)
@@ -48,7 +48,7 @@ static void __init create_trampoline(unsigned long addr)
         * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
         * two instructions it doesn't require any registers.
         */
-       patch_instruction(p, PPC_NOP_INSTR);
+       patch_instruction(p, PPC_INST_NOP);
        patch_branch(++p, addr + PHYSICAL_START, 0);
 }
 
index 0506f54b4237acf706faa1b9160c670c8a245474..4dd38f129153f7c90340cde840774dc11da22500 100644 (file)
@@ -956,7 +956,7 @@ ret_from_crit_exc:
        lwz     r10,crit_srr1@l(r10);
        mtspr   SPRN_SRR0,r9;
        mtspr   SPRN_SRR1,r10;
-       RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+       RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI)
 #endif /* CONFIG_40x */
 
 #ifdef CONFIG_BOOKE
@@ -967,7 +967,7 @@ ret_from_crit_exc:
        stw     r10,KSP_LIMIT(r9)
        RESTORE_xSRR(SRR0,SRR1);
        RESTORE_MMU_REGS;
-       RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+       RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI)
 
        .globl  ret_from_debug_exc
 ret_from_debug_exc:
@@ -981,7 +981,7 @@ ret_from_debug_exc:
        RESTORE_xSRR(SRR0,SRR1);
        RESTORE_xSRR(CSRR0,CSRR1);
        RESTORE_MMU_REGS;
-       RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
+       RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, PPC_RFDI)
 
        .globl  ret_from_mcheck_exc
 ret_from_mcheck_exc:
@@ -992,7 +992,7 @@ ret_from_mcheck_exc:
        RESTORE_xSRR(CSRR0,CSRR1);
        RESTORE_xSRR(DSRR0,DSRR1);
        RESTORE_MMU_REGS;
-       RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
+       RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, PPC_RFMCI)
 #endif /* CONFIG_BOOKE */
 
 /*
index 4c75a1c0a5b4fec5299587199b45c05a91237617..5b5d16b2cac86b0dad038cdcc13c2cc686bd41a2 100644 (file)
@@ -33,7 +33,7 @@
 #ifdef CONFIG_DYNAMIC_FTRACE
 static unsigned int ftrace_nop_replace(void)
 {
-       return PPC_NOP_INSTR;
+       return PPC_INST_NOP;
 }
 
 static unsigned int
@@ -302,7 +302,7 @@ __ftrace_make_nop(struct module *mod,
                return -EINVAL;
        }
 
-       op = PPC_NOP_INSTR;
+       op = PPC_INST_NOP;
 
        if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
                return -EPERM;
@@ -380,7 +380,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
         *  b +8; ld r2,40(r1)
         */
        if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) &&
-           ((op[0] != PPC_NOP_INSTR) || (op[1] != PPC_NOP_INSTR))) {
+           ((op[0] != PPC_INST_NOP) || (op[1] != PPC_INST_NOP))) {
                printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]);
                return -EINVAL;
        }
@@ -423,7 +423,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
                return -EFAULT;
 
        /* It should be pointing to a nop */
-       if (op != PPC_NOP_INSTR) {
+       if (op != PPC_INST_NOP) {
                printk(KERN_ERR "Expected NOP but have %x\n", op);
                return -EINVAL;
        }
index bec18078239daea41c6583e6feca8bc4b334d58c..38e242eb0ef8f835bb79008a6c7a1cb84025e9ec 100644 (file)
@@ -279,7 +279,7 @@ label:
        lwz     r11,GPR11(r8);                                                \
        mfspr   r8,DEBUG_SPRG;                                                \
                                                                              \
-       RFDI;                                                                 \
+       PPC_RFDI;                                                                     \
        b       .;                                                            \
                                                                              \
        /* continue normal handling for a debug exception... */               \
index 8992b031a7b6a6cc54433453b6b991d1610cb5d6..8fbb12508bf3a25b54401ef1907d3930bc30522e 100644 (file)
@@ -329,7 +329,7 @@ static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
    restore r2. */
 static int restore_r2(u32 *instruction, struct module *me)
 {
-       if (*instruction != PPC_NOP_INSTR) {
+       if (*instruction != PPC_INST_NOP) {
                printk("%s: Expect noop after relocate, got %08x\n",
                       me->name, *instruction);
                return 0;
index 5457e9575685291a5a84dcad525cd89b009c9e1e..970d66ec46579202db8e8219d7d708fa9edd657b 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/processor.h>
 #endif
 #include <asm/kexec.h>
+#include <asm/ppc-opcode.h>
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 int (*__debugger)(struct pt_regs *regs);
@@ -637,29 +638,6 @@ static void parse_fpe(struct pt_regs *regs)
  * bits is faster and easier.
  *
  */
-#define INST_MFSPR_PVR         0x7c1f42a6
-#define INST_MFSPR_PVR_MASK    0xfc1fffff
-
-#define INST_DCBA              0x7c0005ec
-#define INST_DCBA_MASK         0xfc0007fe
-
-#define INST_MCRXR             0x7c000400
-#define INST_MCRXR_MASK                0xfc0007fe
-
-#define INST_STRING            0x7c00042a
-#define INST_STRING_MASK       0xfc0007fe
-#define INST_STRING_GEN_MASK   0xfc00067e
-#define INST_LSWI              0x7c0004aa
-#define INST_LSWX              0x7c00042a
-#define INST_STSWI             0x7c0005aa
-#define INST_STSWX             0x7c00052a
-
-#define INST_POPCNTB           0x7c0000f4
-#define INST_POPCNTB_MASK      0xfc0007fe
-
-#define INST_ISEL              0x7c00001e
-#define INST_ISEL_MASK         0xfc00003e
-
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
        u8 rT = (instword >> 21) & 0x1f;
@@ -670,20 +648,20 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
        int pos = 0;
 
        /* Early out if we are an invalid form of lswx */
-       if ((instword & INST_STRING_MASK) == INST_LSWX)
+       if ((instword & PPC_INST_STRING_MASK) == PPC_INST_LSWX)
                if ((rT == rA) || (rT == NB_RB))
                        return -EINVAL;
 
        EA = (rA == 0) ? 0 : regs->gpr[rA];
 
-       switch (instword & INST_STRING_MASK) {
-               case INST_LSWX:
-               case INST_STSWX:
+       switch (instword & PPC_INST_STRING_MASK) {
+               case PPC_INST_LSWX:
+               case PPC_INST_STSWX:
                        EA += NB_RB;
                        num_bytes = regs->xer & 0x7f;
                        break;
-               case INST_LSWI:
-               case INST_STSWI:
+               case PPC_INST_LSWI:
+               case PPC_INST_STSWI:
                        num_bytes = (NB_RB == 0) ? 32 : NB_RB;
                        break;
                default:
@@ -695,9 +673,9 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
                u8 val;
                u32 shift = 8 * (3 - (pos & 0x3));
 
-               switch ((instword & INST_STRING_MASK)) {
-                       case INST_LSWX:
-                       case INST_LSWI:
+               switch ((instword & PPC_INST_STRING_MASK)) {
+                       case PPC_INST_LSWX:
+                       case PPC_INST_LSWI:
                                if (get_user(val, (u8 __user *)EA))
                                        return -EFAULT;
                                /* first time updating this reg,
@@ -706,8 +684,8 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
                                        regs->gpr[rT] = 0;
                                regs->gpr[rT] |= val << shift;
                                break;
-                       case INST_STSWI:
-                       case INST_STSWX:
+                       case PPC_INST_STSWI:
+                       case PPC_INST_STSWX:
                                val = regs->gpr[rT] >> shift;
                                if (put_user(val, (u8 __user *)EA))
                                        return -EFAULT;
@@ -775,18 +753,18 @@ static int emulate_instruction(struct pt_regs *regs)
                return -EFAULT;
 
        /* Emulate the mfspr rD, PVR. */
-       if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+       if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
                rd = (instword >> 21) & 0x1f;
                regs->gpr[rd] = mfspr(SPRN_PVR);
                return 0;
        }
 
        /* Emulating the dcba insn is just a no-op.  */
-       if ((instword & INST_DCBA_MASK) == INST_DCBA)
+       if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA)
                return 0;
 
        /* Emulate the mcrxr insn.  */
-       if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+       if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) {
                int shift = (instword >> 21) & 0x1c;
                unsigned long msk = 0xf0000000UL >> shift;
 
@@ -796,16 +774,16 @@ static int emulate_instruction(struct pt_regs *regs)
        }
 
        /* Emulate load/store string insn. */
-       if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
+       if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING)
                return emulate_string_inst(regs, instword);
 
        /* Emulate the popcntb (Population Count Bytes) instruction. */
-       if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+       if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
                return emulate_popcntb_inst(regs, instword);
        }
 
        /* Emulate isel (Integer Select) instruction */
-       if ((instword & INST_ISEL_MASK) == INST_ISEL) {
+       if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
                return emulate_isel(regs, instword);
        }
 
index 8c5a03be31e07766d123460cf8b273ed6dab6d0b..7e8865bcd683a5291861f3d31e07d75d9e98277d 100644 (file)
@@ -85,7 +85,7 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
        }
 
        for (; dest < end; dest++)
-               patch_instruction(dest, PPC_NOP_INSTR);
+               patch_instruction(dest, PPC_INST_NOP);
 
        return 0;
 }
@@ -122,7 +122,7 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 
        for (; start < end; start++) {
                dest = (void *)start + *start;
-               patch_instruction(dest, PPC_LWSYNC_INSTR);
+               patch_instruction(dest, PPC_INST_LWSYNC);
        }
 }