]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/powerpc/kernel/head_32.h
Merge tag 'dev_groups_all_drivers' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / arch / powerpc / kernel / head_32.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __HEAD_32_H__
3 #define __HEAD_32_H__
4
5 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
6
7 /*
8  * MSR_KERNEL is > 0x8000 on 4xx/Book-E since it include MSR_CE.
9  */
10 .macro __LOAD_MSR_KERNEL r, x
11 .if \x >= 0x8000
12         lis \r, (\x)@h
13         ori \r, \r, (\x)@l
14 .else
15         li \r, (\x)
16 .endif
17 .endm
18 #define LOAD_MSR_KERNEL(r, x) __LOAD_MSR_KERNEL r, x
19
20 /*
21  * Exception entry code.  This code runs with address translation
22  * turned off, i.e. using physical addresses.
23  * We assume sprg3 has the physical address of the current
24  * task's thread_struct.
25  */
26
27 .macro EXCEPTION_PROLOG
28         mtspr   SPRN_SPRG_SCRATCH0,r10
29         mtspr   SPRN_SPRG_SCRATCH1,r11
30         mfcr    r10
31         EXCEPTION_PROLOG_1
32         EXCEPTION_PROLOG_2
33 .endm
34
35 .macro EXCEPTION_PROLOG_1
36         mfspr   r11,SPRN_SRR1           /* check whether user or kernel */
37         andi.   r11,r11,MSR_PR
38         tophys(r11,r1)                  /* use tophys(r1) if kernel */
39         beq     1f
40         mfspr   r11,SPRN_SPRG_THREAD
41         lwz     r11,TASK_STACK-THREAD(r11)
42         addi    r11,r11,THREAD_SIZE
43         tophys(r11,r11)
44 1:      subi    r11,r11,INT_FRAME_SIZE  /* alloc exc. frame */
45 .endm
46
47 .macro EXCEPTION_PROLOG_2
48         stw     r10,_CCR(r11)           /* save registers */
49         stw     r12,GPR12(r11)
50         stw     r9,GPR9(r11)
51         mfspr   r10,SPRN_SPRG_SCRATCH0
52         stw     r10,GPR10(r11)
53         mfspr   r12,SPRN_SPRG_SCRATCH1
54         stw     r12,GPR11(r11)
55         mflr    r10
56         stw     r10,_LINK(r11)
57         mfspr   r12,SPRN_SRR0
58         mfspr   r9,SPRN_SRR1
59         stw     r1,GPR1(r11)
60         stw     r1,0(r11)
61         tovirt(r1,r11)                  /* set new kernel sp */
62 #ifdef CONFIG_40x
63         rlwinm  r9,r9,0,14,12           /* clear MSR_WE (necessary?) */
64 #else
65         li      r10,MSR_KERNEL & ~(MSR_IR|MSR_DR) /* can take exceptions */
66         MTMSRD(r10)                     /* (except for mach check in rtas) */
67 #endif
68         stw     r0,GPR0(r11)
69         lis     r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
70         addi    r10,r10,STACK_FRAME_REGS_MARKER@l
71         stw     r10,8(r11)
72         SAVE_4GPRS(3, r11)
73         SAVE_2GPRS(7, r11)
74 .endm
75
76 .macro SYSCALL_ENTRY trapno
77         mfspr   r12,SPRN_SPRG_THREAD
78         mfcr    r10
79         lwz     r11,TASK_STACK-THREAD(r12)
80         mflr    r9
81         addi    r11,r11,THREAD_SIZE - INT_FRAME_SIZE
82         rlwinm  r10,r10,0,4,2   /* Clear SO bit in CR */
83         tophys(r11,r11)
84         stw     r10,_CCR(r11)           /* save registers */
85         mfspr   r10,SPRN_SRR0
86         stw     r9,_LINK(r11)
87         mfspr   r9,SPRN_SRR1
88         stw     r1,GPR1(r11)
89         stw     r1,0(r11)
90         tovirt(r1,r11)                  /* set new kernel sp */
91         stw     r10,_NIP(r11)
92 #ifdef CONFIG_40x
93         rlwinm  r9,r9,0,14,12           /* clear MSR_WE (necessary?) */
94 #else
95         LOAD_MSR_KERNEL(r10, MSR_KERNEL & ~(MSR_IR|MSR_DR)) /* can take exceptions */
96         MTMSRD(r10)                     /* (except for mach check in rtas) */
97 #endif
98         lis     r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
99         stw     r2,GPR2(r11)
100         addi    r10,r10,STACK_FRAME_REGS_MARKER@l
101         stw     r9,_MSR(r11)
102         li      r2, \trapno + 1
103         stw     r10,8(r11)
104         stw     r2,_TRAP(r11)
105         SAVE_GPR(0, r11)
106         SAVE_4GPRS(3, r11)
107         SAVE_2GPRS(7, r11)
108         addi    r11,r1,STACK_FRAME_OVERHEAD
109         addi    r2,r12,-THREAD
110         stw     r11,PT_REGS(r12)
111 #if defined(CONFIG_40x)
112         /* Check to see if the dbcr0 register is set up to debug.  Use the
113            internal debug mode bit to do this. */
114         lwz     r12,THREAD_DBCR0(r12)
115         andis.  r12,r12,DBCR0_IDM@h
116 #endif
117         ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
118 #if defined(CONFIG_40x)
119         beq+    3f
120         /* From user and task is ptraced - load up global dbcr0 */
121         li      r12,-1                  /* clear all pending debug events */
122         mtspr   SPRN_DBSR,r12
123         lis     r11,global_dbcr0@ha
124         tophys(r11,r11)
125         addi    r11,r11,global_dbcr0@l
126         lwz     r12,0(r11)
127         mtspr   SPRN_DBCR0,r12
128         lwz     r12,4(r11)
129         addi    r12,r12,-1
130         stw     r12,4(r11)
131 #endif
132
133 3:
134         tovirt(r2, r2)                  /* set r2 to current */
135         lis     r11, transfer_to_syscall@h
136         ori     r11, r11, transfer_to_syscall@l
137 #ifdef CONFIG_TRACE_IRQFLAGS
138         /*
139          * If MSR is changing we need to keep interrupts disabled at this point
140          * otherwise we might risk taking an interrupt before we tell lockdep
141          * they are enabled.
142          */
143         LOAD_MSR_KERNEL(r10, MSR_KERNEL)
144         rlwimi  r10, r9, 0, MSR_EE
145 #else
146         LOAD_MSR_KERNEL(r10, MSR_KERNEL | MSR_EE)
147 #endif
148 #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
149         mtspr   SPRN_NRI, r0
150 #endif
151         mtspr   SPRN_SRR1,r10
152         mtspr   SPRN_SRR0,r11
153         SYNC
154         RFI                             /* jump to handler, enable MMU */
155 .endm
156
157 /*
158  * Note: code which follows this uses cr0.eq (set if from kernel),
159  * r11, r12 (SRR0), and r9 (SRR1).
160  *
161  * Note2: once we have set r1 we are in a position to take exceptions
162  * again, and we could thus set MSR:RI at that point.
163  */
164
165 /*
166  * Exception vectors.
167  */
168 #ifdef CONFIG_PPC_BOOK3S
169 #define START_EXCEPTION(n, label)               \
170         . = n;                                  \
171         DO_KVM n;                               \
172 label:
173
174 #else
175 #define START_EXCEPTION(n, label)               \
176         . = n;                                  \
177 label:
178
179 #endif
180
181 #define EXCEPTION(n, label, hdlr, xfer)         \
182         START_EXCEPTION(n, label)               \
183         EXCEPTION_PROLOG;                       \
184         addi    r3,r1,STACK_FRAME_OVERHEAD;     \
185         xfer(n, hdlr)
186
187 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret)           \
188         li      r10,trap;                                       \
189         stw     r10,_TRAP(r11);                                 \
190         LOAD_MSR_KERNEL(r10, msr);                              \
191         bl      tfer;                                           \
192         .long   hdlr;                                           \
193         .long   ret
194
195 #define EXC_XFER_STD(n, hdlr)           \
196         EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full,        \
197                           ret_from_except_full)
198
199 #define EXC_XFER_LITE(n, hdlr)          \
200         EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \
201                           ret_from_except)
202
203 #endif /* __HEAD_32_H__ */