Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fd29752 authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Fix fault handling in unaligned trap handler.



We were not calling kernel_mna_trap_fault() correctly.
Instead of being fancy, just return 0 vs. -EFAULT from
the assembler stubs, and handle that return value as
appropriate.

Create an "__retl_efault" stub for assembler exception
table entries and use it where possible.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8cf14af0
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -540,8 +540,11 @@ bootup_user_stack_end:
prom_tba:	.xword	0
tlb_type:	.word	0	/* Must NOT end up in BSS */
	.section	".fixup",#alloc,#execinstr
	.globl	__ret_efault

	.globl	__ret_efault, __retl_efault
__ret_efault:
	ret
	 restore %g0, -EFAULT, %o0
__retl_efault:
	retl
	 mov	-EFAULT, %o0
+34 −23
Original line number Diff line number Diff line
@@ -157,6 +157,9 @@ sys32_socketcall: /* %o0=call, %o1=args */
	or		%g2, %lo(__socketcall_table_begin), %g2
	jmpl		%g2 + %o0, %g0
	 nop
do_einval:
	retl
	 mov		-EINVAL, %o0

	.align		32
__socketcall_table_begin:
@@ -316,29 +319,37 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int)
	nop
	nop

do_einval:
	retl
	 mov		-EINVAL, %o0
do_efault:
	retl
	 mov		-EFAULT, %o0

	.section	__ex_table
	.align		4
	.word	1b, do_efault, 2b, do_efault, 3b, do_efault, 4b, do_efault
	.word	5b, do_efault, 6b, do_efault, 7b, do_efault, 8b, do_efault
	.word	9b, do_efault, 10b, do_efault, 11b, do_efault, 12b, do_efault
	.word	13b, do_efault, 14b, do_efault, 15b, do_efault, 16b, do_efault
	.word	17b, do_efault, 18b, do_efault, 19b, do_efault, 20b, do_efault
	.word	21b, do_efault, 22b, do_efault, 23b, do_efault, 24b, do_efault
	.word	25b, do_efault, 26b, do_efault, 27b, do_efault, 28b, do_efault
	.word	29b, do_efault, 30b, do_efault, 31b, do_efault, 32b, do_efault
	.word	33b, do_efault, 34b, do_efault, 35b, do_efault, 36b, do_efault
	.word	37b, do_efault, 38b, do_efault, 39b, do_efault, 40b, do_efault
	.word	41b, do_efault, 42b, do_efault, 43b, do_efault, 44b, do_efault
	.word	45b, do_efault, 46b, do_efault, 47b, do_efault, 48b, do_efault
	.word	49b, do_efault, 50b, do_efault, 51b, do_efault, 52b, do_efault
	.word	53b, do_efault, 54b, do_efault, 55b, do_efault, 56b, do_efault
	.word	57b, do_efault, 58b, do_efault, 59b, do_efault, 60b, do_efault
	.word	61b, do_efault, 62b, do_efault
	.word		1b, __retl_efault, 2b, __retl_efault
	.word		3b, __retl_efault, 4b, __retl_efault
	.word		5b, __retl_efault, 6b, __retl_efault
	.word		7b, __retl_efault, 8b, __retl_efault
	.word		9b, __retl_efault, 10b, __retl_efault
	.word		11b, __retl_efault, 12b, __retl_efault
	.word		13b, __retl_efault, 14b, __retl_efault
	.word		15b, __retl_efault, 16b, __retl_efault
	.word		17b, __retl_efault, 18b, __retl_efault
	.word		19b, __retl_efault, 20b, __retl_efault
	.word		21b, __retl_efault, 22b, __retl_efault
	.word		23b, __retl_efault, 24b, __retl_efault
	.word		25b, __retl_efault, 26b, __retl_efault
	.word		27b, __retl_efault, 28b, __retl_efault
	.word		29b, __retl_efault, 30b, __retl_efault
	.word		31b, __retl_efault, 32b, __retl_efault
	.word		33b, __retl_efault, 34b, __retl_efault
	.word		35b, __retl_efault, 36b, __retl_efault
	.word		37b, __retl_efault, 38b, __retl_efault
	.word		39b, __retl_efault, 40b, __retl_efault
	.word		41b, __retl_efault, 42b, __retl_efault
	.word		43b, __retl_efault, 44b, __retl_efault
	.word		45b, __retl_efault, 46b, __retl_efault
	.word		47b, __retl_efault, 48b, __retl_efault
	.word		49b, __retl_efault, 50b, __retl_efault
	.word		51b, __retl_efault, 52b, __retl_efault
	.word		53b, __retl_efault, 54b, __retl_efault
	.word		55b, __retl_efault, 56b, __retl_efault
	.word		57b, __retl_efault, 58b, __retl_efault
	.word		59b, __retl_efault, 60b, __retl_efault
	.word		61b, __retl_efault, 62b, __retl_efault
	.previous
+29 −36
Original line number Diff line number Diff line
@@ -6,13 +6,6 @@

	.text

kernel_unaligned_trap_fault:
	call	kernel_mna_trap_fault
	 nop
	retl
	 nop
	.size	kern_unaligned_trap_fault, .-kern_unaligned_trap_fault

	.globl	__do_int_store
__do_int_store:
	rd	%asi, %o4
@@ -51,24 +44,24 @@ __do_int_store:
0:
	wr	%o4, 0x0, %asi
	retl
	 nop
	 mov	0, %o0
	.size	__do_int_store, .-__do_int_store

	.section	__ex_table
	.word		4b, kernel_unaligned_trap_fault
	.word		5b, kernel_unaligned_trap_fault
	.word		6b, kernel_unaligned_trap_fault
	.word		7b, kernel_unaligned_trap_fault
	.word		8b, kernel_unaligned_trap_fault
	.word		9b, kernel_unaligned_trap_fault
	.word		10b, kernel_unaligned_trap_fault
	.word		11b, kernel_unaligned_trap_fault
	.word		12b, kernel_unaligned_trap_fault
	.word		13b, kernel_unaligned_trap_fault
	.word		14b, kernel_unaligned_trap_fault
	.word		15b, kernel_unaligned_trap_fault
	.word		16b, kernel_unaligned_trap_fault
	.word		17b, kernel_unaligned_trap_fault
	.word		4b, __retl_efault
	.word		5b, __retl_efault
	.word		6b, __retl_efault
	.word		7b, __retl_efault
	.word		8b, __retl_efault
	.word		9b, __retl_efault
	.word		10b, __retl_efault
	.word		11b, __retl_efault
	.word		12b, __retl_efault
	.word		13b, __retl_efault
	.word		14b, __retl_efault
	.word		15b, __retl_efault
	.word		16b, __retl_efault
	.word		17b, __retl_efault
	.previous

	.globl	do_int_load
@@ -133,21 +126,21 @@ do_int_load:
0:
	wr	%o5, 0x0, %asi
	retl
	 nop
	 mov	0, %o0
	.size	__do_int_load, .-__do_int_load

	.section	__ex_table
	.word		4b, kernel_unaligned_trap_fault
	.word		5b, kernel_unaligned_trap_fault
	.word		6b, kernel_unaligned_trap_fault
	.word		7b, kernel_unaligned_trap_fault
	.word		8b, kernel_unaligned_trap_fault
	.word		9b, kernel_unaligned_trap_fault
	.word		10b, kernel_unaligned_trap_fault
	.word		11b, kernel_unaligned_trap_fault
	.word		12b, kernel_unaligned_trap_fault
	.word		13b, kernel_unaligned_trap_fault
	.word		14b, kernel_unaligned_trap_fault
	.word		15b, kernel_unaligned_trap_fault
	.word		16b, kernel_unaligned_trap_fault
	.word		4b, __retl_efault
	.word		5b, __retl_efault
	.word		6b, __retl_efault
	.word		7b, __retl_efault
	.word		8b, __retl_efault
	.word		9b, __retl_efault
	.word		10b, __retl_efault
	.word		11b, __retl_efault
	.word		12b, __retl_efault
	.word		13b, __retl_efault
	.word		14b, __retl_efault
	.word		15b, __retl_efault
	.word		16b, __retl_efault
	.previous
+20 −16
Original line number Diff line number Diff line
@@ -180,13 +180,13 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
	die_if_kernel(str, regs);
}

extern void do_int_load(unsigned long *dest_reg, int size,
extern int do_int_load(unsigned long *dest_reg, int size,
		       unsigned long *saddr, int is_signed, int asi);
	
extern void __do_int_store(unsigned long *dst_addr, int size,
extern int __do_int_store(unsigned long *dst_addr, int size,
			  unsigned long src_val, int asi);

static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
			       struct pt_regs *regs, int asi, int orig_asi)
{
	unsigned long zero = 0;
@@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
			break;
		};
	}
	__do_int_store(dst_addr, size, src_val, asi);
	return __do_int_store(dst_addr, size, src_val, asi);
}

static inline void advance(struct pt_regs *regs)
@@ -242,7 +242,7 @@ static inline int ok_for_kernel(unsigned int insn)
	return !floating_point_load_or_store_p(insn);
}

void kernel_mna_trap_fault(void)
static void kernel_mna_trap_fault(void)
{
	struct pt_regs *regs = current_thread_info()->kern_una_regs;
	unsigned int insn = current_thread_info()->kern_una_insn;
@@ -294,7 +294,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
		kernel_mna_trap_fault();
	} else {
		unsigned long addr, *reg_addr;
		int orig_asi, asi;
		int orig_asi, asi, err;

		addr = compute_effective_address(regs, insn,
						 ((insn >> 25) & 0x1f));
@@ -319,9 +319,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
		switch (dir) {
		case load:
			reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
			do_int_load(reg_addr, size, (unsigned long *) addr,
			err = do_int_load(reg_addr, size,
					  (unsigned long *) addr,
					  decode_signedness(insn), asi);
			if (unlikely(asi != orig_asi)) {
			if (likely(!err) && unlikely(asi != orig_asi)) {
				unsigned long val_in = *reg_addr;
				switch (size) {
				case 2:
@@ -343,7 +344,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
			break;

		case store:
			do_int_store(((insn>>25)&0x1f), size,
			err = do_int_store(((insn>>25)&0x1f), size,
					   (unsigned long *) addr, regs,
					   asi, orig_asi);
			break;
@@ -352,6 +353,9 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
			panic("Impossible kernel unaligned trap.");
			/* Not reached... */
		}
		if (unlikely(err))
			kernel_mna_trap_fault();
		else
			advance(regs);
	}
}
+6 −10
Original line number Diff line number Diff line
@@ -125,15 +125,11 @@ __strncpy_from_user:
	 add	%o2, %o3, %o0
	.size	__strncpy_from_user, .-__strncpy_from_user

	.section .fixup,#alloc,#execinstr
	.align	4
4:	retl
	 mov	-EFAULT, %o0

	.section __ex_table,#alloc
	.align	4
	.word	60b, 4b
	.word	61b, 4b
	.word	62b, 4b
	.word	63b, 4b
	.word	64b, 4b
	.word	60b, __retl_efault
	.word	61b, __retl_efault
	.word	62b, __retl_efault
	.word	63b, __retl_efault
	.word	64b, __retl_efault
	.previous
Loading