diff options
Diffstat (limited to 'arch/avr32/kernel')
| -rw-r--r-- | arch/avr32/kernel/Makefile | 4 | ||||
| -rw-r--r-- | arch/avr32/kernel/avr32_ksyms.c | 4 | ||||
| -rw-r--r-- | arch/avr32/kernel/cpu.c | 122 | ||||
| -rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 81 | ||||
| -rw-r--r-- | arch/avr32/kernel/head.S | 20 | ||||
| -rw-r--r-- | arch/avr32/kernel/init_task.c | 37 | ||||
| -rw-r--r-- | arch/avr32/kernel/irq.c | 48 | ||||
| -rw-r--r-- | arch/avr32/kernel/module.c | 27 | ||||
| -rw-r--r-- | arch/avr32/kernel/process.c | 151 | ||||
| -rw-r--r-- | arch/avr32/kernel/ptrace.c | 64 | ||||
| -rw-r--r-- | arch/avr32/kernel/setup.c | 46 | ||||
| -rw-r--r-- | arch/avr32/kernel/signal.c | 84 | ||||
| -rw-r--r-- | arch/avr32/kernel/sys_avr32.c | 52 | ||||
| -rw-r--r-- | arch/avr32/kernel/syscall-stubs.S | 44 | ||||
| -rw-r--r-- | arch/avr32/kernel/syscall_table.S | 14 | ||||
| -rw-r--r-- | arch/avr32/kernel/time.c | 39 | ||||
| -rw-r--r-- | arch/avr32/kernel/traps.c | 51 | ||||
| -rw-r--r-- | arch/avr32/kernel/vmlinux.lds.S | 75 |
18 files changed, 297 insertions, 666 deletions
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 18229d0d186..119a2e41def 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile @@ -7,8 +7,8 @@ extra-y := head.o vmlinux.lds obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o obj-y += syscall_table.o syscall-stubs.o irq.o obj-y += setup.o traps.o ocd.o ptrace.o -obj-y += signal.o sys_avr32.o process.o time.o -obj-y += init_task.o switch_to.o cpu.o +obj-y += signal.o process.o time.o +obj-y += switch_to.o cpu.o obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_STACKTRACE) += stacktrace.o diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 11e310c567a..d93ead02dae 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -58,8 +58,8 @@ EXPORT_SYMBOL(find_first_zero_bit); EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); -EXPORT_SYMBOL(generic_find_next_le_bit); -EXPORT_SYMBOL(generic_find_next_zero_le_bit); +EXPORT_SYMBOL(find_next_bit_le); +EXPORT_SYMBOL(find_next_zero_bit_le); /* I/O primitives (lib/io-*.S) */ EXPORT_SYMBOL(__raw_readsb); diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c index e84faffbbec..0341ae27c9e 100644 --- a/arch/avr32/kernel/cpu.c +++ b/arch/avr32/kernel/cpu.c @@ -6,7 +6,7 @@ * published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/sysdev.h> +#include <linux/device.h> #include <linux/seq_file.h> #include <linux/cpu.h> #include <linux/module.h> @@ -26,137 +26,141 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); * XXX: If/when a SMP-capable implementation of AVR32 will ever be * made, we must make sure that the code executes on the correct CPU. */ -static ssize_t show_pc0event(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pc0event(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); } -static ssize_t store_pc0event(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, +static ssize_t store_pc0event(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf || val > 0x3f) + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + if (val > 0x3f) return -EINVAL; val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff); sysreg_write(PCCR, val); return count; } -static ssize_t show_pc0count(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pc0count(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pcnt0; pcnt0 = sysreg_read(PCNT0); return sprintf(buf, "%lu\n", pcnt0); } -static ssize_t store_pc0count(struct sys_device *dev, - struct sysdev_attribute *attr, +static ssize_t store_pc0count(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; sysreg_write(PCNT0, val); return count; } -static ssize_t show_pc1event(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pc1event(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); } -static ssize_t store_pc1event(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, +static ssize_t store_pc1event(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf || val > 0x3f) + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + if (val > 0x3f) return -EINVAL; val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff); sysreg_write(PCCR, val); return count; } -static ssize_t show_pc1count(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pc1count(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pcnt1; pcnt1 = sysreg_read(PCNT1); return sprintf(buf, "%lu\n", pcnt1); } -static ssize_t store_pc1count(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, +static ssize_t store_pc1count(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; sysreg_write(PCNT1, val); return count; } -static ssize_t show_pccycles(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pccycles(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pccnt; pccnt = sysreg_read(PCCNT); return sprintf(buf, "%lu\n", pccnt); } -static ssize_t store_pccycles(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, +static ssize_t store_pccycles(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; sysreg_write(PCCNT, val); return count; } -static ssize_t show_pcenable(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_pcenable(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long pccr; pccr = sysreg_read(PCCR); return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); } -static ssize_t store_pcenable(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, +static ssize_t store_pcenable(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { unsigned long pccr, val; - char *endp; + int ret; - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; if (val) val = 1; @@ -167,12 +171,12 @@ static ssize_t store_pcenable(struct sys_device *dev, return count; } -static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event); -static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count); -static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event); -static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count); -static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles); -static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable); +static DEVICE_ATTR(pc0event, 0600, show_pc0event, store_pc0event); +static DEVICE_ATTR(pc0count, 0600, show_pc0count, store_pc0count); +static DEVICE_ATTR(pc1event, 0600, show_pc1event, store_pc1event); +static DEVICE_ATTR(pc1count, 0600, show_pc1count, store_pc1count); +static DEVICE_ATTR(pccycles, 0600, show_pccycles, store_pccycles); +static DEVICE_ATTR(pcenable, 0600, show_pcenable, store_pcenable); #endif /* CONFIG_PERFORMANCE_COUNTERS */ @@ -186,12 +190,12 @@ static int __init topology_init(void) register_cpu(c, cpu); #ifdef CONFIG_PERFORMANCE_COUNTERS - sysdev_create_file(&c->sysdev, &attr_pc0event); - sysdev_create_file(&c->sysdev, &attr_pc0count); - sysdev_create_file(&c->sysdev, &attr_pc1event); - sysdev_create_file(&c->sysdev, &attr_pc1count); - sysdev_create_file(&c->sysdev, &attr_pccycles); - sysdev_create_file(&c->sysdev, &attr_pcenable); + device_create_file(&c->dev, &dev_attr_pc0event); + device_create_file(&c->dev, &dev_attr_pc0count); + device_create_file(&c->dev, &dev_attr_pc1event); + device_create_file(&c->dev, &dev_attr_pc1count); + device_create_file(&c->dev, &dev_attr_pccycles); + device_create_file(&c->dev, &dev_attr_pcenable); #endif } diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 33d49377b8b..7301f4806bb 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -150,10 +150,10 @@ page_not_present: tlbmiss_restore sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_page_fault + call do_page_fault rjmp ret_from_exception .align 2 @@ -250,18 +250,20 @@ syscall_badsys: .global ret_from_fork ret_from_fork: - rcall schedule_tail + call schedule_tail + mov r12, 0 + rjmp syscall_return - /* check for syscall tracing */ - get_thread_info r0 - ld.w r1, r0[TI_flags] - andl r1, _TIF_ALLWORK_MASK, COH - brne syscall_exit_work - rjmp syscall_exit_cont + .global ret_from_kernel_thread +ret_from_kernel_thread: + call schedule_tail + mov r12, r0 + mov lr, r2 /* syscall_return */ + mov pc, r1 syscall_trace_enter: pushm r8-r12 - rcall syscall_trace + call syscall_trace popm r8-r12 rjmp syscall_trace_cont @@ -269,25 +271,25 @@ syscall_exit_work: bld r1, TIF_SYSCALL_TRACE brcc 1f unmask_interrupts - rcall syscall_trace + call syscall_trace mask_interrupts ld.w r1, r0[TI_flags] 1: bld r1, TIF_NEED_RESCHED brcc 2f unmask_interrupts - rcall schedule + call schedule mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b -2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK +2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME tst r1, r2 breq 3f unmask_interrupts mov r12, sp mov r11, r0 - rcall do_notify_resume + call do_notify_resume mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b @@ -394,31 +396,32 @@ handle_critical: mfsr r12, SYSREG_ECR mov r11, sp - rcall do_critical_exception + call do_critical_exception /* We should never get here... */ bad_return: sub r12, pc, (. - 1f) - bral panic + lddpc pc, 2f .align 2 1: .asciz "Return from critical exception!" +2: .long panic .align 1 do_bus_error_write: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mov r11, 1 rjmp 1f do_bus_error_read: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mov r11, 0 1: mfsr r12, SYSREG_BEAR mov r10, sp - rcall do_bus_error + call do_bus_error rjmp ret_from_exception .align 1 @@ -433,7 +436,7 @@ do_nmi_ll: 1: pushm r8, r9 /* PC and SR */ mfsr r12, SYSREG_ECR mov r11, sp - rcall do_nmi + call do_nmi popm r8-r9 mtsr SYSREG_RAR_NMI, r8 tst r0, r0 @@ -457,29 +460,29 @@ do_nmi_ll: handle_address_fault: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_address_exception + call do_address_exception rjmp ret_from_exception handle_protection_fault: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_page_fault + call do_page_fault rjmp ret_from_exception .align 1 do_illegal_opcode_ll: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_illegal_opcode + call do_illegal_opcode rjmp ret_from_exception do_dtlb_modified: @@ -513,11 +516,11 @@ do_dtlb_modified: do_fpe_ll: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex unmask_interrupts mov r12, 26 mov r11, sp - rcall do_fpe + call do_fpe rjmp ret_from_exception ret_from_exception: @@ -553,7 +556,7 @@ fault_resume_kernel: lddsp r4, sp[REG_SR] bld r4, SYSREG_GM_OFFSET brcs 1f - rcall preempt_schedule_irq + call preempt_schedule_irq 1: #endif @@ -582,18 +585,18 @@ fault_exit_work: bld r1, TIF_NEED_RESCHED brcc 1f unmask_interrupts - rcall schedule + call schedule mask_interrupts ld.w r1, r0[TI_flags] rjmp fault_exit_work -1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK +1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME tst r1, r2 breq 2f unmask_interrupts mov r12, sp mov r11, r0 - rcall do_notify_resume + call do_notify_resume mask_interrupts ld.w r1, r0[TI_flags] rjmp fault_exit_work @@ -616,10 +619,10 @@ handle_debug: .Ldebug_fixup_cont: #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_off + call trace_hardirqs_off #endif mov r12, sp - rcall do_debug + call do_debug mov sp, r12 lddsp r2, sp[REG_SR] @@ -643,7 +646,7 @@ handle_debug: mtsr SYSREG_RSR_DBG, r11 mtsr SYSREG_RAR_DBG, r10 #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_on + call trace_hardirqs_on 1: #endif ldmts sp++, r0-lr @@ -676,7 +679,7 @@ debug_resume_kernel: #ifdef CONFIG_TRACE_IRQFLAGS bld r11, SYSREG_GM_OFFSET brcc 1f - rcall trace_hardirqs_on + call trace_hardirqs_on 1: #endif mfsr r2, SYSREG_SR @@ -747,7 +750,7 @@ irq_level\level: mov r11, sp mov r12, \level - rcall do_IRQ + call do_IRQ lddsp r4, sp[REG_SR] bfextu r4, r4, SYSREG_M0_OFFSET, 3 @@ -767,7 +770,7 @@ irq_level\level: 1: #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_on + call trace_hardirqs_on #endif popm r8-r9 mtsr rar_int\level, r8 @@ -807,7 +810,7 @@ irq_level\level: lddsp r4, sp[REG_SR] bld r4, SYSREG_GM_OFFSET brcs 1b - rcall preempt_schedule_irq + call preempt_schedule_irq #endif rjmp 1b .endm diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S index 6163bd0acb9..59eae6dfbed 100644 --- a/arch/avr32/kernel/head.S +++ b/arch/avr32/kernel/head.S @@ -10,33 +10,13 @@ #include <linux/linkage.h> #include <asm/page.h> -#include <asm/thread_info.h> -#include <asm/sysreg.h> .section .init.text,"ax" .global kernel_entry kernel_entry: - /* Initialize status register */ - lddpc r0, init_sr - mtsr SYSREG_SR, r0 - - /* Set initial stack pointer */ - lddpc sp, stack_addr - sub sp, -THREAD_SIZE - -#ifdef CONFIG_FRAME_POINTER - /* Mark last stack frame */ - mov lr, 0 - mov r7, 0 -#endif - /* Start the show */ lddpc pc, kernel_start_addr .align 2 -init_sr: - .long 0x007f0000 /* Supervisor mode, everything masked */ -stack_addr: - .long init_thread_union kernel_start_addr: .long start_kernel diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c deleted file mode 100644 index 44058469c6e..00000000000 --- a/arch/avr32/kernel/init_task.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/sched.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> - -#include <asm/pgtable.h> - -static struct fs_struct init_fs = INIT_FS; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - -/* - * Initial thread structure. Must be aligned on an 8192-byte boundary. - */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c index a8e767d836a..900e49b2258 100644 --- a/arch/avr32/kernel/irq.c +++ b/arch/avr32/kernel/irq.c @@ -14,16 +14,7 @@ #include <linux/kernel_stat.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <linux/sysdev.h> - -/* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves. - */ -void ack_bad_irq(unsigned int irq) -{ - printk("unexpected IRQ %u\n", irq); -} +#include <linux/device.h> /* May be overridden by platform code */ int __weak nmi_enable(void) @@ -35,40 +26,3 @@ void __weak nmi_disable(void) { } - -#ifdef CONFIG_PROC_FS -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *)v, cpu; - struct irqaction *action; - unsigned long flags; - - if (i == 0) { - seq_puts(p, " "); - for_each_online_cpu(cpu) - seq_printf(p, "CPU%d ", cpu); - seq_putc(p, '\n'); - } - - if (i < NR_IRQS) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if (!action) - goto unlock; - - seq_printf(p, "%3d: ", i); - for_each_online_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); - seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-"); - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - - seq_putc(p, '\n'); - unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - - return 0; -} -#endif diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 1167fe9cf6c..2c941290802 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c @@ -19,21 +19,12 @@ #include <linux/moduleloader.h> #include <linux/vmalloc.h> -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(size); -} - void module_free(struct module *mod, void *module_region) { vfree(mod->arch.syminfo); mod->arch.syminfo = NULL; vfree(module_region); - /* FIXME: if module_region == mod->init_region, trim exception - * table entries. */ } static inline int check_rela(Elf32_Rela *rela, struct module *module, @@ -273,7 +264,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, break; case R_AVR32_GOT18SW: if ((relocation & 0xfffe0003) != 0 - && (relocation & 0xfffc0003) != 0xffff0000) + && (relocation & 0xfffc0000) != 0xfffc0000) return reloc_overflow(module, "R_AVR32_GOT18SW", relocation); relocation >>= 2; @@ -301,25 +292,11 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, return ret; } -int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relindex, - struct module *module) -{ - printk(KERN_ERR "module %s: REL relocations are not supported\n", - module->name); - return -ENOEXEC; -} - int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *module) { vfree(module->arch.syminfo); module->arch.syminfo = NULL; - return module_bug_finalize(hdr, sechdrs, module); -} - -void module_arch_cleanup(struct module *module) -{ - module_bug_cleanup(module); + return 0; } diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 2c08ac992ac..42a53e740a7 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -9,7 +9,9 @@ #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/fs.h> +#include <linux/pm.h> #include <linux/ptrace.h> +#include <linux/slab.h> #include <linux/reboot.h> #include <linux/tick.h> #include <linux/uaccess.h> @@ -17,28 +19,20 @@ #include <asm/sysreg.h> #include <asm/ocd.h> +#include <asm/syscalls.h> #include <mach/pm.h> -void (*pm_power_off)(void) = NULL; +void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); /* * This file handles the architecture-dependent parts of process handling.. */ -void cpu_idle(void) +void arch_cpu_idle(void) { - /* endless idle loop with no priority at all */ - while (1) { - tick_nohz_stop_sched_tick(1); - while (!need_resched()) - cpu_idle_sleep(); - tick_nohz_restart_sched_tick(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } + cpu_enter_idle(); } void machine_halt(void) @@ -66,44 +60,6 @@ void machine_restart(char *cmd) } /* - * PC is actually discarded when returning from a system call -- the - * return address must be stored in LR. This function will make sure - * LR points to do_exit before starting the thread. - * - * Also, when returning from fork(), r12 is 0, so we must copy the - * argument as well. - * - * r0 : The argument to the main thread function - * r1 : The address of do_exit - * r2 : The address of the main thread function - */ -asmlinkage extern void kernel_thread_helper(void); -__asm__(" .type kernel_thread_helper, @function\n" - "kernel_thread_helper:\n" - " mov r12, r0\n" - " mov lr, r2\n" - " mov pc, r1\n" - " .size kernel_thread_helper, . - kernel_thread_helper"); - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.r0 = (unsigned long)arg; - regs.r1 = (unsigned long)fn; - regs.r2 = (unsigned long)do_exit; - regs.lr = (unsigned long)kernel_thread_helper; - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = MODE_SUPERVISOR; - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, - 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Free current thread data structures etc */ void exit_thread(void) @@ -248,14 +204,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) show_stack_log_lvl(tsk, (unsigned long)stack, NULL, ""); } -void dump_stack(void) -{ - unsigned long stack; - - show_trace_log_lvl(current, &stack, NULL, ""); -} -EXPORT_SYMBOL(dump_stack); - static const char *cpu_modes[] = { "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" @@ -267,6 +215,8 @@ void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl) unsigned long lr = regs->lr; unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT; + show_regs_print_info(log_lvl); + if (!user_mode(regs)) { sp = (unsigned long)regs + FRAME_SIZE_FULL; @@ -304,9 +254,6 @@ void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl) regs->sr & SR_I0M ? '0' : '.', regs->sr & SR_GM ? 'G' : 'g'); printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]); - printk("%sProcess: %s [%d] (task: %p thread: %p)\n", - log_lvl, current->comm, current->pid, current, - task_thread_info(current)); } void show_regs(struct pt_regs *regs) @@ -329,26 +276,32 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); +asmlinkage void syscall_return(void); -int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) +int copy_thread(unsigned long clone_flags, unsigned long usp, + unsigned long arg, + struct task_struct *p) { - struct pt_regs *childregs; - - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; - *childregs = *regs; - - if (user_mode(regs)) - childregs->sp = usp; - else - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - - childregs->r12 = 0; /* Set return value for child */ + struct pt_regs *childregs = task_pt_regs(p); + + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + p->thread.cpu_context.r0 = arg; + p->thread.cpu_context.r1 = usp; /* fn */ + p->thread.cpu_context.r2 = (unsigned long)syscall_return; + p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; + childregs->sr = MODE_SUPERVISOR; + } else { + *childregs = *current_pt_regs(); + if (usp) + childregs->sp = usp; + childregs->r12 = 0; /* Set return value for child */ + p->thread.cpu_context.pc = (unsigned long)ret_from_fork; + } p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; p->thread.cpu_context.ksp = (unsigned long)childregs; - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; clear_tsk_thread_flag(p, TIF_DEBUG); if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) @@ -357,50 +310,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, return 0; } -/* r12-r8 are dummy parameters to force the compiler to use the stack */ -asmlinkage int sys_fork(struct pt_regs *regs) -{ - return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - unsigned long parent_tidptr, - unsigned long child_tidptr, struct pt_regs *regs) -{ - if (!newsp) - newsp = regs->sp; - return do_fork(clone_flags, newsp, regs, 0, - (int __user *)parent_tidptr, - (int __user *)child_tidptr); -} - -asmlinkage int sys_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, - 0, NULL, NULL); -} - -asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv, - char __user *__user *uenvp, struct pt_regs *regs) -{ - int error; - char *filename; - - filename = getname(ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename, uargv, uenvp, regs); - if (error == 0) - current->ptrace &= ~PT_DTRACE; - putname(filename); - -out: - return error; -} - - /* * This function is supposed to answer the question "who called * schedule()?" @@ -432,7 +341,7 @@ unsigned long get_wchan(struct task_struct *p) * is actually quite ugly. It might be possible to * determine the frame size automatically at build * time by doing this: - * - compile sched.c + * - compile sched/core.c * - disassemble the resulting sched.o * - look for 'sub sp,??' shortly after '<schedule>:' */ diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 1fed38fcf59..4aedcab7cd4 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -28,9 +28,9 @@ static struct pt_regs *get_user_regs(struct task_struct *tsk) THREAD_SIZE - sizeof(struct pt_regs)); } -static void ptrace_single_step(struct task_struct *tsk) +void user_enable_single_step(struct task_struct *tsk) { - pr_debug("ptrace_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", + pr_debug("user_enable_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr); /* @@ -49,6 +49,11 @@ static void ptrace_single_step(struct task_struct *tsk) set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); } +void user_disable_single_step(struct task_struct *child) +{ + /* XXX(hch): a no-op here seems wrong.. */ +} + /* * Called by kernel/ptrace.c when detaching * @@ -141,9 +146,11 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs) return ret; } -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) { int ret; + void __user *datap = (void __user *) data; switch (request) { /* Read the word at location addr in the child process */ @@ -153,8 +160,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_PEEKUSR: - ret = ptrace_read_user(child, addr, - (unsigned long __user *)data); + ret = ptrace_read_user(child, addr, datap); break; /* Write the word in data at location addr */ @@ -167,56 +173,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = ptrace_write_user(child, addr, data); break; - /* continue and stop at next (return from) syscall */ - case PTRACE_SYSCALL: - /* restart after signal */ - case PTRACE_CONT: - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - /* XXX: Are we sure no breakpoints are active here? */ - wake_up_process(child); - ret = 0; - break; - - /* - * Make the child exit. Best I can do is send it a - * SIGKILL. Perhaps it should be put in the status that it - * wants to exit. - */ - case PTRACE_KILL: - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - - /* - * execute single instruction. - */ - case PTRACE_SINGLESTEP: - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - ptrace_single_step(child); - child->exit_code = data; - wake_up_process(child); - ret = 0; - break; - case PTRACE_GETREGS: - ret = ptrace_getregs(child, (void __user *)data); + ret = ptrace_getregs(child, datap); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (const void __user *)data); + ret = ptrace_setregs(child, datap); break; default: diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index d8e623c426c..209ae5ad349 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -283,6 +283,25 @@ static int __init early_parse_fbmem(char *p) } early_param("fbmem", early_parse_fbmem); +/* + * Pick out the memory size. We look for mem=size@start, + * where start and size are "size[KkMmGg]" + */ +static int __init early_mem(char *p) +{ + resource_size_t size, start; + + start = system_ram->start; + size = memparse(p, &p); + if (*p == '@') + start = memparse(p + 1, &p); + + system_ram->start = start; + system_ram->end = system_ram->start + size - 1; + return 0; +} +early_param("mem", early_mem); + static int __init parse_tag_core(struct tag *tag) { if (tag->hdr.size > 2) { @@ -372,6 +391,21 @@ static int __init parse_tag_clock(struct tag *tag) __tagtable(ATAG_CLOCK, parse_tag_clock); /* + * The board_number correspond to the bd->bi_board_number in U-Boot. This + * parameter is only available during initialisation and can be used in some + * kind of board identification. + */ +u32 __initdata board_number; + +static int __init parse_tag_boardinfo(struct tag *tag) +{ + board_number = tag->u.boardinfo.board_number; + + return 0; +} +__tagtable(ATAG_BOARDINFO, parse_tag_boardinfo); + +/* * Scan the tag table for this tag, and call its parse function. The * tag table is built by the linker from all the __tagtable * declarations. @@ -410,7 +444,7 @@ static unsigned long __init find_bootmap_pfn(const struct resource *mem) { unsigned long bootmap_pages, bootmap_len; - unsigned long node_pages = PFN_UP(mem->end - mem->start + 1); + unsigned long node_pages = PFN_UP(resource_size(mem)); unsigned long bootmap_start; bootmap_pages = bootmem_bootmap_pages(node_pages); @@ -507,10 +541,10 @@ static void __init setup_bootmem(void) */ if (res->start >= PFN_PHYS(first_pfn) && res->end < PFN_PHYS(max_pfn)) - reserve_bootmem_node( - NODE_DATA(node), res->start, - res->end - res->start + 1, - BOOTMEM_DEFAULT); + reserve_bootmem_node(NODE_DATA(node), + res->start, + resource_size(res), + BOOTMEM_DEFAULT); } node_set_online(node); @@ -521,7 +555,7 @@ void __init setup_arch (char **cmdline_p) { struct clk *cpu_clk; - init_mm.start_code = (unsigned long)_text; + 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)_end; diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index c5b11f9067f..b80c0b3d2ba 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -15,18 +15,11 @@ #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/unistd.h> -#include <linux/freezer.h> +#include <linux/tracehook.h> #include <asm/uaccess.h> #include <asm/ucontext.h> - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs) -{ - return do_sigaltstack(uss, uoss, regs->sp); -} +#include <asm/syscalls.h> struct rt_sigframe { @@ -75,6 +68,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) struct rt_sigframe __user *frame; sigset_t set; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + frame = (struct rt_sigframe __user *)regs->sp; pr_debug("SIG return: frame = %p\n", frame); @@ -84,16 +80,12 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n", @@ -177,12 +169,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up 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(regs->sp), - &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, regs->sp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -211,7 +198,7 @@ out: return err; } -static inline void restart_syscall(struct pt_regs *regs) +static inline void setup_syscall_restart(struct pt_regs *regs) { if (regs->r12 == -ERESTART_RESTARTBLOCK) regs->r8 = __NR_restart_syscall; @@ -222,14 +209,14 @@ static inline void restart_syscall(struct pt_regs *regs) static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs, int syscall) + struct pt_regs *regs, int syscall) { int ret; /* * Set up the stack frame */ - ret = setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); /* * Check that the resulting registers are sane @@ -237,21 +224,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ret |= !valid_user_regs(regs); /* - * Block the signal if we were unsuccessful. + * Block the signal if we were successful. */ - if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - - if (ret == 0) - return; - - force_sigsegv(sig, current); + if (ret != 0) + force_sigsegv(sig, current); + else + signal_delivered(sig, info, ka, regs, 0); } /* @@ -259,7 +237,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * doesn't want to handle. Thus you cannot kill init even with a * SIGKILL even by mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) +static void do_signal(struct pt_regs *regs, int syscall) { siginfo_t info; int signr; @@ -271,12 +249,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) * without doing anything if so. */ if (!user_mode(regs)) - return 0; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else if (!oldset) - oldset = ¤t->blocked; + return; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (syscall) { @@ -295,21 +268,17 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) } /* fall through */ case -ERESTARTNOINTR: - restart_syscall(regs); + setup_syscall_restart(regs); } } if (signr == 0) { /* No signal to deliver -- put the saved sigmask back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - return 0; + restore_saved_sigmask(); + return; } - handle_signal(signr, &ka, &info, oldset, regs, syscall); - return 1; + handle_signal(signr, &ka, &info, regs, syscall); } asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) @@ -319,6 +288,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) syscall = 1; - if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) - do_signal(regs, ¤t->blocked, syscall); + if (ti->flags & _TIF_SIGPENDING) + do_signal(regs, syscall); + + if (ti->flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } } diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c deleted file mode 100644 index 8e8911e55c8..00000000000 --- a/arch/avr32/kernel/sys_avr32.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/mm.h> -#include <linux/unistd.h> - -#include <asm/mman.h> -#include <asm/uaccess.h> - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, offset); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - return error; -} - -int kernel_execve(const char *file, char **argv, char **envp) -{ - register long scno asm("r8") = __NR_execve; - register long sc1 asm("r12") = (long)file; - register long sc2 asm("r11") = (long)argv; - register long sc3 asm("r10") = (long)envp; - - asm volatile("scall" - : "=r"(sc1) - : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3) - : "cc", "memory"); - return sc1; -} diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 673178e235f..b5fc927cd39 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -20,48 +20,18 @@ __sys_rt_sigsuspend: mov r10, sp rjmp sys_rt_sigsuspend - .global __sys_sigaltstack - .type __sys_sigaltstack,@function -__sys_sigaltstack: - mov r10, sp - rjmp sys_sigaltstack - .global __sys_rt_sigreturn .type __sys_rt_sigreturn,@function __sys_rt_sigreturn: mov r12, sp rjmp sys_rt_sigreturn - .global __sys_fork - .type __sys_fork,@function -__sys_fork: - mov r12, sp - rjmp sys_fork - - .global __sys_clone - .type __sys_clone,@function -__sys_clone: - mov r8, sp - rjmp sys_clone - - .global __sys_vfork - .type __sys_vfork,@function -__sys_vfork: - mov r12, sp - rjmp sys_vfork - - .global __sys_execve - .type __sys_execve,@function -__sys_execve: - mov r9, sp - rjmp sys_execve - .global __sys_mmap2 .type __sys_mmap2,@function __sys_mmap2: pushm lr st.w --sp, ARG6 - rcall sys_mmap2 + call sys_mmap_pgoff sub sp, -4 popm pc @@ -70,7 +40,7 @@ __sys_mmap2: __sys_sendto: pushm lr st.w --sp, ARG6 - rcall sys_sendto + call sys_sendto sub sp, -4 popm pc @@ -79,7 +49,7 @@ __sys_sendto: __sys_recvfrom: pushm lr st.w --sp, ARG6 - rcall sys_recvfrom + call sys_recvfrom sub sp, -4 popm pc @@ -88,7 +58,7 @@ __sys_recvfrom: __sys_pselect6: pushm lr st.w --sp, ARG6 - rcall sys_pselect6 + call sys_pselect6 sub sp, -4 popm pc @@ -97,7 +67,7 @@ __sys_pselect6: __sys_splice: pushm lr st.w --sp, ARG6 - rcall sys_splice + call sys_splice sub sp, -4 popm pc @@ -106,7 +76,7 @@ __sys_splice: __sys_epoll_pwait: pushm lr st.w --sp, ARG6 - rcall sys_epoll_pwait + call sys_epoll_pwait sub sp, -4 popm pc @@ -115,6 +85,6 @@ __sys_epoll_pwait: __sys_sync_file_range: pushm lr st.w --sp, ARG6 - rcall sys_sync_file_range + call sys_sync_file_range sub sp, -4 popm pc diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 7ee0057613b..017a904180c 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -15,7 +15,7 @@ sys_call_table: .long sys_restart_syscall .long sys_exit - .long __sys_fork + .long sys_fork .long sys_read .long sys_write .long sys_open /* 5 */ @@ -24,7 +24,7 @@ sys_call_table: .long sys_creat .long sys_link .long sys_unlink /* 10 */ - .long __sys_execve + .long sys_execve .long sys_chdir .long sys_time .long sys_mknod @@ -57,7 +57,7 @@ sys_call_table: .long sys_dup .long sys_pipe .long sys_times - .long __sys_clone + .long sys_clone .long sys_brk /* 45 */ .long sys_setgid .long sys_getgid @@ -115,7 +115,7 @@ sys_call_table: .long sys_statfs .long sys_fstatfs /* 100 */ .long sys_vhangup - .long __sys_sigaltstack + .long sys_sigaltstack .long sys_syslog .long sys_setitimer .long sys_getitimer /* 105 */ @@ -127,7 +127,7 @@ sys_call_table: .long sys_newuname .long sys_adjtimex .long sys_mprotect - .long __sys_vfork + .long sys_vfork .long sys_init_module /* 115 */ .long sys_delete_module .long sys_quotactl @@ -158,7 +158,7 @@ sys_call_table: .long sys_sched_rr_get_interval .long sys_nanosleep .long sys_poll - .long sys_nfsservctl /* 145 */ + .long sys_ni_syscall /* 145 was nfsservctl */ .long sys_setresgid .long sys_getresgid .long sys_prctl @@ -295,4 +295,6 @@ sys_call_table: .long sys_signalfd .long sys_ni_syscall /* 280, was sys_timerfd */ .long sys_eventfd + .long sys_recvmmsg + .long sys_setns .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c index 283481d74a5..d0f771be9e9 100644 --- a/arch/avr32/kernel/time.c +++ b/arch/avr32/kernel/time.c @@ -12,13 +12,14 @@ #include <linux/irq.h> #include <linux/kernel.h> #include <linux/time.h> +#include <linux/cpu.h> #include <asm/sysreg.h> #include <mach/pm.h> -static cycle_t read_cycle_count(void) +static cycle_t read_cycle_count(struct clocksource *cs) { return (cycle_t)sysreg_read(COUNT); } @@ -35,7 +36,6 @@ static struct clocksource counter = { .rating = 50, .read = read_cycle_count, .mask = CLOCKSOURCE_MASK(32), - .shift = 16, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -59,7 +59,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) static struct irqaction timer_irqaction = { .handler = timer_interrupt, /* Oprofile uses the same irq as the timer, so allow it to be shared */ - .flags = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED, + .flags = IRQF_TIMER | IRQF_SHARED, .name = "avr32_comparator", }; @@ -88,13 +88,24 @@ static void comparator_mode(enum clock_event_mode mode, pr_debug("%s: start\n", evdev->name); /* FALLTHROUGH */ case CLOCK_EVT_MODE_RESUME: - cpu_disable_idle_sleep(); + /* + * If we're using the COUNT and COMPARE registers we + * need to force idle poll. + */ + cpu_idle_poll_ctrl(true); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: sysreg_write(COMPARE, 0); pr_debug("%s: stop\n", evdev->name); - cpu_enable_idle_sleep(); + if (evdev->mode == CLOCK_EVT_MODE_ONESHOT || + evdev->mode == CLOCK_EVT_MODE_RESUME) { + /* + * Only disable idle poll if we have forced that + * in a previous call. + */ + cpu_idle_poll_ctrl(false); + } break; default: BUG(); @@ -106,27 +117,24 @@ static struct clock_event_device comparator = { .features = CLOCK_EVT_FEAT_ONESHOT, .shift = 16, .rating = 50, - .cpumask = CPU_MASK_CPU0, .set_next_event = comparator_next_event, .set_mode = comparator_mode, }; +void read_persistent_clock(struct timespec *ts) +{ + ts->tv_sec = mktime(2007, 1, 1, 0, 0, 0); + ts->tv_nsec = 0; +} + void __init time_init(void) { unsigned long counter_hz; int ret; - xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0); - xtime.tv_nsec = 0; - - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - /* figure rate for counter */ counter_hz = clk_get_rate(boot_cpu_data.clk); - counter.mult = clocksource_hz2mult(counter_hz, counter.shift); - - ret = clocksource_register(&counter); + ret = clocksource_register_hz(&counter, counter_hz); if (ret) pr_debug("timer: could not register clocksource: %d\n", ret); @@ -134,6 +142,7 @@ void __init time_init(void) comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift); comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator); comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1; + comparator.cpumask = cpumask_of(0); sysreg_write(COMPARE, 0); timer_irqaction.dev_id = &comparator; diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 0d987373bc0..682b2478691 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -7,6 +7,7 @@ */ #include <linux/bug.h> +#include <linux/hardirq.h> #include <linux/init.h> #include <linux/kallsyms.h> #include <linux/kdebug.h> @@ -23,7 +24,7 @@ static DEFINE_SPINLOCK(die_lock); -void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) +void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; @@ -31,22 +32,25 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); - printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG, + printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); + + printk(KERN_EMERG); + #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk(KERN_CONT "PREEMPT "); #endif #ifdef CONFIG_FRAME_POINTER - printk("FRAME_POINTER "); + printk(KERN_CONT "FRAME_POINTER "); #endif if (current_cpu_data.features & AVR32_FEATURE_OCD) { unsigned long did = ocd_read(DID); - printk("chip: 0x%03lx:0x%04lx rev %lu\n", + printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n", (did >> 1) & 0x7ff, (did >> 12) & 0x7fff, (did >> 28) & 0xf); } else { - printk("cpu: arch %u r%u / core %u r%u\n", + printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n", current_cpu_data.arch_type, current_cpu_data.arch_revision, current_cpu_data.cpu_type, @@ -57,7 +61,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) show_regs_log_lvl(regs, KERN_EMERG); show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); bust_spinlocks(0); - add_taint(TAINT_DIE); + add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); spin_unlock_irq(&die_lock); if (in_interrupt()) @@ -74,36 +78,23 @@ void _exception(long signr, struct pt_regs *regs, int code, { siginfo_t info; - if (!user_mode(regs)) + if (!user_mode(regs)) { + const struct exception_table_entry *fixup; + + /* Are we prepared to handle this kernel fault? */ + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return; + } die("Unhandled exception in kernel mode", regs, signr); + } memset(&info, 0, sizeof(info)); info.si_signo = signr; info.si_code = code; info.si_addr = (void __user *)addr; force_sig_info(signr, &info, current); - - /* - * Init gets no signals that it doesn't have a handler for. - * That's all very well, but if it has caused a synchronous - * exception and we ignore the resulting signal, it will just - * generate the same exception over and over again and we get - * nowhere. Better to kill it and let the kernel panic. - */ - if (is_global_init(current)) { - __sighandler_t handler; - - spin_lock_irq(¤t->sighand->siglock); - handler = current->sighand->action[signr-1].sa.sa_handler; - spin_unlock_irq(¤t->sighand->siglock); - if (handler == SIG_DFL) { - /* init has generated a synchronous exception - and it doesn't have a handler for the signal */ - printk(KERN_CRIT "init has generated signal %ld " - "but has no handler for it\n", signr); - do_exit(signr); - } - } } asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index 7910d41eb88..a4589176bed 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S @@ -23,7 +23,7 @@ SECTIONS { . = CONFIG_ENTRY_ADDRESS; .init : AT(ADDR(.init) - LOAD_OFFSET) { - _stext = .; + _text = .; __init_begin = .; _sinittext = .; *(.text.reset) @@ -39,34 +39,14 @@ SECTIONS __tagtable_begin = .; *(.taglist.init) __tagtable_end = .; - INIT_DATA - . = ALIGN(16); - __setup_start = .; - *(.init.setup) - __setup_end = .; - . = ALIGN(4); - __initcall_start = .; - INITCALLS - __initcall_end = .; - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - __security_initcall_start = .; - *(.security_initcall.init) - __security_initcall_end = .; -#ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(32); - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; -#endif - . = ALIGN(PAGE_SIZE); - __init_end = .; } + INIT_DATA_SECTION(16) + . = ALIGN(PAGE_SIZE); + __init_end = .; .text : AT(ADDR(.text) - LOAD_OFFSET) { _evba = .; - _text = .; + _stext = .; *(.ex.text) *(.irq.text) KPROBES_TEXT @@ -78,34 +58,16 @@ SECTIONS _etext = .; } = 0xd703d703 - . = ALIGN(4); - __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - + EXCEPTION_TABLE(4) RODATA - . = ALIGN(THREAD_SIZE); - .data : AT(ADDR(.data) - LOAD_OFFSET) { _data = .; _sdata = .; - /* - * First, the init task union, aligned to an 8K boundary. - */ - *(.data.init_task) - /* Then, the page-aligned data */ - . = ALIGN(PAGE_SIZE); - *(.data.page_aligned) - - /* Then, the cacheline aligned data */ - . = ALIGN(L1_CACHE_BYTES); - *(.data.cacheline_aligned) - - /* And the rest... */ + INIT_TASK_DATA(THREAD_SIZE) + PAGE_ALIGNED_DATA(PAGE_SIZE); + CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) *(.data.rel*) DATA_DATA CONSTRUCTORS @@ -113,25 +75,14 @@ SECTIONS _edata = .; } + BSS_SECTION(0, 8, 8) + _end = .; - . = ALIGN(8); - .bss : AT(ADDR(.bss) - LOAD_OFFSET) { - __bss_start = .; - *(.bss) - *(COMMON) - . = ALIGN(8); - __bss_stop = .; - _end = .; - } + DWARF_DEBUG /* When something in the kernel is NOT compiled as a module, the module * cleanup code and data are put into these segments. Both can then be * thrown away, as cleanup code is never called unless it's a module. */ - /DISCARD/ : { - EXIT_DATA - *(.exitcall.exit) - } - - DWARF_DEBUG + DISCARDS } |
