diff options
Diffstat (limited to 'arch/sparc/kernel')
26 files changed, 296 insertions, 303 deletions
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 72308f9b009..6cf591b7e1c 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -51,8 +51,8 @@ obj-y                   += of_device_common.o  obj-y                   += of_device_$(BITS).o  obj-$(CONFIG_SPARC64)   += prom_irqtrans.o -obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o -obj-$(CONFIG_SPARC_LEON)+= leon_pmc.o +obj-$(CONFIG_SPARC32)   += leon_kernel.o +obj-$(CONFIG_SPARC32)   += leon_pmc.o  obj-$(CONFIG_SPARC64)   += reboot.o  obj-$(CONFIG_SPARC64)   += sysfs.o diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 2d181964176..a6c94a2bf9d 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -121,7 +121,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {  		FPU(-1, NULL)  	}  },{ -	4, +	PSR_IMPL_TI,  	.cpu_info = {  		CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"),  		/* SparcClassic  --  borned STP1010TAB-50*/ @@ -191,7 +191,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {  		FPU(-1, NULL)  	}  },{ -	0xF,		/* Aeroflex Gaisler */ +	PSR_IMPL_LEON,		/* Aeroflex Gaisler */  	.cpu_info = {  		CPU(3, "LEON"),  		CPU(-1, NULL) @@ -440,16 +440,16 @@ static int __init cpu_type_probe(void)  	int psr_impl, psr_vers, fpu_vers;  	int psr; -	psr_impl = ((get_psr() >> 28) & 0xf); -	psr_vers = ((get_psr() >> 24) & 0xf); +	psr_impl = ((get_psr() >> PSR_IMPL_SHIFT) & PSR_IMPL_SHIFTED_MASK); +	psr_vers = ((get_psr() >> PSR_VERS_SHIFT) & PSR_VERS_SHIFTED_MASK);  	psr = get_psr();  	put_psr(psr | PSR_EF); -#ifdef CONFIG_SPARC_LEON -	fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7; -#else -	fpu_vers = ((get_fsr() >> 17) & 0x7); -#endif + +	if (psr_impl == PSR_IMPL_LEON) +		fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7; +	else +		fpu_vers = ((get_fsr() >> 17) & 0x7);  	put_psr(psr); diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 2dbe1806e53..dcaa1cf0de4 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -393,7 +393,6 @@ linux_trap_ipi15_sun4d:  	/* FIXME */  1:	b,a	1b -#ifdef CONFIG_SPARC_LEON  	.globl	smpleon_ipi  	.extern leon_ipi_interrupt  	/* SMP per-cpu IPI interrupts are handled specially. */ @@ -424,8 +423,6 @@ linux_trap_ipi15_leon:  	b	ret_trap_lockless_ipi  	 clr	%l6 -#endif /* CONFIG_SPARC_LEON */ -  #endif /* CONFIG_SMP */  	/* This routine handles illegal instructions and privileged @@ -770,8 +767,11 @@ srmmu_fault:  	mov	0x400, %l5  	mov	0x300, %l4 -	lda	[%l5] ASI_M_MMUREGS, %l6	! read sfar first -	lda	[%l4] ASI_M_MMUREGS, %l5	! read sfsr last +LEON_PI(lda	[%l5] ASI_LEON_MMUREGS, %l6)	! read sfar first +SUN_PI_(lda	[%l5] ASI_M_MMUREGS, %l6)	! read sfar first + +LEON_PI(lda	[%l4] ASI_LEON_MMUREGS, %l5)	! read sfsr last +SUN_PI_(lda	[%l4] ASI_M_MMUREGS, %l5)	! read sfsr last  	andn	%l6, 0xfff, %l6  	srl	%l5, 6, %l5			! and encode all info into l7 diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S index 84b5f0d2afd..e3e80d65e39 100644 --- a/arch/sparc/kernel/etrap_32.S +++ b/arch/sparc/kernel/etrap_32.S @@ -234,7 +234,8 @@ tsetup_srmmu_stackchk:  	cmp	%glob_tmp, %sp  	bleu,a	1f -	 lda	[%g0] ASI_M_MMUREGS, %glob_tmp		! read MMU control +LEON_PI( lda	[%g0] ASI_LEON_MMUREGS, %glob_tmp)	! read MMU control +SUN_PI_( lda	[%g0] ASI_M_MMUREGS, %glob_tmp)		! read MMU control  trap_setup_user_stack_is_bolixed:  	/* From user/kernel into invalid window w/bad user @@ -249,18 +250,25 @@ trap_setup_user_stack_is_bolixed:  1:  	/* Clear the fault status and turn on the no_fault bit. */  	or	%glob_tmp, 0x2, %glob_tmp		! or in no_fault bit -	sta	%glob_tmp, [%g0] ASI_M_MMUREGS		! set it +LEON_PI(sta	%glob_tmp, [%g0] ASI_LEON_MMUREGS)		! set it +SUN_PI_(sta	%glob_tmp, [%g0] ASI_M_MMUREGS)		! set it  	/* Dump the registers and cross fingers. */  	STORE_WINDOW(sp)  	/* Clear the no_fault bit and check the status. */  	andn	%glob_tmp, 0x2, %glob_tmp -	sta	%glob_tmp, [%g0] ASI_M_MMUREGS +LEON_PI(sta	%glob_tmp, [%g0] ASI_LEON_MMUREGS) +SUN_PI_(sta	%glob_tmp, [%g0] ASI_M_MMUREGS) +  	mov	AC_M_SFAR, %glob_tmp -	lda	[%glob_tmp] ASI_M_MMUREGS, %g0 +LEON_PI(lda	[%glob_tmp] ASI_LEON_MMUREGS, %g0) +SUN_PI_(lda	[%glob_tmp] ASI_M_MMUREGS, %g0) +  	mov	AC_M_SFSR, %glob_tmp -	lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp	! save away status of winstore +LEON_PI(lda	[%glob_tmp] ASI_LEON_MMUREGS, %glob_tmp)! save away status of winstore +SUN_PI_(lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp)	! save away status of winstore +  	andcc	%glob_tmp, 0x2, %g0			! did we fault?  	bne	trap_setup_user_stack_is_bolixed	! failure  	 nop diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index a0f5c20e4b9..afeb1d77030 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -30,10 +30,6 @@   * the cpu-type   */  	.align 4 -cputyp: -        .word   1 - -	.align 4  	.globl cputypval  cputypval:  	.asciz "sun4m" @@ -46,8 +42,8 @@ cputypvar:  	.align 4 -sun4c_notsup: -	.asciz	"Sparc-Linux sun4/sun4c support does no longer exist.\n\n" +notsup: +	.asciz	"Sparc-Linux sun4/sun4c or MMU-less not supported\n\n"  	.align 4  sun4e_notsup: @@ -123,7 +119,7 @@ current_pc:  		tst	%o0  		be	no_sun4u_here  		 mov	%g4, %o7		/* Previous %o7. */ -	 +  		mov	%o0, %l0		! stash away romvec  		mov	%o0, %g7		! put it here too  		mov	%o1, %l1		! stash away debug_vec too @@ -132,7 +128,7 @@ current_pc:  		set	current_pc, %g5  		cmp	%g3, %g5  		be	already_mapped -		 nop  +		 nop  		/* %l6 will hold the offset we have to subtract  		 * from absolute symbols in order to access areas @@ -192,9 +188,9 @@ copy_prom_done:  		bne	not_a_sun4  		 nop -halt_sun4_or_sun4c: +halt_notsup:  		ld	[%g7 + 0x68], %o1 -		set	sun4c_notsup, %o0 +		set	notsup, %o0  		sub	%o0, %l6, %o0  		call	%o1  		 nop @@ -202,18 +198,31 @@ halt_sun4_or_sun4c:  		 nop  not_a_sun4: +		/* It looks like this is a machine we support. +		 * Now find out what MMU we are dealing with +		 * LEON - identified by the psr.impl field +		 * Viking - identified by the psr.impl field +		 * In all other cases a sun4m srmmu. +		 * We check that the MMU is enabled in all cases. +		 */ + +		/* Check if this is a LEON CPU */ +		rd	%psr, %g3 +		srl	%g3, PSR_IMPL_SHIFT, %g3 +		and	%g3, PSR_IMPL_SHIFTED_MASK, %g3 +		cmp	%g3, PSR_IMPL_LEON +		be	leon_remap		/* It is a LEON - jump */ +		 nop + +		/* Sanity-check, is MMU enabled */  		lda	[%g0] ASI_M_MMUREGS, %g1  		andcc	%g1, 1, %g0 -		be	halt_sun4_or_sun4c +		be	halt_notsup  		 nop -srmmu_remap: -		/* First, check for a viking (TI) module. */ -		set	0x40000000, %g2 -		rd	%psr, %g3 -		and	%g2, %g3, %g3 -		subcc	%g3, 0x0, %g0 -		bz	srmmu_nviking +		/* Check for a viking (TI) module. */ +		cmp	%g3, PSR_IMPL_TI +		bne	srmmu_not_viking  		 nop  		/* Figure out what kind of viking we are on. @@ -228,14 +237,14 @@ srmmu_remap:  		lda	[%g0] ASI_M_MMUREGS, %g3	! peek in the control reg  		and	%g2, %g3, %g3  		subcc	%g3, 0x0, %g0 -		bnz	srmmu_nviking			! is in mbus mode +		bnz	srmmu_not_viking			! is in mbus mode  		 nop -		 +  		rd	%psr, %g3			! DO NOT TOUCH %g3  		andn	%g3, PSR_ET, %g2  		wr	%g2, 0x0, %psr  		WRITE_PAUSE -		 +  		/* Get context table pointer, then convert to  		 * a physical address, which is 36 bits.  		 */ @@ -258,12 +267,12 @@ srmmu_remap:  		lda	[%g4] ASI_M_BYPASS, %o1		! This is a level 1 ptr  		srl	%o1, 0x4, %o1			! Clear low 4 bits  		sll	%o1, 0x8, %o1			! Make physical -		 +  		/* Ok, pull in the PTD. */  		lda	[%o1] ASI_M_BYPASS, %o2		! This is the 0x0 16MB pgd  		/* Calculate to KERNBASE entry. */ -		add	%o1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %o3		 +		add	%o1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %o3  		/* Poke the entry into the calculated address. */  		sta	%o2, [%o3] ASI_M_BYPASS @@ -293,12 +302,12 @@ srmmu_remap:  		b	go_to_highmem  		 nop +srmmu_not_viking:  		/* This works on viking's in Mbus mode and all  		 * other MBUS modules.  It is virtually the same as  		 * the above madness sans turning traps off and flipping  		 * the AC bit.  		 */ -srmmu_nviking:  		set	AC_M_CTPR, %g1  		lda	[%g1] ASI_M_MMUREGS, %g1	! get ctx table ptr  		sll	%g1, 0x4, %g1			! make physical addr @@ -313,6 +322,29 @@ srmmu_nviking:  		 nop					! wheee.... +leon_remap: +		/* Sanity-check, is MMU enabled */ +		lda	[%g0] ASI_LEON_MMUREGS, %g1 +		andcc	%g1, 1, %g0 +		be	halt_notsup +		 nop + +		/* Same code as in the srmmu_not_viking case, +		 * with the LEON ASI for mmuregs +		 */ +		set	AC_M_CTPR, %g1 +		lda	[%g1] ASI_LEON_MMUREGS, %g1	! get ctx table ptr +		sll	%g1, 0x4, %g1			! make physical addr +		lda	[%g1] ASI_M_BYPASS, %g1		! ptr to level 1 pg_table +		srl	%g1, 0x4, %g1 +		sll	%g1, 0x8, %g1			! make phys addr for l1 tbl + +		lda	[%g1] ASI_M_BYPASS, %g2		! get level1 entry for 0x0 +		add	%g1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %g3 +		sta	%g2, [%g3] ASI_M_BYPASS		! place at KERNBASE entry +		b	go_to_highmem +		 nop					! wheee.... +  /* Now do a non-relative jump so that PC is in high-memory */  go_to_highmem:  		set	execute_in_high_mem, %g1 @@ -336,8 +368,9 @@ execute_in_high_mem:  		sethi	%hi(linux_dbvec), %g1  		st	%o1, [%g1 + %lo(linux_dbvec)] -/* Get the machine type via the mysterious romvec node operations. */ - +		/* Get the machine type via the romvec +		 * getprops node operation +		 */  		add	%g7, 0x1c, %l1  		ld	[%l1], %l0  		ld	[%l0], %l0 @@ -356,9 +389,42 @@ execute_in_high_mem:  						! to a buf where above string  						! will get stored by the prom. -#ifdef CONFIG_SPARC_LEON -	        /* no cpu-type check is needed, it is a SPARC-LEON */ +		/* Check value of "compatible" property. +		 * "value" => "model" +		 * leon => sparc_leon +		 * sun4m => sun4m +		 * sun4s => sun4m +		 * sun4d => sun4d +		 * sun4e => "no_sun4e_here" +		 * '*'   => "no_sun4u_here" +		 * Check single letters only +		 */ + +		set	cputypval, %o2 +		/* If cputypval[0] == 'l' (lower case letter L) this is leon */ +		ldub	[%o2], %l1 +		cmp	%l1, 'l' +		be	leon_init +		 nop + +		/* Check cputypval[4] to find the sun model */ +		ldub	[%o2 + 0x4], %l1 + +		cmp	%l1, 'm' +		be	sun4m_init +		 cmp	%l1, 's' +		be	sun4m_init +		 cmp	%l1, 'd' +		be	sun4d_init +		 cmp	%l1, 'e' +		be	no_sun4e_here		! Could be a sun4e. +		 nop +		b	no_sun4u_here		! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) +		 nop + +leon_init: +		/* LEON CPU - set boot_cpu_id */  		sethi	%hi(boot_cpu_id), %g2	! boot-cpu index  #ifdef CONFIG_SMP @@ -376,26 +442,6 @@ execute_in_high_mem:  		ba continue_boot  		 nop -#endif - -/* Check to cputype. We may be booted on a sun4u (64 bit box), - * and sun4d needs special treatment. - */ - -		set	cputypval, %o2 -		ldub	[%o2 + 0x4], %l1 - -		cmp	%l1, 'm' -		be	sun4m_init -		 cmp	%l1, 's' -		be	sun4m_init -		 cmp	%l1, 'd' -		be	sun4d_init -		 cmp	%l1, 'e' -		be	no_sun4e_here		! Could be a sun4e. -		 nop -		b	no_sun4u_here		! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) -		 nop  /* CPUID in bootbus can be found at PA 0xff0140000 */  #define SUN4D_BOOTBUS_CPUID     0xf0140000 @@ -431,9 +477,9 @@ sun4m_init:  /* This sucks, apparently this makes Vikings call prom panic, will fix later */  2:  		rd	%psr, %o1 -		srl	%o1, 28, %o1		! Get a type of the CPU +		srl	%o1, PSR_IMPL_SHIFT, %o1	! Get a type of the CPU -		subcc	%o1, 4, %g0		! TI: Viking or MicroSPARC +		subcc	%o1, PSR_IMPL_TI, %g0		! TI: Viking or MicroSPARC  		be	continue_boot  		 nop @@ -459,10 +505,6 @@ continue_boot:  /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's   * show-time!   */ - -		sethi	%hi(cputyp), %o0 -		st	%g4, [%o0 + %lo(cputyp)] -  		/* Turn on Supervisor, EnableFloating, and all the PIL bits.  		 * Also puts us in register window zero with traps off.  		 */ @@ -480,7 +522,7 @@ continue_boot:  		set	__bss_start , %o0	! First address of BSS  		set	_end , %o1		! Last address of BSS  		add	%o0, 0x1, %o0 -1:	 +1:  		stb	%g0, [%o0]  		subcc	%o0, %o1, %g0  		bl	1b @@ -546,7 +588,7 @@ continue_boot:  		set	dest, %g2; \  		ld	[%g5], %g4; \  		st	%g4, [%g2]; -	 +  		/* Patch for window spills... */  		PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)  		PATCH_INSN(spnwin_patch2_7win, spnwin_patch2) @@ -597,7 +639,7 @@ continue_boot:  		st	%g4, [%g5 + 0x18]  		st	%g4, [%g5 + 0x1c] -2:		 +2:  		sethi	%hi(nwindows), %g4  		st	%g3, [%g4 + %lo(nwindows)]	! store final value  		sub	%g3, 0x1, %g3 @@ -617,18 +659,12 @@ continue_boot:  		wr	%g3, PSR_ET, %psr  		WRITE_PAUSE -		/* First we call prom_init() to set up PROMLIB, then -		 * off to start_kernel(). -		 */ - +		/* Call sparc32_start_kernel(struct linux_romvec *rp) */  		sethi	%hi(prom_vector_p), %g5  		ld	[%g5 + %lo(prom_vector_p)], %o0 -		call	prom_init +		call	sparc32_start_kernel  		 nop -		call 	start_kernel -		 nop -	  		/* We should not get here. */  		call	halt_me  		 nop @@ -659,7 +695,7 @@ sun4u_5:  		.asciz "write"  		.align	4  sun4u_6: -        	.asciz  "\n\rOn sun4u you have to use UltraLinux (64bit) kernel\n\rand not a 32bit sun4[cdem] version\n\r\n\r" +		.asciz  "\n\rOn sun4u you have to use sparc64 kernel\n\rand not a sparc32 version\n\r\n\r"  sun4u_6e:  		.align	4  sun4u_7: diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index a2846f5e32d..0f094db918c 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -55,17 +55,13 @@ const struct sparc32_dma_ops *sparc32_dma_ops;  /* This function must make sure that caches and memory are coherent after DMA   * On LEON systems without cache snooping it flushes the entire D-CACHE.   */ -#ifndef CONFIG_SPARC_LEON  static inline void dma_make_coherent(unsigned long pa, unsigned long len)  { +	if (sparc_cpu_model == sparc_leon) { +		if (!sparc_leon3_snooping_enabled()) +			leon_flush_dcache_all(); +	}  } -#else -static inline void dma_make_coherent(unsigned long pa, unsigned long len) -{ -	if (!sparc_leon3_snooping_enabled()) -		leon_flush_dcache_all(); -} -#endif  static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);  static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, @@ -427,9 +423,6 @@ arch_initcall(sparc_register_ioport);  #endif /* CONFIG_SBUS */ -/* LEON reuses PCI DMA ops */ -#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON) -  /* Allocate and map kernel buffer using consistent mode DMA for a device.   * hwdev should be valid struct pci_dev pointer for PCI devices.   */ @@ -657,14 +650,11 @@ struct dma_map_ops pci32_dma_ops = {  };  EXPORT_SYMBOL(pci32_dma_ops); -#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */ +/* leon re-uses pci32_dma_ops */ +struct dma_map_ops *leon_dma_ops = &pci32_dma_ops; +EXPORT_SYMBOL(leon_dma_ops); -#ifdef CONFIG_SPARC_LEON -struct dma_map_ops *dma_ops = &pci32_dma_ops; -#elif defined(CONFIG_SBUS)  struct dma_map_ops *dma_ops = &sbus_dma_ops; -#endif -  EXPORT_SYMBOL(dma_ops); diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index ae04914f777..c145f6fd123 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c @@ -241,9 +241,6 @@ int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)  	unsigned int cpu_irq;  	int err; -#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON -	struct tt_entry *trap_table; -#endif  	err = request_irq(irq, irq_handler, 0, "floppy", NULL);  	if (err) @@ -264,13 +261,18 @@ int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)  	table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;  	INSTANTIATE(sparc_ttable) -#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON -	trap_table = &trapbase_cpu1; -	INSTANTIATE(trap_table) -	trap_table = &trapbase_cpu2; -	INSTANTIATE(trap_table) -	trap_table = &trapbase_cpu3; -	INSTANTIATE(trap_table) + +#if defined CONFIG_SMP +	if (sparc_cpu_model != sparc_leon) { +		struct tt_entry *trap_table; + +		trap_table = &trapbase_cpu1; +		INSTANTIATE(trap_table) +		trap_table = &trapbase_cpu2; +		INSTANTIATE(trap_table) +		trap_table = &trapbase_cpu3; +		INSTANTIATE(trap_table) +	}  #endif  #undef INSTANTIATE  	/* diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index a86372d3458..291bb5de9ce 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -26,6 +26,9 @@ static inline unsigned long kimage_addr_to_ra(const char *p)  #endif  #ifdef CONFIG_SPARC32 +/* setup_32.c */ +void sparc32_start_kernel(struct linux_romvec *rp); +  /* cpu.c */  extern void cpu_probe(void); diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 77c1b916e4d..e34e2c40c06 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -23,6 +23,7 @@  #include <asm/smp.h>  #include <asm/setup.h> +#include "kernel.h"  #include "prom.h"  #include "irq.h" diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c index 519ca923f59..4e174321097 100644 --- a/arch/sparc/kernel/leon_pmc.c +++ b/arch/sparc/kernel/leon_pmc.c @@ -7,6 +7,7 @@  #include <linux/pm.h>  #include <asm/leon_amba.h> +#include <asm/cpu_type.h>  #include <asm/leon.h>  /* List of Systems that need fixup instructions around power-down instruction */ @@ -65,13 +66,15 @@ void pmc_leon_idle(void)  /* Install LEON Power Down function */  static int __init leon_pmc_install(void)  { -	/* Assign power management IDLE handler */ -	if (pmc_leon_need_fixup()) -		pm_idle = pmc_leon_idle_fixup; -	else -		pm_idle = pmc_leon_idle; +	if (sparc_cpu_model == sparc_leon) { +		/* Assign power management IDLE handler */ +		if (pmc_leon_need_fixup()) +			pm_idle = pmc_leon_idle_fixup; +		else +			pm_idle = pmc_leon_idle; -	printk(KERN_INFO "leon: power management initialized\n"); +		printk(KERN_INFO "leon: power management initialized\n"); +	}  	return 0;  } diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index a469090faf9..0f3fb6d9c8e 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -48,15 +48,13 @@  #include "kernel.h" -#ifdef CONFIG_SPARC_LEON -  #include "irq.h"  extern ctxd_t *srmmu_ctx_table_phys;  static int smp_processors_ready;  extern volatile unsigned long cpu_callin_map[NR_CPUS];  extern cpumask_t smp_commenced_mask; -void __init leon_configure_cache_smp(void); +void __cpuinit leon_configure_cache_smp(void);  static void leon_ipi_init(void);  /* IRQ number of LEON IPIs */ @@ -123,7 +121,7 @@ void __cpuinit leon_callin(void)  extern struct linux_prom_registers smp_penguin_ctable; -void __init leon_configure_cache_smp(void) +void __cpuinit leon_configure_cache_smp(void)  {  	unsigned long cfg = sparc_leon3_get_dcachecfg();  	int me = smp_processor_id(); @@ -507,5 +505,3 @@ void __init leon_init_smp(void)  	sparc32_ipi_ops = &leon_ipi_ops;  } - -#endif /* CONFIG_SPARC_LEON */ diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index fe6787cc62f..cb36e82dcd5 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -65,50 +65,25 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);  struct task_struct *last_task_used_math = NULL;  struct thread_info *current_set[NR_CPUS]; -#ifndef CONFIG_SMP -  /*   * the idle loop on a Sparc... ;)   */  void cpu_idle(void)  { -	/* endless idle loop with no priority at all */ -	for (;;) { -		if (pm_idle) { -			while (!need_resched()) -				(*pm_idle)(); -		} else { -			while (!need_resched()) -				cpu_relax(); -		} -		schedule_preempt_disabled(); -	} -} - -#else +	set_thread_flag(TIF_POLLING_NRFLAG); -/* This is being executed in task 0 'user space'. */ -void cpu_idle(void) -{ -        set_thread_flag(TIF_POLLING_NRFLAG);  	/* endless idle loop with no priority at all */ -	while(1) { -#ifdef CONFIG_SPARC_LEON -		if (pm_idle) { -			while (!need_resched()) +	for (;;) { +		while (!need_resched()) { +			if (pm_idle)  				(*pm_idle)(); -		} else -#endif -		{ -			while (!need_resched()) +			else  				cpu_relax();  		}  		schedule_preempt_disabled();  	}  } -#endif -  /* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */  void machine_halt(void)  { diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 741df916c12..1303021748c 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -23,7 +23,6 @@  #include <linux/of_pdt.h>  #include <asm/prom.h>  #include <asm/oplib.h> -#include <asm/leon.h>  #include "prom.h" diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S index 7abc24e2bf1..6c34de0c2ab 100644 --- a/arch/sparc/kernel/rtrap_32.S +++ b/arch/sparc/kernel/rtrap_32.S @@ -231,11 +231,14 @@ srmmu_rett_stackchk:  	cmp	%g1, %fp  	bleu	ret_trap_user_stack_is_bolixed  	 mov	AC_M_SFSR, %g1 -	lda	[%g1] ASI_M_MMUREGS, %g0 +LEON_PI(lda	[%g1] ASI_LEON_MMUREGS, %g0) +SUN_PI_(lda	[%g1] ASI_M_MMUREGS, %g0) -	lda	[%g0] ASI_M_MMUREGS, %g1 +LEON_PI(lda	[%g0] ASI_LEON_MMUREGS, %g1) +SUN_PI_(lda	[%g0] ASI_M_MMUREGS, %g1)  	or	%g1, 0x2, %g1 -	sta	%g1, [%g0] ASI_M_MMUREGS +LEON_PI(sta	%g1, [%g0] ASI_LEON_MMUREGS) +SUN_PI_(sta	%g1, [%g0] ASI_M_MMUREGS)  	restore	%g0, %g0, %g0 @@ -244,13 +247,16 @@ srmmu_rett_stackchk:  	save	%g0, %g0, %g0  	andn	%g1, 0x2, %g1 -	sta	%g1, [%g0] ASI_M_MMUREGS +LEON_PI(sta	%g1, [%g0] ASI_LEON_MMUREGS) +SUN_PI_(sta	%g1, [%g0] ASI_M_MMUREGS)  	mov	AC_M_SFAR, %g2 -	lda	[%g2] ASI_M_MMUREGS, %g2 +LEON_PI(lda	[%g2] ASI_LEON_MMUREGS, %g2) +SUN_PI_(lda	[%g2] ASI_M_MMUREGS, %g2)  	mov	AC_M_SFSR, %g1 -	lda	[%g1] ASI_M_MMUREGS, %g1 +LEON_PI(lda	[%g1] ASI_LEON_MMUREGS, %g1) +SUN_PI_(lda	[%g1] ASI_M_MMUREGS, %g1)  	andcc	%g1, 0x2, %g0  	be	ret_trap_userwins_ok  	 nop diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index c052313f4dc..efe3e64bba3 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -32,6 +32,7 @@  #include <linux/cpu.h>  #include <linux/kdebug.h>  #include <linux/export.h> +#include <linux/start_kernel.h>  #include <asm/io.h>  #include <asm/processor.h> @@ -45,6 +46,7 @@  #include <asm/cpudata.h>  #include <asm/setup.h>  #include <asm/cacheflush.h> +#include <asm/sections.h>  #include "kernel.h" @@ -237,28 +239,42 @@ static void __init per_cpu_patch(void)  	}  } +struct leon_1insn_patch_entry { +	unsigned int addr; +	unsigned int insn; +}; +  enum sparc_cpu sparc_cpu_model;  EXPORT_SYMBOL(sparc_cpu_model); -struct tt_entry *sparc_ttable; +static __init void leon_patch(void) +{ +	struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch; +	struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end; -struct pt_regs fake_swapper_regs; +	/* Default instruction is leon - no patching */ +	if (sparc_cpu_model == sparc_leon) +		return; -void __init setup_arch(char **cmdline_p) -{ -	int i; -	unsigned long highest_paddr; +	while (start < end) { +		unsigned long addr = start->addr; -	sparc_ttable = (struct tt_entry *) &trapbase; +		*(unsigned int *)(addr) = start->insn; +		flushi(addr); -	/* Initialize PROM console and command line. */ -	*cmdline_p = prom_getbootargs(); -	strcpy(boot_command_line, *cmdline_p); -	parse_early_param(); +		start++; +	} +} -	boot_flags_init(*cmdline_p); +struct tt_entry *sparc_ttable; +struct pt_regs fake_swapper_regs; -	register_console(&prom_early_console); +/* Called from head_32.S - before we have setup anything + * in the kernel. Be very careful with what you do here. + */ +void __init sparc32_start_kernel(struct linux_romvec *rp) +{ +	prom_init(rp);  	/* Set sparc_cpu_model */  	sparc_cpu_model = sun_unknown; @@ -275,6 +291,26 @@ void __init setup_arch(char **cmdline_p)  	if (!strncmp(&cputypval[0], "leon" , 4))  		sparc_cpu_model = sparc_leon; +	leon_patch(); +	start_kernel(); +} + +void __init setup_arch(char **cmdline_p) +{ +	int i; +	unsigned long highest_paddr; + +	sparc_ttable = (struct tt_entry *) &trapbase; + +	/* Initialize PROM console and command line. */ +	*cmdline_p = prom_getbootargs(); +	strcpy(boot_command_line, *cmdline_p); +	parse_early_param(); + +	boot_flags_init(*cmdline_p); + +	register_console(&prom_early_console); +  	printk("ARCH: ");  	switch(sparc_cpu_model) {  	case sun4m: diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index bb1513e45f1..a53e0a5fd3a 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -32,8 +32,6 @@  #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -  /* This magic should be in g_upper[0] for all upper parts   * to be valid.   */ @@ -274,7 +272,6 @@ void do_sigreturn32(struct pt_regs *regs)  		case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);  		case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);  	} -	sigdelsetmask(&set, ~_BLOCKABLE);  	set_current_blocked(&set);  	return; @@ -376,7 +373,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)  		case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32);  		case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);  	} -	sigdelsetmask(&set, ~_BLOCKABLE);  	set_current_blocked(&set);  	return;  segv: @@ -775,7 +771,7 @@ sigsegv:  	return -EFAULT;  } -static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, +static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,  				  siginfo_t *info,  				  sigset_t *oldset, struct pt_regs *regs)  { @@ -787,12 +783,9 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,  		err = setup_frame32(ka, regs, signr, oldset);  	if (err) -		return err; - -	block_sigmask(ka, signr); -	tracehook_signal_handler(signr, info, ka, regs, 0); +		return; -	return 0; +	signal_delivered(signr, info, ka, regs, 0);  }  static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, @@ -841,14 +834,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)  	if (signr > 0) {  		if (restart_syscall)  			syscall_restart32(orig_i0, regs, &ka.sa); -		if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { -			/* A signal was successfully delivered; the saved -			 * sigmask will have been stored in the signal frame, -			 * and will be restored by sigreturn, so we can simply -			 * clear the TS_RESTORE_SIGMASK flag. -			 */ -			current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -		} +		handle_signal32(signr, &ka, &info, oldset, regs);  		return;  	}  	if (restart_syscall && @@ -872,10 +858,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)  	/* If there's no signal to deliver, we just put the saved sigmask  	 * back  	 */ -	if (current_thread_info()->status & TS_RESTORE_SIGMASK) { -		current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -		set_current_blocked(¤t->saved_sigmask); -	} +	restore_saved_sigmask();  }  struct sigstack32 { diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 2b7e849f7c6..68f9c8650af 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -29,8 +29,6 @@  #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -  extern void fpsave(unsigned long *fpregs, unsigned long *fsr,  		   void *fpqueue, unsigned long *fpqdepth);  extern void fpload(unsigned long *fpregs, unsigned long *fsr); @@ -130,7 +128,6 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)  	if (err)  		goto segv_and_exit; -	sigdelsetmask(&set, ~_BLOCKABLE);  	set_current_blocked(&set);  	return; @@ -197,7 +194,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)  			goto segv;  	} -	sigdelsetmask(&set, ~_BLOCKABLE);  	set_current_blocked(&set);  	return;  segv: @@ -449,10 +445,11 @@ sigsegv:  	return -EFAULT;  } -static inline int +static inline void  handle_signal(unsigned long signr, struct k_sigaction *ka, -	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +	      siginfo_t *info, struct pt_regs *regs)  { +	sigset_t *oldset = sigmask_to_save();  	int err;  	if (ka->sa.sa_flags & SA_SIGINFO) @@ -461,12 +458,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,  		err = setup_frame(ka, regs, signr, oldset);  	if (err) -		return err; - -	block_sigmask(ka, signr); -	tracehook_signal_handler(signr, info, ka, regs, 0); +		return; -	return 0; +	signal_delivered(signr, info, ka, regs, 0);  }  static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -498,7 +492,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  {  	struct k_sigaction ka;  	int restart_syscall; -	sigset_t *oldset;  	siginfo_t info;  	int signr; @@ -523,11 +516,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))  		regs->u_regs[UREG_G6] = orig_i0; -	if (test_thread_flag(TIF_RESTORE_SIGMASK)) -		oldset = ¤t->saved_sigmask; -	else -		oldset = ¤t->blocked; -  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);  	/* If the debugger messes with the program counter, it clears @@ -544,15 +532,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	if (signr > 0) {  		if (restart_syscall)  			syscall_restart(orig_i0, regs, &ka.sa); -		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { -			/* a signal was successfully delivered; the saved -			 * sigmask will have been stored in the signal frame, -			 * and will be restored by sigreturn, so we can simply -			 * clear the TIF_RESTORE_SIGMASK flag. -			 */ -			if (test_thread_flag(TIF_RESTORE_SIGMASK)) -				clear_thread_flag(TIF_RESTORE_SIGMASK); -		} +		handle_signal(signr, &ka, &info, regs);  		return;  	}  	if (restart_syscall && @@ -576,22 +556,17 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	/* if there's no signal to deliver, we just put the saved sigmask  	 * back  	 */ -	if (test_thread_flag(TIF_RESTORE_SIGMASK)) { -		clear_thread_flag(TIF_RESTORE_SIGMASK); -		set_current_blocked(¤t->saved_sigmask); -	} +	restore_saved_sigmask();  }  void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,  		      unsigned long thread_info_flags)  { -	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) +	if (thread_info_flags & _TIF_SIGPENDING)  		do_signal(regs, orig_i0);  	if (thread_info_flags & _TIF_NOTIFY_RESUME) {  		clear_thread_flag(TIF_NOTIFY_RESUME);  		tracehook_notify_resume(regs); -		if (current->replacement_session_keyring) -			key_replace_session_keyring();  	}  } diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index eafaab486b2..867de2f8189 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -38,8 +38,6 @@  #include "systbls.h"  #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -  /* {set, get}context() needed for 64-bit SparcLinux userland. */  asmlinkage void sparc64_set_context(struct pt_regs *regs)  { @@ -71,7 +69,6 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)  			if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))  				goto do_sigsegv;  		} -		sigdelsetmask(&set, ~_BLOCKABLE);  		set_current_blocked(&set);  	}  	if (test_thread_flag(TIF_32BIT)) { @@ -315,7 +312,6 @@ void do_rt_sigreturn(struct pt_regs *regs)  	/* Prevent syscall restart.  */  	pt_regs_clear_syscall(regs); -	sigdelsetmask(&set, ~_BLOCKABLE);  	set_current_blocked(&set);  	return;  segv: @@ -466,7 +462,7 @@ sigsegv:  	return -EFAULT;  } -static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, +static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,  				siginfo_t *info,  				sigset_t *oldset, struct pt_regs *regs)  { @@ -475,12 +471,9 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,  	err = setup_rt_frame(ka, regs, signr, oldset,  			     (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);  	if (err) -		return err; - -	block_sigmask(ka, signr); -	tracehook_signal_handler(signr, info, ka, regs, 0); +		return; -	return 0; +	signal_delivered(signr, info, ka, regs, 0);  }  static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -512,7 +505,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  {  	struct k_sigaction ka;  	int restart_syscall; -	sigset_t *oldset; +	sigset_t *oldset = sigmask_to_save();  	siginfo_t info;  	int signr; @@ -538,11 +531,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))  		regs->u_regs[UREG_G6] = orig_i0; -	if (current_thread_info()->status & TS_RESTORE_SIGMASK) -		oldset = ¤t->saved_sigmask; -	else -		oldset = ¤t->blocked; -  #ifdef CONFIG_COMPAT  	if (test_thread_flag(TIF_32BIT)) {  		extern void do_signal32(sigset_t *, struct pt_regs *); @@ -563,14 +551,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	if (signr > 0) {  		if (restart_syscall)  			syscall_restart(orig_i0, regs, &ka.sa); -		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { -			/* A signal was successfully delivered; the saved -			 * sigmask will have been stored in the signal frame, -			 * and will be restored by sigreturn, so we can simply -			 * clear the TS_RESTORE_SIGMASK flag. -			 */ -			current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -		} +		handle_signal(signr, &ka, &info, oldset, regs);  		return;  	}  	if (restart_syscall && @@ -594,10 +575,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)  	/* If there's no signal to deliver, we just put the saved sigmask  	 * back  	 */ -	if (current_thread_info()->status & TS_RESTORE_SIGMASK) { -		current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -		set_current_blocked(¤t->saved_sigmask); -	} +	restore_saved_sigmask();  }  void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) @@ -607,8 +585,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long  	if (thread_info_flags & _TIF_NOTIFY_RESUME) {  		clear_thread_flag(TIF_NOTIFY_RESUME);  		tracehook_notify_resume(regs); -		if (current->replacement_session_keyring) -			key_replace_session_keyring();  	}  } diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index f591598d92f..781bcb10b8b 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -103,8 +103,6 @@ void __cpuinit smp_callin(void)  	if (cheetah_pcache_forced_on)  		cheetah_enable_pcache(); -	local_irq_enable(); -  	callin_flag = 1;  	__asm__ __volatile__("membar #Sync\n\t"  			     "flush  %%g6" : : : "memory"); @@ -124,9 +122,8 @@ void __cpuinit smp_callin(void)  	while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))  		rmb(); -	ipi_call_lock_irq();  	set_cpu_online(cpuid, true); -	ipi_call_unlock_irq(); +	local_irq_enable();  	/* idle thread is expected to have preempt disabled */  	preempt_disable(); @@ -1308,9 +1305,7 @@ int __cpu_disable(void)  	mdelay(1);  	local_irq_disable(); -	ipi_call_lock();  	set_cpu_online(cpu, false); -	ipi_call_unlock();  	cpu_map_rebuild(); diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 3ee51f189a5..275f74fd6f6 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -580,16 +580,9 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr,	unsigned long, old_len,  		unsigned long, new_len, unsigned long, flags,  		unsigned long, new_addr)  { -	unsigned long ret = -EINVAL; -  	if (test_thread_flag(TIF_32BIT)) -		goto out; - -	down_write(¤t->mm->mmap_sem); -	ret = do_mremap(addr, old_len, new_len, flags, new_addr); -	up_write(¤t->mm->mmap_sem); -out: -	return ret;        +		return -EINVAL; +	return sys_mremap(addr, old_len, new_len, flags, new_addr);  }  /* we come to here via sys_nis_syscall so it can setup the regs argument */ diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S index 7364ddc9e5a..af27acab448 100644 --- a/arch/sparc/kernel/trampoline_32.S +++ b/arch/sparc/kernel/trampoline_32.S @@ -149,8 +149,6 @@ sun4d_cpu_startup:  	b,a	smp_do_cpu_idle -#ifdef CONFIG_SPARC_LEON -  	__CPUINIT  	.align	4          .global leon_smp_cpu_startup, smp_penguin_ctable @@ -161,7 +159,7 @@ leon_smp_cpu_startup:          ld [%g1+4],%g1          srl %g1,4,%g1          set 0x00000100,%g5 /* SRMMU_CTXTBL_PTR */ -	sta %g1, [%g5] ASI_M_MMUREGS +	sta %g1, [%g5] ASI_LEON_MMUREGS  	/* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */  	set	(PSR_PIL | PSR_S | PSR_PS), %g1 @@ -207,5 +205,3 @@ leon_smp_cpu_startup:  	 nop  	b,a	smp_do_cpu_idle - -#endif diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index c72fdf55e1c..3b05e669771 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -2054,7 +2054,7 @@ void do_fpieee(struct pt_regs *regs)  	do_fpe_common(regs);  } -extern int do_mathemu(struct pt_regs *, struct fpustate *); +extern int do_mathemu(struct pt_regs *, struct fpustate *, bool);  void do_fpother(struct pt_regs *regs)  { @@ -2068,7 +2068,7 @@ void do_fpother(struct pt_regs *regs)  	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {  	case (2 << 14): /* unfinished_FPop */  	case (3 << 14): /* unimplemented_FPop */ -		ret = do_mathemu(regs, f); +		ret = do_mathemu(regs, f, false);  		break;  	}  	if (ret) @@ -2308,10 +2308,12 @@ void do_illegal_instruction(struct pt_regs *regs)  			} else {  				struct fpustate *f = FPUSTATE; -				/* XXX maybe verify XFSR bits like -				 * XXX do_fpother() does? +				/* On UltraSPARC T2 and later, FPU insns which +				 * are not implemented in HW signal an illegal +				 * instruction trap and do not set the FP Trap +				 * Trap in the %fsr to unimplemented_FPop.  				 */ -				if (do_mathemu(regs, f)) +				if (do_mathemu(regs, f, true))  					return;  			}  		} diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 5cffdc55f07..3e244f31e56 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -443,7 +443,7 @@ static int __init vio_init(void)  	root_vdev = vio_create_one(hp, root, NULL);  	err = -ENODEV;  	if (!root_vdev) { -		printk(KERN_ERR "VIO: Coult not create root device.\n"); +		printk(KERN_ERR "VIO: Could not create root device.\n");  		goto out_release;  	} diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 0e1605697b4..89c2c29f154 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -107,6 +107,11 @@ SECTIONS  		*(.sun4v_2insn_patch)  		__sun4v_2insn_patch_end = .;  	} +	.leon_1insn_patch : { +		__leon_1insn_patch = .; +		*(.leon_1insn_patch) +		__leon_1insn_patch_end = .; +	}  	.swapper_tsb_phys_patch : {  		__swapper_tsb_phys_patch = .;  		*(.swapper_tsb_phys_patch) diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S index 4c2de3cf309..28a7bc69f82 100644 --- a/arch/sparc/kernel/wof.S +++ b/arch/sparc/kernel/wof.S @@ -332,24 +332,30 @@ spwin_srmmu_stackchk:  	 mov	AC_M_SFSR, %glob_tmp  	/* Clear the fault status and turn on the no_fault bit. */ -	lda	[%glob_tmp] ASI_M_MMUREGS, %g0		! eat SFSR +LEON_PI(lda	[%glob_tmp] ASI_LEON_MMUREGS, %g0)	! eat SFSR +SUN_PI_(lda	[%glob_tmp] ASI_M_MMUREGS, %g0)		! eat SFSR -	lda	[%g0] ASI_M_MMUREGS, %glob_tmp		! read MMU control +LEON_PI(lda	[%g0] ASI_LEON_MMUREGS, %glob_tmp)	! read MMU control +SUN_PI_(lda	[%g0] ASI_M_MMUREGS, %glob_tmp)		! read MMU control  	or	%glob_tmp, 0x2, %glob_tmp		! or in no_fault bit -	sta	%glob_tmp, [%g0] ASI_M_MMUREGS		! set it +LEON_PI(sta	%glob_tmp, [%g0] ASI_LEON_MMUREGS)	! set it +SUN_PI_(sta	%glob_tmp, [%g0] ASI_M_MMUREGS)		! set it  	/* Dump the registers and cross fingers. */  	STORE_WINDOW(sp)  	/* Clear the no_fault bit and check the status. */  	andn	%glob_tmp, 0x2, %glob_tmp -	sta	%glob_tmp, [%g0] ASI_M_MMUREGS +LEON_PI(sta	%glob_tmp, [%g0] ASI_LEON_MMUREGS) +SUN_PI_(sta	%glob_tmp, [%g0] ASI_M_MMUREGS)  	mov	AC_M_SFAR, %glob_tmp -	lda	[%glob_tmp] ASI_M_MMUREGS, %g0 +LEON_PI(lda	[%glob_tmp] ASI_LEON_MMUREGS, %g0) +SUN_PI_(lda	[%glob_tmp] ASI_M_MMUREGS, %g0)  	mov	AC_M_SFSR, %glob_tmp -	lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp +LEON_PI(lda	[%glob_tmp] ASI_LEON_MMUREGS, %glob_tmp) +SUN_PI_(lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp)  	andcc	%glob_tmp, 0x2, %g0			! did we fault?  	be,a	spwin_finish_up + 0x4			! cool beans, success  	 restore %g0, %g0, %g0 diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S index 9fde91a249e..2c21cc59683 100644 --- a/arch/sparc/kernel/wuf.S +++ b/arch/sparc/kernel/wuf.S @@ -254,16 +254,19 @@ srmmu_fwin_stackchk:  	mov	AC_M_SFSR, %l4  	cmp	%l5, %sp  	bleu	fwin_user_stack_is_bolixed -	 lda	[%l4] ASI_M_MMUREGS, %g0	! clear fault status +LEON_PI( lda	[%l4] ASI_LEON_MMUREGS, %g0)	! clear fault status +SUN_PI_( lda	[%l4] ASI_M_MMUREGS, %g0)	! clear fault status  	/* The technique is, turn off faults on this processor,  	 * just let the load rip, then check the sfsr to see if  	 * a fault did occur.  Then we turn on fault traps again  	 * and branch conditionally based upon what happened.  	 */ -	lda	[%g0] ASI_M_MMUREGS, %l5	! read mmu-ctrl reg +LEON_PI(lda	[%g0] ASI_LEON_MMUREGS, %l5)	! read mmu-ctrl reg +SUN_PI_(lda	[%g0] ASI_M_MMUREGS, %l5)	! read mmu-ctrl reg  	or	%l5, 0x2, %l5			! turn on no-fault bit -	sta	%l5, [%g0] ASI_M_MMUREGS	! store it +LEON_PI(sta	%l5, [%g0] ASI_LEON_MMUREGS)	! store it +SUN_PI_(sta	%l5, [%g0] ASI_M_MMUREGS)	! store it  	/* Cross fingers and go for it. */  	LOAD_WINDOW(sp) @@ -275,18 +278,22 @@ srmmu_fwin_stackchk:  	/* LOCATION: Window 'T' */ -	lda	[%g0] ASI_M_MMUREGS, %twin_tmp1	! load mmu-ctrl again -	andn	%twin_tmp1, 0x2, %twin_tmp1	! clear no-fault bit -	sta	%twin_tmp1, [%g0] ASI_M_MMUREGS	! store it +LEON_PI(lda	[%g0] ASI_LEON_MMUREGS, %twin_tmp1)	! load mmu-ctrl again +SUN_PI_(lda	[%g0] ASI_M_MMUREGS, %twin_tmp1)	! load mmu-ctrl again +	andn	%twin_tmp1, 0x2, %twin_tmp1		! clear no-fault bit +LEON_PI(sta	%twin_tmp1, [%g0] ASI_LEON_MMUREGS)	! store it +SUN_PI_(sta	%twin_tmp1, [%g0] ASI_M_MMUREGS)	! store it  	mov	AC_M_SFAR, %twin_tmp2 -	lda	[%twin_tmp2] ASI_M_MMUREGS, %g0	! read fault address +LEON_PI(lda	[%twin_tmp2] ASI_LEON_MMUREGS, %g0)	! read fault address +SUN_PI_(lda	[%twin_tmp2] ASI_M_MMUREGS, %g0)	! read fault address  	mov	AC_M_SFSR, %twin_tmp2 -	lda	[%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2	! read fault status -	andcc	%twin_tmp2, 0x2, %g0			! did fault occur? +LEON_PI(lda	[%twin_tmp2] ASI_LEON_MMUREGS, %twin_tmp2) ! read fault status +SUN_PI_(lda	[%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2)	   ! read fault status +	andcc	%twin_tmp2, 0x2, %g0			   ! did fault occur? -	bne	1f					! yep, cleanup +	bne	1f					   ! yep, cleanup  	 nop  	wr	%t_psr, 0x0, %psr  |