Merge tag 'for-linus-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw...
[linux-2.6-microblaze.git] / arch / powerpc / kernel / head_40x.S
index 24724a7..e1360b8 100644 (file)
@@ -89,7 +89,11 @@ _ENTRY(crit_srr0)
        .space  4
 _ENTRY(crit_srr1)
        .space  4
-_ENTRY(saved_ksp_limit)
+_ENTRY(crit_r1)
+       .space  4
+_ENTRY(crit_dear)
+       .space  4
+_ENTRY(crit_esr)
        .space  4
 
 /*
@@ -100,42 +104,62 @@ _ENTRY(saved_ksp_limit)
  * Instead we use a couple of words of memory at low physical addresses.
  * This is OK since we don't support SMP on these processors.
  */
-#define CRITICAL_EXCEPTION_PROLOG                                           \
-       stw     r10,crit_r10@l(0);      /* save two registers to work with */\
-       stw     r11,crit_r11@l(0);                                           \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_SRR3;          /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       lis     r11,critirq_ctx@ha;                                          \
-       tophys(r11,r11);                                                     \
-       lwz     r11,critirq_ctx@l(r11);                                      \
-       beq     1f;                                                          \
-       /* COMING FROM USER MODE */                                          \
-       mfspr   r11,SPRN_SPRG_THREAD;   /* if from user, start at top of   */\
-       lwz     r11,TASK_STACK-THREAD(r11); /* this thread's kernel stack */\
-1:     addi    r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc an excpt frm  */\
-       tophys(r11,r11);                                                     \
-       stw     r10,_CCR(r11);          /* save various registers          */\
-       stw     r12,GPR12(r11);                                              \
-       stw     r9,GPR9(r11);                                                \
-       mflr    r10;                                                         \
-       stw     r10,_LINK(r11);                                              \
-       mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
-       stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
-       mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
-       stw     r9,_ESR(r11);           /* exception was taken             */\
-       mfspr   r12,SPRN_SRR2;                                               \
-       stw     r1,GPR1(r11);                                                \
-       mfspr   r9,SPRN_SRR3;                                                \
-       stw     r1,0(r11);                                                   \
-       tovirt(r1,r11);                                                      \
-       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
-       stw     r0,GPR0(r11);                                                \
-       lis     r10, STACK_FRAME_REGS_MARKER@ha; /* exception frame marker */\
-       addi    r10, r10, STACK_FRAME_REGS_MARKER@l;                         \
-       stw     r10, 8(r11);                                                 \
-       SAVE_4GPRS(3, r11);                                                  \
-       SAVE_2GPRS(7, r11)
+.macro CRITICAL_EXCEPTION_PROLOG trapno name
+       stw     r10,crit_r10@l(0)       /* save two registers to work with */
+       stw     r11,crit_r11@l(0)
+       mfspr   r10,SPRN_SRR0
+       mfspr   r11,SPRN_SRR1
+       stw     r10,crit_srr0@l(0)
+       stw     r11,crit_srr1@l(0)
+       mfspr   r10,SPRN_DEAR
+       mfspr   r11,SPRN_ESR
+       stw     r10,crit_dear@l(0)
+       stw     r11,crit_esr@l(0)
+       mfcr    r10                     /* save CR in r10 for now          */
+       mfspr   r11,SPRN_SRR3           /* check whether user or kernel    */
+       andi.   r11,r11,MSR_PR
+       lis     r11,(critirq_ctx-PAGE_OFFSET)@ha
+       lwz     r11,(critirq_ctx-PAGE_OFFSET)@l(r11)
+       beq     1f
+       /* COMING FROM USER MODE */
+       mfspr   r11,SPRN_SPRG_THREAD    /* if from user, start at top of   */
+       lwz     r11,TASK_STACK-THREAD(r11) /* this thread's kernel stack */
+1:     stw     r1,crit_r1@l(0)
+       addi    r1,r11,THREAD_SIZE-INT_FRAME_SIZE /* Alloc an excpt frm  */
+       LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)) /* re-enable MMU */
+       mtspr   SPRN_SRR1, r11
+       lis     r11, 1f@h
+       ori     r11, r11, 1f@l
+       mtspr   SPRN_SRR0, r11
+       rfi
+
+       .text
+1:
+\name\()_virt:
+       lwz     r11,crit_r1@l(0)
+       stw     r11,GPR1(r1)
+       stw     r11,0(r1)
+       mr      r11,r1
+       stw     r10,_CCR(r11)           /* save various registers          */
+       stw     r12,GPR12(r11)
+       stw     r9,GPR9(r11)
+       mflr    r10
+       stw     r10,_LINK(r11)
+       lis     r9,PAGE_OFFSET@ha
+       lwz     r10,crit_r10@l(r9)
+       lwz     r12,crit_r11@l(r9)
+       stw     r10,GPR10(r11)
+       stw     r12,GPR11(r11)
+       lwz     r12,crit_dear@l(r9)
+       lwz     r9,crit_esr@l(r9)
+       stw     r12,_DEAR(r11)          /* since they may have had stuff   */
+       stw     r9,_ESR(r11)            /* exception was taken             */
+       mfspr   r12,SPRN_SRR2
+       mfspr   r9,SPRN_SRR3
+       rlwinm  r9,r9,0,14,12           /* clear MSR_WE (necessary?)       */
+       COMMON_EXCEPTION_PROLOG_END \trapno + 2
+_ASM_NOKPROBE_SYMBOL(\name\()_virt)
+.endm
 
        /*
         * State at this point:
@@ -155,10 +179,10 @@ _ENTRY(saved_ksp_limit)
  */
 #define CRITICAL_EXCEPTION(n, label, hdlr)                     \
        START_EXCEPTION(n, label);                              \
-       CRITICAL_EXCEPTION_PROLOG;                              \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
-       EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-                         crit_transfer_to_handler, ret_from_crit_exc)
+       CRITICAL_EXCEPTION_PROLOG n label;                              \
+       prepare_transfer_to_handler;                            \
+       bl      hdlr;                                           \
+       b       ret_from_crit_exc
 
 /*
  * 0x0100 - Critical Interrupt Exception
@@ -178,69 +202,67 @@ _ENTRY(saved_ksp_limit)
  * if they can't resolve the lightweight TLB fault.
  */
        START_EXCEPTION(0x0300, DataStorage)
-       EXCEPTION_PROLOG
-       mfspr   r5, SPRN_ESR            /* Grab the ESR, save it */
-       stw     r5, _ESR(r11)
-       mfspr   r4, SPRN_DEAR           /* Grab the DEAR, save it */
-       stw     r4, _DEAR(r11)
-       EXC_XFER_LITE(0x300, handle_page_fault)
+       EXCEPTION_PROLOG 0x300 DataStorage handle_dar_dsisr=1
+       prepare_transfer_to_handler
+       bl      do_page_fault
+       b       interrupt_return
 
 /*
  * 0x0400 - Instruction Storage Exception
  * This is caused by a fetch from non-execute or guarded pages.
  */
        START_EXCEPTION(0x0400, InstructionAccess)
-       EXCEPTION_PROLOG
+       EXCEPTION_PROLOG 0x400 InstructionAccess
        li      r5,0
        stw     r5, _ESR(r11)           /* Zero ESR */
        stw     r12, _DEAR(r11)         /* SRR0 as DEAR */
-       EXC_XFER_LITE(0x400, handle_page_fault)
+       prepare_transfer_to_handler
+       bl      do_page_fault
+       b       interrupt_return
 
 /* 0x0500 - External Interrupt Exception */
-       EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+       EXCEPTION(0x0500, HardwareInterrupt, do_IRQ)
 
 /* 0x0600 - Alignment Exception */
        START_EXCEPTION(0x0600, Alignment)
-       EXCEPTION_PROLOG
-       mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
-       stw     r4,_DEAR(r11)
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x600, alignment_exception)
+       EXCEPTION_PROLOG 0x600 Alignment handle_dar_dsisr=1
+       prepare_transfer_to_handler
+       bl      alignment_exception
+       REST_NVGPRS(r1)
+       b       interrupt_return
 
 /* 0x0700 - Program Exception */
        START_EXCEPTION(0x0700, ProgramCheck)
-       EXCEPTION_PROLOG
-       mfspr   r4,SPRN_ESR             /* Grab the ESR and save it */
-       stw     r4,_ESR(r11)
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x700, program_check_exception)
+       EXCEPTION_PROLOG 0x700 ProgramCheck handle_dar_dsisr=1
+       prepare_transfer_to_handler
+       bl      program_check_exception
+       REST_NVGPRS(r1)
+       b       interrupt_return
 
-       EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_STD)
+       EXCEPTION(0x0800, Trap_08, unknown_exception)
+       EXCEPTION(0x0900, Trap_09, unknown_exception)
+       EXCEPTION(0x0A00, Trap_0A, unknown_exception)
+       EXCEPTION(0x0B00, Trap_0B, unknown_exception)
 
 /* 0x0C00 - System Call Exception */
        START_EXCEPTION(0x0C00, SystemCall)
        SYSCALL_ENTRY   0xc00
 /*     Trap_0D is commented out to get more space for system call exception */
 
-/*     EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_STD) */
-       EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_STD)
+/*     EXCEPTION(0x0D00, Trap_0D, unknown_exception) */
+       EXCEPTION(0x0E00, Trap_0E, unknown_exception)
+       EXCEPTION(0x0F00, Trap_0F, unknown_exception)
 
 /* 0x1000 - Programmable Interval Timer (PIT) Exception */
-       . = 0x1000
+       START_EXCEPTION(0x1000, DecrementerTrap)
        b Decrementer
 
-/* 0x1010 - Fixed Interval Timer (FIT) Exception
-*/
-       . = 0x1010
+/* 0x1010 - Fixed Interval Timer (FIT) Exception */
+       START_EXCEPTION(0x1010, FITExceptionTrap)
        b FITException
 
-/* 0x1020 - Watchdog Timer (WDT) Exception
-*/
-       . = 0x1020
+/* 0x1020 - Watchdog Timer (WDT) Exception */
+       START_EXCEPTION(0x1020, WDTExceptionTrap)
        b WDTException
 
 /* 0x1100 - Data TLB Miss Exception
@@ -249,13 +271,13 @@ _ENTRY(saved_ksp_limit)
  * load TLB entries from the page table if they exist.
  */
        START_EXCEPTION(0x1100, DTLBMiss)
-       mtspr   SPRN_SPRG_SCRATCH0, r10 /* Save some working registers */
-       mtspr   SPRN_SPRG_SCRATCH1, r11
+       mtspr   SPRN_SPRG_SCRATCH5, r10 /* Save some working registers */
+       mtspr   SPRN_SPRG_SCRATCH6, r11
        mtspr   SPRN_SPRG_SCRATCH3, r12
        mtspr   SPRN_SPRG_SCRATCH4, r9
        mfcr    r12
        mfspr   r9, SPRN_PID
-       mtspr   SPRN_SPRG_SCRATCH5, r9
+       rlwimi  r12, r9, 0, 0xff
        mfspr   r10, SPRN_DEAR          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -316,13 +338,12 @@ _ENTRY(saved_ksp_limit)
        /* The bailout.  Restore registers to pre-exception conditions
         * and call the heavyweights to help us out.
         */
-       mfspr   r9, SPRN_SPRG_SCRATCH5
-       mtspr   SPRN_PID, r9
-       mtcr    r12
+       mtspr   SPRN_PID, r12
+       mtcrf   0x80, r12
        mfspr   r9, SPRN_SPRG_SCRATCH4
        mfspr   r12, SPRN_SPRG_SCRATCH3
-       mfspr   r11, SPRN_SPRG_SCRATCH1
-       mfspr   r10, SPRN_SPRG_SCRATCH0
+       mfspr   r11, SPRN_SPRG_SCRATCH6
+       mfspr   r10, SPRN_SPRG_SCRATCH5
        b       DataStorage
 
 /* 0x1200 - Instruction TLB Miss Exception
@@ -330,13 +351,13 @@ _ENTRY(saved_ksp_limit)
  * registers and bailout to a different point.
  */
        START_EXCEPTION(0x1200, ITLBMiss)
-       mtspr   SPRN_SPRG_SCRATCH0, r10  /* Save some working registers */
-       mtspr   SPRN_SPRG_SCRATCH1, r11
+       mtspr   SPRN_SPRG_SCRATCH5, r10  /* Save some working registers */
+       mtspr   SPRN_SPRG_SCRATCH6, r11
        mtspr   SPRN_SPRG_SCRATCH3, r12
        mtspr   SPRN_SPRG_SCRATCH4, r9
        mfcr    r12
        mfspr   r9, SPRN_PID
-       mtspr   SPRN_SPRG_SCRATCH5, r9
+       rlwimi  r12, r9, 0, 0xff
        mfspr   r10, SPRN_SRR0          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -397,28 +418,27 @@ _ENTRY(saved_ksp_limit)
        /* The bailout.  Restore registers to pre-exception conditions
         * and call the heavyweights to help us out.
         */
-       mfspr   r9, SPRN_SPRG_SCRATCH5
-       mtspr   SPRN_PID, r9
-       mtcr    r12
+       mtspr   SPRN_PID, r12
+       mtcrf   0x80, r12
        mfspr   r9, SPRN_SPRG_SCRATCH4
        mfspr   r12, SPRN_SPRG_SCRATCH3
-       mfspr   r11, SPRN_SPRG_SCRATCH1
-       mfspr   r10, SPRN_SPRG_SCRATCH0
+       mfspr   r11, SPRN_SPRG_SCRATCH6
+       mfspr   r10, SPRN_SPRG_SCRATCH5
        b       InstructionAccess
 
-       EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1400, Trap_14, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1A00, Trap_1A, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1B00, Trap_1B, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1C00, Trap_1C, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1D00, Trap_1D, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1E00, Trap_1E, unknown_exception, EXC_XFER_STD)
-       EXCEPTION(0x1F00, Trap_1F, unknown_exception, EXC_XFER_STD)
+       EXCEPTION(0x1300, Trap_13, unknown_exception)
+       EXCEPTION(0x1400, Trap_14, unknown_exception)
+       EXCEPTION(0x1500, Trap_15, unknown_exception)
+       EXCEPTION(0x1600, Trap_16, unknown_exception)
+       EXCEPTION(0x1700, Trap_17, unknown_exception)
+       EXCEPTION(0x1800, Trap_18, unknown_exception)
+       EXCEPTION(0x1900, Trap_19, unknown_exception)
+       EXCEPTION(0x1A00, Trap_1A, unknown_exception)
+       EXCEPTION(0x1B00, Trap_1B, unknown_exception)
+       EXCEPTION(0x1C00, Trap_1C, unknown_exception)
+       EXCEPTION(0x1D00, Trap_1D, unknown_exception)
+       EXCEPTION(0x1E00, Trap_1E, unknown_exception)
+       EXCEPTION(0x1F00, Trap_1F, unknown_exception)
 
 /* Check for a single step debug exception while in an exception
  * handler before state has been saved.  This is to catch the case
@@ -435,7 +455,7 @@ _ENTRY(saved_ksp_limit)
  */
        /* 0x2000 - Debug Exception */
        START_EXCEPTION(0x2000, DebugTrap)
-       CRITICAL_EXCEPTION_PROLOG
+       CRITICAL_EXCEPTION_PROLOG 0x2000 DebugTrap
 
        /*
         * If this is a single step or branch-taken exception in an
@@ -477,32 +497,35 @@ _ENTRY(saved_ksp_limit)
        /* continue normal handling for a critical exception... */
 2:     mfspr   r4,SPRN_DBSR
        stw     r4,_ESR(r11)            /* DebugException takes DBSR in _ESR */
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_TEMPLATE(DebugException, 0x2002, \
-               (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-               crit_transfer_to_handler, ret_from_crit_exc)
+       prepare_transfer_to_handler
+       bl      DebugException
+       b       ret_from_crit_exc
 
        /* Programmable Interval Timer (PIT) Exception. (from 0x1000) */
+       __HEAD
 Decrementer:
-       EXCEPTION_PROLOG
+       EXCEPTION_PROLOG 0x1000 Decrementer
        lis     r0,TSR_PIS@h
        mtspr   SPRN_TSR,r0             /* Clear the PIT exception */
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_LITE(0x1000, timer_interrupt)
+       prepare_transfer_to_handler
+       bl      timer_interrupt
+       b       interrupt_return
 
        /* Fixed Interval Timer (FIT) Exception. (from 0x1010) */
+       __HEAD
 FITException:
-       EXCEPTION_PROLOG
-       addi    r3,r1,STACK_FRAME_OVERHEAD;
-       EXC_XFER_STD(0x1010, unknown_exception)
+       EXCEPTION_PROLOG 0x1010 FITException
+       prepare_transfer_to_handler
+       bl      unknown_exception
+       b       interrupt_return
 
        /* Watchdog Timer (WDT) Exception. (from 0x1020) */
+       __HEAD
 WDTException:
-       CRITICAL_EXCEPTION_PROLOG;
-       addi    r3,r1,STACK_FRAME_OVERHEAD;
-       EXC_XFER_TEMPLATE(WatchdogException, 0x1020+2,
-                         (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),
-                         crit_transfer_to_handler, ret_from_crit_exc)
+       CRITICAL_EXCEPTION_PROLOG 0x1020 WDTException
+       prepare_transfer_to_handler
+       bl      WatchdogException
+       b       ret_from_crit_exc
 
 /* Other PowerPC processors, namely those derived from the 6xx-series
  * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
@@ -510,6 +533,7 @@ WDTException:
  * reserved.
  */
 
+       __HEAD
        /* Damn, I came up one instruction too many to fit into the
         * exception space :-).  Both the instruction and data TLB
         * miss get to this point to load the TLB.
@@ -543,13 +567,12 @@ finish_tlb_load:
 
        /* Done...restore registers and get out of here.
        */
-       mfspr   r9, SPRN_SPRG_SCRATCH5
-       mtspr   SPRN_PID, r9
-       mtcr    r12
+       mtspr   SPRN_PID, r12
+       mtcrf   0x80, r12
        mfspr   r9, SPRN_SPRG_SCRATCH4
        mfspr   r12, SPRN_SPRG_SCRATCH3
-       mfspr   r11, SPRN_SPRG_SCRATCH1
-       mfspr   r10, SPRN_SPRG_SCRATCH0
+       mfspr   r11, SPRN_SPRG_SCRATCH6
+       mfspr   r10, SPRN_SPRG_SCRATCH5
        rfi                     /* Should sync shadow TLBs */
        b       .               /* prevent prefetch past rfi */