mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
Merge branch 'work.sparc32' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
This commit is contained in:
commit
cf64c2a905
14 changed files with 191 additions and 524 deletions
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/extable_64.h>
|
||||
#include <asm/spitfire.h>
|
||||
#include <asm/adi.h>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_EXTABLE64_H
|
||||
#define __ASM_EXTABLE64_H
|
||||
#ifndef __ASM_EXTABLE_H
|
||||
#define __ASM_EXTABLE_H
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
|
@ -1,6 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ___ASM_SPARC_UACCESS_H
|
||||
#define ___ASM_SPARC_UACCESS_H
|
||||
|
||||
#include <asm/extable.h>
|
||||
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/uaccess_64.h>
|
||||
#else
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define ARCH_HAS_SORT_EXTABLE
|
||||
#define ARCH_HAS_SEARCH_EXTABLE
|
||||
|
||||
/* Sparc is not segmented, however we need to be able to fool access_ok()
|
||||
* when doing system calls from kernel mode legitimately.
|
||||
*
|
||||
|
@ -40,36 +37,6 @@
|
|||
#define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size)))
|
||||
#define access_ok(addr, size) __access_ok((unsigned long)(addr), size)
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
* the address at which the program should continue. No registers are
|
||||
* modified, so it is entirely up to the continuation code to figure out
|
||||
* what to do.
|
||||
*
|
||||
* All the routines below use bits of fixup code that are out of line
|
||||
* with the main instruction path. This means when everything is well,
|
||||
* we don't even have to jump over them. Further, they do not intrude
|
||||
* on our cache or tlb entries.
|
||||
*
|
||||
* There is a special way how to put a range of potentially faulting
|
||||
* insns (like twenty ldd/std's with now intervening other instructions)
|
||||
* You specify address of first in insn and 0 in fixup and in the next
|
||||
* exception_table_entry you specify last potentially faulting insn + 1
|
||||
* and in fixup the routine which should handle the fault.
|
||||
* That fixup code will get
|
||||
* (faulting_insn_address - first_insn_in_the_range_address)/4
|
||||
* in %g2 (ie. index of the faulting instruction in the range).
|
||||
*/
|
||||
|
||||
struct exception_table_entry
|
||||
{
|
||||
unsigned long insn, fixup;
|
||||
};
|
||||
|
||||
/* Returns 0 if exception not found and fixup otherwise. */
|
||||
unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
|
||||
|
||||
/* Uh, these should become the main single-value transfer routines..
|
||||
* They automatically use the right size if we just have the right
|
||||
* pointer type..
|
||||
|
@ -252,12 +219,7 @@ static inline unsigned long __clear_user(void __user *addr, unsigned long size)
|
|||
unsigned long ret;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
".section __ex_table,#alloc\n\t"
|
||||
".align 4\n\t"
|
||||
".word 1f,3\n\t"
|
||||
".previous\n\t"
|
||||
"mov %2, %%o1\n"
|
||||
"1:\n\t"
|
||||
"call __bzero\n\t"
|
||||
" mov %1, %%o0\n\t"
|
||||
"mov %%o0, %0\n"
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/string.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/spitfire.h>
|
||||
#include <asm/extable_64.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/extable.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
|
@ -213,10 +214,10 @@ static inline int ok_for_kernel(unsigned int insn)
|
|||
|
||||
static void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
|
||||
{
|
||||
unsigned long g2 = regs->u_regs [UREG_G2];
|
||||
unsigned long fixup = search_extables_range(regs->pc, &g2);
|
||||
const struct exception_table_entry *entry;
|
||||
|
||||
if (!fixup) {
|
||||
entry = search_exception_tables(regs->pc);
|
||||
if (!entry) {
|
||||
unsigned long address = compute_effective_address(regs, insn);
|
||||
if(address < PAGE_SIZE) {
|
||||
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler");
|
||||
|
@ -232,9 +233,8 @@ static void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
|
|||
die_if_kernel("Oops", regs);
|
||||
/* Not reached */
|
||||
}
|
||||
regs->pc = fixup;
|
||||
regs->pc = entry->fixup;
|
||||
regs->npc = regs->pc + 4;
|
||||
regs->u_regs [UREG_G2] = g2;
|
||||
}
|
||||
|
||||
asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
|
||||
|
|
|
@ -155,13 +155,6 @@ cpout: retl ! get outta here
|
|||
.text; \
|
||||
.align 4
|
||||
|
||||
#define EXT(start,end) \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word start, 0, end, cc_fault; \
|
||||
.text; \
|
||||
.align 4
|
||||
|
||||
/* This aligned version executes typically in 8.5 superscalar cycles, this
|
||||
* is the best I can do. I say 8.5 because the final add will pair with
|
||||
* the next ldd in the main unrolled loop. Thus the pipe is always full.
|
||||
|
@ -169,20 +162,20 @@ cpout: retl ! get outta here
|
|||
* please check the fixup code below as well.
|
||||
*/
|
||||
#define CSUMCOPY_BIGCHUNK_ALIGNED(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
|
||||
ldd [src + off + 0x00], t0; \
|
||||
ldd [src + off + 0x08], t2; \
|
||||
EX(ldd [src + off + 0x00], t0); \
|
||||
EX(ldd [src + off + 0x08], t2); \
|
||||
addxcc t0, sum, sum; \
|
||||
ldd [src + off + 0x10], t4; \
|
||||
EX(ldd [src + off + 0x10], t4); \
|
||||
addxcc t1, sum, sum; \
|
||||
ldd [src + off + 0x18], t6; \
|
||||
EX(ldd [src + off + 0x18], t6); \
|
||||
addxcc t2, sum, sum; \
|
||||
std t0, [dst + off + 0x00]; \
|
||||
EX(std t0, [dst + off + 0x00]); \
|
||||
addxcc t3, sum, sum; \
|
||||
std t2, [dst + off + 0x08]; \
|
||||
EX(std t2, [dst + off + 0x08]); \
|
||||
addxcc t4, sum, sum; \
|
||||
std t4, [dst + off + 0x10]; \
|
||||
EX(std t4, [dst + off + 0x10]); \
|
||||
addxcc t5, sum, sum; \
|
||||
std t6, [dst + off + 0x18]; \
|
||||
EX(std t6, [dst + off + 0x18]); \
|
||||
addxcc t6, sum, sum; \
|
||||
addxcc t7, sum, sum;
|
||||
|
||||
|
@ -191,39 +184,39 @@ cpout: retl ! get outta here
|
|||
* Viking MXCC into streaming mode. Ho hum...
|
||||
*/
|
||||
#define CSUMCOPY_BIGCHUNK(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
|
||||
ldd [src + off + 0x00], t0; \
|
||||
ldd [src + off + 0x08], t2; \
|
||||
ldd [src + off + 0x10], t4; \
|
||||
ldd [src + off + 0x18], t6; \
|
||||
st t0, [dst + off + 0x00]; \
|
||||
EX(ldd [src + off + 0x00], t0); \
|
||||
EX(ldd [src + off + 0x08], t2); \
|
||||
EX(ldd [src + off + 0x10], t4); \
|
||||
EX(ldd [src + off + 0x18], t6); \
|
||||
EX(st t0, [dst + off + 0x00]); \
|
||||
addxcc t0, sum, sum; \
|
||||
st t1, [dst + off + 0x04]; \
|
||||
EX(st t1, [dst + off + 0x04]); \
|
||||
addxcc t1, sum, sum; \
|
||||
st t2, [dst + off + 0x08]; \
|
||||
EX(st t2, [dst + off + 0x08]); \
|
||||
addxcc t2, sum, sum; \
|
||||
st t3, [dst + off + 0x0c]; \
|
||||
EX(st t3, [dst + off + 0x0c]); \
|
||||
addxcc t3, sum, sum; \
|
||||
st t4, [dst + off + 0x10]; \
|
||||
EX(st t4, [dst + off + 0x10]); \
|
||||
addxcc t4, sum, sum; \
|
||||
st t5, [dst + off + 0x14]; \
|
||||
EX(st t5, [dst + off + 0x14]); \
|
||||
addxcc t5, sum, sum; \
|
||||
st t6, [dst + off + 0x18]; \
|
||||
EX(st t6, [dst + off + 0x18]); \
|
||||
addxcc t6, sum, sum; \
|
||||
st t7, [dst + off + 0x1c]; \
|
||||
EX(st t7, [dst + off + 0x1c]); \
|
||||
addxcc t7, sum, sum;
|
||||
|
||||
/* Yuck, 6 superscalar cycles... */
|
||||
#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1, t2, t3) \
|
||||
ldd [src - off - 0x08], t0; \
|
||||
ldd [src - off - 0x00], t2; \
|
||||
EX(ldd [src - off - 0x08], t0); \
|
||||
EX(ldd [src - off - 0x00], t2); \
|
||||
addxcc t0, sum, sum; \
|
||||
st t0, [dst - off - 0x08]; \
|
||||
EX(st t0, [dst - off - 0x08]); \
|
||||
addxcc t1, sum, sum; \
|
||||
st t1, [dst - off - 0x04]; \
|
||||
EX(st t1, [dst - off - 0x04]); \
|
||||
addxcc t2, sum, sum; \
|
||||
st t2, [dst - off - 0x00]; \
|
||||
EX(st t2, [dst - off - 0x00]); \
|
||||
addxcc t3, sum, sum; \
|
||||
st t3, [dst - off + 0x04];
|
||||
EX(st t3, [dst - off + 0x04]);
|
||||
|
||||
/* Handle the end cruft code out of band for better cache patterns. */
|
||||
cc_end_cruft:
|
||||
|
@ -331,7 +324,6 @@ __csum_partial_copy_sparc_generic:
|
|||
CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
10: EXT(5b, 10b) ! note for exception handling
|
||||
sub %g1, 128, %g1 ! detract from length
|
||||
addx %g0, %g7, %g7 ! add in last carry bit
|
||||
andcc %g1, 0xffffff80, %g0 ! more to csum?
|
||||
|
@ -356,8 +348,7 @@ cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3,%g4,%g5)
|
|||
CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3,%g4,%g5)
|
||||
CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3,%g4,%g5)
|
||||
CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3,%g4,%g5)
|
||||
12: EXT(cctbl, 12b) ! note for exception table handling
|
||||
addx %g0, %g7, %g7
|
||||
12: addx %g0, %g7, %g7
|
||||
andcc %o3, 0xf, %g0 ! check for low bits set
|
||||
ccte: bne cc_end_cruft ! something left, handle it out of band
|
||||
andcc %o3, 8, %g0 ! begin checks for that code
|
||||
|
@ -367,7 +358,6 @@ ccdbl: CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o
|
|||
CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
|
||||
11: EXT(ccdbl, 11b) ! note for exception table handling
|
||||
sub %g1, 128, %g1 ! detract from length
|
||||
addx %g0, %g7, %g7 ! add in last carry bit
|
||||
andcc %g1, 0xffffff80, %g0 ! more to csum?
|
||||
|
|
|
@ -21,98 +21,134 @@
|
|||
/* Work around cpp -rob */
|
||||
#define ALLOC #alloc
|
||||
#define EXECINSTR #execinstr
|
||||
|
||||
#define EX_ENTRY(l1, l2) \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word l1, l2; \
|
||||
.text;
|
||||
|
||||
#define EX(x,y,a,b) \
|
||||
98: x,y; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
.align 4; \
|
||||
99: ba fixupretl; \
|
||||
a, b, %g3; \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word 98b, 99b; \
|
||||
.text; \
|
||||
.align 4
|
||||
99: retl; \
|
||||
a, b, %o0; \
|
||||
EX_ENTRY(98b, 99b)
|
||||
|
||||
#define EX2(x,y,c,d,e,a,b) \
|
||||
98: x,y; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
.align 4; \
|
||||
99: c, d, e; \
|
||||
ba fixupretl; \
|
||||
a, b, %g3; \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word 98b, 99b; \
|
||||
.text; \
|
||||
.align 4
|
||||
retl; \
|
||||
a, b, %o0; \
|
||||
EX_ENTRY(98b, 99b)
|
||||
|
||||
#define EXO2(x,y) \
|
||||
98: x, y; \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word 98b, 97f; \
|
||||
.text; \
|
||||
.align 4
|
||||
EX_ENTRY(98b, 97f)
|
||||
|
||||
#define EXT(start,end,handler) \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word start, 0, end, handler; \
|
||||
.text; \
|
||||
.align 4
|
||||
#define LD(insn, src, offset, reg, label) \
|
||||
98: insn [%src + (offset)], %reg; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
99: ba label; \
|
||||
mov offset, %g5; \
|
||||
EX_ENTRY(98b, 99b)
|
||||
|
||||
/* Please do not change following macros unless you change logic used
|
||||
* in .fixup at the end of this file as well
|
||||
*/
|
||||
#define ST(insn, dst, offset, reg, label) \
|
||||
98: insn %reg, [%dst + (offset)]; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
99: ba label; \
|
||||
mov offset, %g5; \
|
||||
EX_ENTRY(98b, 99b)
|
||||
|
||||
/* Both these macros have to start with exactly the same insn */
|
||||
/* left: g7 + (g1 % 128) - offset */
|
||||
#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
|
||||
ldd [%src + (offset) + 0x00], %t0; \
|
||||
ldd [%src + (offset) + 0x08], %t2; \
|
||||
ldd [%src + (offset) + 0x10], %t4; \
|
||||
ldd [%src + (offset) + 0x18], %t6; \
|
||||
st %t0, [%dst + (offset) + 0x00]; \
|
||||
st %t1, [%dst + (offset) + 0x04]; \
|
||||
st %t2, [%dst + (offset) + 0x08]; \
|
||||
st %t3, [%dst + (offset) + 0x0c]; \
|
||||
st %t4, [%dst + (offset) + 0x10]; \
|
||||
st %t5, [%dst + (offset) + 0x14]; \
|
||||
st %t6, [%dst + (offset) + 0x18]; \
|
||||
st %t7, [%dst + (offset) + 0x1c];
|
||||
LD(ldd, src, offset + 0x00, t0, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x08, t2, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x10, t4, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x18, t6, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x00, t0, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x04, t1, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x08, t2, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x0c, t3, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x10, t4, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x14, t5, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x18, t6, bigchunk_fault) \
|
||||
ST(st, dst, offset + 0x1c, t7, bigchunk_fault)
|
||||
|
||||
/* left: g7 + (g1 % 128) - offset */
|
||||
#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
|
||||
ldd [%src + (offset) + 0x00], %t0; \
|
||||
ldd [%src + (offset) + 0x08], %t2; \
|
||||
ldd [%src + (offset) + 0x10], %t4; \
|
||||
ldd [%src + (offset) + 0x18], %t6; \
|
||||
std %t0, [%dst + (offset) + 0x00]; \
|
||||
std %t2, [%dst + (offset) + 0x08]; \
|
||||
std %t4, [%dst + (offset) + 0x10]; \
|
||||
std %t6, [%dst + (offset) + 0x18];
|
||||
LD(ldd, src, offset + 0x00, t0, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x08, t2, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x10, t4, bigchunk_fault) \
|
||||
LD(ldd, src, offset + 0x18, t6, bigchunk_fault) \
|
||||
ST(std, dst, offset + 0x00, t0, bigchunk_fault) \
|
||||
ST(std, dst, offset + 0x08, t2, bigchunk_fault) \
|
||||
ST(std, dst, offset + 0x10, t4, bigchunk_fault) \
|
||||
ST(std, dst, offset + 0x18, t6, bigchunk_fault)
|
||||
|
||||
.section .fixup,#alloc,#execinstr
|
||||
bigchunk_fault:
|
||||
sub %g7, %g5, %o0
|
||||
and %g1, 127, %g1
|
||||
retl
|
||||
add %o0, %g1, %o0
|
||||
|
||||
/* left: offset + 16 + (g1 % 16) */
|
||||
#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
|
||||
ldd [%src - (offset) - 0x10], %t0; \
|
||||
ldd [%src - (offset) - 0x08], %t2; \
|
||||
st %t0, [%dst - (offset) - 0x10]; \
|
||||
st %t1, [%dst - (offset) - 0x0c]; \
|
||||
st %t2, [%dst - (offset) - 0x08]; \
|
||||
st %t3, [%dst - (offset) - 0x04];
|
||||
LD(ldd, src, -(offset + 0x10), t0, lastchunk_fault) \
|
||||
LD(ldd, src, -(offset + 0x08), t2, lastchunk_fault) \
|
||||
ST(st, dst, -(offset + 0x10), t0, lastchunk_fault) \
|
||||
ST(st, dst, -(offset + 0x0c), t1, lastchunk_fault) \
|
||||
ST(st, dst, -(offset + 0x08), t2, lastchunk_fault) \
|
||||
ST(st, dst, -(offset + 0x04), t3, lastchunk_fault)
|
||||
|
||||
.section .fixup,#alloc,#execinstr
|
||||
lastchunk_fault:
|
||||
and %g1, 15, %g1
|
||||
retl
|
||||
sub %g1, %g5, %o0
|
||||
|
||||
/* left: o3 + (o2 % 16) - offset */
|
||||
#define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \
|
||||
lduh [%src + (offset) + 0x00], %t0; \
|
||||
lduh [%src + (offset) + 0x02], %t1; \
|
||||
lduh [%src + (offset) + 0x04], %t2; \
|
||||
lduh [%src + (offset) + 0x06], %t3; \
|
||||
sth %t0, [%dst + (offset) + 0x00]; \
|
||||
sth %t1, [%dst + (offset) + 0x02]; \
|
||||
sth %t2, [%dst + (offset) + 0x04]; \
|
||||
sth %t3, [%dst + (offset) + 0x06];
|
||||
LD(lduh, src, offset + 0x00, t0, halfchunk_fault) \
|
||||
LD(lduh, src, offset + 0x02, t1, halfchunk_fault) \
|
||||
LD(lduh, src, offset + 0x04, t2, halfchunk_fault) \
|
||||
LD(lduh, src, offset + 0x06, t3, halfchunk_fault) \
|
||||
ST(sth, dst, offset + 0x00, t0, halfchunk_fault) \
|
||||
ST(sth, dst, offset + 0x02, t1, halfchunk_fault) \
|
||||
ST(sth, dst, offset + 0x04, t2, halfchunk_fault) \
|
||||
ST(sth, dst, offset + 0x06, t3, halfchunk_fault)
|
||||
|
||||
/* left: o3 + (o2 % 16) + offset + 2 */
|
||||
#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
|
||||
ldub [%src - (offset) - 0x02], %t0; \
|
||||
ldub [%src - (offset) - 0x01], %t1; \
|
||||
stb %t0, [%dst - (offset) - 0x02]; \
|
||||
stb %t1, [%dst - (offset) - 0x01];
|
||||
LD(ldub, src, -(offset + 0x02), t0, halfchunk_fault) \
|
||||
LD(ldub, src, -(offset + 0x01), t1, halfchunk_fault) \
|
||||
ST(stb, dst, -(offset + 0x02), t0, halfchunk_fault) \
|
||||
ST(stb, dst, -(offset + 0x01), t1, halfchunk_fault)
|
||||
|
||||
.section .fixup,#alloc,#execinstr
|
||||
halfchunk_fault:
|
||||
and %o2, 15, %o2
|
||||
sub %o3, %g5, %o3
|
||||
retl
|
||||
add %o2, %o3, %o0
|
||||
|
||||
/* left: offset + 2 + (o2 % 2) */
|
||||
#define MOVE_LAST_SHORTCHUNK(src, dst, offset, t0, t1) \
|
||||
LD(ldub, src, -(offset + 0x02), t0, last_shortchunk_fault) \
|
||||
LD(ldub, src, -(offset + 0x01), t1, last_shortchunk_fault) \
|
||||
ST(stb, dst, -(offset + 0x02), t0, last_shortchunk_fault) \
|
||||
ST(stb, dst, -(offset + 0x01), t1, last_shortchunk_fault)
|
||||
|
||||
.section .fixup,#alloc,#execinstr
|
||||
last_shortchunk_fault:
|
||||
and %o2, 1, %o2
|
||||
retl
|
||||
sub %o2, %g5, %o0
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
@ -182,8 +218,6 @@ __copy_user: /* %o0=dst %o1=src %o2=len */
|
|||
MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
80:
|
||||
EXT(5b, 80b, 50f)
|
||||
subcc %g7, 128, %g7
|
||||
add %o1, 128, %o1
|
||||
bne 5b
|
||||
|
@ -201,7 +235,6 @@ __copy_user: /* %o0=dst %o1=src %o2=len */
|
|||
jmpl %o5 + %lo(copy_user_table_end), %g0
|
||||
add %o0, %g7, %o0
|
||||
|
||||
copy_user_table:
|
||||
MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
|
||||
MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
|
||||
MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
|
||||
|
@ -210,7 +243,6 @@ copy_user_table:
|
|||
MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
|
||||
MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
|
||||
copy_user_table_end:
|
||||
EXT(copy_user_table, copy_user_table_end, 51f)
|
||||
be copy_user_last7
|
||||
andcc %g1, 4, %g0
|
||||
|
||||
|
@ -250,8 +282,6 @@ ldd_std:
|
|||
MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
|
||||
81:
|
||||
EXT(ldd_std, 81b, 52f)
|
||||
subcc %g7, 128, %g7
|
||||
add %o1, 128, %o1
|
||||
bne ldd_std
|
||||
|
@ -290,8 +320,6 @@ cannot_optimize:
|
|||
10:
|
||||
MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
|
||||
MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5)
|
||||
82:
|
||||
EXT(10b, 82b, 53f)
|
||||
subcc %o3, 0x10, %o3
|
||||
add %o1, 0x10, %o1
|
||||
bne 10b
|
||||
|
@ -308,8 +336,6 @@ byte_chunk:
|
|||
MOVE_SHORTCHUNK(o1, o0, -0x0c, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3)
|
||||
83:
|
||||
EXT(byte_chunk, 83b, 54f)
|
||||
subcc %o3, 0x10, %o3
|
||||
add %o1, 0x10, %o1
|
||||
bne byte_chunk
|
||||
|
@ -325,16 +351,14 @@ short_end:
|
|||
add %o1, %o3, %o1
|
||||
jmpl %o5 + %lo(short_table_end), %g0
|
||||
andcc %o2, 1, %g0
|
||||
84:
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
|
||||
MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x08, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x06, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x04, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x02, g2, g3)
|
||||
MOVE_LAST_SHORTCHUNK(o1, o0, 0x00, g2, g3)
|
||||
short_table_end:
|
||||
EXT(84b, short_table_end, 55f)
|
||||
be 1f
|
||||
nop
|
||||
EX(ldub [%o1], %g2, add %g0, 1)
|
||||
|
@ -363,123 +387,8 @@ short_aligned_end:
|
|||
.section .fixup,#alloc,#execinstr
|
||||
.align 4
|
||||
97:
|
||||
mov %o2, %g3
|
||||
fixupretl:
|
||||
retl
|
||||
mov %g3, %o0
|
||||
|
||||
/* exception routine sets %g2 to (broken_insn - first_insn)>>2 */
|
||||
50:
|
||||
/* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK
|
||||
* happens. This is derived from the amount ldd reads, st stores, etc.
|
||||
* x = g2 % 12;
|
||||
* g3 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? 0 : (x - 4) * 4);
|
||||
* o0 += (g2 / 12) * 32;
|
||||
*/
|
||||
cmp %g2, 12
|
||||
add %o0, %g7, %o0
|
||||
bcs 1f
|
||||
cmp %g2, 24
|
||||
bcs 2f
|
||||
cmp %g2, 36
|
||||
bcs 3f
|
||||
nop
|
||||
sub %g2, 12, %g2
|
||||
sub %g7, 32, %g7
|
||||
3: sub %g2, 12, %g2
|
||||
sub %g7, 32, %g7
|
||||
2: sub %g2, 12, %g2
|
||||
sub %g7, 32, %g7
|
||||
1: cmp %g2, 4
|
||||
bcs,a 60f
|
||||
clr %g2
|
||||
sub %g2, 4, %g2
|
||||
sll %g2, 2, %g2
|
||||
60: and %g1, 0x7f, %g3
|
||||
sub %o0, %g7, %o0
|
||||
add %g3, %g7, %g3
|
||||
ba fixupretl
|
||||
sub %g3, %g2, %g3
|
||||
51:
|
||||
/* i = 41 - g2; j = i % 6;
|
||||
* g3 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : 16;
|
||||
* o0 -= (i / 6) * 16 + 16;
|
||||
*/
|
||||
neg %g2
|
||||
and %g1, 0xf, %g1
|
||||
add %g2, 41, %g2
|
||||
add %o0, %g1, %o0
|
||||
1: cmp %g2, 6
|
||||
bcs,a 2f
|
||||
cmp %g2, 4
|
||||
add %g1, 16, %g1
|
||||
b 1b
|
||||
sub %g2, 6, %g2
|
||||
2: bcc,a 2f
|
||||
mov 16, %g2
|
||||
inc %g2
|
||||
sll %g2, 2, %g2
|
||||
2: add %g1, %g2, %g3
|
||||
ba fixupretl
|
||||
sub %o0, %g3, %o0
|
||||
52:
|
||||
/* g3 = g1 + g7 - (g2 / 8) * 32 + (g2 & 4) ? (g2 & 3) * 8 : 0;
|
||||
o0 += (g2 / 8) * 32 */
|
||||
andn %g2, 7, %g4
|
||||
add %o0, %g7, %o0
|
||||
andcc %g2, 4, %g0
|
||||
and %g2, 3, %g2
|
||||
sll %g4, 2, %g4
|
||||
sll %g2, 3, %g2
|
||||
bne 60b
|
||||
sub %g7, %g4, %g7
|
||||
ba 60b
|
||||
clr %g2
|
||||
53:
|
||||
/* g3 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 4) ? (g2 & 3) * 2 : 0;
|
||||
o0 += (g2 & 8) */
|
||||
and %g2, 3, %g4
|
||||
andcc %g2, 4, %g0
|
||||
and %g2, 8, %g2
|
||||
sll %g4, 1, %g4
|
||||
be 1f
|
||||
add %o0, %g2, %o0
|
||||
add %g2, %g4, %g2
|
||||
1: and %o2, 0xf, %g3
|
||||
add %g3, %o3, %g3
|
||||
ba fixupretl
|
||||
sub %g3, %g2, %g3
|
||||
54:
|
||||
/* g3 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 2) ? (g2 & 1) : 0;
|
||||
o0 += (g2 / 4) * 2 */
|
||||
srl %g2, 2, %o4
|
||||
and %g2, 1, %o5
|
||||
srl %g2, 1, %g2
|
||||
add %o4, %o4, %o4
|
||||
and %o5, %g2, %o5
|
||||
and %o2, 0xf, %o2
|
||||
add %o0, %o4, %o0
|
||||
sub %o3, %o5, %o3
|
||||
sub %o2, %o4, %o2
|
||||
ba fixupretl
|
||||
add %o2, %o3, %g3
|
||||
55:
|
||||
/* i = 27 - g2;
|
||||
g3 = (o2 & 1) + i / 4 * 2 + !(i & 3);
|
||||
o0 -= i / 4 * 2 + 1 */
|
||||
neg %g2
|
||||
and %o2, 1, %o2
|
||||
add %g2, 27, %g2
|
||||
srl %g2, 2, %o5
|
||||
andcc %g2, 3, %g0
|
||||
mov 1, %g2
|
||||
add %o5, %o5, %o5
|
||||
be,a 1f
|
||||
clr %g2
|
||||
1: add %g2, %o5, %g3
|
||||
sub %o0, %g3, %o0
|
||||
ba fixupretl
|
||||
add %g3, %o2, %g3
|
||||
mov %o2, %o0
|
||||
|
||||
.globl __copy_user_end
|
||||
__copy_user_end:
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
98: x,y; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
.align 4; \
|
||||
99: ba 30f; \
|
||||
99: retl; \
|
||||
a, b, %o0; \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
|
@ -27,35 +27,44 @@
|
|||
.text; \
|
||||
.align 4
|
||||
|
||||
#define EXT(start,end,handler) \
|
||||
#define STORE(source, base, offset, n) \
|
||||
98: std source, [base + offset + n]; \
|
||||
.section .fixup,ALLOC,EXECINSTR; \
|
||||
.align 4; \
|
||||
99: ba 30f; \
|
||||
sub %o3, n - offset, %o3; \
|
||||
.section __ex_table,ALLOC; \
|
||||
.align 4; \
|
||||
.word start, 0, end, handler; \
|
||||
.word 98b, 99b; \
|
||||
.text; \
|
||||
.align 4
|
||||
.align 4;
|
||||
|
||||
#define STORE_LAST(source, base, offset, n) \
|
||||
EX(std source, [base - offset - n], \
|
||||
add %o1, offset + n);
|
||||
|
||||
/* Please don't change these macros, unless you change the logic
|
||||
* in the .fixup section below as well.
|
||||
* Store 64 bytes at (BASE + OFFSET) using value SOURCE. */
|
||||
#define ZERO_BIG_BLOCK(base, offset, source) \
|
||||
std source, [base + offset + 0x00]; \
|
||||
std source, [base + offset + 0x08]; \
|
||||
std source, [base + offset + 0x10]; \
|
||||
std source, [base + offset + 0x18]; \
|
||||
std source, [base + offset + 0x20]; \
|
||||
std source, [base + offset + 0x28]; \
|
||||
std source, [base + offset + 0x30]; \
|
||||
std source, [base + offset + 0x38];
|
||||
#define ZERO_BIG_BLOCK(base, offset, source) \
|
||||
STORE(source, base, offset, 0x00); \
|
||||
STORE(source, base, offset, 0x08); \
|
||||
STORE(source, base, offset, 0x10); \
|
||||
STORE(source, base, offset, 0x18); \
|
||||
STORE(source, base, offset, 0x20); \
|
||||
STORE(source, base, offset, 0x28); \
|
||||
STORE(source, base, offset, 0x30); \
|
||||
STORE(source, base, offset, 0x38);
|
||||
|
||||
#define ZERO_LAST_BLOCKS(base, offset, source) \
|
||||
std source, [base - offset - 0x38]; \
|
||||
std source, [base - offset - 0x30]; \
|
||||
std source, [base - offset - 0x28]; \
|
||||
std source, [base - offset - 0x20]; \
|
||||
std source, [base - offset - 0x18]; \
|
||||
std source, [base - offset - 0x10]; \
|
||||
std source, [base - offset - 0x08]; \
|
||||
std source, [base - offset - 0x00];
|
||||
STORE_LAST(source, base, offset, 0x38); \
|
||||
STORE_LAST(source, base, offset, 0x30); \
|
||||
STORE_LAST(source, base, offset, 0x28); \
|
||||
STORE_LAST(source, base, offset, 0x20); \
|
||||
STORE_LAST(source, base, offset, 0x18); \
|
||||
STORE_LAST(source, base, offset, 0x10); \
|
||||
STORE_LAST(source, base, offset, 0x08); \
|
||||
STORE_LAST(source, base, offset, 0x00);
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
@ -68,8 +77,6 @@ __bzero_begin:
|
|||
.globl memset
|
||||
EXPORT_SYMBOL(__bzero)
|
||||
EXPORT_SYMBOL(memset)
|
||||
.globl __memset_start, __memset_end
|
||||
__memset_start:
|
||||
memset:
|
||||
mov %o0, %g1
|
||||
mov 1, %g4
|
||||
|
@ -122,8 +129,6 @@ __bzero:
|
|||
ZERO_BIG_BLOCK(%o0, 0x00, %g2)
|
||||
subcc %o3, 128, %o3
|
||||
ZERO_BIG_BLOCK(%o0, 0x40, %g2)
|
||||
11:
|
||||
EXT(10b, 11b, 20f)
|
||||
bne 10b
|
||||
add %o0, 128, %o0
|
||||
|
||||
|
@ -138,11 +143,9 @@ __bzero:
|
|||
jmp %o4
|
||||
add %o0, %o2, %o0
|
||||
|
||||
12:
|
||||
ZERO_LAST_BLOCKS(%o0, 0x48, %g2)
|
||||
ZERO_LAST_BLOCKS(%o0, 0x08, %g2)
|
||||
13:
|
||||
EXT(12b, 13b, 21f)
|
||||
be 8f
|
||||
andcc %o1, 4, %g0
|
||||
|
||||
|
@ -182,37 +185,13 @@ __bzero:
|
|||
5:
|
||||
retl
|
||||
clr %o0
|
||||
__memset_end:
|
||||
|
||||
.section .fixup,#alloc,#execinstr
|
||||
.align 4
|
||||
20:
|
||||
cmp %g2, 8
|
||||
bleu 1f
|
||||
and %o1, 0x7f, %o1
|
||||
sub %g2, 9, %g2
|
||||
add %o3, 64, %o3
|
||||
1:
|
||||
sll %g2, 3, %g2
|
||||
add %o3, %o1, %o0
|
||||
b 30f
|
||||
sub %o0, %g2, %o0
|
||||
21:
|
||||
mov 8, %o0
|
||||
and %o1, 7, %o1
|
||||
sub %o0, %g2, %o0
|
||||
sll %o0, 3, %o0
|
||||
b 30f
|
||||
add %o0, %o1, %o0
|
||||
30:
|
||||
/* %o4 is faulting address, %o5 is %pc where fault occurred */
|
||||
save %sp, -104, %sp
|
||||
mov %i5, %o0
|
||||
mov %i7, %o1
|
||||
call lookup_fault
|
||||
mov %i4, %o2
|
||||
ret
|
||||
restore
|
||||
and %o1, 0x7f, %o1
|
||||
retl
|
||||
add %o3, %o1, %o0
|
||||
|
||||
.globl __bzero_end
|
||||
__bzero_end:
|
||||
|
|
|
@ -8,7 +8,7 @@ ccflags-y := -Werror
|
|||
obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
|
||||
obj-y += fault_$(BITS).o
|
||||
obj-y += init_$(BITS).o
|
||||
obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o
|
||||
obj-$(CONFIG_SPARC32) += srmmu.o iommu.o io-unit.o
|
||||
obj-$(CONFIG_SPARC32) += srmmu_access.o
|
||||
obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
|
||||
obj-$(CONFIG_SPARC32) += leon_mm.o
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/arch/sparc/mm/extable.c
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/extable.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
void sort_extable(struct exception_table_entry *start,
|
||||
struct exception_table_entry *finish)
|
||||
{
|
||||
}
|
||||
|
||||
/* Caller knows they are in a range if ret->fixup == 0 */
|
||||
const struct exception_table_entry *
|
||||
search_extable(const struct exception_table_entry *base,
|
||||
const size_t num,
|
||||
unsigned long value)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Single insn entries are encoded as:
|
||||
* word 1: insn address
|
||||
* word 2: fixup code address
|
||||
*
|
||||
* Range entries are encoded as:
|
||||
* word 1: first insn address
|
||||
* word 2: 0
|
||||
* word 3: last insn address + 4 bytes
|
||||
* word 4: fixup code address
|
||||
*
|
||||
* Deleted entries are encoded as:
|
||||
* word 1: unused
|
||||
* word 2: -1
|
||||
*
|
||||
* See asm/uaccess.h for more details.
|
||||
*/
|
||||
|
||||
/* 1. Try to find an exact match. */
|
||||
for (i = 0; i < num; i++) {
|
||||
if (base[i].fixup == 0) {
|
||||
/* A range entry, skip both parts. */
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A deleted entry; see trim_init_extable */
|
||||
if (base[i].fixup == -1)
|
||||
continue;
|
||||
|
||||
if (base[i].insn == value)
|
||||
return &base[i];
|
||||
}
|
||||
|
||||
/* 2. Try to find a range match. */
|
||||
for (i = 0; i < (num - 1); i++) {
|
||||
if (base[i].fixup)
|
||||
continue;
|
||||
|
||||
if (base[i].insn <= value && base[i + 1].insn > value)
|
||||
return &base[i];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
/* We could memmove them around; easier to mark the trimmed ones. */
|
||||
void trim_init_extable(struct module *m)
|
||||
{
|
||||
unsigned int i;
|
||||
bool range;
|
||||
|
||||
for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
|
||||
range = m->extable[i].fixup == 0;
|
||||
|
||||
if (within_module_init(m->extable[i].insn, m)) {
|
||||
m->extable[i].fixup = -1;
|
||||
if (range)
|
||||
m->extable[i+1].fixup = -1;
|
||||
}
|
||||
if (range)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
/* Special extable search, which handles ranges. Returns fixup */
|
||||
unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
|
||||
{
|
||||
const struct exception_table_entry *entry;
|
||||
|
||||
entry = search_exception_tables(addr);
|
||||
if (!entry)
|
||||
return 0;
|
||||
|
||||
/* Inside range? Fix g2 and return correct fixup */
|
||||
if (!entry->fixup) {
|
||||
*g2 = (addr - entry->insn) / 4;
|
||||
return (entry + 1)->fixup;
|
||||
}
|
||||
|
||||
return entry->fixup;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/extable.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/openprom.h>
|
||||
|
@ -54,54 +55,6 @@ static void __noreturn unhandled_fault(unsigned long address,
|
|||
die_if_kernel("Oops", regs);
|
||||
}
|
||||
|
||||
asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
|
||||
unsigned long address)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
unsigned long g2;
|
||||
unsigned int insn;
|
||||
int i;
|
||||
|
||||
i = search_extables_range(ret_pc, &g2);
|
||||
switch (i) {
|
||||
case 3:
|
||||
/* load & store will be handled by fixup */
|
||||
return 3;
|
||||
|
||||
case 1:
|
||||
/* store will be handled by fixup, load will bump out */
|
||||
/* for _to_ macros */
|
||||
insn = *((unsigned int *) pc);
|
||||
if ((insn >> 21) & 1)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* load will be handled by fixup, store will bump out */
|
||||
/* for _from_ macros */
|
||||
insn = *((unsigned int *) pc);
|
||||
if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15)
|
||||
return 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
regs.pc = pc;
|
||||
regs.npc = pc + 4;
|
||||
__asm__ __volatile__(
|
||||
"rd %%psr, %0\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n" : "=r" (regs.psr));
|
||||
unhandled_fault(address, current, ®s);
|
||||
|
||||
/* Not reached */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_signal_msg(struct pt_regs *regs, int sig, int code,
|
||||
unsigned long address, struct task_struct *tsk)
|
||||
|
@ -162,8 +115,6 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
|||
struct vm_area_struct *vma;
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
unsigned int fixup;
|
||||
unsigned long g2;
|
||||
int from_user = !(regs->psr & PSR_PS);
|
||||
int code;
|
||||
vm_fault_t fault;
|
||||
|
@ -281,30 +232,19 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
|||
|
||||
/* Is this in ex_table? */
|
||||
no_context:
|
||||
g2 = regs->u_regs[UREG_G2];
|
||||
if (!from_user) {
|
||||
fixup = search_extables_range(regs->pc, &g2);
|
||||
/* Values below 10 are reserved for other things */
|
||||
if (fixup > 10) {
|
||||
extern const unsigned int __memset_start[];
|
||||
extern const unsigned int __memset_end[];
|
||||
const struct exception_table_entry *entry;
|
||||
|
||||
entry = search_exception_tables(regs->pc);
|
||||
#ifdef DEBUG_EXCEPTIONS
|
||||
printk("Exception: PC<%08lx> faddr<%08lx>\n",
|
||||
regs->pc, address);
|
||||
printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
|
||||
regs->pc, fixup, g2);
|
||||
printk("Exception: PC<%08lx> faddr<%08lx>\n",
|
||||
regs->pc, address);
|
||||
printk("EX_TABLE: insn<%08lx> fixup<%08x>\n",
|
||||
regs->pc, entry->fixup);
|
||||
#endif
|
||||
if ((regs->pc >= (unsigned long)__memset_start &&
|
||||
regs->pc < (unsigned long)__memset_end)) {
|
||||
regs->u_regs[UREG_I4] = address;
|
||||
regs->u_regs[UREG_I5] = regs->pc;
|
||||
}
|
||||
regs->u_regs[UREG_G2] = g2;
|
||||
regs->pc = fixup;
|
||||
regs->npc = regs->pc + 4;
|
||||
return;
|
||||
}
|
||||
regs->pc = entry->fixup;
|
||||
regs->npc = regs->pc + 4;
|
||||
return;
|
||||
}
|
||||
|
||||
unhandled_fault(address, tsk, regs);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* fault_32.c - visible as they are called from assembler */
|
||||
asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
|
||||
unsigned long address);
|
||||
asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
||||
unsigned long address);
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ static inline unsigned long ex_to_insn(const struct exception_table_entry *x)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_HAS_SORT_EXTABLE
|
||||
#ifndef ARCH_HAS_RELATIVE_EXTABLE
|
||||
#define swap_ex NULL
|
||||
#else
|
||||
|
@ -88,9 +87,6 @@ void trim_init_extable(struct module *m)
|
|||
m->num_exentries--;
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
#endif /* !ARCH_HAS_SORT_EXTABLE */
|
||||
|
||||
#ifndef ARCH_HAS_SEARCH_EXTABLE
|
||||
|
||||
static int cmp_ex_search(const void *key, const void *elt)
|
||||
{
|
||||
|
@ -120,4 +116,3 @@ search_extable(const struct exception_table_entry *base,
|
|||
return bsearch(&value, base, num,
|
||||
sizeof(struct exception_table_entry), cmp_ex_search);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue