diff options
Diffstat (limited to 'arch/m68k/kernel')
29 files changed, 3352 insertions, 2490 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 55d5d6b680a..e47778f8588 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -2,16 +2,28 @@  # Makefile for the linux kernel.  # -ifndef CONFIG_SUN3 -  extra-y := head.o -else -  extra-y := sun3-head.o -endif -extra-y	+= vmlinux.lds +extra-$(CONFIG_AMIGA)	:= head.o +extra-$(CONFIG_ATARI)	:= head.o +extra-$(CONFIG_MAC)	:= head.o +extra-$(CONFIG_APOLLO)	:= head.o +extra-$(CONFIG_VME)	:= head.o +extra-$(CONFIG_HP300)	:= head.o +extra-$(CONFIG_Q40)	:= head.o +extra-$(CONFIG_SUN3X)	:= head.o +extra-$(CONFIG_SUN3)	:= sun3-head.o +extra-y			+= vmlinux.lds -obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ -	   sys_m68k.o time.o setup.o m68k_ksyms.o devres.o +obj-y	:= entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o +obj-y	+= setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o -devres-y = ../../../kernel/irq/devres.o +obj-$(CONFIG_MMU_MOTOROLA) += ints.o vectors.o +obj-$(CONFIG_MMU_SUN3) += ints.o vectors.o +obj-$(CONFIG_PCI) += pcibios.o + +obj-$(CONFIG_HAS_DMA)	+= dma.o + +obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o +obj-$(CONFIG_BOOTINFO_PROC)	+= bootinfo_proc.o + +obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o -obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index 78e59b82ebc..3a386341aa6 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -23,11 +23,8 @@ int main(void)  {  	/* offsets into the task struct */  	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); -	DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));  	DEFINE(TASK_MM, offsetof(struct task_struct, mm)); -#ifdef CONFIG_MMU -	DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); -#endif +	DEFINE(TASK_STACK, offsetof(struct task_struct, stack));  	/* offsets into the thread struct */  	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); @@ -57,18 +54,30 @@ int main(void)  	DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));  	DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));  	DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); +  	/* bitfields are a bit difficult */ +#ifdef CONFIG_COLDFIRE +	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2); +#else  	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); +#endif  	/* offsets into the irq_cpustat_t struct */  	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); +	/* signal defines */ +	DEFINE(LSIGSEGV, SIGSEGV); +	DEFINE(LSEGV_MAPERR, SEGV_MAPERR); +	DEFINE(LSIGTRAP, SIGTRAP); +	DEFINE(LTRAP_TRACE, TRAP_TRACE); + +#ifdef CONFIG_MMU  	/* offsets into the bi_record struct */  	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));  	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));  	DEFINE(BIR_DATA, offsetof(struct bi_record, data)); -	/* offsets into font_desc (drivers/video/console/font.h) */ +	/* offsets into the font_desc struct */  	DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));  	DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));  	DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); @@ -76,12 +85,6 @@ int main(void)  	DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));  	DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); -	/* signal defines */ -	DEFINE(LSIGSEGV, SIGSEGV); -	DEFINE(LSEGV_MAPERR, SEGV_MAPERR); -	DEFINE(LSIGTRAP, SIGTRAP); -	DEFINE(LTRAP_TRACE, TRAP_TRACE); -  	/* offsets into the custom struct */  	DEFINE(CUSTOMBASE, &amiga_custom);  	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); @@ -96,5 +99,9 @@ int main(void)  	DEFINE(C_PRA, offsetof(struct CIA, pra));  	DEFINE(ZTWOBASE, zTwoBase); +	/* enum m68k_fixup_type */ +	DEFINE(M68K_FIXUP_MEMOFFSET, m68k_fixup_memoffset); +#endif +  	return 0;  } diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c new file mode 100644 index 00000000000..7ee853e1432 --- /dev/null +++ b/arch/m68k/kernel/bootinfo_proc.c @@ -0,0 +1,80 @@ +/* + * Based on arch/arm/kernel/atags_proc.c + */ + +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/printk.h> +#include <linux/proc_fs.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include <asm/bootinfo.h> +#include <asm/byteorder.h> + + +static char bootinfo_tmp[1536] __initdata; + +static void *bootinfo_copy; +static size_t bootinfo_size; + +static ssize_t bootinfo_read(struct file *file, char __user *buf, +			  size_t count, loff_t *ppos) +{ +	return simple_read_from_buffer(buf, count, ppos, bootinfo_copy, +				       bootinfo_size); +} + +static const struct file_operations bootinfo_fops = { +	.read = bootinfo_read, +	.llseek = default_llseek, +}; + +void __init save_bootinfo(const struct bi_record *bi) +{ +	const void *start = bi; +	size_t size = sizeof(bi->tag); + +	while (be16_to_cpu(bi->tag) != BI_LAST) { +		uint16_t n = be16_to_cpu(bi->size); +		size += n; +		bi = (struct bi_record *)((unsigned long)bi + n); +	} + +	if (size > sizeof(bootinfo_tmp)) { +		pr_err("Cannot save %zu bytes of bootinfo\n", size); +		return; +	} + +	pr_info("Saving %zu bytes of bootinfo\n", size); +	memcpy(bootinfo_tmp, start, size); +	bootinfo_size = size; +} + +static int __init init_bootinfo_procfs(void) +{ +	/* +	 * This cannot go into save_bootinfo() because kmalloc and proc don't +	 * work yet when it is called. +	 */ +	struct proc_dir_entry *pde; + +	if (!bootinfo_size) +		return -EINVAL; + +	bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL); +	if (!bootinfo_copy) +		return -ENOMEM; + +	memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size); + +	pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL); +	if (!pde) { +		kfree(bootinfo_copy); +		return -ENOMEM; +	} + +	return 0; +} + +arch_initcall(init_bootinfo_procfs); diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c index 4bbb3c2a888..e546a5534dd 100644 --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -12,9 +12,12 @@  #include <linux/scatterlist.h>  #include <linux/slab.h>  #include <linux/vmalloc.h> +#include <linux/export.h>  #include <asm/pgalloc.h> +#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) +  void *dma_alloc_coherent(struct device *dev, size_t size,  			 dma_addr_t *handle, gfp_t flag)  { @@ -57,7 +60,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size,  	return addr;  } -EXPORT_SYMBOL(dma_alloc_coherent);  void dma_free_coherent(struct device *dev, size_t size,  		       void *addr, dma_addr_t handle) @@ -65,12 +67,45 @@ void dma_free_coherent(struct device *dev, size_t size,  	pr_debug("dma_free_coherent: %p, %x\n", addr, handle);  	vfree(addr);  } + +#else + +#include <asm/cacheflush.h> + +void *dma_alloc_coherent(struct device *dev, size_t size, +			   dma_addr_t *dma_handle, gfp_t gfp) +{ +	void *ret; +	/* ignore region specifiers */ +	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + +	if (dev == NULL || (*dev->dma_mask < 0xffffffff)) +		gfp |= GFP_DMA; +	ret = (void *)__get_free_pages(gfp, get_order(size)); + +	if (ret != NULL) { +		memset(ret, 0, size); +		*dma_handle = virt_to_phys(ret); +	} +	return ret; +} + +void dma_free_coherent(struct device *dev, size_t size, +			 void *vaddr, dma_addr_t dma_handle) +{ +	free_pages((unsigned long)vaddr, get_order(size)); +} + +#endif /* CONFIG_MMU && !CONFIG_COLDFIRE */ + +EXPORT_SYMBOL(dma_alloc_coherent);  EXPORT_SYMBOL(dma_free_coherent);  void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,  				size_t size, enum dma_data_direction dir)  {  	switch (dir) { +	case DMA_BIDIRECTIONAL:  	case DMA_TO_DEVICE:  		cache_push(handle, size);  		break; diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c new file mode 100644 index 00000000000..ff9708d7192 --- /dev/null +++ b/arch/m68k/kernel/early_printk.c @@ -0,0 +1,67 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2014 Finn Thain + */ + +#include <linux/kernel.h> +#include <linux/console.h> +#include <linux/init.h> +#include <linux/string.h> +#include <asm/setup.h> + +extern void mvme16x_cons_write(struct console *co, +			       const char *str, unsigned count); + +asmlinkage void __init debug_cons_nputs(const char *s, unsigned n); + +static void __ref debug_cons_write(struct console *c, +				   const char *s, unsigned n) +{ +#if !(defined(CONFIG_SUN3)   || defined(CONFIG_M68360) || \ +      defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)) +	if (MACH_IS_MVME16x) +		mvme16x_cons_write(c, s, n); +	else +		debug_cons_nputs(s, n); +#endif +} + +static struct console early_console_instance = { +	.name  = "debug", +	.write = debug_cons_write, +	.flags = CON_PRINTBUFFER | CON_BOOT, +	.index = -1 +}; + +static int __init setup_early_printk(char *buf) +{ +	if (early_console || buf) +		return 0; + +	early_console = &early_console_instance; +	register_console(early_console); + +	return 0; +} +early_param("earlyprintk", setup_early_printk); + +/* + * debug_cons_nputs() defined in arch/m68k/kernel/head.S cannot be called + * after init sections are discarded (for platforms that use it). + */ +#if !(defined(CONFIG_SUN3)   || defined(CONFIG_M68360) || \ +      defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)) + +static int __init unregister_early_console(void) +{ +	if (!early_console || MACH_IS_MVME16x) +		return 0; + +	return unregister_console(early_console); +} +late_initcall(unregister_early_console); + +#endif diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 6360c437dcf..b54ac7aba85 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -34,38 +34,68 @@   */  #include <linux/linkage.h> -#include <asm/entry.h>  #include <asm/errno.h>  #include <asm/setup.h>  #include <asm/segment.h>  #include <asm/traps.h>  #include <asm/unistd.h> -  #include <asm/asm-offsets.h> +#include <asm/entry.h>  .globl system_call, buserr, trap, resume  .globl sys_call_table -.globl sys_fork, sys_clone, sys_vfork -.globl ret_from_interrupt, bad_interrupt +.globl __sys_fork, __sys_clone, __sys_vfork +.globl bad_interrupt  .globl auto_irqhandler_fixup -.globl user_irqvec_fixup, user_irqhandler_fixup +.globl user_irqvec_fixup  .text +ENTRY(__sys_fork) +	SAVE_SWITCH_STACK +	jbsr	sys_fork +	lea     %sp@(24),%sp +	rts + +ENTRY(__sys_clone) +	SAVE_SWITCH_STACK +	pea	%sp@(SWITCH_STACK_SIZE) +	jbsr	m68k_clone +	lea     %sp@(28),%sp +	rts + +ENTRY(__sys_vfork) +	SAVE_SWITCH_STACK +	jbsr	sys_vfork +	lea     %sp@(24),%sp +	rts + +ENTRY(sys_sigreturn) +	SAVE_SWITCH_STACK +	jbsr	do_sigreturn +	RESTORE_SWITCH_STACK +	rts + +ENTRY(sys_rt_sigreturn) +	SAVE_SWITCH_STACK +	jbsr	do_rt_sigreturn +	RESTORE_SWITCH_STACK +	rts +  ENTRY(buserr)  	SAVE_ALL_INT  	GET_CURRENT(%d0)  	movel	%sp,%sp@-		| stack frame pointer argument -	bsrl	buserr_c +	jbsr	buserr_c  	addql	#4,%sp -	jra	.Lret_from_exception +	jra	ret_from_exception  ENTRY(trap)  	SAVE_ALL_INT  	GET_CURRENT(%d0)  	movel	%sp,%sp@-		| stack frame pointer argument -	bsrl	trap_c +	jbsr	trap_c  	addql	#4,%sp -	jra	.Lret_from_exception +	jra	ret_from_exception  	| After a fork we jump here directly from resume,  	| so that %d1 contains the previous task @@ -74,7 +104,48 @@ ENTRY(ret_from_fork)  	movel	%d1,%sp@-  	jsr	schedule_tail  	addql	#4,%sp -	jra	.Lret_from_exception +	jra	ret_from_exception + +ENTRY(ret_from_kernel_thread) +	| a3 contains the kernel thread payload, d7 - its argument +	movel	%d1,%sp@- +	jsr	schedule_tail +	movel	%d7,(%sp) +	jsr	%a3@ +	addql	#4,%sp +	jra	ret_from_exception + +#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) + +#ifdef TRAP_DBG_INTERRUPT + +.globl dbginterrupt +ENTRY(dbginterrupt) +	SAVE_ALL_INT +	GET_CURRENT(%d0) +	movel	%sp,%sp@- 		/* stack frame pointer argument */ +	jsr	dbginterrupt_c +	addql	#4,%sp +	jra	ret_from_exception +#endif + +ENTRY(reschedule) +	/* save top of frame */ +	pea	%sp@ +	jbsr	set_esp0 +	addql	#4,%sp +	pea	ret_from_exception +	jmp	schedule + +ENTRY(ret_from_user_signal) +	moveq #__NR_sigreturn,%d0 +	trap #0 + +ENTRY(ret_from_user_rt_signal) +	movel #__NR_rt_sigreturn,%d0 +	trap #0 + +#else  do_trace_entry:  	movel	#-ENOSYS,%sp@(PT_OFF_D0)| needed for strace @@ -99,7 +170,11 @@ do_trace_exit:  	jra	.Lret_from_exception  ENTRY(ret_from_signal) -	RESTORE_SWITCH_STACK +	movel	%curptr@(TASK_STACK),%a1 +	tstb	%a1@(TINFO_FLAGS+2) +	jge	1f +	jbsr	syscall_trace +1:	RESTORE_SWITCH_STACK  	addql	#4,%sp  /* on 68040 complete pending writebacks if any */  #ifdef CONFIG_M68040 @@ -117,11 +192,13 @@ ENTRY(system_call)  	SAVE_ALL_SYS  	GET_CURRENT(%d1) +	movel	%d1,%a1 +  	| save top of frame  	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)  	| syscall trace? -	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2) +	tstb	%a1@(TINFO_FLAGS+2)  	jmi	do_trace_entry  	cmpl	#NR_syscalls,%d0  	jcc	badsys @@ -130,7 +207,8 @@ syscall:  	movel	%d0,%sp@(PT_OFF_D0)	| save the return value  ret_from_syscall:  	|oriw	#0x0700,%sr -	movew	%curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 +	movel	%curptr@(TASK_STACK),%a1 +	movew	%a1@(TINFO_FLAGS+2),%d0  	jne	syscall_exit_work  1:	RESTORE_ALL @@ -141,7 +219,7 @@ syscall_exit_work:  	jcs	do_trace_exit  	jmi	do_delayed_trace  	lslw	#8,%d0 -	jmi	do_signal_return +	jne	do_signal_return  	pea	resume_userspace  	jra	schedule @@ -156,7 +234,8 @@ ENTRY(ret_from_exception)  	andw	#ALLOWINT,%sr  resume_userspace: -	moveb	%curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 +	movel	%curptr@(TASK_STACK),%a1 +	moveb	%a1@(TINFO_FLAGS+3),%d0  	jne	exit_work  1:	RESTORE_ALL @@ -164,7 +243,7 @@ exit_work:  	| save top of frame  	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)  	lslb	#1,%d0 -	jmi	do_signal_return +	jne	do_signal_return  	pea	resume_userspace  	jra	schedule @@ -174,16 +253,11 @@ do_signal_return:  	subql	#4,%sp			| dummy return address  	SAVE_SWITCH_STACK  	pea	%sp@(SWITCH_STACK_SIZE) -	clrl	%sp@- -	bsrl	do_signal -	addql	#8,%sp +	bsrl	do_notify_resume +	addql	#4,%sp  	RESTORE_SWITCH_STACK  	addql	#4,%sp -	tstl	%d0 -	jeq	resume_userspace -	| when single stepping into handler stop at the first insn -	btst	#6,%curptr@(TASK_INFO+TINFO_FLAGS+2) -	jeq	resume_userspace +	jbra	resume_userspace  do_delayed_trace:  	bclr	#7,%sp@(PT_OFF_SR)	| clear trace bit in SR @@ -201,7 +275,6 @@ do_delayed_trace:  ENTRY(auto_inthandler)  	SAVE_ALL_INT  	GET_CURRENT(%d0) -	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)  					|  put exception # in d0  	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0  	subw	#VEC_SPUR,%d0 @@ -209,32 +282,15 @@ ENTRY(auto_inthandler)  	movel	%sp,%sp@-  	movel	%d0,%sp@-		|  put vector # on stack  auto_irqhandler_fixup = . + 2 -	jsr	__m68k_handle_int	|  process the IRQ +	jsr	do_IRQ			|  process the IRQ  	addql	#8,%sp			|  pop parameters off stack - -ret_from_interrupt: -	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) -	jeq	ret_from_last_interrupt -2:	RESTORE_ALL - -	ALIGN -ret_from_last_interrupt: -	moveq	#(~ALLOWINT>>8)&0xff,%d0 -	andb	%sp@(PT_OFF_SR),%d0 -	jne	2b - -	/* check if we need to do software interrupts */ -	tstl	irq_stat+CPUSTAT_SOFTIRQ_PENDING -	jeq	.Lret_from_exception -	pea	ret_from_exception -	jra	do_softirq +	jra	ret_from_exception  /* Handler for user defined interrupt vectors */  ENTRY(user_inthandler)  	SAVE_ALL_INT  	GET_CURRENT(%d0) -	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)  					|  put exception # in d0  	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0  user_irqvec_fixup = . + 2 @@ -242,81 +298,20 @@ user_irqvec_fixup = . + 2  	movel	%sp,%sp@-  	movel	%d0,%sp@-		|  put vector # on stack -user_irqhandler_fixup = . + 2 -	jsr	__m68k_handle_int	|  process the IRQ +	jsr	do_IRQ			|  process the IRQ  	addql	#8,%sp			|  pop parameters off stack - -	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) -	jeq	ret_from_last_interrupt -	RESTORE_ALL +	jra	ret_from_exception  /* Handler for uninitialized and spurious interrupts */  ENTRY(bad_inthandler)  	SAVE_ALL_INT  	GET_CURRENT(%d0) -	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)  	movel	%sp,%sp@-  	jsr	handle_badint  	addql	#4,%sp - -	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) -	jeq	ret_from_last_interrupt -	RESTORE_ALL - - -ENTRY(sys_fork) -	SAVE_SWITCH_STACK -	pea	%sp@(SWITCH_STACK_SIZE) -	jbsr	m68k_fork -	addql	#4,%sp -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_clone) -	SAVE_SWITCH_STACK -	pea	%sp@(SWITCH_STACK_SIZE) -	jbsr	m68k_clone -	addql	#4,%sp -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_vfork) -	SAVE_SWITCH_STACK -	pea	%sp@(SWITCH_STACK_SIZE) -	jbsr	m68k_vfork -	addql	#4,%sp -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_sigsuspend) -	SAVE_SWITCH_STACK -	pea	%sp@(SWITCH_STACK_SIZE) -	jbsr	do_sigsuspend -	addql	#4,%sp -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_rt_sigsuspend) -	SAVE_SWITCH_STACK -	pea	%sp@(SWITCH_STACK_SIZE) -	jbsr	do_rt_sigsuspend -	addql	#4,%sp -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_sigreturn) -	SAVE_SWITCH_STACK -	jbsr	do_sigreturn -	RESTORE_SWITCH_STACK -	rts - -ENTRY(sys_rt_sigreturn) -	SAVE_SWITCH_STACK -	jbsr	do_rt_sigreturn -	RESTORE_SWITCH_STACK -	rts +	jra	ret_from_exception  resume:  	/* @@ -425,347 +420,4 @@ resume:  	rts -.data -ALIGN -sys_call_table: -	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */ -	.long sys_exit -	.long sys_fork -	.long sys_read -	.long sys_write -	.long sys_open		/* 5 */ -	.long sys_close -	.long sys_waitpid -	.long sys_creat -	.long sys_link -	.long sys_unlink	/* 10 */ -	.long sys_execve -	.long sys_chdir -	.long sys_time -	.long sys_mknod -	.long sys_chmod		/* 15 */ -	.long sys_chown16 -	.long sys_ni_syscall				/* old break syscall holder */ -	.long sys_stat -	.long sys_lseek -	.long sys_getpid	/* 20 */ -	.long sys_mount -	.long sys_oldumount -	.long sys_setuid16 -	.long sys_getuid16 -	.long sys_stime		/* 25 */ -	.long sys_ptrace -	.long sys_alarm -	.long sys_fstat -	.long sys_pause -	.long sys_utime		/* 30 */ -	.long sys_ni_syscall				/* old stty syscall holder */ -	.long sys_ni_syscall				/* old gtty syscall holder */ -	.long sys_access -	.long sys_nice -	.long sys_ni_syscall	/* 35 */	/* old ftime syscall holder */ -	.long sys_sync -	.long sys_kill -	.long sys_rename -	.long sys_mkdir -	.long sys_rmdir		/* 40 */ -	.long sys_dup -	.long sys_pipe -	.long sys_times -	.long sys_ni_syscall				/* old prof syscall holder */ -	.long sys_brk		/* 45 */ -	.long sys_setgid16 -	.long sys_getgid16 -	.long sys_signal -	.long sys_geteuid16 -	.long sys_getegid16	/* 50 */ -	.long sys_acct -	.long sys_umount				/* recycled never used phys() */ -	.long sys_ni_syscall				/* old lock syscall holder */ -	.long sys_ioctl -	.long sys_fcntl		/* 55 */ -	.long sys_ni_syscall				/* old mpx syscall holder */ -	.long sys_setpgid -	.long sys_ni_syscall				/* old ulimit syscall holder */ -	.long sys_ni_syscall -	.long sys_umask		/* 60 */ -	.long sys_chroot -	.long sys_ustat -	.long sys_dup2 -	.long sys_getppid -	.long sys_getpgrp	/* 65 */ -	.long sys_setsid -	.long sys_sigaction -	.long sys_sgetmask -	.long sys_ssetmask -	.long sys_setreuid16	/* 70 */ -	.long sys_setregid16 -	.long sys_sigsuspend -	.long sys_sigpending -	.long sys_sethostname -	.long sys_setrlimit	/* 75 */ -	.long sys_old_getrlimit -	.long sys_getrusage -	.long sys_gettimeofday -	.long sys_settimeofday -	.long sys_getgroups16	/* 80 */ -	.long sys_setgroups16 -	.long sys_old_select -	.long sys_symlink -	.long sys_lstat -	.long sys_readlink	/* 85 */ -	.long sys_uselib -	.long sys_swapon -	.long sys_reboot -	.long sys_old_readdir -	.long sys_old_mmap	/* 90 */ -	.long sys_munmap -	.long sys_truncate -	.long sys_ftruncate -	.long sys_fchmod -	.long sys_fchown16	/* 95 */ -	.long sys_getpriority -	.long sys_setpriority -	.long sys_ni_syscall				/* old profil syscall holder */ -	.long sys_statfs -	.long sys_fstatfs	/* 100 */ -	.long sys_ni_syscall				/* ioperm for i386 */ -	.long sys_socketcall -	.long sys_syslog -	.long sys_setitimer -	.long sys_getitimer	/* 105 */ -	.long sys_newstat -	.long sys_newlstat -	.long sys_newfstat -	.long sys_ni_syscall -	.long sys_ni_syscall	/* 110 */	/* iopl for i386 */ -	.long sys_vhangup -	.long sys_ni_syscall				/* obsolete idle() syscall */ -	.long sys_ni_syscall				/* vm86old for i386 */ -	.long sys_wait4 -	.long sys_swapoff	/* 115 */ -	.long sys_sysinfo -	.long sys_ipc -	.long sys_fsync -	.long sys_sigreturn -	.long sys_clone		/* 120 */ -	.long sys_setdomainname -	.long sys_newuname -	.long sys_cacheflush				/* modify_ldt for i386 */ -	.long sys_adjtimex -	.long sys_mprotect	/* 125 */ -	.long sys_sigprocmask -	.long sys_ni_syscall		/* old "create_module" */ -	.long sys_init_module -	.long sys_delete_module -	.long sys_ni_syscall	/* 130 - old "get_kernel_syms" */ -	.long sys_quotactl -	.long sys_getpgid -	.long sys_fchdir -	.long sys_bdflush -	.long sys_sysfs		/* 135 */ -	.long sys_personality -	.long sys_ni_syscall				/* for afs_syscall */ -	.long sys_setfsuid16 -	.long sys_setfsgid16 -	.long sys_llseek	/* 140 */ -	.long sys_getdents -	.long sys_select -	.long sys_flock -	.long sys_msync -	.long sys_readv		/* 145 */ -	.long sys_writev -	.long sys_getsid -	.long sys_fdatasync -	.long sys_sysctl -	.long sys_mlock		/* 150 */ -	.long sys_munlock -	.long sys_mlockall -	.long sys_munlockall -	.long sys_sched_setparam -	.long sys_sched_getparam	/* 155 */ -	.long sys_sched_setscheduler -	.long sys_sched_getscheduler -	.long sys_sched_yield -	.long sys_sched_get_priority_max -	.long sys_sched_get_priority_min  /* 160 */ -	.long sys_sched_rr_get_interval -	.long sys_nanosleep -	.long sys_mremap -	.long sys_setresuid16 -	.long sys_getresuid16	/* 165 */ -	.long sys_getpagesize -	.long sys_ni_syscall		/* old sys_query_module */ -	.long sys_poll -	.long sys_nfsservctl -	.long sys_setresgid16	/* 170 */ -	.long sys_getresgid16 -	.long sys_prctl -	.long sys_rt_sigreturn -	.long sys_rt_sigaction -	.long sys_rt_sigprocmask	/* 175 */ -	.long sys_rt_sigpending -	.long sys_rt_sigtimedwait -	.long sys_rt_sigqueueinfo -	.long sys_rt_sigsuspend -	.long sys_pread64	/* 180 */ -	.long sys_pwrite64 -	.long sys_lchown16; -	.long sys_getcwd -	.long sys_capget -	.long sys_capset	/* 185 */ -	.long sys_sigaltstack -	.long sys_sendfile -	.long sys_ni_syscall				/* streams1 */ -	.long sys_ni_syscall				/* streams2 */ -	.long sys_vfork		/* 190 */ -	.long sys_getrlimit -	.long sys_mmap2 -	.long sys_truncate64 -	.long sys_ftruncate64 -	.long sys_stat64	/* 195 */ -	.long sys_lstat64 -	.long sys_fstat64 -	.long sys_chown -	.long sys_getuid -	.long sys_getgid	/* 200 */ -	.long sys_geteuid -	.long sys_getegid -	.long sys_setreuid -	.long sys_setregid -	.long sys_getgroups	/* 205 */ -	.long sys_setgroups -	.long sys_fchown -	.long sys_setresuid -	.long sys_getresuid -	.long sys_setresgid	/* 210 */ -	.long sys_getresgid -	.long sys_lchown -	.long sys_setuid -	.long sys_setgid -	.long sys_setfsuid	/* 215 */ -	.long sys_setfsgid -	.long sys_pivot_root -	.long sys_ni_syscall -	.long sys_ni_syscall -	.long sys_getdents64	/* 220 */ -	.long sys_gettid -	.long sys_tkill -	.long sys_setxattr -	.long sys_lsetxattr -	.long sys_fsetxattr	/* 225 */ -	.long sys_getxattr -	.long sys_lgetxattr -	.long sys_fgetxattr -	.long sys_listxattr -	.long sys_llistxattr	/* 230 */ -	.long sys_flistxattr -	.long sys_removexattr -	.long sys_lremovexattr -	.long sys_fremovexattr -	.long sys_futex		/* 235 */ -	.long sys_sendfile64 -	.long sys_mincore -	.long sys_madvise -	.long sys_fcntl64 -	.long sys_readahead	/* 240 */ -	.long sys_io_setup -	.long sys_io_destroy -	.long sys_io_getevents -	.long sys_io_submit -	.long sys_io_cancel	/* 245 */ -	.long sys_fadvise64 -	.long sys_exit_group -	.long sys_lookup_dcookie -	.long sys_epoll_create -	.long sys_epoll_ctl	/* 250 */ -	.long sys_epoll_wait -	.long sys_remap_file_pages -	.long sys_set_tid_address -	.long sys_timer_create -	.long sys_timer_settime	/* 255 */ -	.long sys_timer_gettime -	.long sys_timer_getoverrun -	.long sys_timer_delete -	.long sys_clock_settime -	.long sys_clock_gettime	/* 260 */ -	.long sys_clock_getres -	.long sys_clock_nanosleep -	.long sys_statfs64 -	.long sys_fstatfs64 -	.long sys_tgkill	/* 265 */ -	.long sys_utimes -	.long sys_fadvise64_64 -	.long sys_mbind -	.long sys_get_mempolicy -	.long sys_set_mempolicy	/* 270 */ -	.long sys_mq_open -	.long sys_mq_unlink -	.long sys_mq_timedsend -	.long sys_mq_timedreceive -	.long sys_mq_notify	/* 275 */ -	.long sys_mq_getsetattr -	.long sys_waitid -	.long sys_ni_syscall	/* for sys_vserver */ -	.long sys_add_key -	.long sys_request_key	/* 280 */ -	.long sys_keyctl -	.long sys_ioprio_set -	.long sys_ioprio_get -	.long sys_inotify_init -	.long sys_inotify_add_watch	/* 285 */ -	.long sys_inotify_rm_watch -	.long sys_migrate_pages -	.long sys_openat -	.long sys_mkdirat -	.long sys_mknodat		/* 290 */ -	.long sys_fchownat -	.long sys_futimesat -	.long sys_fstatat64 -	.long sys_unlinkat -	.long sys_renameat		/* 295 */ -	.long sys_linkat -	.long sys_symlinkat -	.long sys_readlinkat -	.long sys_fchmodat -	.long sys_faccessat		/* 300 */ -	.long sys_ni_syscall		/* Reserved for pselect6 */ -	.long sys_ni_syscall		/* Reserved for ppoll */ -	.long sys_unshare -	.long sys_set_robust_list -	.long sys_get_robust_list	/* 305 */ -	.long sys_splice -	.long sys_sync_file_range -	.long sys_tee -	.long sys_vmsplice -	.long sys_move_pages		/* 310 */ -	.long sys_sched_setaffinity -	.long sys_sched_getaffinity -	.long sys_kexec_load -	.long sys_getcpu -	.long sys_epoll_pwait		/* 315 */ -	.long sys_utimensat -	.long sys_signalfd -	.long sys_timerfd_create -	.long sys_eventfd -	.long sys_fallocate		/* 320 */ -	.long sys_timerfd_settime -	.long sys_timerfd_gettime -	.long sys_signalfd4 -	.long sys_eventfd2 -	.long sys_epoll_create1		/* 325 */ -	.long sys_dup3 -	.long sys_pipe2 -	.long sys_inotify_init1 -	.long sys_preadv -	.long sys_pwritev		/* 330 */ -	.long sys_rt_tgsigqueueinfo -	.long sys_perf_event_open -	.long sys_get_thread_area -	.long sys_set_thread_area -	.long sys_atomic_cmpxchg_32	/* 335 */ -	.long sys_atomic_barrier -	.long sys_fanotify_init -	.long sys_fanotify_mark -	.long sys_prlimit64 - +#endif /* CONFIG_MMU && !CONFIG_COLDFIRE */ diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index ef54128baa0..a54788458ca 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -23,7 +23,7 @@  ** 98/04/25 Phil Blundell: added HP300 support  ** 1998/08/30 David Kilzer: Added support for font_desc structures  **            for linux-2.1.115 -** 9/02/11  Richard Zidlicky: added Q40 support (initial vesion 99/01/01) +** 1999/02/11  Richard Zidlicky: added Q40 support (initial version 99/01/01)  ** 2004/05/13 Kars de Jong: Finalised HP300 support  **  ** This file is subject to the terms and conditions of the GNU General Public @@ -134,7 +134,7 @@   *	Thanks to a small helping routine enabling the mmu got quite simple   * and there is only one way left. mmu_engage makes a complete a new mapping   * that only includes the absolute necessary to be able to jump to the final - * postion and to restore the original mapping. + * position and to restore the original mapping.   * As this code doesn't need a transparent translation register anymore this   * means all registers are free to be used by machines that needs them for   * other purposes. @@ -153,7 +153,7 @@   * ------------   *	The console is also able to be turned off.  The console in head.S   * is specifically for debugging and can be very useful.  It is surrounded by - * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good + * #ifdef / #endif clauses so it doesn't have to ship in known-good   * kernels.  It's basic algorithm is to determine the size of the screen   * (in height/width and bit depth) and then use that information for   * displaying an 8x8 font or an 8x16 (widthxheight).  I prefer the 8x8 for @@ -198,9 +198,8 @@   * CONFIG_xxx:	These are the obvious machine configuration defines created   * during configuration.  These are defined in autoconf.h.   * - * CONSOLE:	There is support for head.S console in this file.  This - * console can talk to a Mac frame buffer, but could easily be extrapolated - * to extend it to support other platforms. + * CONSOLE_DEBUG:  Only supports a Mac frame buffer but could easily be + * extended to support other platforms.   *   * TEST_MMU:	This is a test harness for running on any given machine but   * getting an MMU dump for another class of machine.  The classes of machines @@ -222,7 +221,7 @@   * MMU_PRINT:	There is a routine built into head.S that can display the   * MMU data structures.  It outputs its result through the serial_putc   * interface.  So where ever that winds up driving data, that's where the - * mmu struct will appear.  On the Macintosh that's typically the console. + * mmu struct will appear.   *   * SERIAL_DEBUG:	There are a series of putc() macro statements   * scattered through out the code to give progress of status to the @@ -250,51 +249,37 @@   * USE_MFP:	Use the ST-MFP port (Modem1) for serial debug.   *   * Macintosh constants: - * MAC_SERIAL_DEBUG:	Turns on serial debug output for the Macintosh. - * MAC_USE_SCC_A:	Use the SCC port A (modem) for serial debug. - * MAC_USE_SCC_B:	Use the SCC port B (printer) for serial debug (default). + * MAC_USE_SCC_A: Use SCC port A (modem) for serial debug. + * MAC_USE_SCC_B: Use SCC port B (printer) for serial debug.   */  #include <linux/linkage.h>  #include <linux/init.h>  #include <asm/bootinfo.h> +#include <asm/bootinfo-amiga.h> +#include <asm/bootinfo-atari.h> +#include <asm/bootinfo-hp300.h> +#include <asm/bootinfo-mac.h> +#include <asm/bootinfo-q40.h> +#include <asm/bootinfo-vme.h>  #include <asm/setup.h>  #include <asm/entry.h>  #include <asm/pgtable.h>  #include <asm/page.h>  #include <asm/asm-offsets.h> -  #ifdef CONFIG_MAC - -#include <asm/machw.h> - -/* - * Macintosh console support - */ - -#ifdef CONFIG_FRAMEBUFFER_CONSOLE -#define CONSOLE -#define CONSOLE_PENGUIN +#  include <asm/machw.h>  #endif -/* - * Macintosh serial debug support; outputs boot info to the printer - *   and/or modem serial ports - */ -#undef MAC_SERIAL_DEBUG - -/* - * Macintosh serial debug port selection; define one or both; - *   requires MAC_SERIAL_DEBUG to be defined - */ -#define MAC_USE_SCC_A		/* Macintosh modem serial port */ -#define MAC_USE_SCC_B		/* Macintosh printer serial port */ - -#endif	/* CONFIG_MAC */ +#ifdef CONFIG_EARLY_PRINTK +#  define SERIAL_DEBUG +#  if defined(CONFIG_MAC) && defined(CONFIG_FONT_SUPPORT) +#    define CONSOLE_DEBUG +#  endif +#endif  #undef MMU_PRINT  #undef MMU_NOCACHE_KERNEL -#define SERIAL_DEBUG  #undef DEBUG  /* @@ -307,6 +292,7 @@  .globl kernel_pg_dir  .globl availmem +.globl m68k_init_mapped_size  .globl m68k_pgtable_cachemode  .globl m68k_supervisor_cachemode  #ifdef CONFIG_MVME16x @@ -484,22 +470,21 @@ func_define	serial_putc,1  func_define	console_putc,1  func_define	console_init -func_define	console_put_stats  func_define	console_put_penguin  func_define	console_plot_pixel,3  func_define	console_scroll  .macro	putc	ch -#if defined(CONSOLE) || defined(SERIAL_DEBUG) +#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)  	pea	\ch  #endif -#ifdef CONSOLE +#ifdef CONSOLE_DEBUG  	func_call	console_putc  #endif  #ifdef SERIAL_DEBUG  	func_call	serial_putc  #endif -#if defined(CONSOLE) || defined(SERIAL_DEBUG) +#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)  	addql	#4,%sp  #endif  .endm @@ -519,7 +504,7 @@ func_define	putn,1  .endm  .macro	puts		string -#if defined(CONSOLE) || defined(SERIAL_DEBUG) +#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)  	__INITDATA  .Lstr\@:  	.string	"\string" @@ -655,32 +640,9 @@ ENTRY(__start)  	lea	%pc@(L(mac_rowbytes)),%a1  	movel	%a0@,%a1@ -#ifdef MAC_SERIAL_DEBUG  	get_bi_record	BI_MAC_SCCBASE  	lea	%pc@(L(mac_sccbase)),%a1  	movel	%a0@,%a1@ -#endif /* MAC_SERIAL_DEBUG */ - -#if 0 -	/* -	 * Clear the screen -	 */ -	lea	%pc@(L(mac_videobase)),%a0 -	movel	%a0@,%a1 -	lea	%pc@(L(mac_dimensions)),%a0 -	movel	%a0@,%d1 -	swap	%d1		/* #rows is high bytes */ -	andl	#0xFFFF,%d1	/* rows */ -	subl	#10,%d1 -	lea	%pc@(L(mac_rowbytes)),%a0 -loopy2: -	movel	%a0@,%d0 -	subql	#1,%d0 -loopx2: -	moveb	#0x55, %a1@+ -	dbra	%d0,loopx2 -	dbra	%d1,loopy2 -#endif  L(test_notmac):  #endif /* CONFIG_MAC */ @@ -910,15 +872,14 @@ L(nothp):   */  #ifdef CONFIG_MAC  	is_not_mac(L(nocon)) -#ifdef CONSOLE +#  ifdef CONSOLE_DEBUG  	console_init -#ifdef CONSOLE_PENGUIN +#    ifdef CONFIG_LOGO  	console_put_penguin -#endif	/* CONSOLE_PENGUIN */ -	console_put_stats -#endif	/* CONSOLE */ +#    endif /* CONFIG_LOGO */ +#  endif /* CONSOLE_DEBUG */  L(nocon): -#endif	/* CONFIG_MAC */ +#endif /* CONFIG_MAC */  	putc	'\n' @@ -947,10 +908,22 @@ L(nocon):   *   *	This block of code does what's necessary to map in the various kinds   *	of machines for execution of Linux. - *	First map the first 4 MB of kernel code & data + *	First map the first 4, 8, or 16 MB of kernel code & data   */ -	mmu_map	#PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\ +	get_bi_record BI_MEMCHUNK +	movel	%a0@(4),%d0 +	movel	#16*1024*1024,%d1 +	cmpl	%d0,%d1 +	jls	1f +	lsrl	#1,%d1 +	cmpl	%d0,%d1 +	jls	1f +	lsrl	#1,%d1 +1: +	lea	%pc@(m68k_init_mapped_size),%a0 +	movel	%d1,%a0@ +	mmu_map	#PAGE_OFFSET,%pc@(L(phys_kernel_start)),%d1,\  		%pc@(m68k_supervisor_cachemode)  	putc	'C' @@ -969,7 +942,7 @@ L(mmu_init_amiga):  	is_not_040_or_060(1f)  	/* -	 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000 +	 * 040: Map the 16Meg range physical 0x0 up to logical 0x8000.0000  	 */  	mmu_map		#0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S  	/* @@ -982,7 +955,7 @@ L(mmu_init_amiga):  1:  	/* -	 * 030:	Map the 32Meg range physical 0x0 upto logical 0x8000.0000 +	 * 030:	Map the 32Meg range physical 0x0 up to logical 0x8000.0000  	 */  	mmu_map		#0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030  	mmu_map_tt	#1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030 @@ -1074,7 +1047,7 @@ L(notq40):  	is_040(1f)  	/* -	 * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000 +	 * 030: Map the 32Meg range physical 0x0 up to logical 0xf000.0000  	 */  	mmu_map	#0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030 @@ -1082,7 +1055,7 @@ L(notq40):  1:  	/* -	 * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000 +	 * 040: Map the 16Meg range physical 0x0 up to logical 0xf000.0000  	 */  	mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S @@ -1421,15 +1394,13 @@ L(mmu_fixup_done):  	andl	L(mac_videobase),%d0  	addl	#VIDEOMEMBASE,%d0  	movel	%d0,L(mac_videobase) -#if defined(CONSOLE) +#ifdef CONSOLE_DEBUG  	movel	%pc@(L(phys_kernel_start)),%d0  	subl	#PAGE_OFFSET,%d0  	subl	%d0,L(console_font)  	subl	%d0,L(console_font_data)  #endif -#ifdef MAC_SERIAL_DEBUG  	orl	#0x50000000,L(mac_sccbase) -#endif  1:  #endif @@ -1541,7 +1512,7 @@ L(cache_done):  /*   * Find a tag record in the bootinfo structure - * The bootinfo structure is located right after the kernel bss + * The bootinfo structure is located right after the kernel   * Returns: d0: size (-1 if not found)   *          a0: data pointer (end-of-records if not found)   */ @@ -1917,7 +1888,7 @@ mmu_030_print:  	jbne	30b  mmu_print_done: -	puts	"\n\n" +	puts	"\n"  func_return	mmu_print @@ -2759,22 +2730,26 @@ func_return	get_new_page   */  #ifdef CONFIG_MAC +/* You may define either or both of these. */ +#define MAC_USE_SCC_A /* Modem port */ +#define MAC_USE_SCC_B /* Printer port */ +#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B) +/* Initialisation table for SCC with 3.6864 MHz PCLK */  L(scc_initable_mac): -	.byte	9,12		/* Reset */  	.byte	4,0x44		/* x16, 1 stopbit, no parity */  	.byte	3,0xc0		/* receiver: 8 bpc */  	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */ -	.byte	9,0		/* no interrupts */  	.byte	10,0		/* NRZ */  	.byte	11,0x50		/* use baud rate generator */ -	.byte	12,10,13,0	/* 9600 baud */ +	.byte	12,1,13,0	/* 38400 baud */  	.byte	14,1		/* Baud rate generator enable */  	.byte	3,0xc1		/* enable receiver */  	.byte	5,0xea		/* enable transmitter */  	.byte	-1  	.even  #endif +#endif /* CONFIG_MAC */  #ifdef CONFIG_ATARI  /* #define USE_PRINTER */ @@ -2783,14 +2758,12 @@ L(scc_initable_mac):  #define USE_MFP  #if defined(USE_SCC_A) || defined(USE_SCC_B) -#define USE_SCC -/* Initialisation table for SCC */ -L(scc_initable): -	.byte	9,12		/* Reset */ +/* Initialisation table for SCC with 7.9872 MHz PCLK */ +/* PCLK == 8.0539 gives baud == 9680.1 */ +L(scc_initable_atari):  	.byte	4,0x44		/* x16, 1 stopbit, no parity */  	.byte	3,0xc0		/* receiver: 8 bpc */  	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */ -	.byte	9,0		/* no interrupts */  	.byte	10,0		/* NRZ */  	.byte	11,0x50		/* use baud rate generator */  	.byte	12,24,13,0	/* 9600 baud */ @@ -2839,7 +2812,7 @@ LMFP_UDR     = 0xfffa2f   */  /* - * Initialize serial port hardware for 9600/8/1 + * Initialize serial port hardware   */  func_start	serial_init,%d0/%d1/%a0/%a1  	/* @@ -2849,7 +2822,7 @@ func_start	serial_init,%d0/%d1/%a0/%a1  	 *		d0 = boot info offset  	 *	CONFIG_ATARI  	 *		a0 = address of SCC -	 *		a1 = Liobase address/address of scc_initable +	 *		a1 = Liobase address/address of scc_initable_atari  	 *		d0 = init data for serial port  	 *	CONFIG_MAC  	 *		a0 = address of SCC @@ -2870,6 +2843,7 @@ func_start	serial_init,%d0/%d1/%a0/%a1  |	movew	#61,CUSTOMBASE+C_SERPER-ZTWOBASE  1:  #endif +  #ifdef CONFIG_ATARI  	is_not_atari(4f)  	movel	%pc@(L(iobase)),%a1 @@ -2884,9 +2858,21 @@ func_start	serial_init,%d0/%d1/%a0/%a1  	moveb	%a1@(LPSG_READ),%d0  	bset	#5,%d0  	moveb	%d0,%a1@(LPSG_WRITE) -#elif defined(USE_SCC) +#elif defined(USE_SCC_A) || defined(USE_SCC_B)  	lea	%a1@(LSCC_CTRL),%a0 -	lea	%pc@(L(scc_initable)),%a1 +	/* Reset SCC register pointer */ +	moveb	%a0@,%d0 +	/* Reset SCC device: write register pointer then register value */ +	moveb	#9,%a0@ +	moveb	#0xc0,%a0@ +	/* Wait for 5 PCLK cycles, which is about 63 CPU cycles */ +	/* 5 / 7.9872 MHz = approx. 0.63 us = 63 / 100 MHz */ +	movel	#32,%d0 +2: +	subq	#1,%d0 +	jne	2b +	/* Initialize channel */ +	lea	%pc@(L(scc_initable_atari)),%a1  2:	moveb	%a1@+,%d0  	jmi	3f  	moveb	%d0,%a0@ @@ -2904,20 +2890,29 @@ func_start	serial_init,%d0/%d1/%a0/%a1  	jra	L(serial_init_done)  4:  #endif +  #ifdef CONFIG_MAC  	is_not_mac(L(serial_init_not_mac)) -#ifdef MAC_SERIAL_DEBUG -#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B) -#define MAC_USE_SCC_B -#endif +#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)  #define mac_scc_cha_b_ctrl_offset	0x0  #define mac_scc_cha_a_ctrl_offset	0x2  #define mac_scc_cha_b_data_offset	0x4  #define mac_scc_cha_a_data_offset	0x6 - +	movel	%pc@(L(mac_sccbase)),%a0 +	/* Reset SCC register pointer */ +	moveb	%a0@(mac_scc_cha_a_ctrl_offset),%d0 +	/* Reset SCC device: write register pointer then register value */ +	moveb	#9,%a0@(mac_scc_cha_a_ctrl_offset) +	moveb	#0xc0,%a0@(mac_scc_cha_a_ctrl_offset) +	/* Wait for 5 PCLK cycles, which is about 68 CPU cycles */ +	/* 5 / 3.6864 MHz = approx. 1.36 us = 68 / 50 MHz */ +	movel	#35,%d0 +5: +	subq	#1,%d0 +	jne	5b +#endif  #ifdef MAC_USE_SCC_A  	/* Initialize channel A */ -	movel	%pc@(L(mac_sccbase)),%a0  	lea	%pc@(L(scc_initable_mac)),%a1  5:	moveb	%a1@+,%d0  	jmi	6f @@ -2926,12 +2921,8 @@ func_start	serial_init,%d0/%d1/%a0/%a1  	jra	5b  6:  #endif	/* MAC_USE_SCC_A */ -  #ifdef MAC_USE_SCC_B  	/* Initialize channel B */ -#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */ -	movel	%pc@(L(mac_sccbase)),%a0 -#endif	/* MAC_USE_SCC_A */  	lea	%pc@(L(scc_initable_mac)),%a1  7:	moveb	%a1@+,%d0  	jmi	8f @@ -2940,8 +2931,6 @@ func_start	serial_init,%d0/%d1/%a0/%a1  	jra	7b  8:  #endif	/* MAC_USE_SCC_B */ -#endif	/* MAC_SERIAL_DEBUG */ -  	jra	L(serial_init_done)  L(serial_init_not_mac):  #endif	/* CONFIG_MAC */ @@ -2971,6 +2960,15 @@ L(serial_init_not_mac):  2:  #endif +#ifdef CONFIG_MVME16x +	is_not_mvme16x(L(serial_init_not_mvme16x)) +	moveb	#0x10,M167_PCSCCMICR +	moveb	#0x10,M167_PCSCCTICR +	moveb	#0x10,M167_PCSCCRICR +	jra	L(serial_init_done) +L(serial_init_not_mvme16x): +#endif +  #ifdef CONFIG_APOLLO  /* We count on the PROM initializing SIO1 */  #endif @@ -3010,27 +3008,19 @@ func_start	serial_putc,%d0/%d1/%a0/%a1  #ifdef CONFIG_MAC  	is_not_mac(5f) - -#ifdef MAC_SERIAL_DEBUG - -#ifdef MAC_USE_SCC_A +#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)  	movel	%pc@(L(mac_sccbase)),%a1 +#endif +#ifdef MAC_USE_SCC_A  3:	btst	#2,%a1@(mac_scc_cha_a_ctrl_offset)  	jeq	3b  	moveb	%d0,%a1@(mac_scc_cha_a_data_offset)  #endif	/* MAC_USE_SCC_A */ -  #ifdef MAC_USE_SCC_B -#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */ -	movel	%pc@(L(mac_sccbase)),%a1 -#endif	/* MAC_USE_SCC_A */  4:	btst	#2,%a1@(mac_scc_cha_b_ctrl_offset)  	jeq	4b  	moveb	%d0,%a1@(mac_scc_cha_b_data_offset)  #endif	/* MAC_USE_SCC_B */ - -#endif	/* MAC_SERIAL_DEBUG */ -  	jra	L(serial_putc_done)  5:  #endif	/* CONFIG_MAC */ @@ -3051,7 +3041,7 @@ func_start	serial_putc,%d0/%d1/%a0/%a1  	nop  	bset	#5,%d0  	moveb	%d0,%a1@(LPSG_WRITE) -#elif defined(USE_SCC) +#elif defined(USE_SCC_A) || defined(USE_SCC_B)  3:	btst	#2,%a1@(LSCC_CTRL)  	jeq	3b  	moveb	%d0,%a1@(LSCC_DATA) @@ -3078,7 +3068,7 @@ func_start	serial_putc,%d0/%d1/%a0/%a1  	/*  	 * If the loader gave us a board type then we can use that to  	 * select an appropriate output routine; otherwise we just use -	 * the Bug code.  If we haev to use the Bug that means the Bug +	 * the Bug code.  If we have to use the Bug that means the Bug  	 * workspace has to be valid, which means the Bug has to use  	 * the SRAM, which is non-standard.  	 */ @@ -3207,7 +3197,7 @@ func_start	puts,%d0/%a0  	movel	ARG1,%a0  	jra	2f  1: -#ifdef CONSOLE +#ifdef CONSOLE_DEBUG  	console_putc	%d0  #endif  #ifdef SERIAL_DEBUG @@ -3236,7 +3226,7 @@ func_start	putn,%d0-%d2  	jls	2f  	addb	#'A'-('9'+1),%d2  2: -#ifdef CONSOLE +#ifdef CONSOLE_DEBUG  	console_putc	%d2  #endif  #ifdef SERIAL_DEBUG @@ -3246,37 +3236,41 @@ func_start	putn,%d0-%d2  func_return	putn -#ifdef CONFIG_MAC +#ifdef CONFIG_EARLY_PRINTK  /* - *	mac_serial_print - *   *	This routine takes its parameters on the stack.  It then - *	turns around and calls the internal routine.  This routine - *	is used until the Linux console driver initializes itself. + *	turns around and calls the internal routines.  This routine + *	is used by the boot console.   *   *	The calling parameters are: - *		void mac_serial_print(const char *str); + *		void debug_cons_nputs(const char *str, unsigned length)   *   *	This routine does NOT understand variable arguments only   *	simple strings!   */ -ENTRY(mac_serial_print) -	moveml	%d0/%a0,%sp@- -#if 1 -	move	%sr,%sp@- +ENTRY(debug_cons_nputs) +	moveml	%d0/%d1/%a0,%sp@- +	movew	%sr,%sp@-  	ori	#0x0700,%sr -#endif -	movel	%sp@(10),%a0		/* fetch parameter */ +	movel	%sp@(18),%a0		/* fetch parameter */ +	movel	%sp@(22),%d1		/* fetch parameter */  	jra	2f -1:	serial_putc	%d0 -2:	moveb	%a0@+,%d0 -	jne	1b -#if 1 -	move	%sp@+,%sr +1: +#ifdef CONSOLE_DEBUG +	console_putc	%d0 +#endif +#ifdef SERIAL_DEBUG +	serial_putc	%d0  #endif -	moveml	%sp@+,%d0/%a0 +	subq	#1,%d1 +2:	jeq	3f +	moveb	%a0@+,%d0 +	jne	1b +3: +	movew	%sp@+,%sr +	moveml	%sp@+,%d0/%d1/%a0  	rts -#endif /* CONFIG_MAC */ +#endif /* CONFIG_EARLY_PRINTK */  #if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)  func_start	set_leds,%d0/%a0 @@ -3298,7 +3292,7 @@ func_start	set_leds,%d0/%a0  func_return	set_leds  #endif -#ifdef CONSOLE +#ifdef CONSOLE_DEBUG  /*   *	For continuity, see the data alignment   *	to which this structure is tied. @@ -3308,14 +3302,13 @@ func_return	set_leds  #define Lconsole_struct_num_columns	8  #define Lconsole_struct_num_rows	12  #define Lconsole_struct_left_edge	16 -#define Lconsole_struct_penguin_putc	20  func_start	console_init,%a0-%a4/%d0-%d7  	/*  	 *	Some of the register usage that follows  	 *		a0 = pointer to boot_info  	 *		a1 = pointer to screen -	 *		a2 = pointer to Lconsole_globals +	 *		a2 = pointer to console_globals  	 *		d3 = pixel width of screen  	 *		d4 = pixel height of screen  	 *		(d3,d4) ~= (x,y) of a point just below @@ -3403,42 +3396,7 @@ L(console_clear_loop):  1:  func_return	console_init -func_start	console_put_stats,%a0/%d7 -	/* -	 *	Some of the register usage that follows -	 *		a0 = pointer to boot_info -	 *		d7 = value of boot_info fields -	 */ -	puts	"\nMacLinux\n\n" - -#ifdef SERIAL_DEBUG -	puts	" vidaddr:" -	putn	%pc@(L(mac_videobase))		/* video addr. */ - -	puts	"\n  _stext:" -	lea	%pc@(_stext),%a0 -	putn	%a0 - -	puts	"\nbootinfo:" -	lea	%pc@(_end),%a0 -	putn	%a0 - -	puts	"\ncpuid:" -	putn	%pc@(L(cputype)) -	putc	'\n' - -#ifdef MAC_SERIAL_DEBUG -	putn	%pc@(L(mac_sccbase)) -	putc	'\n' -#endif -#  if defined(MMU_PRINT) -	jbsr	mmu_print_machine_cpu_types -#  endif /* MMU_PRINT */ -#endif /* SERIAL_DEBUG */ - -func_return	console_put_stats - -#ifdef CONSOLE_PENGUIN +#ifdef CONFIG_LOGO  func_start	console_put_penguin,%a0-%a1/%d0-%d7  	/*  	 *	Get 'that_penguin' onto the screen in the upper right corner @@ -3779,44 +3737,15 @@ L(white_16):  L(console_plot_pixel_exit):  func_return	console_plot_pixel -#endif /* CONSOLE */ - -#if 0 -/* - * This is some old code lying around.  I don't believe - * it's used or important anymore.  My guess is it contributed - * to getting to this point, but it's done for now. - * It was still in the 2.1.77 head.S, so it's still here. - * (And still not used!) - */ -L(showtest): -	moveml	%a0/%d7,%sp@- -	puts	"A=" -	putn	%a1 - -	.long	0xf0119f15		| ptestr	#5,%a1@,#7,%a0 - -	puts	"DA=" -	putn	%a0 - -	puts	"D=" -	putn	%a0@ +#endif /* CONSOLE_DEBUG */ -	puts	"S=" -	lea	%pc@(L(mmu)),%a0 -	.long	0xf0106200		| pmove		%psr,%a0@ -	clrl	%d7 -	movew	%a0@,%d7 -	putn	%d7 - -	putc	'\n' -	moveml	%sp@+,%a0/%d7 -	rts -#endif	/* 0 */  __INITDATA  	.align	4 +m68k_init_mapped_size: +	.long	0 +  #if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \      defined(CONFIG_HP300) || defined(CONFIG_APOLLO)  L(custom): @@ -3824,19 +3753,18 @@ L(iobase):  	.long 0  #endif -#if defined(CONSOLE) +#ifdef CONSOLE_DEBUG  L(console_globals):  	.long	0		/* cursor column */  	.long	0		/* cursor row */  	.long	0		/* max num columns */  	.long	0		/* max num rows */  	.long	0		/* left edge */ -	.long	0		/* mac putc */  L(console_font):  	.long	0		/* pointer to console font (struct font_desc) */  L(console_font_data):  	.long	0		/* pointer to console font data */ -#endif /* CONSOLE */ +#endif /* CONSOLE_DEBUG */  #if defined(MMU_PRINT)  L(mmu_print_data): @@ -3876,7 +3804,9 @@ M167_CYIER = 0xfff45011  M167_CYLICR = 0xfff45026  M167_CYTEOIR = 0xfff45085  M167_CYTDR = 0xfff450f8 +M167_PCSCCMICR = 0xfff4201d  M167_PCSCCTICR = 0xfff4201e +M167_PCSCCRICR = 0xfff4201f  M167_PCTPIACKR = 0xfff42025  #endif @@ -3886,8 +3816,6 @@ BVME_SCC_DATA_A	= 0xffb0000f  #endif  #if defined(CONFIG_MAC) -L(mac_booter_data): -	.long	0  L(mac_videobase):  	.long	0  L(mac_videodepth): @@ -3896,11 +3824,9 @@ L(mac_dimensions):  	.long	0  L(mac_rowbytes):  	.long	0 -#ifdef MAC_SERIAL_DEBUG  L(mac_sccbase):  	.long	0 -#endif /* MAC_SERIAL_DEBUG */ -#endif +#endif /* CONFIG_MAC */  #if defined (CONFIG_APOLLO)  LSRB0        = 0x10412 diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 761ee0440c9..5b8d66fbf38 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -4,37 +4,17 @@   * This file is subject to the terms and conditions of the GNU General Public   * License.  See the file COPYING in the main directory of this archive   * for more details. - * - * 07/03/96: Timer initialization, and thus mach_sched_init(), - *           removed from request_irq() and moved to init_time(). - *           We should therefore consider renaming our add_isr() and - *           remove_isr() to request_irq() and free_irq() - *           respectively, so they are compliant with the other - *           architectures.                                     /Jes - * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. - *           Removed irq list support, if any machine needs an irq server - *           it must implement this itself (as it's already done), instead - *           only default handler are used with mach_default_handler. - *           request_irq got some flags different from other architectures: - *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one - *                               can be replaced without this flag) - *           - IRQ_FLG_LOCK : handler can't be replaced - *           There are other machine depending flags, see there - *           If you want to replace a default handler you should know what - *           you're doing, since it might handle different other irq sources - *           which must be served                               /Roman Zippel   */  #include <linux/module.h>  #include <linux/types.h>  #include <linux/sched.h>  #include <linux/interrupt.h> -#include <linux/kernel_stat.h>  #include <linux/errno.h>  #include <linux/init.h> +#include <linux/irq.h>  #include <asm/setup.h> -#include <asm/system.h>  #include <asm/irq.h>  #include <asm/traps.h>  #include <asm/page.h> @@ -47,33 +27,22 @@  #endif  extern u32 auto_irqhandler_fixup[]; -extern u32 user_irqhandler_fixup[];  extern u16 user_irqvec_fixup[]; -/* table for system interrupt handlers */ -static struct irq_node *irq_list[NR_IRQS]; -static struct irq_controller *irq_controller[NR_IRQS]; -static int irq_depth[NR_IRQS]; -  static int m68k_first_user_vec; -static struct irq_controller auto_irq_controller = { +static struct irq_chip auto_irq_chip = {  	.name		= "auto", -	.lock		= __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock), -	.startup	= m68k_irq_startup, -	.shutdown	= m68k_irq_shutdown, +	.irq_startup	= m68k_irq_startup, +	.irq_shutdown	= m68k_irq_shutdown,  }; -static struct irq_controller user_irq_controller = { +static struct irq_chip user_irq_chip = {  	.name		= "user", -	.lock		= __SPIN_LOCK_UNLOCKED(user_irq_controller.lock), -	.startup	= m68k_irq_startup, -	.shutdown	= m68k_irq_shutdown, +	.irq_startup	= m68k_irq_startup, +	.irq_shutdown	= m68k_irq_shutdown,  }; -#define NUM_IRQ_NODES 100 -static irq_node_t nodes[NUM_IRQ_NODES]; -  /*   * void init_IRQ(void)   * @@ -89,14 +58,8 @@ void __init init_IRQ(void)  {  	int i; -	/* assembly irq entry code relies on this... */ -	if (HARDIRQ_MASK != 0x00ff0000) { -		extern void hardirq_mask_is_broken(void); -		hardirq_mask_is_broken(); -	} -  	for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) -		irq_controller[i] = &auto_irq_controller; +		irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);  	mach_init_IRQ();  } @@ -106,7 +69,7 @@ void __init init_IRQ(void)   * @handler: called from auto vector interrupts   *   * setup the handler to be called from auto vector interrupts instead of the - * standard __m68k_handle_int(), it will be called with irq numbers in the range + * standard do_IRQ(), it will be called with irq numbers in the range   * from IRQ_AUTO_1 - IRQ_AUTO_7.   */  void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) @@ -120,217 +83,49 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re   * m68k_setup_user_interrupt   * @vec: first user vector interrupt to handle   * @cnt: number of active user vector interrupts - * @handler: called from user vector interrupts   *   * setup user vector interrupts, this includes activating the specified range   * of interrupts, only then these interrupts can be requested (note: this is - * different from auto vector interrupts). An optional handler can be installed - * to be called instead of the default __m68k_handle_int(), it will be called - * with irq numbers starting from IRQ_USER. + * different from auto vector interrupts).   */ -void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, -				      void (*handler)(unsigned int, struct pt_regs *)) +void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)  {  	int i;  	BUG_ON(IRQ_USER + cnt > NR_IRQS);  	m68k_first_user_vec = vec;  	for (i = 0; i < cnt; i++) -		irq_controller[IRQ_USER + i] = &user_irq_controller; +		irq_set_chip_and_handler(i, &user_irq_chip, handle_simple_irq);  	*user_irqvec_fixup = vec - IRQ_USER; -	if (handler) -		*user_irqhandler_fixup = (u32)handler;  	flush_icache();  }  /**   * m68k_setup_irq_controller - * @contr: irq controller which controls specified irq + * @chip: irq chip which controls specified irq + * @handle: flow handler which handles specified irq   * @irq: first irq to be managed by the controller + * @cnt: number of irqs to be managed by the controller   *   * Change the controller for the specified range of irq, which will be used to   * manage these irq. auto/user irq already have a default controller, which can   * be changed as well, but the controller probably should use m68k_irq_startup/   * m68k_irq_shutdown.   */ -void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, +void m68k_setup_irq_controller(struct irq_chip *chip, +			       irq_flow_handler_t handle, unsigned int irq,  			       unsigned int cnt)  {  	int i; -	for (i = 0; i < cnt; i++) -		irq_controller[irq + i] = contr; -} - -irq_node_t *new_irq_node(void) -{ -	irq_node_t *node; -	short i; - -	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { -		if (!node->handler) { -			memset(node, 0, sizeof(*node)); -			return node; -		} -	} - -	printk ("new_irq_node: out of nodes\n"); -	return NULL; -} - -int setup_irq(unsigned int irq, struct irq_node *node) -{ -	struct irq_controller *contr; -	struct irq_node **prev; -	unsigned long flags; - -	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { -		printk("%s: Incorrect IRQ %d from %s\n", -		       __func__, irq, node->devname); -		return -ENXIO; -	} - -	spin_lock_irqsave(&contr->lock, flags); - -	prev = irq_list + irq; -	if (*prev) { -		/* Can't share interrupts unless both agree to */ -		if (!((*prev)->flags & node->flags & IRQF_SHARED)) { -			spin_unlock_irqrestore(&contr->lock, flags); -			return -EBUSY; -		} -		while (*prev) -			prev = &(*prev)->next; -	} - -	if (!irq_list[irq]) { -		if (contr->startup) -			contr->startup(irq); -		else -			contr->enable(irq); -	} -	node->next = NULL; -	*prev = node; - -	spin_unlock_irqrestore(&contr->lock, flags); - -	return 0; -} - -int request_irq(unsigned int irq, -		irq_handler_t handler, -		unsigned long flags, const char *devname, void *dev_id) -{ -	struct irq_node *node; -	int res; - -	node = new_irq_node(); -	if (!node) -		return -ENOMEM; - -	node->handler = handler; -	node->flags   = flags; -	node->dev_id  = dev_id; -	node->devname = devname; - -	res = setup_irq(irq, node); -	if (res) -		node->handler = NULL; - -	return res; -} - -EXPORT_SYMBOL(request_irq); - -void free_irq(unsigned int irq, void *dev_id) -{ -	struct irq_controller *contr; -	struct irq_node **p, *node; -	unsigned long flags; - -	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { -		printk("%s: Incorrect IRQ %d\n", __func__, irq); -		return; +	for (i = 0; i < cnt; i++) { +		irq_set_chip(irq + i, chip); +		if (handle) +			irq_set_handler(irq + i, handle);  	} - -	spin_lock_irqsave(&contr->lock, flags); - -	p = irq_list + irq; -	while ((node = *p)) { -		if (node->dev_id == dev_id) -			break; -		p = &node->next; -	} - -	if (node) { -		*p = node->next; -		node->handler = NULL; -	} else -		printk("%s: Removing probably wrong IRQ %d\n", -		       __func__, irq); - -	if (!irq_list[irq]) { -		if (contr->shutdown) -			contr->shutdown(irq); -		else -			contr->disable(irq); -	} - -	spin_unlock_irqrestore(&contr->lock, flags);  } -EXPORT_SYMBOL(free_irq); - -void enable_irq(unsigned int irq) -{ -	struct irq_controller *contr; -	unsigned long flags; - -	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { -		printk("%s: Incorrect IRQ %d\n", -		       __func__, irq); -		return; -	} - -	spin_lock_irqsave(&contr->lock, flags); -	if (irq_depth[irq]) { -		if (!--irq_depth[irq]) { -			if (contr->enable) -				contr->enable(irq); -		} -	} else -		WARN_ON(1); -	spin_unlock_irqrestore(&contr->lock, flags); -} - -EXPORT_SYMBOL(enable_irq); - -void disable_irq(unsigned int irq) -{ -	struct irq_controller *contr; -	unsigned long flags; - -	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { -		printk("%s: Incorrect IRQ %d\n", -		       __func__, irq); -		return; -	} - -	spin_lock_irqsave(&contr->lock, flags); -	if (!irq_depth[irq]++) { -		if (contr->disable) -			contr->disable(irq); -	} -	spin_unlock_irqrestore(&contr->lock, flags); -} - -EXPORT_SYMBOL(disable_irq); - -void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); - -EXPORT_SYMBOL(disable_irq_nosync); - -int m68k_irq_startup(unsigned int irq) +unsigned int m68k_irq_startup_irq(unsigned int irq)  {  	if (irq <= IRQ_AUTO_7)  		vectors[VEC_SPUR + irq] = auto_inthandler; @@ -339,41 +134,21 @@ int m68k_irq_startup(unsigned int irq)  	return 0;  } -void m68k_irq_shutdown(unsigned int irq) +unsigned int m68k_irq_startup(struct irq_data *data)  { -	if (irq <= IRQ_AUTO_7) -		vectors[VEC_SPUR + irq] = bad_inthandler; -	else -		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; +	return m68k_irq_startup_irq(data->irq);  } - -/* - * Do we need these probe functions on the m68k? - * - *  ... may be useful with ISA devices - */ -unsigned long probe_irq_on (void) +void m68k_irq_shutdown(struct irq_data *data)  { -#ifdef CONFIG_Q40 -	if (MACH_IS_Q40) -		return q40_probe_irq_on(); -#endif -	return 0; -} +	unsigned int irq = data->irq; -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off (unsigned long irqs) -{ -#ifdef CONFIG_Q40 -	if (MACH_IS_Q40) -		return q40_probe_irq_off(irqs); -#endif -	return 0; +	if (irq <= IRQ_AUTO_7) +		vectors[VEC_SPUR + irq] = bad_inthandler; +	else +		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;  } -EXPORT_SYMBOL(probe_irq_off);  unsigned int irq_canonicalize(unsigned int irq)  { @@ -386,52 +161,9 @@ unsigned int irq_canonicalize(unsigned int irq)  EXPORT_SYMBOL(irq_canonicalize); -asmlinkage void m68k_handle_int(unsigned int irq) -{ -	struct irq_node *node; -	kstat_cpu(0).irqs[irq]++; -	node = irq_list[irq]; -	do { -		node->handler(irq, node->dev_id); -		node = node->next; -	} while (node); -} - -asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) -{ -	struct pt_regs *old_regs; -	old_regs = set_irq_regs(regs); -	m68k_handle_int(irq); -	set_irq_regs(old_regs); -}  asmlinkage void handle_badint(struct pt_regs *regs)  { -	kstat_cpu(0).irqs[0]++; -	printk("unexpected interrupt from %u\n", regs->vector); -} - -int show_interrupts(struct seq_file *p, void *v) -{ -	struct irq_controller *contr; -	struct irq_node *node; -	int i = *(loff_t *) v; - -	/* autovector interrupts */ -	if (irq_list[i]) { -		contr = irq_controller[i]; -		node = irq_list[i]; -		seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); -		while ((node = node->next)) -			seq_printf(p, ", %s", node->devname); -		seq_puts(p, "\n"); -	} -	return 0; -} - -#ifdef CONFIG_PROC_FS -void init_irq_proc(void) -{ -	/* Insert /proc/irq driver here */ +	atomic_inc(&irq_err_count); +	pr_warn("unexpected interrupt from %u\n", regs->vector);  } -#endif diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c new file mode 100644 index 00000000000..9ab4f550342 --- /dev/null +++ b/arch/m68k/kernel/irq.c @@ -0,0 +1,39 @@ +/* + * irq.c + * + * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/seq_file.h> +#include <asm/traps.h> + +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +{ +	struct pt_regs *oldregs = set_irq_regs(regs); + +	irq_enter(); +	generic_handle_irq(irq); +	irq_exit(); + +	set_irq_regs(oldregs); +} + + +/* The number of spurious interrupts */ +atomic_t irq_err_count; + +int arch_show_interrupts(struct seq_file *p, int prec) +{ +	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); +	return 0; +} diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index d900e77e536..774c1bd59c3 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -14,3 +14,19 @@ EXPORT_SYMBOL(__ashrdi3);  EXPORT_SYMBOL(__lshrdi3);  EXPORT_SYMBOL(__muldi3); +#if defined(CONFIG_CPU_HAS_NO_MULDIV64) +/* + * Simpler 68k and ColdFire parts also need a few other gcc functions. + */ +extern long long __divsi3(long long, long long); +extern long long __modsi3(long long, long long); +extern long long __mulsi3(long long, long long); +extern long long __udivsi3(long long, long long); +extern long long __umodsi3(long long, long long); + +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__mulsi3); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umodsi3); +#endif diff --git a/arch/m68k/kernel/machine_kexec.c b/arch/m68k/kernel/machine_kexec.c new file mode 100644 index 00000000000..d4affc917d9 --- /dev/null +++ b/arch/m68k/kernel/machine_kexec.c @@ -0,0 +1,58 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + */ +#include <linux/compiler.h> +#include <linux/kexec.h> +#include <linux/mm.h> +#include <linux/delay.h> + +#include <asm/cacheflush.h> +#include <asm/page.h> +#include <asm/setup.h> + +extern const unsigned char relocate_new_kernel[]; +extern const size_t relocate_new_kernel_size; + +int machine_kexec_prepare(struct kimage *kimage) +{ +	return 0; +} + +void machine_kexec_cleanup(struct kimage *kimage) +{ +} + +void machine_shutdown(void) +{ +} + +void machine_crash_shutdown(struct pt_regs *regs) +{ +} + +typedef void (*relocate_kernel_t)(unsigned long ptr, +				  unsigned long start, +				  unsigned long cpu_mmu_flags) __noreturn; + +void machine_kexec(struct kimage *image) +{ +	void *reboot_code_buffer; +	unsigned long cpu_mmu_flags; + +	reboot_code_buffer = page_address(image->control_code_page); + +	memcpy(reboot_code_buffer, relocate_new_kernel, +	       relocate_new_kernel_size); + +	/* +	 * we do not want to be bothered. +	 */ +	local_irq_disable(); + +	pr_info("Will call new kernel at 0x%08lx. Bye...\n", image->start); +	__flush_cache_all(); +	cpu_mmu_flags = m68k_cputype | m68k_mmutype << 8; +	((relocate_kernel_t) reboot_code_buffer)(image->head & PAGE_MASK, +						 image->start, +						 cpu_mmu_flags); +} diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c index cd6bcb1c957..eb46fd6038c 100644 --- a/arch/m68k/kernel/module.c +++ b/arch/m68k/kernel/module.c @@ -19,29 +19,6 @@  #ifdef CONFIG_MODULES -void *module_alloc(unsigned long size) -{ -	if (size == 0) -		return NULL; -	return vmalloc(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ -	vfree(module_region); -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, -			      Elf_Shdr *sechdrs, -			      char *secstrings, -			      struct module *mod) -{ -	return 0; -} -  int apply_relocate(Elf32_Shdr *sechdrs,  		   const char *strtab,  		   unsigned int symindex, @@ -70,7 +47,7 @@ int apply_relocate(Elf32_Shdr *sechdrs,  			*location += sym->st_value;  			break;  		case R_68K_PC32: -			/* Add the value, subtract its postition */ +			/* Add the value, subtract its position */  			*location += sym->st_value - (uint32_t)location;  			break;  		default: @@ -110,7 +87,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,  			*location = rel[i].r_addend + sym->st_value;  			break;  		case R_68K_PC32: -			/* Add the value, subtract its postition */ +			/* Add the value, subtract its position */  			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;  			break;  		default: @@ -127,19 +104,15 @@ int module_finalize(const Elf_Ehdr *hdr,  		    struct module *mod)  {  	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); -  	return 0;  } -void module_arch_cleanup(struct module *mod) -{ -} -  #endif /* CONFIG_MODULES */  void module_fixup(struct module *mod, struct m68k_fixup_info *start,  		  struct m68k_fixup_info *end)  { +#ifdef CONFIG_MMU  	struct m68k_fixup_info *fixup;  	for (fixup = start; fixup < end; fixup++) { @@ -152,4 +125,5 @@ void module_fixup(struct module *mod, struct m68k_fixup_info *start,  			break;  		}  	} +#endif  } diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c new file mode 100644 index 00000000000..931a31ff59d --- /dev/null +++ b/arch/m68k/kernel/pcibios.c @@ -0,0 +1,104 @@ +/* + * pci.c -- basic PCI support code + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + * + * (C) Copyright 2011, Greg Ungerer <gerg@uclinux.org> + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/pci.h> + +/* + * From arch/i386/kernel/pci-i386.c: + * + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + * + * Why? Because some silly external IO cards only decode + * the low 10 bits of the IO address. The 0x00-0xff region + * is reserved for motherboard devices that decode all 16 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff, + * but we want to try to avoid allocating at 0x2900-0x2bff + * which might be mirrored at 0x0100-0x03ff.. + */ +resource_size_t pcibios_align_resource(void *data, const struct resource *res, +	resource_size_t size, resource_size_t align) +{ +	resource_size_t start = res->start; + +	if ((res->flags & IORESOURCE_IO) && (start & 0x300)) +		start = (start + 0x3ff) & ~0x3ff; + +	start = (start + align - 1) & ~(align - 1); + +	return start; +} + +/* + * This is taken from the ARM code for this. + */ +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ +	struct resource *r; +	u16 cmd, newcmd; +	int idx; + +	pci_read_config_word(dev, PCI_COMMAND, &cmd); +	newcmd = cmd; + +	for (idx = 0; idx < 6; idx++) { +		/* Only set up the requested stuff */ +		if (!(mask & (1 << idx))) +			continue; + +		r = dev->resource + idx; +		if (!r->start && r->end) { +			pr_err(KERN_ERR "PCI: Device %s not available because of resource collisions\n", +				pci_name(dev)); +			return -EINVAL; +		} +		if (r->flags & IORESOURCE_IO) +			newcmd |= PCI_COMMAND_IO; +		if (r->flags & IORESOURCE_MEM) +			newcmd |= PCI_COMMAND_MEMORY; +	} + +	/* +	 * Bridges (eg, cardbus bridges) need to be fully enabled +	 */ +	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) +		newcmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + + +	if (newcmd != cmd) { +		pr_info("PCI: enabling device %s (0x%04x -> 0x%04x)\n", +			pci_name(dev), cmd, newcmd); +		pci_write_config_word(dev, PCI_COMMAND, newcmd); +	} +	return 0; +} + +void pcibios_fixup_bus(struct pci_bus *bus) +{ +	struct pci_dev *dev; + +	list_for_each_entry(dev, &bus->devices, bus_list) { +		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); +		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); +	} +} + +char *pcibios_setup(char *str) +{ +	return str; +} + diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 18732ab2329..c55ff719fa7 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -18,7 +18,6 @@  #include <linux/slab.h>  #include <linux/fs.h>  #include <linux/smp.h> -#include <linux/smp_lock.h>  #include <linux/stddef.h>  #include <linux/unistd.h>  #include <linux/ptrace.h> @@ -26,32 +25,17 @@  #include <linux/reboot.h>  #include <linux/init_task.h>  #include <linux/mqueue.h> +#include <linux/rcupdate.h>  #include <asm/uaccess.h> -#include <asm/system.h>  #include <asm/traps.h>  #include <asm/machdep.h>  #include <asm/setup.h>  #include <asm/pgtable.h> -/* - * Initial task/thread structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -union thread_union init_thread_union __init_task_data -	__attribute__((aligned(THREAD_SIZE))) = -		{ INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task);  asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void);  /* @@ -67,40 +51,16 @@ unsigned long thread_saved_pc(struct task_struct *tsk)  		return sw->retpc;  } -/* - * The idle loop on an m68k.. - */ -static void default_idle(void) +void arch_cpu_idle(void)  { -	if (!need_resched())  #if defined(MACH_ATARI_ONLY) -		/* block out HSYNC on the atari (falcon) */ -		__asm__("stop #0x2200" : : : "cc"); +	/* block out HSYNC on the atari (falcon) */ +	__asm__("stop #0x2200" : : : "cc");  #else -		__asm__("stop #0x2000" : : : "cc"); +	__asm__("stop #0x2000" : : : "cc");  #endif  } -void (*idle)(void) = default_idle; - -/* - * The idle thread. There's no useful work to be - * done, so just try to conserve power and have a - * low exit latency (ie sit in a loop waiting for - * somebody to say that they'd like to reschedule) - */ -void cpu_idle(void) -{ -	/* endless idle loop with no priority at all */ -	while (1) { -		while (!need_resched()) -			idle(); -		preempt_enable_no_resched(); -		schedule(); -		preempt_disable(); -	} -} -  void machine_restart(char * __unused)  {  	if (mach_reset) @@ -140,120 +100,47 @@ void show_regs(struct pt_regs * regs)  		printk("USP: %08lx\n", rdusp());  } -/* - * Create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ -	int pid; -	mm_segment_t fs; - -	fs = get_fs(); -	set_fs (KERNEL_DS); - -	{ -	register long retval __asm__ ("d0"); -	register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; - -	retval = __NR_clone; -	__asm__ __volatile__ -	  ("clrl %%d2\n\t" -	   "trap #0\n\t"		/* Linux/m68k system call */ -	   "tstl %0\n\t"		/* child or parent */ -	   "jne 1f\n\t"			/* parent - jump */ -	   "lea %%sp@(%c7),%6\n\t"	/* reload current */ -	   "movel %6@,%6\n\t" -	   "movel %3,%%sp@-\n\t"	/* push argument */ -	   "jsr %4@\n\t"		/* call fn */ -	   "movel %0,%%d1\n\t"		/* pass exit value */ -	   "movel %2,%%d0\n\t"		/* exit */ -	   "trap #0\n" -	   "1:" -	   : "+d" (retval) -	   : "i" (__NR_clone), "i" (__NR_exit), -	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), -	     "i" (-THREAD_SIZE) -	   : "d2"); - -	pid = retval; -	} - -	set_fs (fs); -	return pid; -} -EXPORT_SYMBOL(kernel_thread); -  void flush_thread(void)  { -	unsigned long zero = 0; -	set_fs(USER_DS);  	current->thread.fs = __USER_DS; -	if (!FPU_IS_EMU) -		asm volatile (".chip 68k/68881\n\t" -			      "frestore %0@\n\t" -			      ".chip 68k" : : "a" (&zero)); +#ifdef CONFIG_FPU +	if (!FPU_IS_EMU) { +		unsigned long zero = 0; +		asm volatile("frestore %0": :"m" (zero)); +	} +#endif  }  /* - * "m68k_fork()".. By the time we get here, the - * non-volatile registers have also been saved on the - * stack. We do some ugly pointer stuff here.. (see - * also copy_thread) + * Why not generic sys_clone, you ask?  m68k passes all arguments on stack. + * And we need all registers saved, which means a bunch of stuff pushed + * on top of pt_regs, which means that sys_clone() arguments would be + * buried.  We could, of course, copy them, but it's too costly for no + * good reason - generic clone() would have to copy them *again* for + * do_fork() anyway.  So in this case it's actually better to pass pt_regs * + * and extract arguments for do_fork() from there.  Eventually we might + * go for calling do_fork() directly from the wrapper, but only after we + * are finished with do_fork() prototype conversion.   */ - -asmlinkage int m68k_fork(struct pt_regs *regs) -{ -	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); -} - -asmlinkage int m68k_vfork(struct pt_regs *regs) -{ -	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, -		       NULL, NULL); -} -  asmlinkage int m68k_clone(struct pt_regs *regs)  { -	unsigned long clone_flags; -	unsigned long newsp; -	int __user *parent_tidptr, *child_tidptr; - -	/* syscall2 puts clone_flags in d1 and usp in d2 */ -	clone_flags = regs->d1; -	newsp = regs->d2; -	parent_tidptr = (int __user *)regs->d3; -	child_tidptr = (int __user *)regs->d4; -	if (!newsp) -		newsp = rdusp(); -	return do_fork(clone_flags, newsp, regs, 0, -		       parent_tidptr, child_tidptr); +	/* regs will be equal to current_pt_regs() */ +	return do_fork(regs->d1, regs->d2, 0, +		       (int __user *)regs->d3, (int __user *)regs->d4);  }  int copy_thread(unsigned long clone_flags, unsigned long usp, -		 unsigned long unused, -		 struct task_struct * p, struct pt_regs * regs) +		 unsigned long arg, struct task_struct *p)  { -	struct pt_regs * childregs; -	struct switch_stack * childstack, *stack; -	unsigned long *retp; - -	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; +	struct fork_frame { +		struct switch_stack sw; +		struct pt_regs regs; +	} *frame; -	*childregs = *regs; -	childregs->d0 = 0; +	frame = (struct fork_frame *) (task_stack_page(p) + THREAD_SIZE) - 1; -	retp = ((unsigned long *) regs); -	stack = ((struct switch_stack *) retp) - 1; - -	childstack = ((struct switch_stack *) childregs) - 1; -	*childstack = *stack; -	childstack->retpc = (unsigned long)ret_from_fork; - -	p->thread.usp = usp; -	p->thread.ksp = (unsigned long)childstack; - -	if (clone_flags & CLONE_SETTLS) -		task_thread_info(p)->tp_value = regs->d5; +	p->thread.ksp = (unsigned long)frame; +	p->thread.esp0 = (unsigned long)&frame->regs;  	/*  	 * Must save the current SFC/DFC value, NOT the value when @@ -261,24 +148,62 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  	 */  	p->thread.fs = get_fs().seg; +	if (unlikely(p->flags & PF_KTHREAD)) { +		/* kernel thread */ +		memset(frame, 0, sizeof(struct fork_frame)); +		frame->regs.sr = PS_S; +		frame->sw.a3 = usp; /* function */ +		frame->sw.d7 = arg; +		frame->sw.retpc = (unsigned long)ret_from_kernel_thread; +		p->thread.usp = 0; +		return 0; +	} +	memcpy(frame, container_of(current_pt_regs(), struct fork_frame, regs), +		sizeof(struct fork_frame)); +	frame->regs.d0 = 0; +	frame->sw.retpc = (unsigned long)ret_from_fork; +	p->thread.usp = usp ?: rdusp(); + +	if (clone_flags & CLONE_SETTLS) +		task_thread_info(p)->tp_value = frame->regs.d5; + +#ifdef CONFIG_FPU  	if (!FPU_IS_EMU) {  		/* Copy the current fpu state */  		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); -		if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) -		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" -				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1" -				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) -				: "memory"); +		if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) { +			if (CPU_IS_COLDFIRE) { +				asm volatile ("fmovemd %/fp0-%/fp7,%0\n\t" +					      "fmovel %/fpiar,%1\n\t" +					      "fmovel %/fpcr,%2\n\t" +					      "fmovel %/fpsr,%3" +					      : +					      : "m" (p->thread.fp[0]), +						"m" (p->thread.fpcntl[0]), +						"m" (p->thread.fpcntl[1]), +						"m" (p->thread.fpcntl[2]) +					      : "memory"); +			} else { +				asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" +					      "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" +					      : +					      : "m" (p->thread.fp[0]), +						"m" (p->thread.fpcntl[0]) +					      : "memory"); +			} +		} +  		/* Restore the state in case the fpu was busy */  		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));  	} +#endif /* CONFIG_FPU */  	return 0;  }  /* Fill in the fpu structure for a core dump.  */ - +#ifdef CONFIG_FPU  int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)  {  	char fpustate[216]; @@ -302,35 +227,32 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)  	if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])  		return 0; -	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" -		:: "m" (fpu->fpcntl[0]) -		: "memory"); -	asm volatile ("fmovemx %/fp0-%/fp7,%0" -		:: "m" (fpu->fpregs[0]) -		: "memory"); +	if (CPU_IS_COLDFIRE) { +		asm volatile ("fmovel %/fpiar,%0\n\t" +			      "fmovel %/fpcr,%1\n\t" +			      "fmovel %/fpsr,%2\n\t" +			      "fmovemd %/fp0-%/fp7,%3" +			      : +			      : "m" (fpu->fpcntl[0]), +				"m" (fpu->fpcntl[1]), +				"m" (fpu->fpcntl[2]), +				"m" (fpu->fpregs[0]) +			      : "memory"); +	} else { +		asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" +			      : +			      : "m" (fpu->fpcntl[0]) +			      : "memory"); +		asm volatile ("fmovemx %/fp0-%/fp7,%0" +			      : +			      : "m" (fpu->fpregs[0]) +			      : "memory"); +	} +  	return 1;  }  EXPORT_SYMBOL(dump_fpu); - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *name, -			  const char __user *const __user *argv, -			  const char __user *const __user *envp) -{ -	int error; -	char * filename; -	struct pt_regs *regs = (struct pt_regs *) &name; - -	filename = getname(name); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		return error; -	error = do_execve(filename, argv, envp, regs); -	putname(filename); -	return error; -} +#endif /* CONFIG_FPU */  unsigned long get_wchan(struct task_struct *p)  { diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 0b252683cef..1bc10e62b9a 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -18,11 +18,11 @@  #include <linux/ptrace.h>  #include <linux/user.h>  #include <linux/signal.h> +#include <linux/tracehook.h>  #include <asm/uaccess.h>  #include <asm/page.h>  #include <asm/pgtable.h> -#include <asm/system.h>  #include <asm/processor.h>  /* @@ -145,11 +145,13 @@ void user_enable_single_step(struct task_struct *child)  	set_tsk_thread_flag(child, TIF_DELAYED_TRACE);  } +#ifdef CONFIG_MMU  void user_enable_block_step(struct task_struct *child)  {  	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;  	put_reg(child, PT_SR, tmp | T0_BIT);  } +#endif  void user_disable_single_step(struct task_struct *child)  { @@ -180,6 +182,14 @@ long arch_ptrace(struct task_struct *child, long request,  			if (FPU_IS_EMU && (regno < 45) && !(regno % 3))  				tmp = ((tmp & 0xffff0000) << 15) |  				      ((tmp & 0x0000ffff) << 16); +#ifndef CONFIG_MMU +		} else if (regno == 49) { +			tmp = child->mm->start_code; +		} else if (regno == 50) { +			tmp = child->mm->start_data; +		} else if (regno == 51) { +			tmp = child->mm->end_code; +#endif  		} else  			goto out_eio;  		ret = put_user(tmp, datap); @@ -275,3 +285,20 @@ asmlinkage void syscall_trace(void)  		current->exit_code = 0;  	}  } + +#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) +asmlinkage int syscall_trace_enter(void) +{ +	int ret = 0; + +	if (test_thread_flag(TIF_SYSCALL_TRACE)) +		ret = tracehook_report_syscall_entry(task_pt_regs(current)); +	return ret; +} + +asmlinkage void syscall_trace_leave(void) +{ +	if (test_thread_flag(TIF_SYSCALL_TRACE)) +		tracehook_report_syscall_exit(task_pt_regs(current), 0); +} +#endif /* CONFIG_COLDFIRE */ diff --git a/arch/m68k/kernel/relocate_kernel.S b/arch/m68k/kernel/relocate_kernel.S new file mode 100644 index 00000000000..3e09a89067a --- /dev/null +++ b/arch/m68k/kernel/relocate_kernel.S @@ -0,0 +1,159 @@ +#include <linux/linkage.h> + +#include <asm/asm-offsets.h> +#include <asm/page.h> +#include <asm/setup.h> + + +#define MMU_BASE	8		/* MMU flags base in cpu_mmu_flags */ + +.text + +ENTRY(relocate_new_kernel) +	movel %sp@(4),%a0		/* a0 = ptr */ +	movel %sp@(8),%a1		/* a1 = start */ +	movel %sp@(12),%d1		/* d1 = cpu_mmu_flags */ +	movew #PAGE_MASK,%d2		/* d2 = PAGE_MASK */ + +	/* Disable MMU */ + +	btst #MMU_BASE + MMUB_68851,%d1 +	jeq 3f + +1:	/* 68851 or 68030 */ + +	lea %pc@(.Lcopy),%a4 +2:	addl #0x00000000,%a4		/* virt_to_phys() */ + +	.section ".m68k_fixup","aw" +	.long M68K_FIXUP_MEMOFFSET, 2b+2 +	.previous + +	.chip 68030 +	pmove %tc,%d0			/* Disable MMU */ +	bclr #7,%d0 +	pmove %d0,%tc +	jmp %a4@			/* Jump to physical .Lcopy */ +	.chip 68k + +3: +	btst #MMU_BASE + MMUB_68030,%d1 +	jne 1b + +	btst #MMU_BASE + MMUB_68040,%d1 +	jeq 6f + +4:	/* 68040 or 68060 */ + +	lea %pc@(.Lcont040),%a4 +5:	addl #0x00000000,%a4		/* virt_to_phys() */ + +	.section ".m68k_fixup","aw" +	.long M68K_FIXUP_MEMOFFSET, 5b+2 +	.previous + +	movel %a4,%d0 +	andl #0xff000000,%d0 +	orw #0xe020,%d0			/* Map 16 MiB, enable, cacheable */ +	.chip 68040 +	movec %d0,%itt0 +	movec %d0,%dtt0 +	.chip 68k +	jmp %a4@			/* Jump to physical .Lcont040 */ + +.Lcont040: +	moveq #0,%d0 +	.chip 68040 +	movec %d0,%tc			/* Disable MMU */ +	movec %d0,%itt0 +	movec %d0,%itt1 +	movec %d0,%dtt0 +	movec %d0,%dtt1 +	.chip 68k +	jra .Lcopy + +6: +	btst #MMU_BASE + MMUB_68060,%d1 +	jne 4b + +.Lcopy: +	movel %a0@+,%d0			/* d0 = entry = *ptr */ +	jeq .Lflush + +	btst #2,%d0			/* entry & IND_DONE? */ +	jne .Lflush + +	btst #1,%d0			/* entry & IND_INDIRECTION? */ +	jeq 1f +	andw %d2,%d0 +	movel %d0,%a0			/* ptr = entry & PAGE_MASK */ +	jra .Lcopy + +1: +	btst #0,%d0			/* entry & IND_DESTINATION? */ +	jeq 2f +	andw %d2,%d0 +	movel %d0,%a2			/* a2 = dst = entry & PAGE_MASK */ +	jra .Lcopy + +2: +	btst #3,%d0			/* entry & IND_SOURCE? */ +	jeq .Lcopy + +	andw %d2,%d0 +	movel %d0,%a3			/* a3 = src = entry & PAGE_MASK */ +	movew #PAGE_SIZE/32 - 1,%d0	/* d0 = PAGE_SIZE/32 - 1 */ +3: +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	movel %a3@+,%a2@+		/* *dst++ = *src++ */ +	dbf %d0, 3b +	jra .Lcopy + +.Lflush: +	/* Flush all caches */ + +	btst #CPUB_68020,%d1 +	jeq 2f + +1:	/* 68020 or 68030 */ +	.chip 68030 +	movec %cacr,%d0 +	orw #0x808,%d0 +	movec %d0,%cacr +	.chip 68k +	jra .Lreincarnate + +2: +	btst #CPUB_68030,%d1 +	jne 1b + +	btst #CPUB_68040,%d1 +	jeq 4f + +3:	/* 68040 or 68060 */ +	.chip 68040 +	nop +	cpusha %bc +	nop +	cinva %bc +	nop +	.chip 68k +	jra .Lreincarnate + +4: +	btst #CPUB_68060,%d1 +	jne 3b + +.Lreincarnate: +	jmp %a1@ + +relocate_new_kernel_end: + +ENTRY(relocate_new_kernel_size) +	.long relocate_new_kernel_end - relocate_new_kernel diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index b3963ab3d14..4bf129f1d2e 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -1,528 +1,5 @@ -/* - *  linux/arch/m68k/kernel/setup.c - * - *  Copyright (C) 1995  Hamish Macdonald - */ - -/* - * This file handles the architecture-dependent parts of system setup - */ - -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/console.h> -#include <linux/genhd.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/bootmem.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/module.h> -#include <linux/initrd.h> - -#include <asm/bootinfo.h> -#include <asm/sections.h> -#include <asm/setup.h> -#include <asm/fpu.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/machdep.h> -#ifdef CONFIG_AMIGA -#include <asm/amigahw.h> -#endif -#ifdef CONFIG_ATARI -#include <asm/atarihw.h> -#include <asm/atari_stram.h> -#endif -#ifdef CONFIG_SUN3X -#include <asm/dvma.h> -#endif - -#if !FPSTATESIZE || !NR_IRQS -#warning No CPU/platform type selected, your kernel will not work! -#warning Are you building an allnoconfig kernel? -#endif - -unsigned long m68k_machtype; -EXPORT_SYMBOL(m68k_machtype); -unsigned long m68k_cputype; -EXPORT_SYMBOL(m68k_cputype); -unsigned long m68k_fputype; -unsigned long m68k_mmutype; -EXPORT_SYMBOL(m68k_mmutype); -#ifdef CONFIG_VME -unsigned long vme_brdtype; -EXPORT_SYMBOL(vme_brdtype); -#endif - -int m68k_is040or060; -EXPORT_SYMBOL(m68k_is040or060); - -extern unsigned long availmem; - -int m68k_num_memory; -EXPORT_SYMBOL(m68k_num_memory); -int m68k_realnum_memory; -EXPORT_SYMBOL(m68k_realnum_memory); -unsigned long m68k_memoffset; -struct mem_info m68k_memory[NUM_MEMINFO]; -EXPORT_SYMBOL(m68k_memory); - -struct mem_info m68k_ramdisk; - -static char m68k_command_line[CL_SIZE]; - -void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; -/* machine dependent irq functions */ -void (*mach_init_IRQ) (void) __initdata = NULL; -void (*mach_get_model) (char *model); -void (*mach_get_hardware_list) (struct seq_file *m); -/* machine dependent timer functions */ -unsigned long (*mach_gettimeoffset) (void); -int (*mach_hwclk) (int, struct rtc_time*); -EXPORT_SYMBOL(mach_hwclk); -int (*mach_set_clock_mmss) (unsigned long); -unsigned int (*mach_get_ss)(void); -int (*mach_get_rtc_pll)(struct rtc_pll_info *); -int (*mach_set_rtc_pll)(struct rtc_pll_info *); -EXPORT_SYMBOL(mach_get_ss); -EXPORT_SYMBOL(mach_get_rtc_pll); -EXPORT_SYMBOL(mach_set_rtc_pll); -void (*mach_reset)( void ); -void (*mach_halt)( void ); -void (*mach_power_off)( void ); -long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#ifdef CONFIG_HEARTBEAT -void (*mach_heartbeat) (int); -EXPORT_SYMBOL(mach_heartbeat); -#endif -#ifdef CONFIG_M68K_L2_CACHE -void (*mach_l2_flush) (int); -#endif -#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) -void (*mach_beep)(unsigned int, unsigned int); -EXPORT_SYMBOL(mach_beep); -#endif -#if defined(CONFIG_ISA) && defined(MULTI_ISA) -int isa_type; -int isa_sex; -EXPORT_SYMBOL(isa_type); -EXPORT_SYMBOL(isa_sex); -#endif - -extern int amiga_parse_bootinfo(const struct bi_record *); -extern int atari_parse_bootinfo(const struct bi_record *); -extern int mac_parse_bootinfo(const struct bi_record *); -extern int q40_parse_bootinfo(const struct bi_record *); -extern int bvme6000_parse_bootinfo(const struct bi_record *); -extern int mvme16x_parse_bootinfo(const struct bi_record *); -extern int mvme147_parse_bootinfo(const struct bi_record *); -extern int hp300_parse_bootinfo(const struct bi_record *); -extern int apollo_parse_bootinfo(const struct bi_record *); - -extern void config_amiga(void); -extern void config_atari(void); -extern void config_mac(void); -extern void config_sun3(void); -extern void config_apollo(void); -extern void config_mvme147(void); -extern void config_mvme16x(void); -extern void config_bvme6000(void); -extern void config_hp300(void); -extern void config_q40(void); -extern void config_sun3x(void); - -#define MASK_256K 0xfffc0000 - -extern void paging_init(void); - -static void __init m68k_parse_bootinfo(const struct bi_record *record) -{ -	while (record->tag != BI_LAST) { -		int unknown = 0; -		const unsigned long *data = record->data; - -		switch (record->tag) { -		case BI_MACHTYPE: -		case BI_CPUTYPE: -		case BI_FPUTYPE: -		case BI_MMUTYPE: -			/* Already set up by head.S */ -			break; - -		case BI_MEMCHUNK: -			if (m68k_num_memory < NUM_MEMINFO) { -				m68k_memory[m68k_num_memory].addr = data[0]; -				m68k_memory[m68k_num_memory].size = data[1]; -				m68k_num_memory++; -			} else -				printk("m68k_parse_bootinfo: too many memory chunks\n"); -			break; - -		case BI_RAMDISK: -			m68k_ramdisk.addr = data[0]; -			m68k_ramdisk.size = data[1]; -			break; - -		case BI_COMMAND_LINE: -			strlcpy(m68k_command_line, (const char *)data, -				sizeof(m68k_command_line)); -			break; - -		default: -			if (MACH_IS_AMIGA) -				unknown = amiga_parse_bootinfo(record); -			else if (MACH_IS_ATARI) -				unknown = atari_parse_bootinfo(record); -			else if (MACH_IS_MAC) -				unknown = mac_parse_bootinfo(record); -			else if (MACH_IS_Q40) -				unknown = q40_parse_bootinfo(record); -			else if (MACH_IS_BVME6000) -				unknown = bvme6000_parse_bootinfo(record); -			else if (MACH_IS_MVME16x) -				unknown = mvme16x_parse_bootinfo(record); -			else if (MACH_IS_MVME147) -				unknown = mvme147_parse_bootinfo(record); -			else if (MACH_IS_HP300) -				unknown = hp300_parse_bootinfo(record); -			else if (MACH_IS_APOLLO) -				unknown = apollo_parse_bootinfo(record); -			else -				unknown = 1; -		} -		if (unknown) -			printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n", -			       record->tag); -		record = (struct bi_record *)((unsigned long)record + -					      record->size); -	} - -	m68k_realnum_memory = m68k_num_memory; -#ifdef CONFIG_SINGLE_MEMORY_CHUNK -	if (m68k_num_memory > 1) { -		printk("Ignoring last %i chunks of physical memory\n", -		       (m68k_num_memory - 1)); -		m68k_num_memory = 1; -	} -#endif -} - -void __init setup_arch(char **cmdline_p) -{ -	int i; - -	/* The bootinfo is located right after the kernel bss */ -	m68k_parse_bootinfo((const struct bi_record *)_end); - -	if (CPU_IS_040) -		m68k_is040or060 = 4; -	else if (CPU_IS_060) -		m68k_is040or060 = 6; - -	/* FIXME: m68k_fputype is passed in by Penguin booter, which can -	 * be confused by software FPU emulation. BEWARE. -	 * We should really do our own FPU check at startup. -	 * [what do we do with buggy 68LC040s? if we have problems -	 *  with them, we should add a test to check_bugs() below] */ -#ifndef CONFIG_M68KFPU_EMU_ONLY -	/* clear the fpu if we have one */ -	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) { -		volatile int zero = 0; -		asm volatile ("frestore %0" : : "m" (zero)); -	} -#endif - -	if (CPU_IS_060) { -		u32 pcr; - -		asm (".chip 68060; movec %%pcr,%0; .chip 68k" -		     : "=d" (pcr)); -		if (((pcr >> 8) & 0xff) <= 5) { -			printk("Enabling workaround for errata I14\n"); -			asm (".chip 68060; movec %0,%%pcr; .chip 68k" -			     : : "d" (pcr | 0x20)); -		} -	} - -	init_mm.start_code = PAGE_OFFSET; -	init_mm.end_code = (unsigned long)_etext; -	init_mm.end_data = (unsigned long)_edata; -	init_mm.brk = (unsigned long)_end; - -	*cmdline_p = m68k_command_line; -	memcpy(boot_command_line, *cmdline_p, CL_SIZE); - -	parse_early_param(); - -#ifdef CONFIG_DUMMY_CONSOLE -	conswitchp = &dummy_con; -#endif - -	switch (m68k_machtype) { -#ifdef CONFIG_AMIGA -	case MACH_AMIGA: -		config_amiga(); -		break; -#endif -#ifdef CONFIG_ATARI -	case MACH_ATARI: -		config_atari(); -		break; -#endif -#ifdef CONFIG_MAC -	case MACH_MAC: -		config_mac(); -		break; -#endif -#ifdef CONFIG_SUN3 -	case MACH_SUN3: -		config_sun3(); -		break; -#endif -#ifdef CONFIG_APOLLO -	case MACH_APOLLO: -		config_apollo(); -		break; -#endif -#ifdef CONFIG_MVME147 -	case MACH_MVME147: -		config_mvme147(); -		break; -#endif -#ifdef CONFIG_MVME16x -	case MACH_MVME16x: -		config_mvme16x(); -		break; -#endif -#ifdef CONFIG_BVME6000 -	case MACH_BVME6000: -		config_bvme6000(); -		break; -#endif -#ifdef CONFIG_HP300 -	case MACH_HP300: -		config_hp300(); -		break; -#endif -#ifdef CONFIG_Q40 -	case MACH_Q40: -		config_q40(); -		break; -#endif -#ifdef CONFIG_SUN3X -	case MACH_SUN3X: -		config_sun3x(); -		break; -#endif -	default: -		panic("No configuration setup"); -	} - -	paging_init(); - -#ifndef CONFIG_SUN3 -	for (i = 1; i < m68k_num_memory; i++) -		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, -				  m68k_memory[i].size); -#ifdef CONFIG_BLK_DEV_INITRD -	if (m68k_ramdisk.size) { -		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)), -				     m68k_ramdisk.addr, m68k_ramdisk.size, -				     BOOTMEM_DEFAULT); -		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); -		initrd_end = initrd_start + m68k_ramdisk.size; -		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end); -	} -#endif - -#ifdef CONFIG_ATARI -	if (MACH_IS_ATARI) -		atari_stram_reserve_pages((void *)availmem); -#endif -#ifdef CONFIG_SUN3X -	if (MACH_IS_SUN3X) { -		dvma_init(); -	} -#endif - -#endif /* !CONFIG_SUN3 */ - -/* set ISA defs early as possible */ -#if defined(CONFIG_ISA) && defined(MULTI_ISA) -	if (MACH_IS_Q40) { -		isa_type = ISA_TYPE_Q40; -		isa_sex = 0; -	} -#ifdef CONFIG_AMIGA_PCMCIA -	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) { -		isa_type = ISA_TYPE_AG; -		isa_sex = 1; -	} -#endif -#endif -} - -static int show_cpuinfo(struct seq_file *m, void *v) -{ -	const char *cpu, *mmu, *fpu; -	unsigned long clockfreq, clockfactor; - -#define LOOP_CYCLES_68020	(8) -#define LOOP_CYCLES_68030	(8) -#define LOOP_CYCLES_68040	(3) -#define LOOP_CYCLES_68060	(1) - -	if (CPU_IS_020) { -		cpu = "68020"; -		clockfactor = LOOP_CYCLES_68020; -	} else if (CPU_IS_030) { -		cpu = "68030"; -		clockfactor = LOOP_CYCLES_68030; -	} else if (CPU_IS_040) { -		cpu = "68040"; -		clockfactor = LOOP_CYCLES_68040; -	} else if (CPU_IS_060) { -		cpu = "68060"; -		clockfactor = LOOP_CYCLES_68060; -	} else { -		cpu = "680x0"; -		clockfactor = 0; -	} - -#ifdef CONFIG_M68KFPU_EMU_ONLY -	fpu = "none(soft float)"; +#ifdef CONFIG_MMU +#include "setup_mm.c"  #else -	if (m68k_fputype & FPU_68881) -		fpu = "68881"; -	else if (m68k_fputype & FPU_68882) -		fpu = "68882"; -	else if (m68k_fputype & FPU_68040) -		fpu = "68040"; -	else if (m68k_fputype & FPU_68060) -		fpu = "68060"; -	else if (m68k_fputype & FPU_SUNFPA) -		fpu = "Sun FPA"; -	else -		fpu = "none"; -#endif - -	if (m68k_mmutype & MMU_68851) -		mmu = "68851"; -	else if (m68k_mmutype & MMU_68030) -		mmu = "68030"; -	else if (m68k_mmutype & MMU_68040) -		mmu = "68040"; -	else if (m68k_mmutype & MMU_68060) -		mmu = "68060"; -	else if (m68k_mmutype & MMU_SUN3) -		mmu = "Sun-3"; -	else if (m68k_mmutype & MMU_APOLLO) -		mmu = "Apollo"; -	else -		mmu = "unknown"; - -	clockfreq = loops_per_jiffy * HZ * clockfactor; - -	seq_printf(m, "CPU:\t\t%s\n" -		   "MMU:\t\t%s\n" -		   "FPU:\t\t%s\n" -		   "Clocking:\t%lu.%1luMHz\n" -		   "BogoMips:\t%lu.%02lu\n" -		   "Calibration:\t%lu loops\n", -		   cpu, mmu, fpu, -		   clockfreq/1000000,(clockfreq/100000)%10, -		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100, -		   loops_per_jiffy); -	return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ -	return *pos < 1 ? (void *)1 : NULL; -} -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ -	++*pos; -	return NULL; -} -static void c_stop(struct seq_file *m, void *v) -{ -} -const struct seq_operations cpuinfo_op = { -	.start	= c_start, -	.next	= c_next, -	.stop	= c_stop, -	.show	= show_cpuinfo, -}; - -#ifdef CONFIG_PROC_HARDWARE -static int hardware_proc_show(struct seq_file *m, void *v) -{ -	char model[80]; -	unsigned long mem; -	int i; - -	if (mach_get_model) -		mach_get_model(model); -	else -		strcpy(model, "Unknown m68k"); - -	seq_printf(m, "Model:\t\t%s\n", model); -	for (mem = 0, i = 0; i < m68k_num_memory; i++) -		mem += m68k_memory[i].size; -	seq_printf(m, "System Memory:\t%ldK\n", mem >> 10); - -	if (mach_get_hardware_list) -		mach_get_hardware_list(m); - -	return 0; -} - -static int hardware_proc_open(struct inode *inode, struct file *file) -{ -	return single_open(file, hardware_proc_show, NULL); -} - -static const struct file_operations hardware_proc_fops = { -	.open		= hardware_proc_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= single_release, -}; - -static int __init proc_hardware_init(void) -{ -	proc_create("hardware", 0, NULL, &hardware_proc_fops); -	return 0; -} -module_init(proc_hardware_init); +#include "setup_no.c"  #endif - -void check_bugs(void) -{ -#ifndef CONFIG_M68KFPU_EMU -	if (m68k_fputype == 0) { -		printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, " -			"WHICH IS REQUIRED BY LINUX/M68K ***\n"); -		printk(KERN_EMERG "Upgrade your hardware or join the FPU " -			"emulation project\n"); -		panic("no FPU"); -	} -#endif /* !CONFIG_M68KFPU_EMU */ -} - -#ifdef CONFIG_ADB -static int __init adb_probe_sync_enable (char *str) { -	extern int __adb_probe_sync; -	__adb_probe_sync = 1; -	return 1; -} - -__setup("adb_sync", adb_probe_sync_enable); -#endif /* CONFIG_ADB */ diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c new file mode 100644 index 00000000000..5b8ec4d5f8e --- /dev/null +++ b/arch/m68k/kernel/setup_mm.c @@ -0,0 +1,570 @@ +/* + *  linux/arch/m68k/kernel/setup.c + * + *  Copyright (C) 1995  Hamish Macdonald + */ + +/* + * This file handles the architecture-dependent parts of system setup + */ + +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fs.h> +#include <linux/console.h> +#include <linux/genhd.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/bootmem.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/module.h> +#include <linux/initrd.h> + +#include <asm/bootinfo.h> +#include <asm/byteorder.h> +#include <asm/sections.h> +#include <asm/setup.h> +#include <asm/fpu.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/machdep.h> +#ifdef CONFIG_AMIGA +#include <asm/amigahw.h> +#endif +#ifdef CONFIG_ATARI +#include <asm/atarihw.h> +#include <asm/atari_stram.h> +#endif +#ifdef CONFIG_SUN3X +#include <asm/dvma.h> +#endif +#include <asm/natfeat.h> + +#if !FPSTATESIZE || !NR_IRQS +#warning No CPU/platform type selected, your kernel will not work! +#warning Are you building an allnoconfig kernel? +#endif + +unsigned long m68k_machtype; +EXPORT_SYMBOL(m68k_machtype); +unsigned long m68k_cputype; +EXPORT_SYMBOL(m68k_cputype); +unsigned long m68k_fputype; +unsigned long m68k_mmutype; +EXPORT_SYMBOL(m68k_mmutype); +#ifdef CONFIG_VME +unsigned long vme_brdtype; +EXPORT_SYMBOL(vme_brdtype); +#endif + +int m68k_is040or060; +EXPORT_SYMBOL(m68k_is040or060); + +extern unsigned long availmem; + +int m68k_num_memory; +EXPORT_SYMBOL(m68k_num_memory); +int m68k_realnum_memory; +EXPORT_SYMBOL(m68k_realnum_memory); +unsigned long m68k_memoffset; +struct m68k_mem_info m68k_memory[NUM_MEMINFO]; +EXPORT_SYMBOL(m68k_memory); + +static struct m68k_mem_info m68k_ramdisk __initdata; + +static char m68k_command_line[CL_SIZE] __initdata; + +void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; +/* machine dependent irq functions */ +void (*mach_init_IRQ) (void) __initdata = NULL; +void (*mach_get_model) (char *model); +void (*mach_get_hardware_list) (struct seq_file *m); +/* machine dependent timer functions */ +int (*mach_hwclk) (int, struct rtc_time*); +EXPORT_SYMBOL(mach_hwclk); +int (*mach_set_clock_mmss) (unsigned long); +unsigned int (*mach_get_ss)(void); +int (*mach_get_rtc_pll)(struct rtc_pll_info *); +int (*mach_set_rtc_pll)(struct rtc_pll_info *); +EXPORT_SYMBOL(mach_get_ss); +EXPORT_SYMBOL(mach_get_rtc_pll); +EXPORT_SYMBOL(mach_set_rtc_pll); +void (*mach_reset)( void ); +void (*mach_halt)( void ); +void (*mach_power_off)( void ); +long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ +#ifdef CONFIG_HEARTBEAT +void (*mach_heartbeat) (int); +EXPORT_SYMBOL(mach_heartbeat); +#endif +#ifdef CONFIG_M68K_L2_CACHE +void (*mach_l2_flush) (int); +#endif +#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) +void (*mach_beep)(unsigned int, unsigned int); +EXPORT_SYMBOL(mach_beep); +#endif +#if defined(CONFIG_ISA) && defined(MULTI_ISA) +int isa_type; +int isa_sex; +EXPORT_SYMBOL(isa_type); +EXPORT_SYMBOL(isa_sex); +#endif + +extern int amiga_parse_bootinfo(const struct bi_record *); +extern int atari_parse_bootinfo(const struct bi_record *); +extern int mac_parse_bootinfo(const struct bi_record *); +extern int q40_parse_bootinfo(const struct bi_record *); +extern int bvme6000_parse_bootinfo(const struct bi_record *); +extern int mvme16x_parse_bootinfo(const struct bi_record *); +extern int mvme147_parse_bootinfo(const struct bi_record *); +extern int hp300_parse_bootinfo(const struct bi_record *); +extern int apollo_parse_bootinfo(const struct bi_record *); + +extern void config_amiga(void); +extern void config_atari(void); +extern void config_mac(void); +extern void config_sun3(void); +extern void config_apollo(void); +extern void config_mvme147(void); +extern void config_mvme16x(void); +extern void config_bvme6000(void); +extern void config_hp300(void); +extern void config_q40(void); +extern void config_sun3x(void); + +#define MASK_256K 0xfffc0000 + +extern void paging_init(void); + +static void __init m68k_parse_bootinfo(const struct bi_record *record) +{ +	uint16_t tag; + +	save_bootinfo(record); + +	while ((tag = be16_to_cpu(record->tag)) != BI_LAST) { +		int unknown = 0; +		const void *data = record->data; +		uint16_t size = be16_to_cpu(record->size); + +		switch (tag) { +		case BI_MACHTYPE: +		case BI_CPUTYPE: +		case BI_FPUTYPE: +		case BI_MMUTYPE: +			/* Already set up by head.S */ +			break; + +		case BI_MEMCHUNK: +			if (m68k_num_memory < NUM_MEMINFO) { +				const struct mem_info *m = data; +				m68k_memory[m68k_num_memory].addr = +					be32_to_cpu(m->addr); +				m68k_memory[m68k_num_memory].size = +					be32_to_cpu(m->size); +				m68k_num_memory++; +			} else +				pr_warn("%s: too many memory chunks\n", +					__func__); +			break; + +		case BI_RAMDISK: +			{ +				const struct mem_info *m = data; +				m68k_ramdisk.addr = be32_to_cpu(m->addr); +				m68k_ramdisk.size = be32_to_cpu(m->size); +			} +			break; + +		case BI_COMMAND_LINE: +			strlcpy(m68k_command_line, data, +				sizeof(m68k_command_line)); +			break; + +		default: +			if (MACH_IS_AMIGA) +				unknown = amiga_parse_bootinfo(record); +			else if (MACH_IS_ATARI) +				unknown = atari_parse_bootinfo(record); +			else if (MACH_IS_MAC) +				unknown = mac_parse_bootinfo(record); +			else if (MACH_IS_Q40) +				unknown = q40_parse_bootinfo(record); +			else if (MACH_IS_BVME6000) +				unknown = bvme6000_parse_bootinfo(record); +			else if (MACH_IS_MVME16x) +				unknown = mvme16x_parse_bootinfo(record); +			else if (MACH_IS_MVME147) +				unknown = mvme147_parse_bootinfo(record); +			else if (MACH_IS_HP300) +				unknown = hp300_parse_bootinfo(record); +			else if (MACH_IS_APOLLO) +				unknown = apollo_parse_bootinfo(record); +			else +				unknown = 1; +		} +		if (unknown) +			pr_warn("%s: unknown tag 0x%04x ignored\n", __func__, +				tag); +		record = (struct bi_record *)((unsigned long)record + size); +	} + +	m68k_realnum_memory = m68k_num_memory; +#ifdef CONFIG_SINGLE_MEMORY_CHUNK +	if (m68k_num_memory > 1) { +		pr_warn("%s: ignoring last %i chunks of physical memory\n", +			__func__, (m68k_num_memory - 1)); +		m68k_num_memory = 1; +	} +#endif +} + +void __init setup_arch(char **cmdline_p) +{ +#ifndef CONFIG_SUN3 +	int i; +#endif + +	/* The bootinfo is located right after the kernel */ +	if (!CPU_IS_COLDFIRE) +		m68k_parse_bootinfo((const struct bi_record *)_end); + +	if (CPU_IS_040) +		m68k_is040or060 = 4; +	else if (CPU_IS_060) +		m68k_is040or060 = 6; + +	/* FIXME: m68k_fputype is passed in by Penguin booter, which can +	 * be confused by software FPU emulation. BEWARE. +	 * We should really do our own FPU check at startup. +	 * [what do we do with buggy 68LC040s? if we have problems +	 *  with them, we should add a test to check_bugs() below] */ +#ifndef CONFIG_M68KFPU_EMU_ONLY +	/* clear the fpu if we have one */ +	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060|FPU_COLDFIRE)) { +		volatile int zero = 0; +		asm volatile ("frestore %0" : : "m" (zero)); +	} +#endif + +	if (CPU_IS_060) { +		u32 pcr; + +		asm (".chip 68060; movec %%pcr,%0; .chip 68k" +		     : "=d" (pcr)); +		if (((pcr >> 8) & 0xff) <= 5) { +			pr_warn("Enabling workaround for errata I14\n"); +			asm (".chip 68060; movec %0,%%pcr; .chip 68k" +			     : : "d" (pcr | 0x20)); +		} +	} + +	init_mm.start_code = PAGE_OFFSET; +	init_mm.end_code = (unsigned long)_etext; +	init_mm.end_data = (unsigned long)_edata; +	init_mm.brk = (unsigned long)_end; + +#if defined(CONFIG_BOOTPARAM) +	strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE); +	m68k_command_line[CL_SIZE - 1] = 0; +#endif /* CONFIG_BOOTPARAM */ +	*cmdline_p = m68k_command_line; +	memcpy(boot_command_line, *cmdline_p, CL_SIZE); + +	parse_early_param(); + +#ifdef CONFIG_DUMMY_CONSOLE +	conswitchp = &dummy_con; +#endif + +	switch (m68k_machtype) { +#ifdef CONFIG_AMIGA +	case MACH_AMIGA: +		config_amiga(); +		break; +#endif +#ifdef CONFIG_ATARI +	case MACH_ATARI: +		config_atari(); +		break; +#endif +#ifdef CONFIG_MAC +	case MACH_MAC: +		config_mac(); +		break; +#endif +#ifdef CONFIG_SUN3 +	case MACH_SUN3: +		config_sun3(); +		break; +#endif +#ifdef CONFIG_APOLLO +	case MACH_APOLLO: +		config_apollo(); +		break; +#endif +#ifdef CONFIG_MVME147 +	case MACH_MVME147: +		config_mvme147(); +		break; +#endif +#ifdef CONFIG_MVME16x +	case MACH_MVME16x: +		config_mvme16x(); +		break; +#endif +#ifdef CONFIG_BVME6000 +	case MACH_BVME6000: +		config_bvme6000(); +		break; +#endif +#ifdef CONFIG_HP300 +	case MACH_HP300: +		config_hp300(); +		break; +#endif +#ifdef CONFIG_Q40 +	case MACH_Q40: +		config_q40(); +		break; +#endif +#ifdef CONFIG_SUN3X +	case MACH_SUN3X: +		config_sun3x(); +		break; +#endif +#ifdef CONFIG_COLDFIRE +	case MACH_M54XX: +		config_BSP(NULL, 0); +		break; +#endif +	default: +		panic("No configuration setup"); +	} + +	paging_init(); + +#ifdef CONFIG_NATFEAT +	nf_init(); +#endif + +#ifndef CONFIG_SUN3 +	for (i = 1; i < m68k_num_memory; i++) +		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, +				  m68k_memory[i].size); +#ifdef CONFIG_BLK_DEV_INITRD +	if (m68k_ramdisk.size) { +		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)), +				     m68k_ramdisk.addr, m68k_ramdisk.size, +				     BOOTMEM_DEFAULT); +		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); +		initrd_end = initrd_start + m68k_ramdisk.size; +		pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end); +	} +#endif + +#ifdef CONFIG_ATARI +	if (MACH_IS_ATARI) +		atari_stram_reserve_pages((void *)availmem); +#endif +#ifdef CONFIG_SUN3X +	if (MACH_IS_SUN3X) { +		dvma_init(); +	} +#endif + +#endif /* !CONFIG_SUN3 */ + +/* set ISA defs early as possible */ +#if defined(CONFIG_ISA) && defined(MULTI_ISA) +	if (MACH_IS_Q40) { +		isa_type = ISA_TYPE_Q40; +		isa_sex = 0; +	} +#ifdef CONFIG_AMIGA_PCMCIA +	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) { +		isa_type = ISA_TYPE_AG; +		isa_sex = 1; +	} +#endif +#ifdef CONFIG_ATARI_ROM_ISA +	if (MACH_IS_ATARI) { +		isa_type = ISA_TYPE_ENEC; +		isa_sex = 0; +	} +#endif +#endif +} + +static int show_cpuinfo(struct seq_file *m, void *v) +{ +	const char *cpu, *mmu, *fpu; +	unsigned long clockfreq, clockfactor; + +#define LOOP_CYCLES_68020	(8) +#define LOOP_CYCLES_68030	(8) +#define LOOP_CYCLES_68040	(3) +#define LOOP_CYCLES_68060	(1) +#define LOOP_CYCLES_COLDFIRE	(2) + +	if (CPU_IS_020) { +		cpu = "68020"; +		clockfactor = LOOP_CYCLES_68020; +	} else if (CPU_IS_030) { +		cpu = "68030"; +		clockfactor = LOOP_CYCLES_68030; +	} else if (CPU_IS_040) { +		cpu = "68040"; +		clockfactor = LOOP_CYCLES_68040; +	} else if (CPU_IS_060) { +		cpu = "68060"; +		clockfactor = LOOP_CYCLES_68060; +	} else if (CPU_IS_COLDFIRE) { +		cpu = "ColdFire"; +		clockfactor = LOOP_CYCLES_COLDFIRE; +	} else { +		cpu = "680x0"; +		clockfactor = 0; +	} + +#ifdef CONFIG_M68KFPU_EMU_ONLY +	fpu = "none(soft float)"; +#else +	if (m68k_fputype & FPU_68881) +		fpu = "68881"; +	else if (m68k_fputype & FPU_68882) +		fpu = "68882"; +	else if (m68k_fputype & FPU_68040) +		fpu = "68040"; +	else if (m68k_fputype & FPU_68060) +		fpu = "68060"; +	else if (m68k_fputype & FPU_SUNFPA) +		fpu = "Sun FPA"; +	else if (m68k_fputype & FPU_COLDFIRE) +		fpu = "ColdFire"; +	else +		fpu = "none"; +#endif + +	if (m68k_mmutype & MMU_68851) +		mmu = "68851"; +	else if (m68k_mmutype & MMU_68030) +		mmu = "68030"; +	else if (m68k_mmutype & MMU_68040) +		mmu = "68040"; +	else if (m68k_mmutype & MMU_68060) +		mmu = "68060"; +	else if (m68k_mmutype & MMU_SUN3) +		mmu = "Sun-3"; +	else if (m68k_mmutype & MMU_APOLLO) +		mmu = "Apollo"; +	else if (m68k_mmutype & MMU_COLDFIRE) +		mmu = "ColdFire"; +	else +		mmu = "unknown"; + +	clockfreq = loops_per_jiffy * HZ * clockfactor; + +	seq_printf(m, "CPU:\t\t%s\n" +		   "MMU:\t\t%s\n" +		   "FPU:\t\t%s\n" +		   "Clocking:\t%lu.%1luMHz\n" +		   "BogoMips:\t%lu.%02lu\n" +		   "Calibration:\t%lu loops\n", +		   cpu, mmu, fpu, +		   clockfreq/1000000,(clockfreq/100000)%10, +		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100, +		   loops_per_jiffy); +	return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ +	return *pos < 1 ? (void *)1 : NULL; +} +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ +	++*pos; +	return NULL; +} +static void c_stop(struct seq_file *m, void *v) +{ +} +const struct seq_operations cpuinfo_op = { +	.start	= c_start, +	.next	= c_next, +	.stop	= c_stop, +	.show	= show_cpuinfo, +}; + +#ifdef CONFIG_PROC_HARDWARE +static int hardware_proc_show(struct seq_file *m, void *v) +{ +	char model[80]; +	unsigned long mem; +	int i; + +	if (mach_get_model) +		mach_get_model(model); +	else +		strcpy(model, "Unknown m68k"); + +	seq_printf(m, "Model:\t\t%s\n", model); +	for (mem = 0, i = 0; i < m68k_num_memory; i++) +		mem += m68k_memory[i].size; +	seq_printf(m, "System Memory:\t%ldK\n", mem >> 10); + +	if (mach_get_hardware_list) +		mach_get_hardware_list(m); + +	return 0; +} + +static int hardware_proc_open(struct inode *inode, struct file *file) +{ +	return single_open(file, hardware_proc_show, NULL); +} + +static const struct file_operations hardware_proc_fops = { +	.open		= hardware_proc_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; + +static int __init proc_hardware_init(void) +{ +	proc_create("hardware", 0, NULL, &hardware_proc_fops); +	return 0; +} +module_init(proc_hardware_init); +#endif + +void check_bugs(void) +{ +#ifndef CONFIG_M68KFPU_EMU +	if (m68k_fputype == 0) { +		pr_emerg("*** YOU DO NOT HAVE A FLOATING POINT UNIT, " +			"WHICH IS REQUIRED BY LINUX/M68K ***\n"); +		pr_emerg("Upgrade your hardware or join the FPU " +			"emulation project\n"); +		panic("no FPU"); +	} +#endif /* !CONFIG_M68KFPU_EMU */ +} + +#ifdef CONFIG_ADB +static int __init adb_probe_sync_enable (char *str) { +	extern int __adb_probe_sync; +	__adb_probe_sync = 1; +	return 1; +} + +__setup("adb_sync", adb_probe_sync_enable); +#endif /* CONFIG_ADB */ diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c new file mode 100644 index 00000000000..88c27d94a72 --- /dev/null +++ b/arch/m68k/kernel/setup_no.c @@ -0,0 +1,316 @@ +/* + *  linux/arch/m68knommu/kernel/setup.c + * + *  Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com) + *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org> + *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com} + *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com> + *  Copyright (C) 1995       Hamish Macdonald + *  Copyright (C) 2000       Lineo Inc. (www.lineo.com) + *  Copyright (C) 2001 	     Lineo, Inc. <www.lineo.com> + * + *  68VZ328 Fixes/support    Evan Stawnyczy <e@lineo.ca> + */ + +/* + * This file handles the architecture-dependent parts of system setup + */ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/console.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/bootmem.h> +#include <linux/seq_file.h> +#include <linux/init.h> +#include <linux/initrd.h> +#include <linux/root_dev.h> +#include <linux/rtc.h> + +#include <asm/setup.h> +#include <asm/irq.h> +#include <asm/machdep.h> +#include <asm/pgtable.h> +#include <asm/sections.h> + +unsigned long memory_start; +unsigned long memory_end; + +EXPORT_SYMBOL(memory_start); +EXPORT_SYMBOL(memory_end); + +char __initdata command_line[COMMAND_LINE_SIZE]; + +/* machine dependent timer functions */ +void (*mach_sched_init)(irq_handler_t handler) __initdata = NULL; +int (*mach_set_clock_mmss)(unsigned long); +int (*mach_hwclk) (int, struct rtc_time*); + +/* machine dependent reboot functions */ +void (*mach_reset)(void); +void (*mach_halt)(void); +void (*mach_power_off)(void); + +#ifdef CONFIG_M68000 +#if defined(CONFIG_M68328) +#define CPU_NAME	"MC68328" +#elif defined(CONFIG_M68EZ328) +#define CPU_NAME	"MC68EZ328" +#elif defined(CONFIG_M68VZ328) +#define CPU_NAME	"MC68VZ328" +#else +#define CPU_NAME	"MC68000" +#endif +#endif /* CONFIG_M68000 */ +#ifdef CONFIG_M68360 +#define CPU_NAME	"MC68360" +#endif +#ifndef CPU_NAME +#define	CPU_NAME	"UNKNOWN" +#endif + +/* + * Different cores have different instruction execution timings. + * The old/traditional 68000 cores are basically all the same, at 16. + * The ColdFire cores vary a little, their values are defined in their + * headers. We default to the standard 68000 value here. + */ +#ifndef CPU_INSTR_PER_JIFFY +#define	CPU_INSTR_PER_JIFFY	16 +#endif + +#if defined(CONFIG_UBOOT) +/* + * parse_uboot_commandline + * + * Copies u-boot commandline arguments and store them in the proper linux + * variables. + * + * Assumes: + *	_init_sp global contains the address in the stack pointer when the + *	kernel starts (see head.S::_start) + * + *	U-Boot calling convention: + *	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); + * + *	_init_sp can be parsed as such + * + *	_init_sp+00 = u-boot cmd after jsr into kernel (skip) + *	_init_sp+04 = &kernel board_info (residual data) + *	_init_sp+08 = &initrd_start + *	_init_sp+12 = &initrd_end + *	_init_sp+16 = &cmd_start + *	_init_sp+20 = &cmd_end + * + *	This also assumes that the memory locations pointed to are still + *	unmodified. U-boot places them near the end of external SDRAM. + * + * Argument(s): + *	commandp = the linux commandline arg container to fill. + *	size     = the sizeof commandp. + * + * Returns: + */ +static void __init parse_uboot_commandline(char *commandp, int size) +{ +	extern unsigned long _init_sp; +	unsigned long *sp; +	unsigned long uboot_kbd; +	unsigned long uboot_initrd_start, uboot_initrd_end; +	unsigned long uboot_cmd_start, uboot_cmd_end; + + +	sp = (unsigned long *)_init_sp; +	uboot_kbd = sp[1]; +	uboot_initrd_start = sp[2]; +	uboot_initrd_end = sp[3]; +	uboot_cmd_start = sp[4]; +	uboot_cmd_end = sp[5]; + +	if (uboot_cmd_start && uboot_cmd_end) +		strncpy(commandp, (const char *)uboot_cmd_start, size); +#if defined(CONFIG_BLK_DEV_INITRD) +	if (uboot_initrd_start && uboot_initrd_end && +		(uboot_initrd_end > uboot_initrd_start)) { +		initrd_start = uboot_initrd_start; +		initrd_end = uboot_initrd_end; +		ROOT_DEV = Root_RAM0; +		printk(KERN_INFO "initrd at 0x%lx:0x%lx\n", +			initrd_start, initrd_end); +	} +#endif /* if defined(CONFIG_BLK_DEV_INITRD) */ +} +#endif /* #if defined(CONFIG_UBOOT) */ + +void __init setup_arch(char **cmdline_p) +{ +	int bootmap_size; + +	memory_start = PAGE_ALIGN(_ramstart); +	memory_end = _ramend; + +	init_mm.start_code = (unsigned long) &_stext; +	init_mm.end_code = (unsigned long) &_etext; +	init_mm.end_data = (unsigned long) &_edata; +	init_mm.brk = (unsigned long) 0; + +	config_BSP(&command_line[0], sizeof(command_line)); + +#if defined(CONFIG_BOOTPARAM) +	strncpy(&command_line[0], CONFIG_BOOTPARAM_STRING, sizeof(command_line)); +	command_line[sizeof(command_line) - 1] = 0; +#endif /* CONFIG_BOOTPARAM */ + +#if defined(CONFIG_UBOOT) +	/* CONFIG_UBOOT and CONFIG_BOOTPARAM defined, concatenate cmdline */ +	#if defined(CONFIG_BOOTPARAM) +		/* Add the whitespace separator */ +		command_line[strlen(CONFIG_BOOTPARAM_STRING)] = ' '; +		/* Parse uboot command line into the rest of the buffer */ +		parse_uboot_commandline( +			&command_line[(strlen(CONFIG_BOOTPARAM_STRING)+1)], +			(sizeof(command_line) - +			(strlen(CONFIG_BOOTPARAM_STRING)+1))); +	/* Only CONFIG_UBOOT defined, create cmdline */ +	#else +		parse_uboot_commandline(&command_line[0], sizeof(command_line)); +	#endif /* CONFIG_BOOTPARAM */ +	command_line[sizeof(command_line) - 1] = 0; +#endif /* CONFIG_UBOOT */ + +	printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU_NAME "\n"); + +#ifdef CONFIG_UCDIMM +	printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n"); +#endif +#ifdef CONFIG_M68VZ328 +	printk(KERN_INFO "M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n"); +#endif +#ifdef CONFIG_COLDFIRE +	printk(KERN_INFO "COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n"); +#ifdef CONFIG_M5307 +	printk(KERN_INFO "Modified for M5307 by Dave Miller, dmiller@intellistor.com\n"); +#endif +#ifdef CONFIG_ELITE +	printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n"); +#endif +#endif +	printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); + +#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ) +	printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n"); +#endif +#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 ) +	printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n"); +#endif +#if defined (CONFIG_M68360) +	printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n"); +	printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n"); +#endif +#ifdef CONFIG_DRAGEN2 +	printk(KERN_INFO "DragonEngine II board support by Georges Menie\n"); +#endif +#ifdef CONFIG_M5235EVB +	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n"); +#endif + +	pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", +		 _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); +	pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", +		 __bss_stop, memory_start, memory_start, memory_end); + +	/* Keep a copy of command line */ +	*cmdline_p = &command_line[0]; +	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); +	boot_command_line[COMMAND_LINE_SIZE-1] = 0; + +#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE) +	conswitchp = &dummy_con; +#endif + +	/* +	 * Give all the memory to the bootmap allocator, tell it to put the +	 * boot mem_map at the start of memory. +	 */ +	bootmap_size = init_bootmem_node( +			NODE_DATA(0), +			memory_start >> PAGE_SHIFT, /* map goes here */ +			PAGE_OFFSET >> PAGE_SHIFT,	/* 0 on coldfire */ +			memory_end >> PAGE_SHIFT); +	/* +	 * Free the usable memory, we have to make sure we do not free +	 * the bootmem bitmap so we then reserve it after freeing it :-) +	 */ +	free_bootmem(memory_start, memory_end - memory_start); +	reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT); + +#if defined(CONFIG_UBOOT) && defined(CONFIG_BLK_DEV_INITRD) +	if ((initrd_start > 0) && (initrd_start < initrd_end) && +			(initrd_end < memory_end)) +		reserve_bootmem(initrd_start, initrd_end - initrd_start, +				 BOOTMEM_DEFAULT); +#endif /* if defined(CONFIG_BLK_DEV_INITRD) */ + +	/* +	 * Get kmalloc into gear. +	 */ +	paging_init(); +} + +/* + *	Get CPU information for use by the procfs. + */ +static int show_cpuinfo(struct seq_file *m, void *v) +{ +	char *cpu, *mmu, *fpu; +	u_long clockfreq; + +	cpu = CPU_NAME; +	mmu = "none"; +	fpu = "none"; +	clockfreq = (loops_per_jiffy * HZ) * CPU_INSTR_PER_JIFFY; + +	seq_printf(m, "CPU:\t\t%s\n" +		      "MMU:\t\t%s\n" +		      "FPU:\t\t%s\n" +		      "Clocking:\t%lu.%1luMHz\n" +		      "BogoMips:\t%lu.%02lu\n" +		      "Calibration:\t%lu loops\n", +		      cpu, mmu, fpu, +		      clockfreq / 1000000, +		      (clockfreq / 100000) % 10, +		      (loops_per_jiffy * HZ) / 500000, +		      ((loops_per_jiffy * HZ) / 5000) % 100, +		      (loops_per_jiffy * HZ)); + +	return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ +	return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ +	++*pos; +	return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +const struct seq_operations cpuinfo_op = { +	.start	= c_start, +	.next	= c_next, +	.stop	= c_stop, +	.show	= show_cpuinfo, +}; + diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 4b387538706..57fd286e4b0 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -42,22 +42,34 @@  #include <linux/personality.h>  #include <linux/tty.h>  #include <linux/binfmts.h> +#include <linux/module.h> +#include <linux/tracehook.h>  #include <asm/setup.h>  #include <asm/uaccess.h>  #include <asm/pgtable.h>  #include <asm/traps.h>  #include <asm/ucontext.h> +#include <asm/cacheflush.h> -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) +#ifdef CONFIG_MMU -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); +/* + * Handle the slight differences in classic 68k and ColdFire trap frames. + */ +#ifdef CONFIG_COLDFIRE +#define	FORMAT		4 +#define	FMT4SIZE	0 +#else +#define	FORMAT		0 +#define	FMT4SIZE	sizeof(((struct frame *)0)->un.fmt4) +#endif -const int frame_extra_sizes[16] = { +static const int frame_size_change[16] = {    [1]	= -1, /* sizeof(((struct frame *)0)->un.fmt1), */    [2]	= sizeof(((struct frame *)0)->un.fmt2),    [3]	= sizeof(((struct frame *)0)->un.fmt3), -  [4]	= sizeof(((struct frame *)0)->un.fmt4), +  [4]	= FMT4SIZE,    [5]	= -1, /* sizeof(((struct frame *)0)->un.fmt5), */    [6]	= -1, /* sizeof(((struct frame *)0)->un.fmt6), */    [7]	= sizeof(((struct frame *)0)->un.fmt7), @@ -71,94 +83,154 @@ const int frame_extra_sizes[16] = {    [15]	= -1, /* sizeof(((struct frame *)0)->un.fmtf), */  }; -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int do_sigsuspend(struct pt_regs *regs) +static inline int frame_extra_sizes(int f)  { -	old_sigset_t mask = regs->d3; -	sigset_t saveset; - -	mask &= _BLOCKABLE; -	saveset = current->blocked; -	siginitset(¤t->blocked, mask); -	recalc_sigpending(); - -	regs->d0 = -EINTR; -	while (1) { -		current->state = TASK_INTERRUPTIBLE; -		schedule(); -		if (do_signal(&saveset, regs)) -			return -EINTR; -	} +	return frame_size_change[f];  } -asmlinkage int -do_rt_sigsuspend(struct pt_regs *regs) +int handle_kernel_fault(struct pt_regs *regs)  { -	sigset_t __user *unewset = (sigset_t __user *)regs->d1; -	size_t sigsetsize = (size_t)regs->d2; -	sigset_t saveset, newset; - -	/* XXX: Don't preclude handling different sized sigset_t's.  */ -	if (sigsetsize != sizeof(sigset_t)) -		return -EINVAL; - -	if (copy_from_user(&newset, unewset, sizeof(newset))) -		return -EFAULT; -	sigdelsetmask(&newset, ~_BLOCKABLE); - -	saveset = current->blocked; -	current->blocked = newset; -	recalc_sigpending(); - -	regs->d0 = -EINTR; -	while (1) { -		current->state = TASK_INTERRUPTIBLE; -		schedule(); -		if (do_signal(&saveset, regs)) -			return -EINTR; -	} +	const struct exception_table_entry *fixup; +	struct pt_regs *tregs; + +	/* Are we prepared to handle this kernel fault? */ +	fixup = search_exception_tables(regs->pc); +	if (!fixup) +		return 0; + +	/* Create a new four word stack frame, discarding the old one. */ +	regs->stkadj = frame_extra_sizes(regs->format); +	tregs =	(struct pt_regs *)((long)regs + regs->stkadj); +	tregs->vector = regs->vector; +	tregs->format = FORMAT; +	tregs->pc = fixup->fixup; +	tregs->sr = regs->sr; + +	return 1;  } -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, -	      struct old_sigaction __user *oact) +void ptrace_signal_deliver(void)  { -	struct k_sigaction new_ka, old_ka; -	int ret; - -	if (act) { -		old_sigset_t mask; -		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) || -		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) -			return -EFAULT; -		__get_user(new_ka.sa.sa_flags, &act->sa_flags); -		__get_user(mask, &act->sa_mask); -		siginitset(&new_ka.sa.sa_mask, mask); +	struct pt_regs *regs = signal_pt_regs(); +	if (regs->orig_d0 < 0) +		return; +	switch (regs->d0) { +	case -ERESTARTNOHAND: +	case -ERESTARTSYS: +	case -ERESTARTNOINTR: +		regs->d0 = regs->orig_d0; +		regs->orig_d0 = -1; +		regs->pc -= 2; +		break;  	} +} -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); +static inline void push_cache (unsigned long vaddr) +{ +	/* +	 * Using the old cache_push_v() was really a big waste. +	 * +	 * What we are trying to do is to flush 8 bytes to ram. +	 * Flushing 2 cache lines of 16 bytes is much cheaper than +	 * flushing 1 or 2 pages, as previously done in +	 * cache_push_v(). +	 *                                                     Jes +	 */ +	if (CPU_IS_040) { +		unsigned long temp; + +		__asm__ __volatile__ (".chip 68040\n\t" +				      "nop\n\t" +				      "ptestr (%1)\n\t" +				      "movec %%mmusr,%0\n\t" +				      ".chip 68k" +				      : "=r" (temp) +				      : "a" (vaddr)); + +		temp &= PAGE_MASK; +		temp |= vaddr & ~PAGE_MASK; -	if (!ret && oact) { -		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || -		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) -			return -EFAULT; -		__put_user(old_ka.sa.sa_flags, &oact->sa_flags); -		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); +		__asm__ __volatile__ (".chip 68040\n\t" +				      "nop\n\t" +				      "cpushl %%bc,(%0)\n\t" +				      ".chip 68k" +				      : : "a" (temp)); +	} +	else if (CPU_IS_060) { +		unsigned long temp; +		__asm__ __volatile__ (".chip 68060\n\t" +				      "plpar (%0)\n\t" +				      ".chip 68k" +				      : "=a" (temp) +				      : "0" (vaddr)); +		__asm__ __volatile__ (".chip 68060\n\t" +				      "cpushl %%bc,(%0)\n\t" +				      ".chip 68k" +				      : : "a" (temp)); +	} else if (!CPU_IS_COLDFIRE) { +		/* +		 * 68030/68020 have no writeback cache; +		 * still need to clear icache. +		 * Note that vaddr is guaranteed to be long word aligned. +		 */ +		unsigned long temp; +		asm volatile ("movec %%cacr,%0" : "=r" (temp)); +		temp += 4; +		asm volatile ("movec %0,%%caar\n\t" +			      "movec %1,%%cacr" +			      : : "r" (vaddr), "r" (temp)); +		asm volatile ("movec %0,%%caar\n\t" +			      "movec %1,%%cacr" +			      : : "r" (vaddr + 4), "r" (temp)); +	} else { +		/* CPU_IS_COLDFIRE */ +#if defined(CONFIG_CACHE_COPYBACK) +		flush_cf_dcache(0, DCACHE_MAX_ADDR); +#endif +		/* Invalidate instruction cache for the pushed bytes */ +		clear_cf_icache(vaddr, vaddr + 8);  	} +} -	return ret; +static inline void adjustformat(struct pt_regs *regs) +{  } -asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) +static inline void save_a5_state(struct sigcontext *sc, struct pt_regs *regs)  { -	return do_sigaltstack(uss, uoss, rdusp());  } +#else /* CONFIG_MMU */ + +void ret_from_user_signal(void); +void ret_from_user_rt_signal(void); + +static inline int frame_extra_sizes(int f) +{ +	/* No frame size adjustments required on non-MMU CPUs */ +	return 0; +} + +static inline void adjustformat(struct pt_regs *regs) +{ +	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data; +	/* +	 * set format byte to make stack appear modulo 4, which it will +	 * be when doing the rte +	 */ +	regs->format = 0x4; +} + +static inline void save_a5_state(struct sigcontext *sc, struct pt_regs *regs) +{ +	sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5; +} + +static inline void push_cache(unsigned long vaddr) +{ +} + +#endif /* CONFIG_MMU */  /*   * Do a signal return; undo the signal stack. @@ -189,6 +261,12 @@ struct rt_sigframe  	struct ucontext uc;  }; +#define FPCONTEXT_SIZE	216 +#define uc_fpstate	uc_filler[0] +#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4] +#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1] + +#ifdef CONFIG_FPU  static unsigned char fpu_version;	/* version number of fpu, set by setup_frame */ @@ -205,7 +283,8 @@ static inline int restore_fpu_state(struct sigcontext *sc)  	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {  	    /* Verify the frame format.  */ -	    if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) +	    if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && +		 (sc->sc_fpstate[0] != fpu_version))  		goto out;  	    if (CPU_IS_020_OR_030) {  		if (m68k_fputype & FPU_68881 && @@ -224,34 +303,53 @@ static inline int restore_fpu_state(struct sigcontext *sc)                        sc->sc_fpstate[3] == 0x60 ||  		      sc->sc_fpstate[3] == 0xe0))  		    goto out; +	    } else if (CPU_IS_COLDFIRE) { +		if (!(sc->sc_fpstate[0] == 0x00 || +		      sc->sc_fpstate[0] == 0x05 || +		      sc->sc_fpstate[0] == 0xe5)) +		    goto out;  	    } else  		goto out; -	    __asm__ volatile (".chip 68k/68881\n\t" -			      "fmovemx %0,%%fp0-%%fp1\n\t" -			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" -			      ".chip 68k" -			      : /* no outputs */ -			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); +	    if (CPU_IS_COLDFIRE) { +		__asm__ volatile ("fmovemd %0,%%fp0-%%fp1\n\t" +				  "fmovel %1,%%fpcr\n\t" +				  "fmovel %2,%%fpsr\n\t" +				  "fmovel %3,%%fpiar" +				  : /* no outputs */ +				  : "m" (sc->sc_fpregs[0]), +				    "m" (sc->sc_fpcntl[0]), +				    "m" (sc->sc_fpcntl[1]), +				    "m" (sc->sc_fpcntl[2])); +	    } else { +		__asm__ volatile (".chip 68k/68881\n\t" +				  "fmovemx %0,%%fp0-%%fp1\n\t" +				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" +				  ".chip 68k" +				  : /* no outputs */ +				  : "m" (*sc->sc_fpregs), +				    "m" (*sc->sc_fpcntl)); +	    } +	} + +	if (CPU_IS_COLDFIRE) { +		__asm__ volatile ("frestore %0" : : "m" (*sc->sc_fpstate)); +	} else { +		__asm__ volatile (".chip 68k/68881\n\t" +				  "frestore %0\n\t" +				  ".chip 68k" +				  : : "m" (*sc->sc_fpstate));  	} -	__asm__ volatile (".chip 68k/68881\n\t" -			  "frestore %0\n\t" -			  ".chip 68k" : : "m" (*sc->sc_fpstate));  	err = 0;  out:  	return err;  } -#define FPCONTEXT_SIZE	216 -#define uc_fpstate	uc_filler[0] -#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4] -#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1] -  static inline int rt_restore_fpu_state(struct ucontext __user *uc)  {  	unsigned char fpstate[FPCONTEXT_SIZE]; -	int context_size = CPU_IS_060 ? 8 : 0; +	int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);  	fpregset_t fpregs;  	int err = 1; @@ -270,10 +368,11 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc)  	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))  		goto out;  	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { -		if (!CPU_IS_060) +		if (!(CPU_IS_060 || CPU_IS_COLDFIRE))  			context_size = fpstate[1];  		/* Verify the frame format.  */ -		if (!CPU_IS_060 && (fpstate[0] != fpu_version)) +		if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && +		     (fpstate[0] != fpu_version))  			goto out;  		if (CPU_IS_020_OR_030) {  			if (m68k_fputype & FPU_68881 && @@ -292,62 +391,210 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc)  			      fpstate[3] == 0x60 ||  			      fpstate[3] == 0xe0))  				goto out; +		} else if (CPU_IS_COLDFIRE) { +			if (!(fpstate[3] == 0x00 || +			      fpstate[3] == 0x05 || +			      fpstate[3] == 0xe5)) +				goto out;  		} else  			goto out;  		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,  				     sizeof(fpregs)))  			goto out; -		__asm__ volatile (".chip 68k/68881\n\t" -				  "fmovemx %0,%%fp0-%%fp7\n\t" -				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" -				  ".chip 68k" -				  : /* no outputs */ -				  : "m" (*fpregs.f_fpregs), -				    "m" (*fpregs.f_fpcntl)); + +		if (CPU_IS_COLDFIRE) { +			__asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t" +					  "fmovel %1,%%fpcr\n\t" +					  "fmovel %2,%%fpsr\n\t" +					  "fmovel %3,%%fpiar" +					  : /* no outputs */ +					  : "m" (fpregs.f_fpregs[0]), +					    "m" (fpregs.f_fpcntl[0]), +					    "m" (fpregs.f_fpcntl[1]), +					    "m" (fpregs.f_fpcntl[2])); +		} else { +			__asm__ volatile (".chip 68k/68881\n\t" +					  "fmovemx %0,%%fp0-%%fp7\n\t" +					  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" +					  ".chip 68k" +					  : /* no outputs */ +					  : "m" (*fpregs.f_fpregs), +					    "m" (*fpregs.f_fpcntl)); +		}  	}  	if (context_size &&  	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,  			     context_size))  		goto out; -	__asm__ volatile (".chip 68k/68881\n\t" -			  "frestore %0\n\t" -			  ".chip 68k" : : "m" (*fpstate)); + +	if (CPU_IS_COLDFIRE) { +		__asm__ volatile ("frestore %0" : : "m" (*fpstate)); +	} else { +		__asm__ volatile (".chip 68k/68881\n\t" +				  "frestore %0\n\t" +				  ".chip 68k" +				  : : "m" (*fpstate)); +	}  	err = 0;  out:  	return err;  } -static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, -		   int *pd0) +/* + * Set up a signal frame. + */ +static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)  { -	int fsize, formatvec; -	struct sigcontext context; -	int err; +	if (FPU_IS_EMU) { +		/* save registers */ +		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); +		memcpy(sc->sc_fpregs, current->thread.fp, 24); +		return; +	} -	/* Always make any pending restarted system calls return -EINTR */ -	current_thread_info()->restart_block.fn = do_no_restart_syscall; +	if (CPU_IS_COLDFIRE) { +		__asm__ volatile ("fsave %0" +				  : : "m" (*sc->sc_fpstate) : "memory"); +	} else { +		__asm__ volatile (".chip 68k/68881\n\t" +				  "fsave %0\n\t" +				  ".chip 68k" +				  : : "m" (*sc->sc_fpstate) : "memory"); +	} -	/* get previous context */ -	if (copy_from_user(&context, usc, sizeof(context))) -		goto badframe; +	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { +		fpu_version = sc->sc_fpstate[0]; +		if (CPU_IS_020_OR_030 && +		    regs->vector >= (VEC_FPBRUC * 4) && +		    regs->vector <= (VEC_FPNAN * 4)) { +			/* Clear pending exception in 68882 idle frame */ +			if (*(unsigned short *) sc->sc_fpstate == 0x1f38) +				sc->sc_fpstate[0x38] |= 1 << 3; +		} -	/* restore passed registers */ -	regs->d1 = context.sc_d1; -	regs->a0 = context.sc_a0; -	regs->a1 = context.sc_a1; -	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); -	regs->pc = context.sc_pc; -	regs->orig_d0 = -1;		/* disable syscall checks */ -	wrusp(context.sc_usp); -	formatvec = context.sc_formatvec; -	regs->format = formatvec >> 12; -	regs->vector = formatvec & 0xfff; +		if (CPU_IS_COLDFIRE) { +			__asm__ volatile ("fmovemd %%fp0-%%fp1,%0\n\t" +					  "fmovel %%fpcr,%1\n\t" +					  "fmovel %%fpsr,%2\n\t" +					  "fmovel %%fpiar,%3" +					  : "=m" (sc->sc_fpregs[0]), +					    "=m" (sc->sc_fpcntl[0]), +					    "=m" (sc->sc_fpcntl[1]), +					    "=m" (sc->sc_fpcntl[2]) +					  : /* no inputs */ +					  : "memory"); +		} else { +			__asm__ volatile (".chip 68k/68881\n\t" +					  "fmovemx %%fp0-%%fp1,%0\n\t" +					  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" +					  ".chip 68k" +					  : "=m" (*sc->sc_fpregs), +					    "=m" (*sc->sc_fpcntl) +					  : /* no inputs */ +					  : "memory"); +		} +	} +} -	err = restore_fpu_state(&context); +static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) +{ +	unsigned char fpstate[FPCONTEXT_SIZE]; +	int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0); +	int err = 0; + +	if (FPU_IS_EMU) { +		/* save fpu control register */ +		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, +				current->thread.fpcntl, 12); +		/* save all other fpu register */ +		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, +				current->thread.fp, 96); +		return err; +	} + +	if (CPU_IS_COLDFIRE) { +		__asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory"); +	} else { +		__asm__ volatile (".chip 68k/68881\n\t" +				  "fsave %0\n\t" +				  ".chip 68k" +				  : : "m" (*fpstate) : "memory"); +	} + +	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); +	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { +		fpregset_t fpregs; +		if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) +			context_size = fpstate[1]; +		fpu_version = fpstate[0]; +		if (CPU_IS_020_OR_030 && +		    regs->vector >= (VEC_FPBRUC * 4) && +		    regs->vector <= (VEC_FPNAN * 4)) { +			/* Clear pending exception in 68882 idle frame */ +			if (*(unsigned short *) fpstate == 0x1f38) +				fpstate[0x38] |= 1 << 3; +		} +		if (CPU_IS_COLDFIRE) { +			__asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t" +					  "fmovel %%fpcr,%1\n\t" +					  "fmovel %%fpsr,%2\n\t" +					  "fmovel %%fpiar,%3" +					  : "=m" (fpregs.f_fpregs[0]), +					    "=m" (fpregs.f_fpcntl[0]), +					    "=m" (fpregs.f_fpcntl[1]), +					    "=m" (fpregs.f_fpcntl[2]) +					  : /* no inputs */ +					  : "memory"); +		} else { +			__asm__ volatile (".chip 68k/68881\n\t" +					  "fmovemx %%fp0-%%fp7,%0\n\t" +					  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" +					  ".chip 68k" +					  : "=m" (*fpregs.f_fpregs), +					    "=m" (*fpregs.f_fpcntl) +					  : /* no inputs */ +					  : "memory"); +		} +		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, +				    sizeof(fpregs)); +	} +	if (context_size) +		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, +				    context_size); +	return err; +} -	fsize = frame_extra_sizes[regs->format]; +#else /* CONFIG_FPU */ + +/* + * For the case with no FPU configured these all do nothing. + */ +static inline int restore_fpu_state(struct sigcontext *sc) +{ +	return 0; +} + +static inline int rt_restore_fpu_state(struct ucontext __user *uc) +{ +	return 0; +} + +static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) +{ +} + +static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) +{ +	return 0; +} + +#endif /* CONFIG_FPU */ + +static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, +			       void __user *fp) +{ +	int fsize = frame_extra_sizes(formatvec >> 12);  	if (fsize < 0) {  		/*  		 * user process trying to return with weird frame format @@ -355,19 +602,29 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u  #ifdef DEBUG  		printk("user process returning with weird frame format\n");  #endif -		goto badframe; +		return 1;  	} +	if (!fsize) { +		regs->format = formatvec >> 12; +		regs->vector = formatvec & 0xfff; +	} else { +		struct switch_stack *sw = (struct switch_stack *)regs - 1; +		unsigned long buf[fsize / 2]; /* yes, twice as much */ -	/* OK.	Make room on the supervisor stack for the extra junk, -	 * if necessary. -	 */ +		/* that'll make sure that expansion won't crap over data */ +		if (copy_from_user(buf + fsize / 4, fp, fsize)) +			return 1; -	if (fsize) { -		struct switch_stack *sw = (struct switch_stack *)regs - 1; -		regs->d0 = context.sc_d0; +		/* point of no return */ +		regs->format = formatvec >> 12; +		regs->vector = formatvec & 0xfff;  #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) -		__asm__ __volatile__ -			("   movel %0,%/a0\n\t" +		__asm__ __volatile__ ( +#ifdef CONFIG_COLDFIRE +			 "   movel %0,%/sp\n\t" +			 "   bra ret_from_signal\n" +#else +			 "   movel %0,%/a0\n\t"  			 "   subl %1,%/a0\n\t"     /* make room on stack */  			 "   movel %/a0,%/sp\n\t"  /* set stack pointer */  			 /* move switch_stack and pt_regs */ @@ -376,30 +633,51 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u  			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */  			 "   lsrl  #2,%1\n\t"  			 "   subql #1,%1\n\t" -			 "2: movesl %4@+,%2\n\t" -			 "3: movel %2,%/a0@+\n\t" +			 /* copy to the gap we'd made */ +			 "2: movel %4@+,%/a0@+\n\t"  			 "   dbra %1,2b\n\t"  			 "   bral ret_from_signal\n" -			 "4:\n" -			 ".section __ex_table,\"a\"\n" -			 "   .align 4\n" -			 "   .long 2b,4b\n" -			 "   .long 3b,4b\n" -			 ".previous" +#endif  			 : /* no outputs, it doesn't ever return */  			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), -			   "n" (frame_offset), "a" (fp) +			   "n" (frame_offset), "a" (buf + fsize/4)  			 : "a0");  #undef frame_offset -		/* -		 * If we ever get here an exception occurred while -		 * building the above stack-frame. -		 */ -		goto badframe;  	} +	return 0; +} -	*pd0 = context.sc_d0; -	return err; +static inline int +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp) +{ +	int formatvec; +	struct sigcontext context; +	int err = 0; + +	/* Always make any pending restarted system calls return -EINTR */ +	current_thread_info()->restart_block.fn = do_no_restart_syscall; + +	/* get previous context */ +	if (copy_from_user(&context, usc, sizeof(context))) +		goto badframe; + +	/* restore passed registers */ +	regs->d0 = context.sc_d0; +	regs->d1 = context.sc_d1; +	regs->a0 = context.sc_a0; +	regs->a1 = context.sc_a1; +	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); +	regs->pc = context.sc_pc; +	regs->orig_d0 = -1;		/* disable syscall checks */ +	wrusp(context.sc_usp); +	formatvec = context.sc_formatvec; + +	err = restore_fpu_state(&context); + +	if (err || mangle_kernel_stack(regs, formatvec, fp)) +		goto badframe; + +	return 0;  badframe:  	return 1; @@ -407,9 +685,9 @@ badframe:  static inline int  rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, -		    struct ucontext __user *uc, int *pd0) +		    struct ucontext __user *uc)  { -	int fsize, temp; +	int temp;  	greg_t __user *gregs = uc->uc_mcontext.gregs;  	unsigned long usp;  	int err; @@ -443,65 +721,17 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,  	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);  	regs->orig_d0 = -1;		/* disable syscall checks */  	err |= __get_user(temp, &uc->uc_formatvec); -	regs->format = temp >> 12; -	regs->vector = temp & 0xfff;  	err |= rt_restore_fpu_state(uc); +	err |= restore_altstack(&uc->uc_stack); -	if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) -		goto badframe; - -	fsize = frame_extra_sizes[regs->format]; -	if (fsize < 0) { -		/* -		 * user process trying to return with weird frame format -		 */ -#ifdef DEBUG -		printk("user process returning with weird frame format\n"); -#endif +	if (err)  		goto badframe; -	} - -	/* OK.	Make room on the supervisor stack for the extra junk, -	 * if necessary. -	 */ -	if (fsize) { -#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) -		__asm__ __volatile__ -			("   movel %0,%/a0\n\t" -			 "   subl %1,%/a0\n\t"     /* make room on stack */ -			 "   movel %/a0,%/sp\n\t"  /* set stack pointer */ -			 /* move switch_stack and pt_regs */ -			 "1: movel %0@+,%/a0@+\n\t" -			 "   dbra %2,1b\n\t" -			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ -			 "   lsrl  #2,%1\n\t" -			 "   subql #1,%1\n\t" -			 "2: movesl %4@+,%2\n\t" -			 "3: movel %2,%/a0@+\n\t" -			 "   dbra %1,2b\n\t" -			 "   bral ret_from_signal\n" -			 "4:\n" -			 ".section __ex_table,\"a\"\n" -			 "   .align 4\n" -			 "   .long 2b,4b\n" -			 "   .long 3b,4b\n" -			 ".previous" -			 : /* no outputs, it doesn't ever return */ -			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), -			   "n" (frame_offset), "a" (&uc->uc_extra) -			 : "a0"); -#undef frame_offset -		/* -		 * If we ever get here an exception occurred while -		 * building the above stack-frame. -		 */ +	if (mangle_kernel_stack(regs, temp, &uc->uc_extra))  		goto badframe; -	} -	*pd0 = regs->d0; -	return err; +	return 0;  badframe:  	return 1; @@ -514,7 +744,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)  	unsigned long usp = rdusp();  	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);  	sigset_t set; -	int d0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe; @@ -524,13 +753,11 @@ asmlinkage int do_sigreturn(unsigned long __unused)  			      sizeof(frame->extramask))))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); -	current->blocked = set; -	recalc_sigpending(); +	set_current_blocked(&set); -	if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) +	if (restore_sigcontext(regs, &frame->sc, frame + 1))  		goto badframe; -	return d0; +	return regs->d0;  badframe:  	force_sig(SIGSEGV, current); @@ -544,115 +771,23 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)  	unsigned long usp = rdusp();  	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);  	sigset_t set; -	int d0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe;  	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); -	current->blocked = set; -	recalc_sigpending(); +	set_current_blocked(&set); -	if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) +	if (rt_restore_ucontext(regs, sw, &frame->uc))  		goto badframe; -	return d0; +	return regs->d0;  badframe:  	force_sig(SIGSEGV, current);  	return 0;  } -/* - * Set up a signal frame. - */ - -static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) -{ -	if (FPU_IS_EMU) { -		/* save registers */ -		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); -		memcpy(sc->sc_fpregs, current->thread.fp, 24); -		return; -	} - -	__asm__ volatile (".chip 68k/68881\n\t" -			  "fsave %0\n\t" -			  ".chip 68k" -			  : : "m" (*sc->sc_fpstate) : "memory"); - -	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { -		fpu_version = sc->sc_fpstate[0]; -		if (CPU_IS_020_OR_030 && -		    regs->vector >= (VEC_FPBRUC * 4) && -		    regs->vector <= (VEC_FPNAN * 4)) { -			/* Clear pending exception in 68882 idle frame */ -			if (*(unsigned short *) sc->sc_fpstate == 0x1f38) -				sc->sc_fpstate[0x38] |= 1 << 3; -		} -		__asm__ volatile (".chip 68k/68881\n\t" -				  "fmovemx %%fp0-%%fp1,%0\n\t" -				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" -				  ".chip 68k" -				  : "=m" (*sc->sc_fpregs), -				    "=m" (*sc->sc_fpcntl) -				  : /* no inputs */ -				  : "memory"); -	} -} - -static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) -{ -	unsigned char fpstate[FPCONTEXT_SIZE]; -	int context_size = CPU_IS_060 ? 8 : 0; -	int err = 0; - -	if (FPU_IS_EMU) { -		/* save fpu control register */ -		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, -				current->thread.fpcntl, 12); -		/* save all other fpu register */ -		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, -				current->thread.fp, 96); -		return err; -	} - -	__asm__ volatile (".chip 68k/68881\n\t" -			  "fsave %0\n\t" -			  ".chip 68k" -			  : : "m" (*fpstate) : "memory"); - -	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); -	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { -		fpregset_t fpregs; -		if (!CPU_IS_060) -			context_size = fpstate[1]; -		fpu_version = fpstate[0]; -		if (CPU_IS_020_OR_030 && -		    regs->vector >= (VEC_FPBRUC * 4) && -		    regs->vector <= (VEC_FPNAN * 4)) { -			/* Clear pending exception in 68882 idle frame */ -			if (*(unsigned short *) fpstate == 0x1f38) -				fpstate[0x38] |= 1 << 3; -		} -		__asm__ volatile (".chip 68k/68881\n\t" -				  "fmovemx %%fp0-%%fp7,%0\n\t" -				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" -				  ".chip 68k" -				  : "=m" (*fpregs.f_fpregs), -				    "=m" (*fpregs.f_fpcntl) -				  : /* no inputs */ -				  : "memory"); -		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, -				    sizeof(fpregs)); -	} -	if (context_size) -		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, -				    context_size); -	return err; -} -  static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,  			     unsigned long mask)  { @@ -665,6 +800,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,  	sc->sc_sr = regs->sr;  	sc->sc_pc = regs->pc;  	sc->sc_formatvec = regs->format << 12 | regs->vector; +	save_a5_state(sc, regs);  	save_fpu_state(sc, regs);  } @@ -698,67 +834,6 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *  	return err;  } -static inline void push_cache (unsigned long vaddr) -{ -	/* -	 * Using the old cache_push_v() was really a big waste. -	 * -	 * What we are trying to do is to flush 8 bytes to ram. -	 * Flushing 2 cache lines of 16 bytes is much cheaper than -	 * flushing 1 or 2 pages, as previously done in -	 * cache_push_v(). -	 *                                                     Jes -	 */ -	if (CPU_IS_040) { -		unsigned long temp; - -		__asm__ __volatile__ (".chip 68040\n\t" -				      "nop\n\t" -				      "ptestr (%1)\n\t" -				      "movec %%mmusr,%0\n\t" -				      ".chip 68k" -				      : "=r" (temp) -				      : "a" (vaddr)); - -		temp &= PAGE_MASK; -		temp |= vaddr & ~PAGE_MASK; - -		__asm__ __volatile__ (".chip 68040\n\t" -				      "nop\n\t" -				      "cpushl %%bc,(%0)\n\t" -				      ".chip 68k" -				      : : "a" (temp)); -	} -	else if (CPU_IS_060) { -		unsigned long temp; -		__asm__ __volatile__ (".chip 68060\n\t" -				      "plpar (%0)\n\t" -				      ".chip 68k" -				      : "=a" (temp) -				      : "0" (vaddr)); -		__asm__ __volatile__ (".chip 68060\n\t" -				      "cpushl %%bc,(%0)\n\t" -				      ".chip 68k" -				      : : "a" (temp)); -	} -	else { -		/* -		 * 68030/68020 have no writeback cache; -		 * still need to clear icache. -		 * Note that vaddr is guaranteed to be long word aligned. -		 */ -		unsigned long temp; -		asm volatile ("movec %%cacr,%0" : "=r" (temp)); -		temp += 4; -		asm volatile ("movec %0,%%caar\n\t" -			      "movec %1,%%cacr" -			      : : "r" (vaddr), "r" (temp)); -		asm volatile ("movec %0,%%caar\n\t" -			      "movec %1,%%cacr" -			      : : "r" (vaddr + 4), "r" (temp)); -	} -} -  static inline void __user *  get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)  { @@ -775,11 +850,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)  	return (void __user *)((usp - frame_size) & -8UL);  } -static void setup_frame (int sig, struct k_sigaction *ka, +static int setup_frame (int sig, struct k_sigaction *ka,  			 sigset_t *set, struct pt_regs *regs)  {  	struct sigframe __user *frame; -	int fsize = frame_extra_sizes[regs->format]; +	int fsize = frame_extra_sizes(regs->format);  	struct sigcontext context;  	int err = 0; @@ -793,10 +868,8 @@ static void setup_frame (int sig, struct k_sigaction *ka,  	frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); -	if (fsize) { +	if (fsize)  		err |= copy_to_user (frame + 1, regs + 1, fsize); -		regs->stkadj = fsize; -	}  	err |= __put_user((current_thread_info()->exec_domain  			   && current_thread_info()->exec_domain->signal_invmap @@ -816,21 +889,36 @@ static void setup_frame (int sig, struct k_sigaction *ka,  	err |= copy_to_user (&frame->sc, &context, sizeof(context));  	/* Set up to return from userspace.  */ +#ifdef CONFIG_MMU  	err |= __put_user(frame->retcode, &frame->pretcode);  	/* moveq #,d0; trap #0 */  	err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),  			  (long __user *)(frame->retcode)); +#else +	err |= __put_user((void *) ret_from_user_signal, &frame->pretcode); +#endif  	if (err)  		goto give_sigsegv;  	push_cache ((unsigned long) &frame->retcode); -	/* Set up registers for signal handler */ +	/* +	 * Set up registers for signal handler.  All the state we are about +	 * to destroy is successfully copied to sigframe. +	 */  	wrusp ((unsigned long) frame);  	regs->pc = (unsigned long) ka->sa.sa_handler; +	adjustformat(regs); + +	/* +	 * This is subtle; if we build more than one sigframe, all but the +	 * first one will see frame format 0 and have fsize == 0, so we won't +	 * screw stkadj. +	 */ +	if (fsize) +		regs->stkadj = fsize; -adjust_stack:  	/* Prepare to skip over the extra stuff in the exception frame.  */  	if (regs->stkadj) {  		struct pt_regs *tregs = @@ -845,18 +933,18 @@ adjust_stack:  		tregs->pc = regs->pc;  		tregs->sr = regs->sr;  	} -	return; +	return 0;  give_sigsegv:  	force_sigsegv(sig, current); -	goto adjust_stack; +	return err;  } -static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,  			    sigset_t *set, struct pt_regs *regs)  {  	struct rt_sigframe __user *frame; -	int fsize = frame_extra_sizes[regs->format]; +	int fsize = frame_extra_sizes(regs->format);  	int err = 0;  	if (fsize < 0) { @@ -869,10 +957,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,  	frame = get_sigframe(ka, regs, sizeof(*frame)); -	if (fsize) { +	if (fsize)  		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); -		regs->stkadj = fsize; -	}  	err |= __put_user((current_thread_info()->exec_domain  			   && current_thread_info()->exec_domain->signal_invmap @@ -887,15 +973,12 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,  	/* Create the ucontext.  */  	err |= __put_user(0, &frame->uc.uc_flags);  	err |= __put_user(NULL, &frame->uc.uc_link); -	err |= __put_user((void __user *)current->sas_ss_sp, -			  &frame->uc.uc_stack.ss_sp); -	err |= __put_user(sas_ss_flags(rdusp()), -			  &frame->uc.uc_stack.ss_flags); -	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); +	err |= __save_altstack(&frame->uc.uc_stack, rdusp());  	err |= rt_setup_ucontext(&frame->uc, regs);  	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));  	/* Set up to return from userspace.  */ +#ifdef CONFIG_MMU  	err |= __put_user(frame->retcode, &frame->pretcode);  #ifdef __mcoldfire__  	/* movel #__NR_rt_sigreturn,d0; trap #0 */ @@ -908,17 +991,31 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,  			  (long __user *)(frame->retcode + 0));  	err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));  #endif +#else +	err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode); +#endif /* CONFIG_MMU */  	if (err)  		goto give_sigsegv;  	push_cache ((unsigned long) &frame->retcode); -	/* Set up registers for signal handler */ +	/* +	 * Set up registers for signal handler.  All the state we are about +	 * to destroy is successfully copied to sigframe. +	 */  	wrusp ((unsigned long) frame);  	regs->pc = (unsigned long) ka->sa.sa_handler; +	adjustformat(regs); + +	/* +	 * This is subtle; if we build more than one sigframe, all but the +	 * first one will see frame format 0 and have fsize == 0, so we won't +	 * screw stkadj. +	 */ +	if (fsize) +		regs->stkadj = fsize; -adjust_stack:  	/* Prepare to skip over the extra stuff in the exception frame.  */  	if (regs->stkadj) {  		struct pt_regs *tregs = @@ -933,11 +1030,11 @@ adjust_stack:  		tregs->pc = regs->pc;  		tregs->sr = regs->sr;  	} -	return; +	return 0;  give_sigsegv:  	force_sigsegv(sig, current); -	goto adjust_stack; +	return err;  }  static inline void @@ -973,28 +1070,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)  	}  } -void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) -{ -	if (regs->orig_d0 < 0) -		return; -	switch (regs->d0) { -	case -ERESTARTNOHAND: -	case -ERESTARTSYS: -	case -ERESTARTNOINTR: -		regs->d0 = regs->orig_d0; -		regs->orig_d0 = -1; -		regs->pc -= 2; -		break; -	} -} -  /*   * OK, we're invoking a handler   */  static void  handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, -	      sigset_t *oldset, struct pt_regs *regs) +	      struct pt_regs *regs)  { +	sigset_t *oldset = sigmask_to_save(); +	int err;  	/* are we from a system call? */  	if (regs->orig_d0 >= 0)  		/* If so, check system call restarting.. */ @@ -1002,17 +1086,19 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,  	/* set up the stack frame */  	if (ka->sa.sa_flags & SA_SIGINFO) -		setup_rt_frame(sig, ka, info, oldset, regs); +		err = setup_rt_frame(sig, ka, info, oldset, regs);  	else -		setup_frame(sig, ka, oldset, regs); +		err = setup_frame(sig, ka, oldset, regs); + +	if (err) +		return; -	if (ka->sa.sa_flags & SA_ONESHOT) -		ka->sa.sa_handler = SIG_DFL; +	signal_delivered(sig, info, ka, regs, 0); -	sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); -	if (!(ka->sa.sa_flags & SA_NODEFER)) -		sigaddset(¤t->blocked,sig); -	recalc_sigpending(); +	if (test_thread_flag(TIF_DELAYED_TRACE)) { +		regs->sr &= ~0x8000; +		send_sig(SIGTRAP, current, 1); +	}  }  /* @@ -1020,7 +1106,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,   * want to handle. Thus you cannot kill init even with a SIGKILL even by   * mistake.   */ -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +static void do_signal(struct pt_regs *regs)  {  	siginfo_t info;  	struct k_sigaction ka; @@ -1028,14 +1114,11 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)  	current->thread.esp0 = (unsigned long) regs; -	if (!oldset) -		oldset = ¤t->blocked; -  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);  	if (signr > 0) {  		/* Whee!  Actually deliver the signal.  */ -		handle_signal(signr, &ka, &info, oldset, regs); -		return 1; +		handle_signal(signr, &ka, &info, regs); +		return;  	}  	/* Did we come from a system call? */ @@ -1043,5 +1126,15 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)  		/* Restart the system call - no handlers present */  		handle_restart(regs, NULL, 0); -	return 0; +	/* If there's no signal to deliver, we just restore the saved mask.  */ +	restore_saved_sigmask(); +} + +void do_notify_resume(struct pt_regs *regs) +{ +	if (test_thread_flag(TIF_SIGPENDING)) +		do_signal(regs); + +	if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) +		tracehook_notify_resume(regs);  } diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 3db2e7f902a..3a480b3df0d 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -27,7 +27,10 @@  #include <asm/traps.h>  #include <asm/page.h>  #include <asm/unistd.h> -#include <linux/elf.h> +#include <asm/cacheflush.h> + +#ifdef CONFIG_MMU +  #include <asm/tlb.h>  asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, @@ -447,39 +450,6 @@ out:  	return ret;  } -asmlinkage int sys_getpagesize(void) -{ -	return PAGE_SIZE; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, -		  const char *const argv[], -		  const char *const envp[]) -{ -	register long __res asm ("%d0") = __NR_execve; -	register long __a asm ("%d1") = (long)(filename); -	register long __b asm ("%d2") = (long)(argv); -	register long __c asm ("%d3") = (long)(envp); -	asm volatile ("trap  #0" : "+d" (__res) -			: "d" (__a), "d" (__b), "d" (__c)); -	return __res; -} - -asmlinkage unsigned long sys_get_thread_area(void) -{ -	return current_thread_info()->tp_value; -} - -asmlinkage int sys_set_thread_area(unsigned long tp) -{ -	current_thread_info()->tp_value = tp; -	return 0; -} -  /* This syscall gets its arguments in A0 (mem), D2 (oldval) and     D1 (newval).  */  asmlinkage int @@ -509,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,  			goto bad_access;  		} -		mem_value = *mem; +		/* +		 * No need to check for EFAULT; we know that the page is +		 * present and writable. +		 */ +		__get_user(mem_value, mem);  		if (mem_value == oldval) -			*mem = newval; +			__put_user(newval, mem);  		pte_unmap_unlock(pte, ptl);  		up_read(&mm->mmap_sem); @@ -539,6 +513,53 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,  	}  } +#else + +/* sys_cacheflush -- flush (part of) the processor cache.  */ +asmlinkage int +sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) +{ +	flush_cache_all(); +	return 0; +} + +/* This syscall gets its arguments in A0 (mem), D2 (oldval) and +   D1 (newval).  */ +asmlinkage int +sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, +		      unsigned long __user * mem) +{ +	struct mm_struct *mm = current->mm; +	unsigned long mem_value; + +	down_read(&mm->mmap_sem); + +	mem_value = *mem; +	if (mem_value == oldval) +		*mem = newval; + +	up_read(&mm->mmap_sem); +	return mem_value; +} + +#endif /* CONFIG_MMU */ + +asmlinkage int sys_getpagesize(void) +{ +	return PAGE_SIZE; +} + +asmlinkage unsigned long sys_get_thread_area(void) +{ +	return current_thread_info()->tp_value; +} + +asmlinkage int sys_set_thread_area(unsigned long tp) +{ +	current_thread_info()->tp_value = tp; +	return 0; +} +  asmlinkage int sys_atomic_barrier(void)  {  	/* no code needed for uniprocs */ diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S new file mode 100644 index 00000000000..501e1021278 --- /dev/null +++ b/arch/m68k/kernel/syscalltable.S @@ -0,0 +1,375 @@ +/* + *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com) + * + *  Based on older entry.S files, the following copyrights apply: + * + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>, + *                      Kenneth Albanowski <kjahds@kjahds.com>, + *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)  + *  Copyright (C) 1991, 1992  Linus Torvalds + * + *  Linux/m68k support by Hamish Macdonald + */ + +#include <linux/linkage.h> + +#ifndef CONFIG_MMU +#define sys_mmap2		sys_mmap_pgoff +#endif + +.section .rodata +ALIGN +ENTRY(sys_call_table) +	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */ +	.long sys_exit +	.long __sys_fork +	.long sys_read +	.long sys_write +	.long sys_open			/* 5 */ +	.long sys_close +	.long sys_waitpid +	.long sys_creat +	.long sys_link +	.long sys_unlink		/* 10 */ +	.long sys_execve +	.long sys_chdir +	.long sys_time +	.long sys_mknod +	.long sys_chmod			/* 15 */ +	.long sys_chown16 +	.long sys_ni_syscall		/* old break syscall holder */ +	.long sys_stat +	.long sys_lseek +	.long sys_getpid		/* 20 */ +	.long sys_mount +	.long sys_oldumount +	.long sys_setuid16 +	.long sys_getuid16 +	.long sys_stime			/* 25 */ +	.long sys_ptrace +	.long sys_alarm +	.long sys_fstat +	.long sys_pause +	.long sys_utime			/* 30 */ +	.long sys_ni_syscall		/* old stty syscall holder */ +	.long sys_ni_syscall		/* old gtty syscall holder */ +	.long sys_access +	.long sys_nice +	.long sys_ni_syscall		/* 35 - old ftime syscall holder */ +	.long sys_sync +	.long sys_kill +	.long sys_rename +	.long sys_mkdir +	.long sys_rmdir			/* 40 */ +	.long sys_dup +	.long sys_pipe +	.long sys_times +	.long sys_ni_syscall		/* old prof syscall holder */ +	.long sys_brk			/* 45 */ +	.long sys_setgid16 +	.long sys_getgid16 +	.long sys_signal +	.long sys_geteuid16 +	.long sys_getegid16		/* 50 */ +	.long sys_acct +	.long sys_umount		/* recycled never used phys() */ +	.long sys_ni_syscall		/* old lock syscall holder */ +	.long sys_ioctl +	.long sys_fcntl			/* 55 */ +	.long sys_ni_syscall		/* old mpx syscall holder */ +	.long sys_setpgid +	.long sys_ni_syscall		/* old ulimit syscall holder */ +	.long sys_ni_syscall +	.long sys_umask			/* 60 */ +	.long sys_chroot +	.long sys_ustat +	.long sys_dup2 +	.long sys_getppid +	.long sys_getpgrp		/* 65 */ +	.long sys_setsid +	.long sys_sigaction +	.long sys_sgetmask +	.long sys_ssetmask +	.long sys_setreuid16		/* 70 */ +	.long sys_setregid16 +	.long sys_sigsuspend +	.long sys_sigpending +	.long sys_sethostname +	.long sys_setrlimit		/* 75 */ +	.long sys_old_getrlimit +	.long sys_getrusage +	.long sys_gettimeofday +	.long sys_settimeofday +	.long sys_getgroups16		/* 80 */ +	.long sys_setgroups16 +	.long sys_old_select +	.long sys_symlink +	.long sys_lstat +	.long sys_readlink		/* 85 */ +	.long sys_uselib +	.long sys_swapon +	.long sys_reboot +	.long sys_old_readdir +	.long sys_old_mmap		/* 90 */ +	.long sys_munmap +	.long sys_truncate +	.long sys_ftruncate +	.long sys_fchmod +	.long sys_fchown16		/* 95 */ +	.long sys_getpriority +	.long sys_setpriority +	.long sys_ni_syscall		/* old profil syscall holder */ +	.long sys_statfs +	.long sys_fstatfs		/* 100 */ +	.long sys_ni_syscall		/* ioperm for i386 */ +	.long sys_socketcall +	.long sys_syslog +	.long sys_setitimer +	.long sys_getitimer		/* 105 */ +	.long sys_newstat +	.long sys_newlstat +	.long sys_newfstat +	.long sys_ni_syscall +	.long sys_ni_syscall		/* 110 - iopl for i386 */ +	.long sys_vhangup +	.long sys_ni_syscall		/* obsolete idle() syscall */ +	.long sys_ni_syscall		/* vm86old for i386 */ +	.long sys_wait4 +	.long sys_swapoff		/* 115 */ +	.long sys_sysinfo +	.long sys_ipc +	.long sys_fsync +	.long sys_sigreturn +	.long __sys_clone		/* 120 */ +	.long sys_setdomainname +	.long sys_newuname +	.long sys_cacheflush		/* modify_ldt for i386 */ +	.long sys_adjtimex +	.long sys_mprotect		/* 125 */ +	.long sys_sigprocmask +	.long sys_ni_syscall		/* old "create_module" */ +	.long sys_init_module +	.long sys_delete_module +	.long sys_ni_syscall		/* 130 - old "get_kernel_syms" */ +	.long sys_quotactl +	.long sys_getpgid +	.long sys_fchdir +	.long sys_bdflush +	.long sys_sysfs			/* 135 */ +	.long sys_personality +	.long sys_ni_syscall		/* for afs_syscall */ +	.long sys_setfsuid16 +	.long sys_setfsgid16 +	.long sys_llseek		/* 140 */ +	.long sys_getdents +	.long sys_select +	.long sys_flock +	.long sys_msync +	.long sys_readv			/* 145 */ +	.long sys_writev +	.long sys_getsid +	.long sys_fdatasync +	.long sys_sysctl +	.long sys_mlock			/* 150 */ +	.long sys_munlock +	.long sys_mlockall +	.long sys_munlockall +	.long sys_sched_setparam +	.long sys_sched_getparam	/* 155 */ +	.long sys_sched_setscheduler +	.long sys_sched_getscheduler +	.long sys_sched_yield +	.long sys_sched_get_priority_max +	.long sys_sched_get_priority_min  /* 160 */ +	.long sys_sched_rr_get_interval +	.long sys_nanosleep +	.long sys_mremap +	.long sys_setresuid16 +	.long sys_getresuid16		/* 165 */ +	.long sys_getpagesize +	.long sys_ni_syscall		/* old "query_module" */ +	.long sys_poll +	.long sys_ni_syscall		/* old nfsservctl */ +	.long sys_setresgid16		/* 170 */ +	.long sys_getresgid16 +	.long sys_prctl +	.long sys_rt_sigreturn +	.long sys_rt_sigaction +	.long sys_rt_sigprocmask	/* 175 */ +	.long sys_rt_sigpending +	.long sys_rt_sigtimedwait +	.long sys_rt_sigqueueinfo +	.long sys_rt_sigsuspend +	.long sys_pread64		/* 180 */ +	.long sys_pwrite64 +	.long sys_lchown16 +	.long sys_getcwd +	.long sys_capget +	.long sys_capset		/* 185 */ +	.long sys_sigaltstack +	.long sys_sendfile +	.long sys_ni_syscall		/* streams1 */ +	.long sys_ni_syscall		/* streams2 */ +	.long __sys_vfork		/* 190 */ +	.long sys_getrlimit +	.long sys_mmap2 +	.long sys_truncate64 +	.long sys_ftruncate64 +	.long sys_stat64		/* 195 */ +	.long sys_lstat64 +	.long sys_fstat64 +	.long sys_chown +	.long sys_getuid +	.long sys_getgid		/* 200 */ +	.long sys_geteuid +	.long sys_getegid +	.long sys_setreuid +	.long sys_setregid +	.long sys_getgroups		/* 205 */ +	.long sys_setgroups +	.long sys_fchown +	.long sys_setresuid +	.long sys_getresuid +	.long sys_setresgid		/* 210 */ +	.long sys_getresgid +	.long sys_lchown +	.long sys_setuid +	.long sys_setgid +	.long sys_setfsuid		/* 215 */ +	.long sys_setfsgid +	.long sys_pivot_root +	.long sys_ni_syscall +	.long sys_ni_syscall +	.long sys_getdents64		/* 220 */ +	.long sys_gettid +	.long sys_tkill +	.long sys_setxattr +	.long sys_lsetxattr +	.long sys_fsetxattr		/* 225 */ +	.long sys_getxattr +	.long sys_lgetxattr +	.long sys_fgetxattr +	.long sys_listxattr +	.long sys_llistxattr		/* 230 */ +	.long sys_flistxattr +	.long sys_removexattr +	.long sys_lremovexattr +	.long sys_fremovexattr +	.long sys_futex			/* 235 */ +	.long sys_sendfile64 +	.long sys_mincore +	.long sys_madvise +	.long sys_fcntl64 +	.long sys_readahead		/* 240 */ +	.long sys_io_setup +	.long sys_io_destroy +	.long sys_io_getevents +	.long sys_io_submit +	.long sys_io_cancel		/* 245 */ +	.long sys_fadvise64 +	.long sys_exit_group +	.long sys_lookup_dcookie +	.long sys_epoll_create +	.long sys_epoll_ctl		/* 250 */ +	.long sys_epoll_wait +	.long sys_remap_file_pages +	.long sys_set_tid_address +	.long sys_timer_create +	.long sys_timer_settime		/* 255 */ +	.long sys_timer_gettime +	.long sys_timer_getoverrun +	.long sys_timer_delete +	.long sys_clock_settime +	.long sys_clock_gettime		/* 260 */ +	.long sys_clock_getres +	.long sys_clock_nanosleep +	.long sys_statfs64 +	.long sys_fstatfs64 +	.long sys_tgkill		/* 265 */ +	.long sys_utimes +	.long sys_fadvise64_64 +	.long sys_mbind +	.long sys_get_mempolicy +	.long sys_set_mempolicy		/* 270 */ +	.long sys_mq_open +	.long sys_mq_unlink +	.long sys_mq_timedsend +	.long sys_mq_timedreceive +	.long sys_mq_notify		/* 275 */ +	.long sys_mq_getsetattr +	.long sys_waitid +	.long sys_ni_syscall		/* for sys_vserver */ +	.long sys_add_key +	.long sys_request_key		/* 280 */ +	.long sys_keyctl +	.long sys_ioprio_set +	.long sys_ioprio_get +	.long sys_inotify_init +	.long sys_inotify_add_watch	/* 285 */ +	.long sys_inotify_rm_watch +	.long sys_migrate_pages +	.long sys_openat +	.long sys_mkdirat +	.long sys_mknodat		/* 290 */ +	.long sys_fchownat +	.long sys_futimesat +	.long sys_fstatat64 +	.long sys_unlinkat +	.long sys_renameat		/* 295 */ +	.long sys_linkat +	.long sys_symlinkat +	.long sys_readlinkat +	.long sys_fchmodat +	.long sys_faccessat		/* 300 */ +	.long sys_pselect6 +	.long sys_ppoll +	.long sys_unshare +	.long sys_set_robust_list +	.long sys_get_robust_list	/* 305 */ +	.long sys_splice +	.long sys_sync_file_range +	.long sys_tee +	.long sys_vmsplice +	.long sys_move_pages		/* 310 */ +	.long sys_sched_setaffinity +	.long sys_sched_getaffinity +	.long sys_kexec_load +	.long sys_getcpu +	.long sys_epoll_pwait		/* 315 */ +	.long sys_utimensat +	.long sys_signalfd +	.long sys_timerfd_create +	.long sys_eventfd +	.long sys_fallocate		/* 320 */ +	.long sys_timerfd_settime +	.long sys_timerfd_gettime +	.long sys_signalfd4 +	.long sys_eventfd2 +	.long sys_epoll_create1		/* 325 */ +	.long sys_dup3 +	.long sys_pipe2 +	.long sys_inotify_init1 +	.long sys_preadv +	.long sys_pwritev		/* 330 */ +	.long sys_rt_tgsigqueueinfo +	.long sys_perf_event_open +	.long sys_get_thread_area +	.long sys_set_thread_area +	.long sys_atomic_cmpxchg_32	/* 335 */ +	.long sys_atomic_barrier +	.long sys_fanotify_init +	.long sys_fanotify_mark +	.long sys_prlimit64 +	.long sys_name_to_handle_at	/* 340 */ +	.long sys_open_by_handle_at +	.long sys_clock_adjtime +	.long sys_syncfs +	.long sys_setns +	.long sys_process_vm_readv	/* 345 */ +	.long sys_process_vm_writev +	.long sys_kcmp +	.long sys_finit_module +	.long sys_sched_setattr +	.long sys_sched_getattr		/* 350 */ +	.long sys_renameat2 + diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 06438dac08f..3857737e395 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -11,6 +11,7 @@   */  #include <linux/errno.h> +#include <linux/export.h>  #include <linux/module.h>  #include <linux/sched.h>  #include <linux/kernel.h> @@ -28,20 +29,18 @@  #include <linux/timex.h>  #include <linux/profile.h> -static inline int set_rtc_mmss(unsigned long nowtime) -{ -  if (mach_set_clock_mmss) -    return mach_set_clock_mmss (nowtime); -  return -1; -} + +unsigned long (*mach_random_get_entropy)(void); +EXPORT_SYMBOL_GPL(mach_random_get_entropy); +  /*   * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick + * as well as call the "xtime_update()" routine every clocktick   */  static irqreturn_t timer_interrupt(int irq, void *dummy)  { -	do_timer(1); +	xtime_update(1);  	update_process_times(user_mode(get_irq_regs()));  	profile_tick(CPU_PROFILING); @@ -87,15 +86,7 @@ void read_persistent_clock(struct timespec *ts)  	}  } -void __init time_init(void) -{ -	mach_sched_init(timer_interrupt); -} - -u32 arch_gettimeoffset(void) -{ -	return mach_gettimeoffset() * 1000; -} +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET  static int __init rtc_init(void)  { @@ -105,10 +96,14 @@ static int __init rtc_init(void)  		return -ENODEV;  	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); -	if (IS_ERR(pdev)) -		return PTR_ERR(pdev); - -	return 0; +	return PTR_ERR_OR_ZERO(pdev);  }  module_init(rtc_init); + +#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ + +void __init time_init(void) +{ +	mach_sched_init(timer_interrupt); +} diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index ada4f4cca81..6c9ca24830e 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -32,126 +32,12 @@  #include <asm/setup.h>  #include <asm/fpu.h> -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/traps.h>  #include <asm/pgalloc.h>  #include <asm/machdep.h>  #include <asm/siginfo.h> -/* assembler routines */ -asmlinkage void system_call(void); -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void nmihandler(void); -#ifdef CONFIG_M68KFPU_EMU -asmlinkage void fpu_emu(void); -#endif - -e_vector vectors[256] = { -	[VEC_BUSERR]	= buserr, -	[VEC_SYS]	= system_call, -}; - -/* nmi handler for the Amiga */ -asm(".text\n" -    __ALIGN_STR "\n" -    "nmihandler: rte"); - -/* - * this must be called very early as the kernel might - * use some instruction that are emulated on the 060 - */ -void __init base_trap_init(void) -{ -	if(MACH_IS_SUN3X) { -		extern e_vector *sun3x_prom_vbr; - -		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); -	} - -	/* setup the exception vector table */ -	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); - -	if (CPU_IS_060) { -		/* set up ISP entry points */ -		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); - -		vectors[VEC_UNIMPII] = unimp_vec; -	} -} - -void __init trap_init (void) -{ -	int i; - -	for (i = VEC_SPUR; i <= VEC_INT7; i++) -		vectors[i] = bad_inthandler; - -	for (i = 0; i < VEC_USER; i++) -		if (!vectors[i]) -			vectors[i] = trap; - -	for (i = VEC_USER; i < 256; i++) -		vectors[i] = bad_inthandler; - -#ifdef CONFIG_M68KFPU_EMU -	if (FPU_IS_EMU) -		vectors[VEC_LINE11] = fpu_emu; -#endif - -	if (CPU_IS_040 && !FPU_IS_EMU) { -		/* set up FPSP entry points */ -		asmlinkage void dz_vec(void) asm ("dz"); -		asmlinkage void inex_vec(void) asm ("inex"); -		asmlinkage void ovfl_vec(void) asm ("ovfl"); -		asmlinkage void unfl_vec(void) asm ("unfl"); -		asmlinkage void snan_vec(void) asm ("snan"); -		asmlinkage void operr_vec(void) asm ("operr"); -		asmlinkage void bsun_vec(void) asm ("bsun"); -		asmlinkage void fline_vec(void) asm ("fline"); -		asmlinkage void unsupp_vec(void) asm ("unsupp"); - -		vectors[VEC_FPDIVZ] = dz_vec; -		vectors[VEC_FPIR] = inex_vec; -		vectors[VEC_FPOVER] = ovfl_vec; -		vectors[VEC_FPUNDER] = unfl_vec; -		vectors[VEC_FPNAN] = snan_vec; -		vectors[VEC_FPOE] = operr_vec; -		vectors[VEC_FPBRUC] = bsun_vec; -		vectors[VEC_LINE11] = fline_vec; -		vectors[VEC_FPUNSUP] = unsupp_vec; -	} - -	if (CPU_IS_060 && !FPU_IS_EMU) { -		/* set up IFPSP entry points */ -		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); -		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); -		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); -		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); -		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); -		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); -		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); -		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); -		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); - -		vectors[VEC_FPNAN] = snan_vec6; -		vectors[VEC_FPOE] = operr_vec6; -		vectors[VEC_FPOVER] = ovfl_vec6; -		vectors[VEC_FPUNDER] = unfl_vec6; -		vectors[VEC_FPDIVZ] = dz_vec6; -		vectors[VEC_FPIR] = inex_vec6; -		vectors[VEC_LINE11] = fline_vec6; -		vectors[VEC_FPUNSUP] = unsupp_vec6; -		vectors[VEC_UNIMPEA] = effadd_vec6; -	} - -        /* if running on an amiga, make the NMI interrupt do nothing */ -	if (MACH_IS_AMIGA) { -		vectors[VEC_INT7] = nmihandler; -	} -} -  static const char *vec_names[] = {  	[VEC_RESETSP]	= "RESET SP", @@ -247,9 +133,7 @@ static inline void access_error060 (struct frame *fp)  {  	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ -#ifdef DEBUG -	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); -#endif +	pr_debug("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);  	if (fslw & MMU060_BPE) {  		/* branch prediction error -> clear branch cache */ @@ -276,9 +160,7 @@ static inline void access_error060 (struct frame *fp)  		}  		if (fslw & MMU060_W)  			errorcode |= 2; -#ifdef DEBUG -		printk("errorcode = %d\n", errorcode ); -#endif +		pr_debug("errorcode = %ld\n", errorcode);  		do_page_fault(&fp->ptregs, addr, errorcode);  	} else if (fslw & (MMU060_SEE)){  		/* Software Emulation Error. @@ -287,8 +169,9 @@ static inline void access_error060 (struct frame *fp)  		send_fault_sig(&fp->ptregs);  	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||  		   send_fault_sig(&fp->ptregs) > 0) { -		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); -		printk( "68060 access error, fslw=%lx\n", fslw ); +		pr_err("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, +		       fp->un.fmt4.effaddr); +		pr_err("68060 access error, fslw=%lx\n", fslw);  		trap_c( fp );  	}  } @@ -339,9 +222,7 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba,  	set_fs(old_fs); -#ifdef DEBUG -	printk("do_040writeback1, res=%d\n",res); -#endif +	pr_debug("do_040writeback1, res=%d\n", res);  	return res;  } @@ -363,7 +244,7 @@ static inline void do_040writebacks(struct frame *fp)  	int res = 0;  #if 0  	if (fp->un.fmt7.wb1s & WBV_040) -		printk("access_error040: cannot handle 1st writeback. oops.\n"); +		pr_err("access_error040: cannot handle 1st writeback. oops.\n");  #endif  	if ((fp->un.fmt7.wb2s & WBV_040) && @@ -416,14 +297,12 @@ static inline void access_error040(struct frame *fp)  	unsigned short ssw = fp->un.fmt7.ssw;  	unsigned long mmusr; -#ifdef DEBUG -	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); -        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, +	pr_debug("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); +	pr_debug("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,  		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); -	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", +	pr_debug("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",  		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,  		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); -#endif  	if (ssw & ATC_040) {  		unsigned long addr = fp->un.fmt7.faddr; @@ -438,9 +317,7 @@ static inline void access_error040(struct frame *fp)  		/* MMU error, get the MMUSR info for this access */  		mmusr = probe040(!(ssw & RW_040), addr, ssw); -#ifdef DEBUG -		printk("mmusr = %lx\n", mmusr); -#endif +		pr_debug("mmusr = %lx\n", mmusr);  		errorcode = 1;  		if (!(mmusr & MMU_R_040)) {  			/* clear the invalid atc entry */ @@ -454,14 +331,10 @@ static inline void access_error040(struct frame *fp)  			errorcode |= 2;  		if (do_page_fault(&fp->ptregs, addr, errorcode)) { -#ifdef DEBUG -			printk("do_page_fault() !=0\n"); -#endif +			pr_debug("do_page_fault() !=0\n");  			if (user_mode(&fp->ptregs)){  				/* delay writebacks after signal delivery */ -#ifdef DEBUG -			        printk(".. was usermode - return\n"); -#endif +				pr_debug(".. was usermode - return\n");  				return;  			}  			/* disable writeback into user space from kernel @@ -469,9 +342,7 @@ static inline void access_error040(struct frame *fp)                           * the writeback won't do good)  			 */  disable_wb: -#ifdef DEBUG -			printk(".. disabling wb2\n"); -#endif +			pr_debug(".. disabling wb2\n");  			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)  				fp->un.fmt7.wb2s &= ~WBV_040;  			if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) @@ -485,7 +356,7 @@ disable_wb:  		current->thread.signo = SIGBUS;  		current->thread.faddr = fp->un.fmt7.faddr;  		if (send_fault_sig(&fp->ptregs) >= 0) -			printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, +			pr_err("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,  			       fp->un.fmt7.faddr);  		goto disable_wb;  	} @@ -508,19 +379,17 @@ static inline void bus_error030 (struct frame *fp)  	unsigned short ssw = fp->un.fmtb.ssw;  	extern unsigned long _sun3_map_test_start, _sun3_map_test_end; -#ifdef DEBUG  	if (ssw & (FC | FB)) -		printk ("Instruction fault at %#010lx\n", +		pr_debug("Instruction fault at %#010lx\n",  			ssw & FC ?  			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2  			:  			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);  	if (ssw & DF) -		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", +		pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",  			ssw & RW ? "read" : "write",  			fp->un.fmtb.daddr,  			space_names[ssw & DFC], fp->ptregs.pc); -#endif  	/*  	 * Check if this page should be demand-mapped. This needs to go before @@ -543,7 +412,7 @@ static inline void bus_error030 (struct frame *fp)  			  return;  			/* instruction fault or kernel data fault! */  			if (ssw & (FC | FB)) -				printk ("Instruction fault at %#010lx\n", +				pr_err("Instruction fault at %#010lx\n",  					fp->ptregs.pc);  			if (ssw & DF) {  				/* was this fault incurred testing bus mappings? */ @@ -553,12 +422,12 @@ static inline void bus_error030 (struct frame *fp)  					return;  				} -				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", +				pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",  					ssw & RW ? "read" : "write",  					fp->un.fmtb.daddr,  					space_names[ssw & DFC], fp->ptregs.pc);  			} -			printk ("BAD KERNEL BUSERR\n"); +			pr_err("BAD KERNEL BUSERR\n");  			die_if_kernel("Oops", &fp->ptregs,0);  			force_sig(SIGKILL, current); @@ -587,12 +456,11 @@ static inline void bus_error030 (struct frame *fp)  		else if (buserr_type & SUN3_BUSERR_INVALID)  			errorcode = 0x00;  		else { -#ifdef DEBUG -			printk ("*** unexpected busfault type=%#04x\n", buserr_type); -			printk ("invalid %s access at %#lx from pc %#lx\n", -				!(ssw & RW) ? "write" : "read", addr, -				fp->ptregs.pc); -#endif +			pr_debug("*** unexpected busfault type=%#04x\n", +				 buserr_type); +			pr_debug("invalid %s access at %#lx from pc %#lx\n", +				 !(ssw & RW) ? "write" : "read", addr, +				 fp->ptregs.pc);  			die_if_kernel ("Oops", &fp->ptregs, buserr_type);  			force_sig (SIGBUS, current);  			return; @@ -620,12 +488,10 @@ static inline void bus_error030 (struct frame *fp)  		addr -= 2;  	if (buserr_type & SUN3_BUSERR_INVALID) { -		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) +		if (!mmu_emu_handle_fault(addr, 1, 0))  			do_page_fault (&fp->ptregs, addr, 0);         } else { -#ifdef DEBUG -		printk ("protection fault on insn access (segv).\n"); -#endif +		pr_debug("protection fault on insn access (segv).\n");  		force_sig (SIGSEGV, current);         }  } @@ -639,22 +505,22 @@ static inline void bus_error030 (struct frame *fp)  	unsigned short ssw = fp->un.fmtb.ssw;  #ifdef DEBUG  	unsigned long desc; +#endif -	printk ("pid = %x  ", current->pid); -	printk ("SSW=%#06x  ", ssw); +	pr_debug("pid = %x  ", current->pid); +	pr_debug("SSW=%#06x  ", ssw);  	if (ssw & (FC | FB)) -		printk ("Instruction fault at %#010lx\n", +		pr_debug("Instruction fault at %#010lx\n",  			ssw & FC ?  			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2  			:  			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);  	if (ssw & DF) -		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", +		pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",  			ssw & RW ? "read" : "write",  			fp->un.fmtb.daddr,  			space_names[ssw & DFC], fp->ptregs.pc); -#endif  	/* ++andreas: If a data fault and an instruction fault happen  	   at the same time map in both pages.  */ @@ -665,30 +531,26 @@ static inline void bus_error030 (struct frame *fp)  #ifdef DEBUG  		asm volatile ("ptestr %3,%2@,#7,%0\n\t" -			      "pmove %%psr,%1@" -			      : "=a&" (desc) -			      : "a" (&temp), "a" (addr), "d" (ssw)); +			      "pmove %%psr,%1" +			      : "=a&" (desc), "=m" (temp) +			      : "a" (addr), "d" (ssw)); +		pr_debug("mmusr is %#x for addr %#lx in task %p\n", +			 temp, addr, current); +		pr_debug("descriptor address is 0x%p, contents %#lx\n", +			 __va(desc), *(unsigned long *)__va(desc));  #else  		asm volatile ("ptestr %2,%1@,#7\n\t" -			      "pmove %%psr,%0@" -			      : : "a" (&temp), "a" (addr), "d" (ssw)); +			      "pmove %%psr,%0" +			      : "=m" (temp) : "a" (addr), "d" (ssw));  #endif  		mmusr = temp; - -#ifdef DEBUG -		printk("mmusr is %#x for addr %#lx in task %p\n", -		       mmusr, addr, current); -		printk("descriptor address is %#lx, contents %#lx\n", -		       __va(desc), *(unsigned long *)__va(desc)); -#endif -  		errorcode = (mmusr & MMU_I) ? 0 : 1;  		if (!(ssw & RW) || (ssw & RM))  			errorcode |= 2;  		if (mmusr & (MMU_I | MMU_WP)) {  			if (ssw & 4) { -				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", +				pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",  				       ssw & RW ? "read" : "write",  				       fp->un.fmtb.daddr,  				       space_names[ssw & DFC], fp->ptregs.pc); @@ -701,9 +563,10 @@ static inline void bus_error030 (struct frame *fp)  		} else if (!(mmusr & MMU_I)) {  			/* probably a 020 cas fault */  			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) -				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); +				pr_err("unexpected bus error (%#x,%#x)\n", ssw, +				       mmusr);  		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) { -			printk("invalid %s access at %#lx from pc %#lx\n", +			pr_err("invalid %s access at %#lx from pc %#lx\n",  			       !(ssw & RW) ? "write" : "read", addr,  			       fp->ptregs.pc);  			die_if_kernel("Oops",&fp->ptregs,mmusr); @@ -714,29 +577,25 @@ static inline void bus_error030 (struct frame *fp)  			static volatile long tlong;  #endif -			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", +			pr_err("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",  			       !(ssw & RW) ? "write" : "read", addr,  			       fp->ptregs.pc, ssw);  			asm volatile ("ptestr #1,%1@,#0\n\t" -				      "pmove %%psr,%0@" -				      : /* no outputs */ -				      : "a" (&temp), "a" (addr)); +				      "pmove %%psr,%0" +				      : "=m" (temp) +				      : "a" (addr));  			mmusr = temp; -			printk ("level 0 mmusr is %#x\n", mmusr); +			pr_err("level 0 mmusr is %#x\n", mmusr);  #if 0 -			asm volatile ("pmove %%tt0,%0@" -				      : /* no outputs */ -				      : "a" (&tlong)); -			printk("tt0 is %#lx, ", tlong); -			asm volatile ("pmove %%tt1,%0@" -				      : /* no outputs */ -				      : "a" (&tlong)); -			printk("tt1 is %#lx\n", tlong); -#endif -#ifdef DEBUG -			printk("Unknown SIGSEGV - 1\n"); +			asm volatile ("pmove %%tt0,%0" +				      : "=m" (tlong)); +			pr_debug("tt0 is %#lx, ", tlong); +			asm volatile ("pmove %%tt1,%0" +				      : "=m" (tlong)); +			pr_debug("tt1 is %#lx\n", tlong);  #endif +			pr_debug("Unknown SIGSEGV - 1\n");  			die_if_kernel("Oops",&fp->ptregs,mmusr);  			force_sig(SIGSEGV, current);  			return; @@ -757,10 +616,9 @@ static inline void bus_error030 (struct frame *fp)  		return;  	if (fp->ptregs.sr & PS_S) { -		printk("Instruction fault at %#010lx\n", -			fp->ptregs.pc); +		pr_err("Instruction fault at %#010lx\n", fp->ptregs.pc);  	buserr: -		printk ("BAD KERNEL BUSERR\n"); +		pr_err("BAD KERNEL BUSERR\n");  		die_if_kernel("Oops",&fp->ptregs,0);  		force_sig(SIGKILL, current);  		return; @@ -781,31 +639,25 @@ static inline void bus_error030 (struct frame *fp)  #ifdef DEBUG  	asm volatile ("ptestr #1,%2@,#7,%0\n\t" -		      "pmove %%psr,%1@" -		      : "=a&" (desc) -		      : "a" (&temp), "a" (addr)); +		      "pmove %%psr,%1" +		      : "=a&" (desc), "=m" (temp) +		      : "a" (addr)); +	pr_debug("mmusr is %#x for addr %#lx in task %p\n", +		temp, addr, current); +	pr_debug("descriptor address is 0x%p, contents %#lx\n", +		__va(desc), *(unsigned long *)__va(desc));  #else  	asm volatile ("ptestr #1,%1@,#7\n\t" -		      "pmove %%psr,%0@" -		      : : "a" (&temp), "a" (addr)); +		      "pmove %%psr,%0" +		      : "=m" (temp) : "a" (addr));  #endif  	mmusr = temp; - -#ifdef DEBUG -	printk ("mmusr is %#x for addr %#lx in task %p\n", -		mmusr, addr, current); -	printk ("descriptor address is %#lx, contents %#lx\n", -		__va(desc), *(unsigned long *)__va(desc)); -#endif -  	if (mmusr & MMU_I)  		do_page_fault (&fp->ptregs, addr, 0);  	else if (mmusr & (MMU_B|MMU_L|MMU_S)) { -		printk ("invalid insn access at %#lx from pc %#lx\n", +		pr_err("invalid insn access at %#lx from pc %#lx\n",  			addr, fp->ptregs.pc); -#ifdef DEBUG -		printk("Unknown SIGSEGV - 2\n"); -#endif +		pr_debug("Unknown SIGSEGV - 2\n");  		die_if_kernel("Oops",&fp->ptregs,mmusr);  		force_sig(SIGSEGV, current);  		return; @@ -819,15 +671,117 @@ create_atc_entry:  #endif /* CPU_M68020_OR_M68030 */  #endif /* !CONFIG_SUN3 */ +#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) +#include <asm/mcfmmu.h> + +/* + *	The following table converts the FS encoding of a ColdFire + *	exception stack frame into the error_code value needed by + *	do_fault. +*/ +static const unsigned char fs_err_code[] = { +	0,  /* 0000 */ +	0,  /* 0001 */ +	0,  /* 0010 */ +	0,  /* 0011 */ +	1,  /* 0100 */ +	0,  /* 0101 */ +	0,  /* 0110 */ +	0,  /* 0111 */ +	2,  /* 1000 */ +	3,  /* 1001 */ +	2,  /* 1010 */ +	0,  /* 1011 */ +	1,  /* 1100 */ +	1,  /* 1101 */ +	0,  /* 1110 */ +	0   /* 1111 */ +}; + +static inline void access_errorcf(unsigned int fs, struct frame *fp) +{ +	unsigned long mmusr, addr; +	unsigned int err_code; +	int need_page_fault; + +	mmusr = mmu_read(MMUSR); +	addr = mmu_read(MMUAR); + +	/* +	 * error_code: +	 *	bit 0 == 0 means no page found, 1 means protection fault +	 *	bit 1 == 0 means read, 1 means write +	 */ +	switch (fs) { +	case  5:  /* 0101 TLB opword X miss */ +		need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0); +		addr = fp->ptregs.pc; +		break; +	case  6:  /* 0110 TLB extension word X miss */ +		need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1); +		addr = fp->ptregs.pc + sizeof(long); +		break; +	case 10:  /* 1010 TLB W miss */ +		need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0); +		break; +	case 14: /* 1110 TLB R miss */ +		need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0); +		break; +	default: +		/* 0000 Normal  */ +		/* 0001 Reserved */ +		/* 0010 Interrupt during debug service routine */ +		/* 0011 Reserved */ +		/* 0100 X Protection */ +		/* 0111 IFP in emulator mode */ +		/* 1000 W Protection*/ +		/* 1001 Write error*/ +		/* 1011 Reserved*/ +		/* 1100 R Protection*/ +		/* 1101 R Protection*/ +		/* 1111 OEP in emulator mode*/ +		need_page_fault = 1; +		break; +	} + +	if (need_page_fault) { +		err_code = fs_err_code[fs]; +		if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */ +			err_code |= 2; /* bit1 - write, bit0 - protection */ +		do_page_fault(&fp->ptregs, addr, err_code); +	} +} +#endif /* CONFIG_COLDFIRE CONFIG_MMU */ +  asmlinkage void buserr_c(struct frame *fp)  {  	/* Only set esp0 if coming from user mode */  	if (user_mode(&fp->ptregs))  		current->thread.esp0 = (unsigned long) fp; -#ifdef DEBUG -	printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); -#endif +	pr_debug("*** Bus Error *** Format is %x\n", fp->ptregs.format); + +#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) +	if (CPU_IS_COLDFIRE) { +		unsigned int fs; +		fs = (fp->ptregs.vector & 0x3) | +			((fp->ptregs.vector & 0xc00) >> 8); +		switch (fs) { +		case 0x5: +		case 0x6: +		case 0x7: +		case 0x9: +		case 0xa: +		case 0xd: +		case 0xe: +		case 0xf: +			access_errorcf(fs, fp); +			return; +		default: +			break; +		} +	} +#endif /* CONFIG_COLDFIRE && CONFIG_MMU */  	switch (fp->ptregs.format) {  #if defined (CONFIG_M68060) @@ -848,9 +802,7 @@ asmlinkage void buserr_c(struct frame *fp)  #endif  	default:  	  die_if_kernel("bad frame format",&fp->ptregs,0); -#ifdef DEBUG -	  printk("Unknown SIGSEGV - 4\n"); -#endif +	  pr_debug("Unknown SIGSEGV - 4\n");  	  force_sig(SIGSEGV, current);  	}  } @@ -864,7 +816,7 @@ void show_trace(unsigned long *stack)  	unsigned long addr;  	int i; -	printk("Call Trace:"); +	pr_info("Call Trace:");  	addr = (unsigned long)stack + THREAD_SIZE - 1;  	endstack = (unsigned long *)(addr & -THREAD_SIZE);  	i = 0; @@ -881,13 +833,13 @@ void show_trace(unsigned long *stack)  		if (__kernel_text_address(addr)) {  #ifndef CONFIG_KALLSYMS  			if (i % 5 == 0) -				printk("\n       "); +				pr_cont("\n       ");  #endif -			printk(" [<%08lx>] %pS\n", addr, (void *)addr); +			pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr);  			i++;  		}  	} -	printk("\n"); +	pr_cont("\n");  }  void show_registers(struct pt_regs *regs) @@ -899,81 +851,87 @@ void show_registers(struct pt_regs *regs)  	int i;  	print_modules(); -	printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); -	printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2); -	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n", +	pr_info("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); +	pr_info("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2); +	pr_info("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",  	       regs->d0, regs->d1, regs->d2, regs->d3); -	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n", +	pr_info("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",  	       regs->d4, regs->d5, regs->a0, regs->a1); -	printk("Process %s (pid: %d, task=%p)\n", +	pr_info("Process %s (pid: %d, task=%p)\n",  		current->comm, task_pid_nr(current), current);  	addr = (unsigned long)&fp->un; -	printk("Frame format=%X ", regs->format); +	pr_info("Frame format=%X ", regs->format);  	switch (regs->format) {  	case 0x2: -		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); +		pr_cont("instr addr=%08lx\n", fp->un.fmt2.iaddr);  		addr += sizeof(fp->un.fmt2);  		break;  	case 0x3: -		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); +		pr_cont("eff addr=%08lx\n", fp->un.fmt3.effaddr);  		addr += sizeof(fp->un.fmt3);  		break;  	case 0x4: -		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" -			: "eff addr=%08lx pc=%08lx\n"), -			fp->un.fmt4.effaddr, fp->un.fmt4.pc); +		if (CPU_IS_060) +			pr_cont("fault addr=%08lx fslw=%08lx\n", +				fp->un.fmt4.effaddr, fp->un.fmt4.pc); +		else +			pr_cont("eff addr=%08lx pc=%08lx\n", +				fp->un.fmt4.effaddr, fp->un.fmt4.pc);  		addr += sizeof(fp->un.fmt4);  		break;  	case 0x7: -		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", +		pr_cont("eff addr=%08lx ssw=%04x faddr=%08lx\n",  			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); -		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", +		pr_info("wb 1 stat/addr/data: %04x %08lx %08lx\n",  			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); -		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", +		pr_info("wb 2 stat/addr/data: %04x %08lx %08lx\n",  			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); -		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", +		pr_info("wb 3 stat/addr/data: %04x %08lx %08lx\n",  			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); -		printk("push data: %08lx %08lx %08lx %08lx\n", +		pr_info("push data: %08lx %08lx %08lx %08lx\n",  			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,  			fp->un.fmt7.pd3);  		addr += sizeof(fp->un.fmt7);  		break;  	case 0x9: -		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); +		pr_cont("instr addr=%08lx\n", fp->un.fmt9.iaddr);  		addr += sizeof(fp->un.fmt9);  		break;  	case 0xa: -		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", +		pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",  			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,  			fp->un.fmta.daddr, fp->un.fmta.dobuf);  		addr += sizeof(fp->un.fmta);  		break;  	case 0xb: -		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", +		pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",  			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,  			fp->un.fmtb.daddr, fp->un.fmtb.dobuf); -		printk("baddr=%08lx dibuf=%08lx ver=%x\n", +		pr_info("baddr=%08lx dibuf=%08lx ver=%x\n",  			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);  		addr += sizeof(fp->un.fmtb);  		break;  	default: -		printk("\n"); +		pr_cont("\n");  	}  	show_stack(NULL, (unsigned long *)addr); -	printk("Code:"); +	pr_info("Code:");  	set_fs(KERNEL_DS);  	cp = (u16 *)regs->pc;  	for (i = -8; i < 16; i++) {  		if (get_user(c, cp + i) && i >= 0) { -			printk(" Bad PC value."); +			pr_cont(" Bad PC value.");  			break;  		} -		printk(i ? " %04x" : " <%04x>", c); +		if (i) +			pr_cont(" %04x", c); +		else +			pr_cont(" <%04x>", c);  	}  	set_fs(old_fs); -	printk ("\n"); +	pr_cont("\n");  }  void show_stack(struct task_struct *task, unsigned long *stack) @@ -990,80 +948,80 @@ void show_stack(struct task_struct *task, unsigned long *stack)  	}  	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); -	printk("Stack from %08lx:", (unsigned long)stack); +	pr_info("Stack from %08lx:", (unsigned long)stack);  	p = stack;  	for (i = 0; i < kstack_depth_to_print; i++) {  		if (p + 1 > endstack)  			break;  		if (i % 8 == 0) -			printk("\n       "); -		printk(" %08lx", *p++); +			pr_cont("\n       "); +		pr_cont(" %08lx", *p++);  	} -	printk("\n"); +	pr_cont("\n");  	show_trace(stack);  }  /* - * The architecture-independent backtrace generator + * The vector number returned in the frame pointer may also contain + * the "fs" (Fault Status) bits on ColdFire. These are in the bottom + * 2 bits, and upper 2 bits. So we need to mask out the real vector + * number before using it in comparisons. You don't need to do this on + * real 68k parts, but it won't hurt either.   */ -void dump_stack(void) -{ -	unsigned long stack; - -	show_trace(&stack); -} - -EXPORT_SYMBOL(dump_stack);  void bad_super_trap (struct frame *fp)  { +	int vector = (fp->ptregs.vector >> 2) & 0xff; +  	console_verbose(); -	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names)) -		printk ("*** %s ***   FORMAT=%X\n", -			vec_names[(fp->ptregs.vector) >> 2], +	if (vector < ARRAY_SIZE(vec_names)) +		pr_err("*** %s ***   FORMAT=%X\n", +			vec_names[vector],  			fp->ptregs.format);  	else -		printk ("*** Exception %d ***   FORMAT=%X\n", -			(fp->ptregs.vector) >> 2, -			fp->ptregs.format); -	if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) { +		pr_err("*** Exception %d ***   FORMAT=%X\n", +			vector, fp->ptregs.format); +	if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) {  		unsigned short ssw = fp->un.fmtb.ssw; -		printk ("SSW=%#06x  ", ssw); +		pr_err("SSW=%#06x  ", ssw);  		if (ssw & RC) -			printk ("Pipe stage C instruction fault at %#010lx\n", +			pr_err("Pipe stage C instruction fault at %#010lx\n",  				(fp->ptregs.format) == 0xA ?  				fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);  		if (ssw & RB) -			printk ("Pipe stage B instruction fault at %#010lx\n", +			pr_err("Pipe stage B instruction fault at %#010lx\n",  				(fp->ptregs.format) == 0xA ?  				fp->ptregs.pc + 4 : fp->un.fmtb.baddr);  		if (ssw & DF) -			printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", +			pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",  				ssw & RW ? "read" : "write",  				fp->un.fmtb.daddr, space_names[ssw & DFC],  				fp->ptregs.pc);  	} -	printk ("Current process id is %d\n", task_pid_nr(current)); +	pr_err("Current process id is %d\n", task_pid_nr(current));  	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);  }  asmlinkage void trap_c(struct frame *fp)  {  	int sig; +	int vector = (fp->ptregs.vector >> 2) & 0xff;  	siginfo_t info;  	if (fp->ptregs.sr & PS_S) { -		if ((fp->ptregs.vector >> 2) == VEC_TRACE) { -			/* traced a trapping instruction */ -		} else +		if (vector == VEC_TRACE) { +			/* traced a trapping instruction on a 68020/30, +			 * real exception will be executed afterwards. +			 */ +		} else if (!handle_kernel_fault(&fp->ptregs))  			bad_super_trap(fp);  		return;  	}  	/* send the appropriate signal to the user program */ -	switch ((fp->ptregs.vector) >> 2) { +	switch (vector) {  	    case VEC_ADDRERR:  		info.si_code = BUS_ADRALN;  		sig = SIGBUS; @@ -1174,12 +1132,17 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)  		return;  	console_verbose(); -	printk("%s: %08x\n",str,nr); +	pr_crit("%s: %08x\n", str, nr);  	show_registers(fp); -	add_taint(TAINT_DIE); +	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);  	do_exit(SIGSEGV);  } +asmlinkage void set_esp0(unsigned long ssp) +{ +	current->thread.esp0 = ssp; +} +  /*   * This function is called if an error occur while accessing   * user-space from the fpsp040 code. diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c new file mode 100644 index 00000000000..322c977bb9e --- /dev/null +++ b/arch/m68k/kernel/vectors.c @@ -0,0 +1,144 @@ +/* + *  vectors.c + * + *  Copyright (C) 1993, 1994 by Hamish Macdonald + * + *  68040 fixes by Michael Rausch + *  68040 fixes by Martin Apel + *  68040 fixes and writeback by Richard Zidlicky + *  68060 fixes by Roman Hodek + *  68060 fixes by Jesper Skov + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file COPYING in the main directory of this archive + * for more details. + */ + +/* + * Sets up all exception vectors + */ +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/kallsyms.h> + +#include <asm/setup.h> +#include <asm/fpu.h> +#include <asm/traps.h> + +/* assembler routines */ +asmlinkage void system_call(void); +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void nmihandler(void); +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpu_emu(void); +#endif + +e_vector vectors[256]; + +/* nmi handler for the Amiga */ +asm(".text\n" +    __ALIGN_STR "\n" +    "nmihandler: rte"); + +/* + * this must be called very early as the kernel might + * use some instruction that are emulated on the 060 + * and so we're prepared for early probe attempts (e.g. nf_init). + */ +void __init base_trap_init(void) +{ +	if (MACH_IS_SUN3X) { +		extern e_vector *sun3x_prom_vbr; + +		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); +	} + +	/* setup the exception vector table */ +	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + +	if (CPU_IS_060) { +		/* set up ISP entry points */ +		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); + +		vectors[VEC_UNIMPII] = unimp_vec; +	} + +	vectors[VEC_BUSERR] = buserr; +	vectors[VEC_ILLEGAL] = trap; +	vectors[VEC_SYS] = system_call; +} + +void __init trap_init (void) +{ +	int i; + +	for (i = VEC_SPUR; i <= VEC_INT7; i++) +		vectors[i] = bad_inthandler; + +	for (i = 0; i < VEC_USER; i++) +		if (!vectors[i]) +			vectors[i] = trap; + +	for (i = VEC_USER; i < 256; i++) +		vectors[i] = bad_inthandler; + +#ifdef CONFIG_M68KFPU_EMU +	if (FPU_IS_EMU) +		vectors[VEC_LINE11] = fpu_emu; +#endif + +	if (CPU_IS_040 && !FPU_IS_EMU) { +		/* set up FPSP entry points */ +		asmlinkage void dz_vec(void) asm ("dz"); +		asmlinkage void inex_vec(void) asm ("inex"); +		asmlinkage void ovfl_vec(void) asm ("ovfl"); +		asmlinkage void unfl_vec(void) asm ("unfl"); +		asmlinkage void snan_vec(void) asm ("snan"); +		asmlinkage void operr_vec(void) asm ("operr"); +		asmlinkage void bsun_vec(void) asm ("bsun"); +		asmlinkage void fline_vec(void) asm ("fline"); +		asmlinkage void unsupp_vec(void) asm ("unsupp"); + +		vectors[VEC_FPDIVZ] = dz_vec; +		vectors[VEC_FPIR] = inex_vec; +		vectors[VEC_FPOVER] = ovfl_vec; +		vectors[VEC_FPUNDER] = unfl_vec; +		vectors[VEC_FPNAN] = snan_vec; +		vectors[VEC_FPOE] = operr_vec; +		vectors[VEC_FPBRUC] = bsun_vec; +		vectors[VEC_LINE11] = fline_vec; +		vectors[VEC_FPUNSUP] = unsupp_vec; +	} + +	if (CPU_IS_060 && !FPU_IS_EMU) { +		/* set up IFPSP entry points */ +		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); +		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); +		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); +		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); +		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); +		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); +		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); +		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); +		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); + +		vectors[VEC_FPNAN] = snan_vec6; +		vectors[VEC_FPOE] = operr_vec6; +		vectors[VEC_FPOVER] = ovfl_vec6; +		vectors[VEC_FPUNDER] = unfl_vec6; +		vectors[VEC_FPDIVZ] = dz_vec6; +		vectors[VEC_FPIR] = inex_vec6; +		vectors[VEC_LINE11] = fline_vec6; +		vectors[VEC_FPUNSUP] = unsupp_vec6; +		vectors[VEC_UNIMPEA] = effadd_vec6; +	} + +        /* if running on an amiga, make the NMI interrupt do nothing */ +	if (MACH_IS_AMIGA) { +		vectors[VEC_INT7] = nmihandler; +	} +} + diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds new file mode 100644 index 00000000000..06a763f49fd --- /dev/null +++ b/arch/m68k/kernel/vmlinux-nommu.lds @@ -0,0 +1,91 @@ +/* + *	vmlinux.lds.S -- master linker script for m68knommu arch + * + *	(C) Copyright 2002-2012, Greg Ungerer <gerg@snapgear.com> + * + *	This linker script is equipped to build either ROM loaded or RAM + *	run kernels. + */ + +#if defined(CONFIG_RAMKERNEL) +#define	KTEXT_ADDR	CONFIG_KERNELBASE +#endif +#if defined(CONFIG_ROMKERNEL) +#define	KTEXT_ADDR	CONFIG_ROMSTART +#define	KDATA_ADDR	CONFIG_KERNELBASE +#define	LOAD_OFFSET	KDATA_ADDR + (ADDR(.text) + SIZEOF(.text)) +#endif + +#include <asm/page.h> +#include <asm/thread_info.h> +#include <asm-generic/vmlinux.lds.h> + +OUTPUT_ARCH(m68k) +ENTRY(_start) + +jiffies = jiffies_64 + 4; + +SECTIONS { + +#ifdef CONFIG_ROMVEC +	. = CONFIG_ROMVEC; +	.romvec : { +		__rom_start = .; +		_romvec = .; +		*(.romvec) +		*(.data..initvect) +	} +#endif + +	. = KTEXT_ADDR; + +	_text = .; +	_stext = .; +	.text : { +		HEAD_TEXT +		TEXT_TEXT +		SCHED_TEXT +		LOCK_TEXT +		*(.fixup) +		. = ALIGN(16); +	} +	_etext = .; + +#ifdef KDATA_ADDR +	. = KDATA_ADDR; +#endif + +	_sdata = .; +	RO_DATA_SECTION(PAGE_SIZE) +	RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) +	_edata = .; + +	EXCEPTION_TABLE(16) +	NOTES + +	. = ALIGN(PAGE_SIZE); +	__init_begin = .; +	INIT_TEXT_SECTION(PAGE_SIZE) +	INIT_DATA_SECTION(16) +	PERCPU_SECTION(16) +	.m68k_fixup : { +		__start_fixup = .; +		*(.m68k_fixup) +		__stop_fixup = .; +	} +	.init.data : { +		. = ALIGN(PAGE_SIZE); +		__init_end = .; +	} + +	BSS_SECTION(0, 0, 0) + +	_end = .; + +	STABS_DEBUG +	.comment 0 : { *(.comment) } + +	/* Sections to be discarded */ +	DISCARDS +} + diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 878be5f38ca..d0993594f55 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -25,6 +25,8 @@ SECTIONS    EXCEPTION_TABLE(16) +  _sdata = .;			/* Start of data section */ +    RODATA    RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 1ad6b7ad2c1..8080469ee6c 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -25,6 +25,7 @@ SECTIONS    _etext = .;			/* End of text section */    EXCEPTION_TABLE(16) :data +  _sdata = .;			/* Start of rw data section */    RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) :data    /* End of data goes *here* so that freeing init code works properly. */    _edata = .; diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S index 99ba315bd0a..69ec7963887 100644 --- a/arch/m68k/kernel/vmlinux.lds.S +++ b/arch/m68k/kernel/vmlinux.lds.S @@ -1,3 +1,4 @@ +#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)  PHDRS  {    text PT_LOAD FILEHDR PHDRS FLAGS (7); @@ -8,3 +9,6 @@ PHDRS  #else  #include "vmlinux-std.lds"  #endif +#else +#include "vmlinux-nommu.lds" +#endif  | 
