Skip to content

Commit d1434e0

Browse files
committed
parisc/unaligned: Use EFAULT fixup handler in unaligned handlers
Convert the inline assembly code to use the automatic EFAULT exception handler. With that the fixup code can be dropped. The other change is to allow double-word only when a 64-bit kernel is used instead of depending on CONFIG_PA20. Signed-off-by: Helge Deller <deller@gmx.de>
1 parent 8278cc1 commit d1434e0

1 file changed

Lines changed: 55 additions & 105 deletions

File tree

arch/parisc/kernel/unaligned.c

Lines changed: 55 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@
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)
@@ -114,15 +107,14 @@
114107
#define IM14(i) IM((i),14)
115108

116109
#define ERR_NOTHANDLED -1
117-
#define ERR_PAGEFAULT -2
118110

119111
int unaligned_enabled __read_mostly = 1;
120112

121113
static 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)
268239
static 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

299265
static 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
}
345306
static 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

Comments
 (0)