linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* sparc vs. gcc 4.3
@ 2008-03-03 19:26 Adrian Bunk
  2008-03-03 21:03 ` David Miller
  2008-03-03 23:02 ` David Miller
  0 siblings, 2 replies; 5+ messages in thread
From: Adrian Bunk @ 2008-03-03 19:26 UTC (permalink / raw)
  To: wli; +Cc: sparclinux, linux-kernel

Trying to build a sparc kernel with a gcc 4.3 release candidate fails 
with the following error:

<--  snip  -->

...
  LD      arch/sparc/boot/image
arch/sparc/kernel/built-in.o:(__ex_table+0x394): undefined reference to `kernel_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x39c): undefined reference to `kernel_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x3a4): undefined reference to `kernel_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x3ac): undefined reference to `kernel_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x3b4): undefined reference to `kernel_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x3bc): more undefined references to `kernel_unaligned_trap_fault' follow
arch/sparc/kernel/built-in.o:(__ex_table+0x46c): undefined reference to `user_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x474): undefined reference to `user_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x47c): undefined reference to `user_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x484): undefined reference to `user_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x48c): undefined reference to `user_unaligned_trap_fault'
arch/sparc/kernel/built-in.o:(__ex_table+0x494): more undefined references to `user_unaligned_trap_fault' follow
make[2]: *** [arch/sparc/boot/image] Error 1

<--  snip  -->

Does anyone have a clue what's going wrong here?

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: sparc vs. gcc 4.3
  2008-03-03 19:26 sparc vs. gcc 4.3 Adrian Bunk
@ 2008-03-03 21:03 ` David Miller
  2008-03-03 21:41   ` Harvey Harrison
  2008-03-03 23:02 ` David Miller
  1 sibling, 1 reply; 5+ messages in thread
From: David Miller @ 2008-03-03 21:03 UTC (permalink / raw)
  To: bunk; +Cc: wli, sparclinux, linux-kernel

From: Adrian Bunk <bunk@kernel.org>
Date: Mon, 3 Mar 2008 21:26:51 +0200

>   LD      arch/sparc/boot/image
> arch/sparc/kernel/built-in.o:(__ex_table+0x394): undefined reference to `kernel_unaligned_trap_fault'
...
> arch/sparc/kernel/built-in.o:(__ex_table+0x46c): undefined reference to `user_unaligned_trap_fault'

> Does anyone have a clue what's going wrong here?

We hit the same problem a while back on sparc64 too.

GCC can't see how the inline asm is reachable so eliminates it
entirely.  We hide the label inside the inline asm string and call it
from exception handlers.

The way we fixed this on sparc64 was quite invasive (patch below for
reference), so I'll try to come up with something simpler.

commit a3f9985843b674cbcb58f39fab8416675e7ab842
Author: David S. Miller <davem@davemloft.net>
Date:   Fri Aug 19 15:55:33 2005 -0700

    [SPARC64]: Move kernel unaligned trap handlers into assembler file.
    
    GCC 4.x really dislikes the games we are playing in
    unaligned.c, and the cleanest way to fix this is to
    move things into assembler.
    
    Noted by Al Viro.
    
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 093281b..6f00ab8 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror
 extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
-		   traps.o devices.o auxio.o \
+		   traps.o devices.o auxio.o una_asm.o \
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 100b010..0c9e54b 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -2127,6 +2127,9 @@ void __init trap_init(void)
 	    TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
 	    TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
 	    TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
+	    TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
+	    TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
+	    TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
 	    TI_FPREGS != offsetof(struct thread_info, fpregs) ||
 	    (TI_FPREGS & (64 - 1)))
 		thread_info_offsets_are_bolixed_dave();
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S
new file mode 100644
index 0000000..cbb4058
--- /dev/null
+++ b/arch/sparc64/kernel/una_asm.S
@@ -0,0 +1,153 @@
+/* una_asm.S: Kernel unaligned trap assembler helpers.
+ *
+ * Copyright (C) 1996,2005 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+	.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
+	wr	%o3, 0, %asi
+	ldx	[%o2], %g3
+	cmp	%o1, 2
+	be,pn	%icc, 2f
+	 cmp	%o1, 4
+	be,pt	%icc, 1f
+	 srlx	%g3, 24, %g2
+	srlx	%g3, 56, %g1
+	srlx	%g3, 48, %g7
+4:	stba	%g1, [%o0] %asi
+	srlx	%g3, 40, %g1
+5:	stba	%g7, [%o0 + 1] %asi
+	srlx	%g3, 32, %g7
+6:	stba	%g1, [%o0 + 2] %asi
+7:	stba	%g7, [%o0 + 3] %asi
+	srlx	%g3, 16, %g1
+8:	stba	%g2, [%o0 + 4] %asi
+	srlx	%g3, 8, %g7
+9:	stba	%g1, [%o0 + 5] %asi
+10:	stba	%g7, [%o0 + 6] %asi
+	ba,pt	%xcc, 0f
+11:	 stba	%g3, [%o0 + 7] %asi
+1:	srl	%g3, 16, %g7
+12:	stba	%g2, [%o0] %asi
+	srl	%g3, 8, %g2
+13:	stba	%g7, [%o0 + 1] %asi
+14:	stba	%g2, [%o0 + 2] %asi
+	ba,pt	%xcc, 0f
+15:	 stba	%g3, [%o0 + 3] %asi
+2:	srl	%g3, 8, %g2
+16:	stba	%g2, [%o0] %asi
+17:	stba	%g3, [%o0 + 1] %asi
+0:
+	wr	%o4, 0x0, %asi
+	retl
+	 nop
+	.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
+	.previous
+
+	.globl	do_int_load
+do_int_load:
+	rd	%asi, %o5
+	wr	%o4, 0, %asi
+	cmp	%o1, 8
+	bge,pn	%icc, 9f
+	 cmp	%o1, 4
+	be,pt	%icc, 6f
+4:	 lduba	[%o2] %asi, %g2
+5:	lduba	[%o2 + 1] %asi, %g3
+	sll	%g2, 8, %g2
+	brz,pt	%o3, 3f
+	 add	%g2, %g3, %g2
+	sllx	%g2, 48, %g2
+	srax	%g2, 48, %g2
+3:	ba,pt	%xcc, 0f
+	 stx	%g2, [%o0]
+6:	lduba	[%o2 + 1] %asi, %g3
+	sll	%g2, 24, %g2
+7:	lduba	[%o2 + 2] %asi, %g7
+	sll	%g3, 16, %g3
+8:	lduba	[%o2 + 3] %asi, %g1
+	sll	%g7, 8, %g7
+	or	%g2, %g3, %g2
+	or	%g7, %g1, %g7
+	or	%g2, %g7, %g2
+	brnz,a,pt %o3, 3f
+	 sra	%g2, 0, %g2
+3:	ba,pt	%xcc, 0f
+	 stx	%g2, [%o0]
+9:	lduba	[%o2] %asi, %g2
+10:	lduba	[%o2 + 1] %asi, %g3
+	sllx	%g2, 56, %g2
+11:	lduba	[%o2 + 2] %asi, %g7
+	sllx	%g3, 48, %g3
+12:	lduba	[%o2 + 3] %asi, %g1
+	sllx	%g7, 40, %g7
+	sllx	%g1, 32, %g1
+	or	%g2, %g3, %g2
+	or	%g7, %g1, %g7
+13:	lduba	[%o2 + 4] %asi, %g3
+	or	%g2, %g7, %g7
+14:	lduba	[%o2 + 5] %asi, %g1
+	sllx	%g3, 24, %g3
+15:	lduba	[%o2 + 6] %asi, %g2
+	sllx	%g1, 16, %g1
+	or	%g7, %g3, %g7
+16:	lduba	[%o2 + 7] %asi, %g3
+	sllx	%g2, 8, %g2
+	or	%g7, %g1, %g7
+	or	%g2, %g3, %g2
+	or	%g7, %g2, %g7
+	cmp	%o1, 8
+	be,a,pt %icc, 0f
+	 stx	%g7, [%o0]
+	srlx	%g7, 32, %g2
+	sra	%g7, 0, %g7
+	stx	%g2, [%o0]
+	stx	%g7, [%o0 + 8]
+0:
+	wr	%o5, 0x0, %asi
+	retl
+	 nop
+	.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
+	.previous
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 4372bf3..11c3e88 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -180,169 +180,28 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
 	die_if_kernel(str, regs);
 }
 
-#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({		\
-__asm__ __volatile__ (								\
-	"wr	%4, 0, %%asi\n\t"						\
-	"cmp	%1, 8\n\t"							\
-	"bge,pn	%%icc, 9f\n\t"							\
-	" cmp	%1, 4\n\t"							\
-	"be,pt	%%icc, 6f\n"							\
-"4:\t"	" lduba	[%2] %%asi, %%l1\n"						\
-"5:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
-	"sll	%%l1, 8, %%l1\n\t"						\
-	"brz,pt	%3, 3f\n\t"							\
-	" add	%%l1, %%l2, %%l1\n\t"						\
-	"sllx	%%l1, 48, %%l1\n\t"						\
-	"srax	%%l1, 48, %%l1\n"						\
-"3:\t"	"ba,pt	%%xcc, 0f\n\t"							\
-	" stx	%%l1, [%0]\n"							\
-"6:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
-	"sll	%%l1, 24, %%l1\n"						\
-"7:\t"	"lduba	[%2 + 2] %%asi, %%g7\n\t"					\
-	"sll	%%l2, 16, %%l2\n"						\
-"8:\t"	"lduba	[%2 + 3] %%asi, %%g1\n\t"					\
-	"sll	%%g7, 8, %%g7\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n\t"						\
-	"or	%%l1, %%g7, %%l1\n\t"						\
-	"brnz,a,pt %3, 3f\n\t"							\
-	" sra	%%l1, 0, %%l1\n"						\
-"3:\t"	"ba,pt	%%xcc, 0f\n\t"							\
-	" stx	%%l1, [%0]\n"							\
-"9:\t"	"lduba	[%2] %%asi, %%l1\n"						\
-"10:\t"	"lduba	[%2 + 1] %%asi, %%l2\n\t"					\
-	"sllx	%%l1, 56, %%l1\n"						\
-"11:\t"	"lduba	[%2 + 2] %%asi, %%g7\n\t"					\
-	"sllx	%%l2, 48, %%l2\n"						\
-"12:\t"	"lduba	[%2 + 3] %%asi, %%g1\n\t"					\
-	"sllx	%%g7, 40, %%g7\n\t"						\
-	"sllx	%%g1, 32, %%g1\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n"						\
-"13:\t"	"lduba	[%2 + 4] %%asi, %%l2\n\t"					\
-	"or	%%l1, %%g7, %%g7\n"						\
-"14:\t"	"lduba	[%2 + 5] %%asi, %%g1\n\t"					\
-	"sllx	%%l2, 24, %%l2\n"						\
-"15:\t"	"lduba	[%2 + 6] %%asi, %%l1\n\t"					\
-	"sllx	%%g1, 16, %%g1\n\t"						\
-	"or	%%g7, %%l2, %%g7\n"						\
-"16:\t"	"lduba	[%2 + 7] %%asi, %%l2\n\t"					\
-	"sllx	%%l1, 8, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%l1, %%g7\n\t"						\
-	"cmp	%1, 8\n\t"							\
-	"be,a,pt %%icc, 0f\n\t"							\
-	" stx	%%g7, [%0]\n\t"							\
-	"srlx	%%g7, 32, %%l1\n\t"						\
-	"sra	%%g7, 0, %%g7\n\t"						\
-	"stx	%%l1, [%0]\n\t"							\
-	"stx	%%g7, [%0 + 8]\n"						\
-"0:\n\t"									\
-	"wr	%%g0, %5, %%asi\n\n\t"						\
-	".section __ex_table\n\t"						\
-	".word	4b, " #errh "\n\t"						\
-	".word	5b, " #errh "\n\t"						\
-	".word	6b, " #errh "\n\t"						\
-	".word	7b, " #errh "\n\t"						\
-	".word	8b, " #errh "\n\t"						\
-	".word	9b, " #errh "\n\t"						\
-	".word	10b, " #errh "\n\t"						\
-	".word	11b, " #errh "\n\t"						\
-	".word	12b, " #errh "\n\t"						\
-	".word	13b, " #errh "\n\t"						\
-	".word	14b, " #errh "\n\t"						\
-	".word	15b, " #errh "\n\t"						\
-	".word	16b, " #errh "\n\n\t"						\
-	".previous\n\t"								\
-	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed),		\
-	  "r" (asi), "i" (ASI_AIUS)						\
-	: "l1", "l2", "g7", "g1", "cc");					\
-})
+extern void do_int_load(unsigned long *dest_reg, int size,
+			unsigned long *saddr, int is_signed, int asi);
 	
-#define store_common(dst_addr, size, src_val, asi, errh) ({			\
-__asm__ __volatile__ (								\
-	"wr	%3, 0, %%asi\n\t"						\
-	"ldx	[%2], %%l1\n"							\
-	"cmp	%1, 2\n\t"							\
-	"be,pn	%%icc, 2f\n\t"							\
-	" cmp	%1, 4\n\t"							\
-	"be,pt	%%icc, 1f\n\t"							\
-	" srlx	%%l1, 24, %%l2\n\t"						\
-	"srlx	%%l1, 56, %%g1\n\t"						\
-	"srlx	%%l1, 48, %%g7\n"						\
-"4:\t"	"stba	%%g1, [%0] %%asi\n\t"						\
-	"srlx	%%l1, 40, %%g1\n"						\
-"5:\t"	"stba	%%g7, [%0 + 1] %%asi\n\t"					\
-	"srlx	%%l1, 32, %%g7\n"						\
-"6:\t"	"stba	%%g1, [%0 + 2] %%asi\n"						\
-"7:\t"	"stba	%%g7, [%0 + 3] %%asi\n\t"					\
-	"srlx	%%l1, 16, %%g1\n"						\
-"8:\t"	"stba	%%l2, [%0 + 4] %%asi\n\t"					\
-	"srlx	%%l1, 8, %%g7\n"						\
-"9:\t"	"stba	%%g1, [%0 + 5] %%asi\n"						\
-"10:\t"	"stba	%%g7, [%0 + 6] %%asi\n\t"					\
-	"ba,pt	%%xcc, 0f\n"							\
-"11:\t"	" stba	%%l1, [%0 + 7] %%asi\n"						\
-"1:\t"	"srl	%%l1, 16, %%g7\n"						\
-"12:\t"	"stba	%%l2, [%0] %%asi\n\t"						\
-	"srl	%%l1, 8, %%l2\n"						\
-"13:\t"	"stba	%%g7, [%0 + 1] %%asi\n"						\
-"14:\t"	"stba	%%l2, [%0 + 2] %%asi\n\t"					\
-	"ba,pt	%%xcc, 0f\n"							\
-"15:\t"	" stba	%%l1, [%0 + 3] %%asi\n"						\
-"2:\t"	"srl	%%l1, 8, %%l2\n"						\
-"16:\t"	"stba	%%l2, [%0] %%asi\n"						\
-"17:\t"	"stba	%%l1, [%0 + 1] %%asi\n"						\
-"0:\n\t"									\
-	"wr	%%g0, %4, %%asi\n\n\t"						\
-	".section __ex_table\n\t"						\
-	".word	4b, " #errh "\n\t"						\
-	".word	5b, " #errh "\n\t"						\
-	".word	6b, " #errh "\n\t"						\
-	".word	7b, " #errh "\n\t"						\
-	".word	8b, " #errh "\n\t"						\
-	".word	9b, " #errh "\n\t"						\
-	".word	10b, " #errh "\n\t"						\
-	".word	11b, " #errh "\n\t"						\
-	".word	12b, " #errh "\n\t"						\
-	".word	13b, " #errh "\n\t"						\
-	".word	14b, " #errh "\n\t"						\
-	".word	15b, " #errh "\n\t"						\
-	".word	16b, " #errh "\n\t"						\
-	".word	17b, " #errh "\n\n\t"						\
-	".previous\n\t"								\
-	: : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\
-	: "l1", "l2", "g7", "g1", "cc");					\
-})
-
-#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({		\
-	unsigned long zero = 0;							\
-	unsigned long *src_val = &zero;						\
-										\
-	if (size == 16) {							\
-		size = 8;							\
-		zero = (((long)(reg_num ? 					\
-		        (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |	\
-			(unsigned)fetch_reg(reg_num + 1, regs);			\
-	} else if (reg_num) src_val = fetch_reg_addr(reg_num, regs);		\
-	store_common(dst_addr, size, src_val, asi, errh);			\
-})
-
-extern void smp_capture(void);
-extern void smp_release(void);
-
-#define do_atomic(srcdest_reg, mem, errh) ({					\
-	unsigned long flags, tmp;						\
-										\
-	smp_capture();								\
-	local_irq_save(flags);							\
-	tmp = *srcdest_reg;							\
-	do_integer_load(srcdest_reg, 4, mem, 0, errh);				\
-	store_common(mem, 4, &tmp, errh);					\
-	local_irq_restore(flags);						\
-	smp_release();								\
-})
+extern void __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,
+				struct pt_regs *regs, int asi)
+{
+	unsigned long zero = 0;
+	unsigned long *src_val = &zero;
+
+	if (size == 16) {
+		size = 8;
+		zero = (((long)(reg_num ?
+		        (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |
+			(unsigned)fetch_reg(reg_num + 1, regs);
+	} else if (reg_num) {
+		src_val = fetch_reg_addr(reg_num, regs);
+	}
+	__do_int_store(dst_addr, size, src_val, asi);
+}
 
 static inline void advance(struct pt_regs *regs)
 {
@@ -364,24 +223,29 @@ static inline int ok_for_kernel(unsigned int insn)
 	return !floating_point_load_or_store_p(insn);
 }
 
-void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault");
-
-void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
+void kernel_mna_trap_fault(void)
 {
-	unsigned long g2 = regs->u_regs [UREG_G2];
+	struct pt_regs *regs = current_thread_info()->kern_una_regs;
+	unsigned int insn = current_thread_info()->kern_una_insn;
+	unsigned long g2 = regs->u_regs[UREG_G2];
 	unsigned long fixup = search_extables_range(regs->tpc, &g2);
 
 	if (!fixup) {
-		unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
+		unsigned long address;
+
+		address = compute_effective_address(regs, insn,
+						    ((insn >> 25) & 0x1f));
         	if (address < PAGE_SIZE) {
-                	printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler");
+                	printk(KERN_ALERT "Unable to handle kernel NULL "
+			       "pointer dereference in mna handler");
         	} else
-                	printk(KERN_ALERT "Unable to handle kernel paging request in mna handler");
+                	printk(KERN_ALERT "Unable to handle kernel paging "
+			       "request in mna handler");
 	        printk(KERN_ALERT " at virtual address %016lx\n",address);
-		printk(KERN_ALERT "current->{mm,active_mm}->context = %016lx\n",
+		printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n",
 			(current->mm ? CTX_HWBITS(current->mm->context) :
 			CTX_HWBITS(current->active_mm->context)));
-		printk(KERN_ALERT "current->{mm,active_mm}->pgd = %016lx\n",
+		printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n",
 			(current->mm ? (unsigned long) current->mm->pgd :
 			(unsigned long) current->active_mm->pgd));
 	        die_if_kernel("Oops", regs);
@@ -400,48 +264,41 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
 	enum direction dir = decode_direction(insn);
 	int size = decode_access_size(insn);
 
+	current_thread_info()->kern_una_regs = regs;
+	current_thread_info()->kern_una_insn = insn;
+
 	if (!ok_for_kernel(insn) || dir == both) {
-		printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n",
-		       regs->tpc);
-		unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs);
-
-		__asm__ __volatile__ ("\n"
-"kernel_unaligned_trap_fault:\n\t"
-		"mov	%0, %%o0\n\t"
-		"call	kernel_mna_trap_fault\n\t"
-		" mov	%1, %%o1\n\t"
-		:
-		: "r" (regs), "r" (insn)
-		: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
-		  "g1", "g2", "g3", "g4", "g7", "cc");
+		printk("Unsupported unaligned load/store trap for kernel "
+		       "at <%016lx>.\n", regs->tpc);
+		unaligned_panic("Kernel does fpu/atomic "
+				"unaligned load/store.", regs);
+
+		kernel_mna_trap_fault();
 	} else {
-		unsigned long addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
+		unsigned long addr;
 
+		addr = compute_effective_address(regs, insn,
+						 ((insn >> 25) & 0x1f));
 #ifdef DEBUG_MNA
-		printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n",
-		       regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
+		printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] "
+		       "retpc[%016lx]\n",
+		       regs->tpc, dirstrings[dir], addr, size,
+		       regs->u_regs[UREG_RETPC]);
 #endif
 		switch (dir) {
 		case load:
-			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
-					size, (unsigned long *) addr,
-					decode_signedness(insn), decode_asi(insn, regs),
-					kernel_unaligned_trap_fault);
+			do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
+				    size, (unsigned long *) addr,
+				    decode_signedness(insn),
+				    decode_asi(insn, regs));
 			break;
 
 		case store:
-			do_integer_store(((insn>>25)&0x1f), size,
-					 (unsigned long *) addr, regs,
-					 decode_asi(insn, regs),
-					 kernel_unaligned_trap_fault);
-			break;
-#if 0 /* unsupported */
-		case both:
-			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
-				  (unsigned long *) addr,
-				  kernel_unaligned_trap_fault);
+			do_int_store(((insn>>25)&0x1f), size,
+				     (unsigned long *) addr, regs,
+				     decode_asi(insn, regs));
 			break;
-#endif
+
 		default:
 			panic("Impossible kernel unaligned trap.");
 			/* Not reached... */
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index 352d994..c94d8b3 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -68,6 +68,9 @@ struct thread_info {
 
 	struct restart_block	restart_block;
 
+	struct pt_regs		*kern_una_regs;
+	unsigned int		kern_una_insn;
+
 	unsigned long		fpregs[0] __attribute__ ((aligned(64)));
 };
 
@@ -103,6 +106,8 @@ struct thread_info {
 #define TI_PCR		0x00000490
 #define TI_CEE_STUFF	0x00000498
 #define TI_RESTART_BLOCK 0x000004a0
+#define TI_KUNA_REGS	0x000004c8
+#define TI_KUNA_INSN	0x000004d0
 #define TI_FPREGS	0x00000500
 
 /* We embed this in the uppermost byte of thread_info->flags */

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: sparc vs. gcc 4.3
  2008-03-03 21:03 ` David Miller
@ 2008-03-03 21:41   ` Harvey Harrison
  2008-03-03 22:02     ` David Miller
  0 siblings, 1 reply; 5+ messages in thread
From: Harvey Harrison @ 2008-03-03 21:41 UTC (permalink / raw)
  To: David Miller; +Cc: bunk, wli, sparclinux, linux-kernel

On Mon, 2008-03-03 at 13:03 -0800, David Miller wrote:
> From: Adrian Bunk <bunk@kernel.org>
> Date: Mon, 3 Mar 2008 21:26:51 +0200
> 
> >   LD      arch/sparc/boot/image
> > arch/sparc/kernel/built-in.o:(__ex_table+0x394): undefined reference to `kernel_unaligned_trap_fault'
> ...
> > arch/sparc/kernel/built-in.o:(__ex_table+0x46c): undefined reference to `user_unaligned_trap_fault'
> 
> > Does anyone have a clue what's going wrong here?
> 
> We hit the same problem a while back on sparc64 too.
> 
> GCC can't see how the inline asm is reachable so eliminates it
> entirely.  We hide the label inside the inline asm string and call it
> from exception handlers.
> 
> The way we fixed this on sparc64 was quite invasive (patch below for
> reference), so I'll try to come up with something simpler.

Could you hide the asm inside an actual function and annotate the
function with __used?

Similar to how the kprobes has a function called kretprobe_trampoline_holder
for their trampoline asm?

arch/x86/kernel/kprobes.c line 584

Cheers,

Harvey



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: sparc vs. gcc 4.3
  2008-03-03 21:41   ` Harvey Harrison
@ 2008-03-03 22:02     ` David Miller
  0 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2008-03-03 22:02 UTC (permalink / raw)
  To: harvey.harrison; +Cc: bunk, wli, sparclinux, linux-kernel

From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Mon, 03 Mar 2008 13:41:11 -0800

> Could you hide the asm inside an actual function and annotate the
> function with __used?

Won't work, the asm needs to be inlined because it needs to:

1) Know where local variables are located

2) Has to run in the context of the stack frame the
   call site runs in so that the tail-call it's doing works

And actually all of this is why the sparc64 fix turned out to
be so invasive, and I'll need to do the same for sparc32
as a result.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: sparc vs. gcc 4.3
  2008-03-03 19:26 sparc vs. gcc 4.3 Adrian Bunk
  2008-03-03 21:03 ` David Miller
@ 2008-03-03 23:02 ` David Miller
  1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2008-03-03 23:02 UTC (permalink / raw)
  To: bunk; +Cc: wli, sparclinux, linux-kernel

From: Adrian Bunk <bunk@kernel.org>
Date: Mon, 3 Mar 2008 21:26:51 +0200

> Does anyone have a clue what's going wrong here?

Adrian, here is the patch I'll submit to fix this.

Thanks for your report.

commit f0e98c387e61de00646be31fab4c2fa0224e1efb
Author: David S. Miller <davem@davemloft.net>
Date:   Mon Mar 3 15:01:05 2008 -0800

    [SPARC]: Fix link errors with gcc-4.3
    
    Reported by Adrian Bunk.
    
    Just like in changeset a3f9985843b674cbcb58f39fab8416675e7ab842
    ("[SPARC64]: Move kernel unaligned trap handlers into assembler
    file.") we have to move the assembler bits into a seperate
    asm file because as far as the compiler is concerned
    these inline bits we're doing in unaligned.c are unreachable.
    
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index e795f28..bf1b15d 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.62 2000/12/15 00:41:17 davem Exp $
+#
 # Makefile for the linux kernel.
 #
 
@@ -12,7 +12,8 @@ obj-y    := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \
 	    sys_sparc.o sunos_asm.o systbls.o \
 	    time.o windows.o cpu.o devices.o sclow.o \
 	    tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o semaphore.o prom.o of_device.o devres.o
+	    unaligned.o una_asm.o muldiv.o semaphore.o \
+	    prom.o of_device.o devres.o
 
 devres-y = ../../../kernel/irq/devres.o
 
diff --git a/arch/sparc/kernel/una_asm.S b/arch/sparc/kernel/una_asm.S
new file mode 100644
index 0000000..8cc0345
--- /dev/null
+++ b/arch/sparc/kernel/una_asm.S
@@ -0,0 +1,153 @@
+/* una_asm.S: Kernel unaligned trap assembler helpers.
+ *
+ * Copyright (C) 1996,2005,2008 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/errno.h>
+
+	.text
+
+retl_efault:
+	retl
+	 mov	-EFAULT, %o0
+
+	/* int __do_int_store(unsigned long *dst_addr, int size,
+	 *                    unsigned long *src_val)
+	 *
+	 * %o0 = dest_addr
+	 * %o1 = size
+	 * %o2 = src_val
+	 *
+	 * Return '0' on success, -EFAULT on failure.
+	 */
+	.globl	__do_int_store
+__do_int_store:
+	ld	[%o2], %g1
+	cmp	%1, 2
+	be	2f
+	 cmp	%1, 4
+	be	1f
+	 srl	%g1, 24, %g2
+	srl	%g1, 16, %g7
+4:	stb	%g2, [%o0]
+	srl	%g1, 8, %g2
+5:	stb	%g7, [%o0 + 1]
+	ld	[%o2 + 4], %g7
+6:	stb	%g2, [%o0 + 2]
+	srl	%g7, 24, %g2
+7:	stb	%g1, [%o0 + 3]
+	srl	%g7, 16, %g1
+8:	stb	%g2, [%o0 + 4]
+	srl	%g7, 8, %g2
+9:	stb	%g1, [%o0 + 5]
+10:	stb	%g2, [%o0 + 6]
+	b	0f
+11:	 stb	%g7, [%o0 + 7]
+1:	srl	%g1, 16, %g7
+12:	stb	%g2, [%o0]
+	srl	%g1, 8, %g2
+13:	stb	%g7, [%o0 + 1]
+14:	stb	%g2, [%o0 + 2]
+	b	0f
+15:	 stb	%g1, [%o0 + 3]
+2:	srl	%g1, 8, %g2
+16:	stb	%g2, [%o0]
+17:	stb	%g1, [%o0 + 1]
+0:	retl
+	 mov	0, %o0
+
+	.section __ex_table,#alloc
+	.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
+
+	/* int do_int_load(unsigned long *dest_reg, int size,
+	 *                 unsigned long *saddr, int is_signed)
+	 *
+	 * %o0 = dest_reg
+	 * %o1 = size
+	 * %o2 = saddr
+	 * %o3 = is_signed
+	 *
+	 * Return '0' on success, -EFAULT on failure.
+	 */
+	.globl	do_int_load
+do_int_load:
+	cmp	%o1, 8
+	be	9f
+	 cmp	%o1, 4
+	be	6f
+4:	 ldub	[%o2], %g1
+5:	ldub	[%o2 + 1], %g2
+	sll	%g1, 8, %g1
+	tst	%o3
+	be	3f
+	 or	%g1, %g2, %g1
+	sll	%g1, 16, %g1
+	sra	%g1, 16, %g1
+3:	b	0f
+	 st	%g1, [%o0]
+6:	ldub	[%o2 + 1], %g2
+	sll	%g1, 24, %g1
+7:	ldub	[%o2 + 2], %g7
+	sll	%g2, 16, %g2
+8:	ldub	[%o2 + 3], %g3
+	sll	%g7, 8, %g7
+	or	%g3, %g2, %g3
+	or	%g7, %g3, %g7
+	or	%g1, %g7, %g1
+	b	0f
+	 st	%g1, [%o0]
+9:	ldub	[%o2], %g1
+10:	ldub	[%o2 + 1], %g2
+	sll	%g1, 24, %g1
+11:	ldub	[%o2 + 2], %g7
+	sll	%g2, 16, %g2
+12:	ldub	[%o2 + 3], %g3
+	sll	%g7, 8, %g7
+	or	%g1, %g2, %g1
+	or	%g7, %g3, %g7
+	or	%g1, %g7, %g7
+13:	ldub	[%o2 + 4], %g1
+	st	%g7, [%o0]
+14:	ldub	[%o2 + 5], %g2
+	sll	%g1, 24, %g1
+15:	ldub	[%o2 + 6], %g7
+	sll	%g2, 16, %g2
+16:	ldub	[%o2 + 7], %g3
+	sll	%g7, 8, %g7
+	or	%g1, %g2, %g1
+	or	%g7, %g3, %g7
+	or	%g1, %g7, %g7
+	st	%g7, [%o0 + 4]
+0:	retl
+	 mov	0, %o0
+
+	.section __ex_table,#alloc
+	.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
diff --git a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned.c
index a6330fb..33857be 100644
--- a/arch/sparc/kernel/unaligned.c
+++ b/arch/sparc/kernel/unaligned.c
@@ -175,157 +175,31 @@ static void unaligned_panic(char *str)
 	panic(str);
 }
 
-#define do_integer_load(dest_reg, size, saddr, is_signed, errh) ({		\
-__asm__ __volatile__ (								\
-	"cmp	%1, 8\n\t"							\
-	"be	9f\n\t"								\
-	" cmp	%1, 4\n\t"							\
-	"be	6f\n"								\
-"4:\t"	" ldub	[%2], %%l1\n"							\
-"5:\t"	"ldub	[%2 + 1], %%l2\n\t"						\
-	"sll	%%l1, 8, %%l1\n\t"						\
-	"tst	%3\n\t"								\
-	"be	3f\n\t"								\
-	" add	%%l1, %%l2, %%l1\n\t"						\
-	"sll	%%l1, 16, %%l1\n\t"						\
-	"sra	%%l1, 16, %%l1\n"						\
-"3:\t"	"b	0f\n\t"								\
-	" st	%%l1, [%0]\n"							\
-"6:\t"	"ldub	[%2 + 1], %%l2\n\t"						\
-	"sll	%%l1, 24, %%l1\n"						\
-"7:\t"	"ldub	[%2 + 2], %%g7\n\t"						\
-	"sll	%%l2, 16, %%l2\n"						\
-"8:\t"	"ldub	[%2 + 3], %%g1\n\t"						\
-	"sll	%%g7, 8, %%g7\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n\t"						\
-	"or	%%l1, %%g7, %%l1\n\t"						\
-	"b	0f\n\t"								\
-	" st	%%l1, [%0]\n"							\
-"9:\t"	"ldub	[%2], %%l1\n"							\
-"10:\t"	"ldub	[%2 + 1], %%l2\n\t"						\
-	"sll	%%l1, 24, %%l1\n"						\
-"11:\t"	"ldub	[%2 + 2], %%g7\n\t"						\
-	"sll	%%l2, 16, %%l2\n"						\
-"12:\t"	"ldub	[%2 + 3], %%g1\n\t"						\
-	"sll	%%g7, 8, %%g7\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n\t"						\
-	"or	%%l1, %%g7, %%g7\n"						\
-"13:\t"	"ldub	[%2 + 4], %%l1\n\t"						\
-	"st	%%g7, [%0]\n"							\
-"14:\t"	"ldub	[%2 + 5], %%l2\n\t"						\
-	"sll	%%l1, 24, %%l1\n"						\
-"15:\t"	"ldub	[%2 + 6], %%g7\n\t"						\
-	"sll	%%l2, 16, %%l2\n"						\
-"16:\t"	"ldub	[%2 + 7], %%g1\n\t"						\
-	"sll	%%g7, 8, %%g7\n\t"						\
-	"or	%%l1, %%l2, %%l1\n\t"						\
-	"or	%%g7, %%g1, %%g7\n\t"						\
-	"or	%%l1, %%g7, %%g7\n\t"						\
-	"st	%%g7, [%0 + 4]\n"						\
-"0:\n\n\t"									\
-	".section __ex_table,#alloc\n\t"					\
-	".word	4b, " #errh "\n\t"						\
-	".word	5b, " #errh "\n\t"						\
-	".word	6b, " #errh "\n\t"						\
-	".word	7b, " #errh "\n\t"						\
-	".word	8b, " #errh "\n\t"						\
-	".word	9b, " #errh "\n\t"						\
-	".word	10b, " #errh "\n\t"						\
-	".word	11b, " #errh "\n\t"						\
-	".word	12b, " #errh "\n\t"						\
-	".word	13b, " #errh "\n\t"						\
-	".word	14b, " #errh "\n\t"						\
-	".word	15b, " #errh "\n\t"						\
-	".word	16b, " #errh "\n\n\t"						\
-	".previous\n\t"								\
-	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed)		\
-	: "l1", "l2", "g7", "g1", "cc");					\
-})
-	
-#define store_common(dst_addr, size, src_val, errh) ({				\
-__asm__ __volatile__ (								\
-	"ld	[%2], %%l1\n"							\
-	"cmp	%1, 2\n\t"							\
-	"be	2f\n\t"								\
-	" cmp	%1, 4\n\t"							\
-	"be	1f\n\t"								\
-	" srl	%%l1, 24, %%l2\n\t"						\
-	"srl	%%l1, 16, %%g7\n"						\
-"4:\t"	"stb	%%l2, [%0]\n\t"							\
-	"srl	%%l1, 8, %%l2\n"						\
-"5:\t"	"stb	%%g7, [%0 + 1]\n\t"						\
-	"ld	[%2 + 4], %%g7\n"						\
-"6:\t"	"stb	%%l2, [%0 + 2]\n\t"						\
-	"srl	%%g7, 24, %%l2\n"						\
-"7:\t"	"stb	%%l1, [%0 + 3]\n\t"						\
-	"srl	%%g7, 16, %%l1\n"						\
-"8:\t"	"stb	%%l2, [%0 + 4]\n\t"						\
-	"srl	%%g7, 8, %%l2\n"						\
-"9:\t"	"stb	%%l1, [%0 + 5]\n"						\
-"10:\t"	"stb	%%l2, [%0 + 6]\n\t"						\
-	"b	0f\n"								\
-"11:\t"	" stb	%%g7, [%0 + 7]\n"						\
-"1:\t"	"srl	%%l1, 16, %%g7\n"						\
-"12:\t"	"stb	%%l2, [%0]\n\t"							\
-	"srl	%%l1, 8, %%l2\n"						\
-"13:\t"	"stb	%%g7, [%0 + 1]\n"						\
-"14:\t"	"stb	%%l2, [%0 + 2]\n\t"						\
-	"b	0f\n"								\
-"15:\t"	" stb	%%l1, [%0 + 3]\n"						\
-"2:\t"	"srl	%%l1, 8, %%l2\n"						\
-"16:\t"	"stb	%%l2, [%0]\n"							\
-"17:\t"	"stb	%%l1, [%0 + 1]\n"						\
-"0:\n\n\t"									\
-	".section __ex_table,#alloc\n\t"					\
-	".word	4b, " #errh "\n\t"						\
-	".word	5b, " #errh "\n\t"						\
-	".word	6b, " #errh "\n\t"						\
-	".word	7b, " #errh "\n\t"						\
-	".word	8b, " #errh "\n\t"						\
-	".word	9b, " #errh "\n\t"						\
-	".word	10b, " #errh "\n\t"						\
-	".word	11b, " #errh "\n\t"						\
-	".word	12b, " #errh "\n\t"						\
-	".word	13b, " #errh "\n\t"						\
-	".word	14b, " #errh "\n\t"						\
-	".word	15b, " #errh "\n\t"						\
-	".word	16b, " #errh "\n\t"						\
-	".word	17b, " #errh "\n\n\t"						\
-	".previous\n\t"								\
-	: : "r" (dst_addr), "r" (size), "r" (src_val)				\
-	: "l1", "l2", "g7", "g1", "cc");					\
-})
-
-#define do_integer_store(reg_num, size, dst_addr, regs, errh) ({		\
-	unsigned long *src_val;							\
-	static unsigned long zero[2] = { 0, };					\
-										\
-	if (reg_num) src_val = fetch_reg_addr(reg_num, regs);			\
-	else {									\
-		src_val = &zero[0];						\
-		if (size == 8)							\
-			zero[1] = fetch_reg(1, regs);				\
-	}									\
-	store_common(dst_addr, size, src_val, errh);				\
-})
+/* una_asm.S */
+extern int do_int_load(unsigned long *dest_reg, int size,
+		       unsigned long *saddr, int is_signed);
+extern int __do_int_store(unsigned long *dst_addr, int size,
+			  unsigned long *src_val);
+
+static int do_int_store(int reg_num, int size, unsigned long *dst_addr,
+			struct pt_regs *regs)
+{
+	unsigned long zero[2] = { 0, 0 };
+	unsigned long *src_val;
+
+	if (reg_num)
+		src_val = fetch_reg_addr(reg_num, regs);
+	else {
+		src_val = &zero[0];
+		if (size == 8)
+			zero[1] = fetch_reg(1, regs);
+	}
+	return __do_int_store(dst_addr, size, src_val);
+}
 
 extern void smp_capture(void);
 extern void smp_release(void);
 
-#define do_atomic(srcdest_reg, mem, errh) ({					\
-	unsigned long flags, tmp;						\
-										\
-	smp_capture();								\
-	local_irq_save(flags);							\
-	tmp = *srcdest_reg;							\
-	do_integer_load(srcdest_reg, 4, mem, 0, errh);				\
-	store_common(mem, 4, &tmp, errh);					\
-	local_irq_restore(flags);						\
-	smp_release();								\
-})
-
 static inline void advance(struct pt_regs *regs)
 {
 	regs->pc   = regs->npc;
@@ -342,9 +216,7 @@ static inline int ok_for_kernel(unsigned int insn)
 	return !floating_point_load_or_store_p(insn);
 }
 
-void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault");
-
-void kernel_mna_trap_fault(struct pt_regs *regs, 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);
@@ -379,48 +251,34 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 		printk("Unsupported unaligned load/store trap for kernel at <%08lx>.\n",
 		       regs->pc);
 		unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
-
-		__asm__ __volatile__ ("\n"
-"kernel_unaligned_trap_fault:\n\t"
-		"mov	%0, %%o0\n\t"
-		"call	kernel_mna_trap_fault\n\t"
-		" mov	%1, %%o1\n\t"
-		:
-		: "r" (regs), "r" (insn)
-		: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
-		  "g1", "g2", "g3", "g4", "g5", "g7", "cc");
 	} else {
 		unsigned long addr = compute_effective_address(regs, insn);
+		int err;
 
 #ifdef DEBUG_MNA
 		printk("KMNA: pc=%08lx [dir=%s addr=%08lx size=%d] retpc[%08lx]\n",
 		       regs->pc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
 #endif
-		switch(dir) {
+		switch (dir) {
 		case load:
-			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
-					size, (unsigned long *) addr,
-					decode_signedness(insn),
-					kernel_unaligned_trap_fault);
+			err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
+							 regs),
+					  size, (unsigned long *) addr,
+					  decode_signedness(insn));
 			break;
 
 		case store:
-			do_integer_store(((insn>>25)&0x1f), size,
-					 (unsigned long *) addr, regs,
-					 kernel_unaligned_trap_fault);
+			err = do_int_store(((insn>>25)&0x1f), size,
+					   (unsigned long *) addr, regs);
 			break;
-#if 0 /* unsupported */
-		case both:
-			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
-				  (unsigned long *) addr,
-				  kernel_unaligned_trap_fault);
-			break;
-#endif
 		default:
 			panic("Impossible kernel unaligned trap.");
 			/* Not reached... */
 		}
-		advance(regs);
+		if (err)
+			kernel_mna_trap_fault(regs, insn);
+		else
+			advance(regs);
 	}
 }
 
@@ -459,9 +317,7 @@ static inline int ok_for_user(struct pt_regs *regs, unsigned int insn,
 	return 0;
 }
 
-void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("user_mna_trap_fault");
-
-void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
+static void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
 {
 	siginfo_t info;
 
@@ -485,7 +341,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 	if(!ok_for_user(regs, insn, dir)) {
 		goto kill_user;
 	} else {
-		int size = decode_access_size(insn);
+		int err, size = decode_access_size(insn);
 		unsigned long addr;
 
 		if(floating_point_load_or_store_p(insn)) {
@@ -496,48 +352,34 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 		addr = compute_effective_address(regs, insn);
 		switch(dir) {
 		case load:
-			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
-					size, (unsigned long *) addr,
-					decode_signedness(insn),
-					user_unaligned_trap_fault);
+			err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
+							 regs),
+					  size, (unsigned long *) addr,
+					  decode_signedness(insn));
 			break;
 
 		case store:
-			do_integer_store(((insn>>25)&0x1f), size,
-					 (unsigned long *) addr, regs,
-					 user_unaligned_trap_fault);
+			err = do_int_store(((insn>>25)&0x1f), size,
+					   (unsigned long *) addr, regs);
 			break;
 
 		case both:
-#if 0 /* unsupported */
-			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
-				  (unsigned long *) addr,
-				  user_unaligned_trap_fault);
-#else
 			/*
 			 * This was supported in 2.4. However, we question
 			 * the value of SWAP instruction across word boundaries.
 			 */
 			printk("Unaligned SWAP unsupported.\n");
-			goto kill_user;
-#endif
+			err = -EFAULT;
 			break;
 
 		default:
 			unaligned_panic("Impossible user unaligned trap.");
-
-			__asm__ __volatile__ ("\n"
-"user_unaligned_trap_fault:\n\t"
-			"mov	%0, %%o0\n\t"
-			"call	user_mna_trap_fault\n\t"
-			" mov	%1, %%o1\n\t"
-			:
-			: "r" (regs), "r" (insn)
-			: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
-			  "g1", "g2", "g3", "g4", "g5", "g7", "cc");
 			goto out;
 		}
-		advance(regs);
+		if (err)
+			goto kill_user;
+		else
+			advance(regs);
 		goto out;
 	}
 

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-03-03 23:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-03 19:26 sparc vs. gcc 4.3 Adrian Bunk
2008-03-03 21:03 ` David Miller
2008-03-03 21:41   ` Harvey Harrison
2008-03-03 22:02     ` David Miller
2008-03-03 23:02 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).