Commit 3c2dde6d authored by Kumar Gala's avatar Kumar Gala Committed by Linus Torvalds

[PATCH] ppc32: refactor common Book-E exception handling macros

Refefactor common Book-E exception handling macros into a single file to
reduce code duplication.
Signed-off-by: default avatarKumar Gala <kumar.gala@freescale.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a4eadb56
......@@ -41,16 +41,9 @@
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>
#include "head_booke.h"
/*
* Macros
*/
#define SET_IVOR(vector_number, vector_label) \
li r26,vector_label@l; \
mtspr SPRN_IVOR##vector_number,r26; \
sync
/* As with the other PowerPC ports, it is expected that when code
* execution begins here, the following registers contain valid, yet
* optional, information:
......@@ -302,234 +295,6 @@ skpinv: addi r4,r4,1 /* Increment */
* We align on a 32 byte cache line boundary for good measure.
*/
#define NORMAL_EXCEPTION_PROLOG \
mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
mtspr SPRN_SPRG1,r11; \
mtspr SPRN_SPRG4W,r1; \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
beq 1f; \
mfspr r1,SPRG3; /* if from user, start at top of */\
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
tophys(r11,r1); \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
mfspr r10,SPRG0; \
stw r10,GPR10(r11); \
mfspr r12,SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
mfspr r10,SPRG4R; \
mfspr r12,SRR0; \
stw r10,GPR1(r11); \
mfspr r9,SRR1; \
stw r10,0(r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
* 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. For Book E
* processors, we also have a reserved register (SPRG2) that is only used
* in critical exceptions so we can free up a GPR to use as the base for
* indirect access to the critical exception save area. This is necessary
* since the MMU is always on and the save area is offset from KERNELBASE.
*/
#define CRITICAL_EXCEPTION_PROLOG \
mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
lis r8,crit_save@ha; \
stw r10,crit_r10@l(r8); \
stw r11,crit_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,crit_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,crit_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,crit_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,crit_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,crit_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,crit_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,crit_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,crit_srr1@l(r8); \
mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,critical_stack_top@h; \
ori r11,r11,critical_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,CSRR0; \
stw r1,GPR1(r11); \
mfspr r9,CSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
* have their own save area. For Book E processors, we also have a
* reserved register (SPRG6) that is only used in machine check exceptions
* so we can free up a GPR to use as the base for indirect access to the
* machine check exception save area. This is necessary since the MMU
* is always on and the save area is offset from KERNELBASE.
*/
#define MCHECK_EXCEPTION_PROLOG \
mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \
lis r8,mcheck_save@ha; \
stw r10,mcheck_r10@l(r8); \
stw r11,mcheck_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,mcheck_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,mcheck_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,mcheck_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,mcheck_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,mcheck_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,mcheck_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,mcheck_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,mcheck_srr1@l(r8); \
mfspr r10,CSRR0; \
stw r10,mcheck_csrr0@l(r8); \
mfspr r10,CSRR1; \
stw r10,mcheck_csrr1@l(r8); \
mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,mcheck_stack_top@h; \
ori r11,r11,mcheck_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,MCSRR0; \
stw r1,GPR1(r11); \
mfspr r9,MCSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception vectors.
*/
#define START_EXCEPTION(label) \
.align 5; \
label:
#define FINISH_EXCEPTION(func) \
bl transfer_to_handler_full; \
.long func; \
.long ret_from_except_full
#define EXCEPTION(n, label, hdlr, xfer) \
START_EXCEPTION(label); \
NORMAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
xfer(n, hdlr)
#define CRITICAL_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
CRITICAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define MCHECK_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
MCHECK_EXCEPTION_PROLOG; \
lis r4,MCSR_MCS@h; \
mtspr SPRN_MCSR,r4; \
mfspr r5,SPRN_ESR; \
stw r5,_ESR(r11); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, mcheck_transfer_to_handler, \
ret_from_mcheck_exc)
#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
li r10,trap; \
stw r10,TRAP(r11); \
lis r10,msr@h; \
ori r10,r10,msr@l; \
copyee(r10, r9); \
bl tfer; \
.long hdlr; \
.long ret
#define COPY_EE(d, s) rlwimi d,s,0,16,16
#define NOCOPY(d, s)
#define EXC_XFER_STD(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
ret_from_except)
#define EXC_XFER_EE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_EE_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
ret_from_except)
interrupt_base:
/* Critical Input Interrupt */
CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
......
#ifndef __HEAD_BOOKE_H__
#define __HEAD_BOOKE_H__
/*
* Macros used for common Book-e exception handling
*/
#define SET_IVOR(vector_number, vector_label) \
li r26,vector_label@l; \
mtspr SPRN_IVOR##vector_number,r26; \
sync
#define NORMAL_EXCEPTION_PROLOG \
mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
mtspr SPRN_SPRG1,r11; \
mtspr SPRN_SPRG4W,r1; \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
beq 1f; \
mfspr r1,SPRG3; /* if from user, start at top of */\
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
tophys(r11,r1); \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
mfspr r10,SPRG0; \
stw r10,GPR10(r11); \
mfspr r12,SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
mfspr r10,SPRG4R; \
mfspr r12,SRR0; \
stw r10,GPR1(r11); \
mfspr r9,SRR1; \
stw r10,0(r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
* 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. For Book E
* processors, we also have a reserved register (SPRG2) that is only used
* in critical exceptions so we can free up a GPR to use as the base for
* indirect access to the critical exception save area. This is necessary
* since the MMU is always on and the save area is offset from KERNELBASE.
*/
#define CRITICAL_EXCEPTION_PROLOG \
mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
lis r8,crit_save@ha; \
stw r10,crit_r10@l(r8); \
stw r11,crit_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,crit_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,crit_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,crit_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,crit_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,crit_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,crit_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,crit_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,crit_srr1@l(r8); \
mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,critical_stack_top@h; \
ori r11,r11,critical_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,CSRR0; \
stw r1,GPR1(r11); \
mfspr r9,CSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
* have their own save area. For Book E processors, we also have a
* reserved register (SPRG6) that is only used in machine check exceptions
* so we can free up a GPR to use as the base for indirect access to the
* machine check exception save area. This is necessary since the MMU
* is always on and the save area is offset from KERNELBASE.
*/
#define MCHECK_EXCEPTION_PROLOG \
mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \
lis r8,mcheck_save@ha; \
stw r10,mcheck_r10@l(r8); \
stw r11,mcheck_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,mcheck_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,mcheck_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,mcheck_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,mcheck_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,mcheck_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,mcheck_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,mcheck_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,mcheck_srr1@l(r8); \
mfspr r10,CSRR0; \
stw r10,mcheck_csrr0@l(r8); \
mfspr r10,CSRR1; \
stw r10,mcheck_csrr1@l(r8); \
mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,mcheck_stack_top@h; \
ori r11,r11,mcheck_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,MCSRR0; \
stw r1,GPR1(r11); \
mfspr r9,MCSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception vectors.
*/
#define START_EXCEPTION(label) \
.align 5; \
label:
#define FINISH_EXCEPTION(func) \
bl transfer_to_handler_full; \
.long func; \
.long ret_from_except_full
#define EXCEPTION(n, label, hdlr, xfer) \
START_EXCEPTION(label); \
NORMAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
xfer(n, hdlr)
#define CRITICAL_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
CRITICAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define MCHECK_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
MCHECK_EXCEPTION_PROLOG; \
mfspr r5,SPRN_ESR; \
stw r5,_ESR(r11); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, mcheck_transfer_to_handler, \
ret_from_mcheck_exc)
#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
li r10,trap; \
stw r10,TRAP(r11); \
lis r10,msr@h; \
ori r10,r10,msr@l; \
copyee(r10, r9); \
bl tfer; \
.long hdlr; \
.long ret
#define COPY_EE(d, s) rlwimi d,s,0,16,16
#define NOCOPY(d, s)
#define EXC_XFER_STD(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
ret_from_except)
#define EXC_XFER_EE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_EE_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
ret_from_except)
#endif /* __HEAD_BOOKE_H__ */
......@@ -41,15 +41,7 @@
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>
/*
* Macros
*/
#define SET_IVOR(vector_number, vector_label) \
li r26,vector_label@l; \
mtspr SPRN_IVOR##vector_number,r26; \
sync
#include "head_booke.h"
/* As with the other PowerPC ports, it is expected that when code
* execution begins here, the following registers contain valid, yet
......@@ -371,232 +363,6 @@ skpinv: addi r6,r6,1 /* Increment */
* We align on a 32 byte cache line boundary for good measure.
*/
#define NORMAL_EXCEPTION_PROLOG \
mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
mtspr SPRN_SPRG1,r11; \
mtspr SPRN_SPRG4W,r1; \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
beq 1f; \
mfspr r1,SPRG3; /* if from user, start at top of */\
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
tophys(r11,r1); \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
mfspr r10,SPRG0; \
stw r10,GPR10(r11); \
mfspr r12,SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
mfspr r10,SPRG4R; \
mfspr r12,SRR0; \
stw r10,GPR1(r11); \
mfspr r9,SRR1; \
stw r10,0(r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
* 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. For Book E
* processors, we also have a reserved register (SPRG2) that is only used
* in critical exceptions so we can free up a GPR to use as the base for
* indirect access to the critical exception save area. This is necessary
* since the MMU is always on and the save area is offset from KERNELBASE.
*/
#define CRITICAL_EXCEPTION_PROLOG \
mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
lis r8,crit_save@ha; \
stw r10,crit_r10@l(r8); \
stw r11,crit_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,crit_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,crit_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,crit_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,crit_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,crit_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,crit_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,crit_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,crit_srr1@l(r8); \
mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,critical_stack_top@h; \
ori r11,r11,critical_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,CSRR0; \
stw r1,GPR1(r11); \
mfspr r9,CSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
* have their own save area. For Book E processors, we also have a
* reserved register (SPRG6) that is only used in machine check exceptions
* so we can free up a GPR to use as the base for indirect access to the
* machine check exception save area. This is necessary since the MMU
* is always on and the save area is offset from KERNELBASE.
*/
#define MCHECK_EXCEPTION_PROLOG \
mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \
lis r8,mcheck_save@ha; \
stw r10,mcheck_r10@l(r8); \
stw r11,mcheck_r11@l(r8); \
mfspr r10,SPRG0; \
stw r10,mcheck_sprg0@l(r8); \
mfspr r10,SPRG1; \
stw r10,mcheck_sprg1@l(r8); \
mfspr r10,SPRG4R; \
stw r10,mcheck_sprg4@l(r8); \
mfspr r10,SPRG5R; \
stw r10,mcheck_sprg5@l(r8); \
mfspr r10,SPRG7R; \
stw r10,mcheck_sprg7@l(r8); \
mfspr r10,SPRN_PID; \
stw r10,mcheck_pid@l(r8); \
mfspr r10,SRR0; \
stw r10,mcheck_srr0@l(r8); \
mfspr r10,SRR1; \
stw r10,mcheck_srr1@l(r8); \
mfspr r10,CSRR0; \
stw r10,mcheck_csrr0@l(r8); \
mfspr r10,CSRR1; \
stw r10,mcheck_csrr1@l(r8); \
mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
lis r11,mcheck_stack_top@h; \
ori r11,r11,mcheck_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
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,MCSRR0; \
stw r1,GPR1(r11); \
mfspr r9,MCSRR1; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
/*
* Exception vectors.
*/
#define START_EXCEPTION(label) \
.align 5; \
label:
#define FINISH_EXCEPTION(func) \
bl transfer_to_handler_full; \
.long func; \
.long ret_from_except_full
#define EXCEPTION(n, label, hdlr, xfer) \
START_EXCEPTION(label); \
NORMAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
xfer(n, hdlr)
#define CRITICAL_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
CRITICAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define MCHECK_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
MCHECK_EXCEPTION_PROLOG; \
mfspr r5,SPRN_ESR; \
stw r5,_ESR(r11); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, mcheck_transfer_to_handler, \
ret_from_mcheck_exc)
#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
li r10,trap; \
stw r10,TRAP(r11); \
lis r10,msr@h; \
ori r10,r10,msr@l; \
copyee(r10, r9); \
bl tfer; \
.long hdlr; \
.long ret
#define COPY_EE(d, s) rlwimi d,s,0,16,16
#define NOCOPY(d, s)
#define EXC_XFER_STD(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
ret_from_except)
#define EXC_XFER_EE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
ret_from_except_full)
#define EXC_XFER_EE_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
ret_from_except)
interrupt_base:
/* Critical Input Interrupt */
CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
......
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