3131#define RFMT "%08lx"
3232#endif
3333
34- #define FIXUP_BRANCH (lbl ) \
35- "\tldil L%%" #lbl ", %%r1\n" \
36- "\tldo R%%" #lbl "(%%r1), %%r1\n" \
37- "\tbv,n %%r0(%%r1)\n"
38- /* If you use FIXUP_BRANCH, then you must list this clobber */
39- #define FIXUP_BRANCH_CLOBBER "r1"
40-
4134/* 1111 1100 0000 0000 0001 0011 1100 0000 */
4235#define OPCODE1 (a ,b ,c ) ((a)<<26|(b)<<12|(c)<<6)
4336#define OPCODE2 (a ,b ) ((a)<<26|(b)<<1)
114107#define IM14 (i ) IM((i),14)
115108
116109#define ERR_NOTHANDLED -1
117- #define ERR_PAGEFAULT -2
118110
119111int unaligned_enabled __read_mostly = 1 ;
120112
121113static int emulate_ldh (struct pt_regs * regs , int toreg )
122114{
123115 unsigned long saddr = regs -> ior ;
124116 unsigned long val = 0 ;
125- int ret ;
117+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
126118
127119 DPRINTF ("load " RFMT ":" RFMT " to r%d for 2 bytes\n" ,
128120 regs -> isr , regs -> ior , toreg );
@@ -132,17 +124,12 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
132124"1: ldbs 0(%%sr1,%3), %%r20\n"
133125"2: ldbs 1(%%sr1,%3), %0\n"
134126" depw %%r20, 23, 24, %0\n"
135- " copy %%r0, %1\n"
136127"3: \n"
137- " .section .fixup,\"ax\"\n"
138- "4: ldi -2, %1\n"
139- FIXUP_BRANCH (3b )
140- " .previous\n"
141- ASM_EXCEPTIONTABLE_ENTRY (1b , 4b )
142- ASM_EXCEPTIONTABLE_ENTRY (2b , 4b )
143- : "=r" (val ), "=r" (ret )
128+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 3b )
129+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 3b )
130+ : "=r" (val ), "+r" (ret )
144131 : "0" (val ), "r" (saddr ), "r" (regs -> isr )
145- : "r20" , FIXUP_BRANCH_CLOBBER );
132+ : "r20" );
146133
147134 DPRINTF ("val = 0x" RFMT "\n" , val );
148135
@@ -156,7 +143,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
156143{
157144 unsigned long saddr = regs -> ior ;
158145 unsigned long val = 0 ;
159- int ret ;
146+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
160147
161148 DPRINTF ("load " RFMT ":" RFMT " to r%d for 4 bytes\n" ,
162149 regs -> isr , regs -> ior , toreg );
@@ -170,17 +157,12 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
170157" subi 32,%%r19,%%r19\n"
171158" mtctl %%r19,11\n"
172159" vshd %0,%%r20,%0\n"
173- " copy %%r0, %1\n"
174160"3: \n"
175- " .section .fixup,\"ax\"\n"
176- "4: ldi -2, %1\n"
177- FIXUP_BRANCH (3b )
178- " .previous\n"
179- ASM_EXCEPTIONTABLE_ENTRY (1b , 4b )
180- ASM_EXCEPTIONTABLE_ENTRY (2b , 4b )
181- : "=r" (val ), "=r" (ret )
161+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 3b )
162+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 3b )
163+ : "=r" (val ), "+r" (ret )
182164 : "0" (val ), "r" (saddr ), "r" (regs -> isr )
183- : "r19" , "r20" , FIXUP_BRANCH_CLOBBER );
165+ : "r19" , "r20" );
184166
185167 DPRINTF ("val = 0x" RFMT "\n" , val );
186168
@@ -195,16 +177,15 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
195177{
196178 unsigned long saddr = regs -> ior ;
197179 __u64 val = 0 ;
198- int ret ;
180+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
199181
200182 DPRINTF ("load " RFMT ":" RFMT " to r%d for 8 bytes\n" ,
201183 regs -> isr , regs -> ior , toreg );
202- #ifdef CONFIG_PA20
203184
204- #ifndef CONFIG_64BIT
205- if (! flop )
206- return -1 ;
207- #endif
185+ if (! IS_ENABLED ( CONFIG_64BIT ) && ! flop )
186+ return ERR_NOTHANDLED ;
187+
188+ #ifdef CONFIG_64BIT
208189 __asm__ __volatile__ (
209190" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */
210191" mtsp %4, %%sr1\n"
@@ -214,17 +195,12 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
214195" subi 64,%%r19,%%r19\n"
215196" mtsar %%r19\n"
216197" shrpd %0,%%r20,%%sar,%0\n"
217- " copy %%r0, %1\n"
218198"3: \n"
219- " .section .fixup,\"ax\"\n"
220- "4: ldi -2, %1\n"
221- FIXUP_BRANCH (3b )
222- " .previous\n"
223- ASM_EXCEPTIONTABLE_ENTRY (1b ,4b )
224- ASM_EXCEPTIONTABLE_ENTRY (2b ,4b )
225- : "=r" (val ), "=r" (ret )
199+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 3b )
200+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 3b )
201+ : "=r" (val ), "+r" (ret )
226202 : "0" (val ), "r" (saddr ), "r" (regs -> isr )
227- : "r19" , "r20" , FIXUP_BRANCH_CLOBBER );
203+ : "r19" , "r20" );
228204#else
229205 {
230206 unsigned long valh = 0 ,vall = 0 ;
@@ -239,18 +215,13 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
239215" mtsar %%r19\n"
240216" vshd %0,%1,%0\n"
241217" vshd %1,%%r20,%1\n"
242- " copy %%r0, %2\n"
243218"4: \n"
244- " .section .fixup,\"ax\"\n"
245- "5: ldi -2, %2\n"
246- FIXUP_BRANCH (4b )
247- " .previous\n"
248- ASM_EXCEPTIONTABLE_ENTRY (1b ,5b )
249- ASM_EXCEPTIONTABLE_ENTRY (2b ,5b )
250- ASM_EXCEPTIONTABLE_ENTRY (3b ,5b )
251- : "=r" (valh ), "=r" (vall ), "=r" (ret )
219+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 4b )
220+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 4b )
221+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (3b , 4b )
222+ : "=r" (valh ), "=r" (vall ), "+r" (ret )
252223 : "0" (valh ), "1" (vall ), "r" (saddr ), "r" (regs -> isr )
253- : "r19" , "r20" , FIXUP_BRANCH_CLOBBER );
224+ : "r19" , "r20" );
254225 val = ((__u64 )valh <<32 )|(__u64 )vall ;
255226 }
256227#endif
@@ -268,7 +239,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
268239static int emulate_sth (struct pt_regs * regs , int frreg )
269240{
270241 unsigned long val = regs -> gr [frreg ];
271- int ret ;
242+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
272243
273244 if (!frreg )
274245 val = 0 ;
@@ -281,25 +252,20 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
281252" extrw,u %1, 23, 8, %%r19\n"
282253"1: stb %1, 1(%%sr1, %2)\n"
283254"2: stb %%r19, 0(%%sr1, %2)\n"
284- " copy %%r0, %0\n"
285255"3: \n"
286- " .section .fixup,\"ax\"\n"
287- "4: ldi -2, %0\n"
288- FIXUP_BRANCH (3b )
289- " .previous\n"
290- ASM_EXCEPTIONTABLE_ENTRY (1b ,4b )
291- ASM_EXCEPTIONTABLE_ENTRY (2b ,4b )
292- : "=r" (ret )
256+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 3b )
257+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 3b )
258+ : "+ r " (ret)
293259 : " r " (val), " r " (regs->ior), " r " (regs->isr)
294- : "r19" , FIXUP_BRANCH_CLOBBER );
260+ : " r19 " );
295261
296262 return ret ;
297263}
298264
299265static int emulate_stw (struct pt_regs * regs , int frreg , int flop )
300266{
301267 unsigned long val ;
302- int ret ;
268+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
303269
304270 if (flop )
305271 val = ((__u32 * )(regs -> fr ))[frreg ];
@@ -328,24 +294,19 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
328294" or %%r1, %%r21, %%r21\n"
329295" stw %%r20,0(%%sr1,%2)\n"
330296" stw %%r21,4(%%sr1,%2)\n"
331- " copy %%r0, %0\n"
332297"3: \n"
333- " .section .fixup,\"ax\"\n"
334- "4: ldi -2, %0\n"
335- FIXUP_BRANCH (3b )
336- " .previous\n"
337- ASM_EXCEPTIONTABLE_ENTRY (1b ,4b )
338- ASM_EXCEPTIONTABLE_ENTRY (2b ,4b )
339- : "=r" (ret )
298+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 3b )
299+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 3b )
300+ : "+ r " (ret)
340301 : " r " (val), " r " (regs->ior), " r " (regs->isr)
341- : "r19" , "r20" , "r21" , "r22" , "r1" , FIXUP_BRANCH_CLOBBER );
302+ : " r19 ", " r20 ", " r21 ", " r22 ", " r1 " );
342303
343304 return ret ;
344305}
345306static int emulate_std (struct pt_regs * regs , int frreg , int flop )
346307{
347308 __u64 val ;
348- int ret ;
309+ ASM_EXCEPTIONTABLE_VAR ( ret ) ;
349310
350311 if (flop )
351312 val = regs -> fr [frreg ];
@@ -357,11 +318,10 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
357318 DPRINTF ("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n" , frreg ,
358319 val , regs -> isr , regs -> ior );
359320
360- #ifdef CONFIG_PA20
361- #ifndef CONFIG_64BIT
362- if (!flop )
363- return -1 ;
364- #endif
321+ if (!IS_ENABLED (CONFIG_64BIT ) && !flop )
322+ return ERR_NOTHANDLED ;
323+
324+ #ifdef CONFIG_64BIT
365325 __asm__ __volatile__ (
366326" mtsp %3, %%sr1\n"
367327" depd,z %2, 60, 3, %%r19\n"
@@ -378,19 +338,14 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
378338" or %%r1, %%r21, %%r21\n"
379339"3: std %%r20,0(%%sr1,%2)\n"
380340"4: std %%r21,8(%%sr1,%2)\n"
381- " copy %%r0, %0\n"
382341"5: \n"
383- " .section .fixup,\"ax\"\n"
384- "6: ldi -2, %0\n"
385- FIXUP_BRANCH (5b )
386- " .previous\n"
387- ASM_EXCEPTIONTABLE_ENTRY (1b ,6b )
388- ASM_EXCEPTIONTABLE_ENTRY (2b ,6b )
389- ASM_EXCEPTIONTABLE_ENTRY (3b ,6b )
390- ASM_EXCEPTIONTABLE_ENTRY (4b ,6b )
391- : "=r" (ret )
342+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 5b )
343+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 5b )
344+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (3b , 5b )
345+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (4b , 5b )
346+ : "+ r " (ret)
392347 : " r " (val), " r " (regs->ior), " r " (regs->isr)
393- : "r19" , "r20" , "r21" , "r22" , "r1" , FIXUP_BRANCH_CLOBBER );
348+ : " r19 ", " r20 ", " r21 ", " r22 ", " r1 " );
394349#else
395350 {
396351 unsigned long valh = (val >>32 ),vall = (val & 0xffffffffl );
@@ -412,20 +367,15 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
412367"3: stw %1,0(%%sr1,%3)\n"
413368"4: stw %%r1,4(%%sr1,%3)\n"
414369"5: stw %2,8(%%sr1,%3)\n"
415- " copy %%r0, %0\n"
416370"6: \n"
417- " .section .fixup,\"ax\"\n"
418- "7: ldi -2, %0\n"
419- FIXUP_BRANCH (6b )
420- " .previous\n"
421- ASM_EXCEPTIONTABLE_ENTRY (1b ,7b )
422- ASM_EXCEPTIONTABLE_ENTRY (2b ,7b )
423- ASM_EXCEPTIONTABLE_ENTRY (3b ,7b )
424- ASM_EXCEPTIONTABLE_ENTRY (4b ,7b )
425- ASM_EXCEPTIONTABLE_ENTRY (5b ,7b )
426- : "=r" (ret )
371+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (1b , 6b )
372+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (2b , 6b )
373+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (3b , 6b )
374+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (4b , 6b )
375+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT (5b , 6b )
376+ : "+ r " (ret)
427377 : " r " (valh), " r " (vall), " r " (regs->ior), " r " (regs->isr)
428- : "r19" , "r20" , "r21" , "r1" , FIXUP_BRANCH_CLOBBER );
378+ : " r19 ", " r20 ", " r21 ", " r1 " );
429379 }
430380#endif
431381
@@ -547,7 +497,7 @@ void handle_unaligned(struct pt_regs *regs)
547497 ret = emulate_stw (regs , R2 (regs -> iir ),0 );
548498 break ;
549499
550- #ifdef CONFIG_PA20
500+ #ifdef CONFIG_64BIT
551501 case OPCODE_LDD_I :
552502 case OPCODE_LDDA_I :
553503 case OPCODE_LDD_S :
@@ -606,7 +556,7 @@ void handle_unaligned(struct pt_regs *regs)
606556 flop = 1 ;
607557 ret = emulate_std (regs , R2 (regs -> iir ),1 );
608558 break ;
609- #ifdef CONFIG_PA20
559+ #ifdef CONFIG_64BIT
610560 case OPCODE_LDD_L :
611561 ret = emulate_ldd (regs , R2 (regs -> iir ),0 );
612562 break ;
@@ -673,7 +623,7 @@ void handle_unaligned(struct pt_regs *regs)
673623 printk (KERN_CRIT "Unaligned handler failed, ret = %d\n" , ret );
674624 die_if_kernel ("Unaligned data reference" , regs , 28 );
675625
676- if (ret == ERR_PAGEFAULT )
626+ if (ret == - EFAULT )
677627 {
678628 force_sig_fault (SIGSEGV , SEGV_MAPERR ,
679629 (void __user * )regs -> ior );
0 commit comments