diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/head-common.S | 40 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 7 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 69 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 13 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 22 |
7 files changed, 108 insertions, 51 deletions
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 19326d7cdeb3..a98d0c933db0 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -350,7 +350,7 @@ CALL(sys_set_robust_list) CALL(sys_get_robust_list) /* 340 */ CALL(sys_splice) - CALL(sys_arm_sync_file_range) + CALL(sys_sync_file_range2) CALL(sys_tee) CALL(sys_vmsplice) CALL(sys_move_pages) diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index a52da0ddb43d..024a9cf469b4 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -20,7 +20,8 @@ __switch_data: .long _end @ r7 .long processor_id @ r4 .long __machine_arch_type @ r5 - .long cr_alignment @ r6 + .long __atags_pointer @ r6 + .long cr_alignment @ r7 .long init_thread_union + THREAD_START_SP @ sp /* @@ -29,6 +30,7 @@ __switch_data: * * r0 = cp#15 control register * r1 = machine ID + * r2 = atags pointer * r9 = processor ID */ .type __mmap_switched, %function @@ -47,11 +49,12 @@ __mmap_switched: strcc fp, [r6],#4 bcc 1b - ldmia r3, {r4, r5, r6, sp} + ldmia r3, {r4, r5, r6, r7, sp} str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type + str r2, [r6] @ Save atags pointer bic r4, r0, #CR_A @ Clear 'A' bit - stmia r6, {r0, r4} @ Save control register values + stmia r7, {r0, r4} @ Save control register values b start_kernel /* @@ -215,3 +218,34 @@ ENTRY(lookup_machine_type) bl __lookup_machine_type mov r0, r5 ldmfd sp!, {r4 - r6, pc} + +/* Determine validity of the r2 atags pointer. The heuristic requires + * that the pointer be aligned, in the first 16k of physical RAM and + * that the ATAG_CORE marker is first and present. Future revisions + * of this function may be more lenient with the physical address and + * may also be able to move the ATAGS block if necessary. + * + * r8 = machinfo + * + * Returns: + * r2 either valid atags pointer, or zero + * r5, r6 corrupted + */ + + .type __vet_atags, %function +__vet_atags: + tst r2, #0x3 @ aligned? + bne 1f + + ldr r5, [r2, #0] @ is first tag ATAG_CORE? + subs r5, r5, #ATAG_CORE_SIZE + bne 1f + ldr r5, [r2, #4] + ldr r6, =ATAG_CORE + cmp r5, r6 + bne 1f + + mov pc, lr @ atag pointer is ok + +1: mov r2, #0 + mov pc, lr diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 41f98b4ba2ee..7898cbc9861a 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -29,6 +29,10 @@ #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) +#define ATAG_CORE 0x54410001 +#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) + + /* * swapper_pg_dir is the virtual address of the initial page table. * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must @@ -61,7 +65,7 @@ * * This is normally called from the decompressor code. The requirements * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, - * r1 = machine nr. + * r1 = machine nr, r2 = atags pointer. * * This code is mostly position independent, so if you link the kernel at * 0xc0008000, you call this at __pa(0xc0008000). @@ -85,6 +89,7 @@ ENTRY(stext) bl __lookup_machine_type @ r5=machinfo movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a' + bl __vet_atags bl __create_page_tables /* diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 5d6e6523598b..93b7f8e22dcc 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -28,6 +28,7 @@ #include <linux/elfcore.h> #include <linux/pm.h> #include <linux/tick.h> +#include <linux/utsname.h> #include <asm/leds.h> #include <asm/processor.h> @@ -43,6 +44,10 @@ static const char *processor_modes[] = { "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" }; +static const char *isa_modes[] = { + "ARM" , "Thumb" , "Jazelle", "ThumbEE" +}; + extern void setup_mm_for_reboot(char mode); static volatile int hlt_counter; @@ -199,16 +204,19 @@ void machine_restart(char * __unused) void __show_regs(struct pt_regs *regs) { - unsigned long flags = condition_codes(regs); + unsigned long flags; + char buf[64]; - printk("CPU: %d\n", smp_processor_id()); + printk("CPU: %d %s (%s %.*s)\n", + smp_processor_id(), print_tainted(), init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); print_symbol("PC is at %s\n", instruction_pointer(regs)); print_symbol("LR is at %s\n", regs->ARM_lr); - printk("pc : [<%08lx>] lr : [<%08lx>] %s\n" + printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" "sp : %08lx ip : %08lx fp : %08lx\n", - instruction_pointer(regs), - regs->ARM_lr, print_tainted(), regs->ARM_sp, - regs->ARM_ip, regs->ARM_fp); + regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, + regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); printk("r10: %08lx r9 : %08lx r8 : %08lx\n", regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); @@ -218,36 +226,39 @@ void __show_regs(struct pt_regs *regs) printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); - printk("Flags: %c%c%c%c", - flags & PSR_N_BIT ? 'N' : 'n', - flags & PSR_Z_BIT ? 'Z' : 'z', - flags & PSR_C_BIT ? 'C' : 'c', - flags & PSR_V_BIT ? 'V' : 'v'); - printk(" IRQs o%s FIQs o%s Mode %s%s Segment %s\n", - interrupts_enabled(regs) ? "n" : "ff", + + flags = regs->ARM_cpsr; + buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; + buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; + buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; + buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; + buf[4] = '\0'; + + printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n", + buf, interrupts_enabled(regs) ? "n" : "ff", fast_interrupts_enabled(regs) ? "n" : "ff", processor_modes[processor_mode(regs)], - thumb_mode(regs) ? " (T)" : "", + isa_modes[isa_mode(regs)], get_fs() == get_ds() ? "kernel" : "user"); -#if CONFIG_CPU_CP15 +#ifdef CONFIG_CPU_CP15 { unsigned int ctrl; - __asm__ ( - " mrc p15, 0, %0, c1, c0\n" - : "=r" (ctrl)); - printk("Control: %04X\n", ctrl); - } + + buf[0] = '\0'; #ifdef CONFIG_CPU_CP15_MMU - { - unsigned int transbase, dac; - __asm__ ( - " mrc p15, 0, %0, c2, c0\n" - " mrc p15, 0, %1, c3, c0\n" - : "=r" (transbase), "=r" (dac)); - printk("Table: %08X DAC: %08X\n", - transbase, dac); - } + { + unsigned int transbase, dac; + asm("mrc p15, 0, %0, c2, c0\n\t" + "mrc p15, 0, %1, c3, c0\n" + : "=r" (transbase), "=r" (dac)); + snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", + transbase, dac); + } #endif + asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); + + printk("Control: %08x%s\n", ctrl, buf); + } #endif } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 650eac1bc0a6..5be2e987b843 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -63,6 +63,8 @@ unsigned int processor_id; unsigned int __machine_arch_type; EXPORT_SYMBOL(__machine_arch_type); +unsigned int __atags_pointer __initdata; + unsigned int system_rev; EXPORT_SYMBOL(system_rev); @@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p) if (mdesc->soft_reboot) reboot_setup("s"); - if (mdesc->boot_params) + if (__atags_pointer) + tags = phys_to_virt(__atags_pointer); + else if (mdesc->boot_params) tags = phys_to_virt(mdesc->boot_params); /* diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 1ca2d5174fcb..4d25e49a14f7 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -328,16 +328,3 @@ asmlinkage long sys_arm_fadvise64_64(int fd, int advice, { return sys_fadvise64_64(fd, offset, len, advice); } - -/* - * Yet more syscall fsckage - we can't fit sys_sync_file_range's - * arguments into the available registers with EABI. So, let's - * create an ARM specific syscall for this which has _sane_ - * arguments. (This incidentally also has an ABI-independent - * argument layout.) - */ -asmlinkage long sys_arm_sync_file_range(int fd, unsigned int flags, - loff_t offset, loff_t nbytes) -{ - return sys_sync_file_range(fd, offset, nbytes, flags); -} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 10ff36e4e414..237f4999b9a1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -181,9 +181,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) void dump_stack(void) { -#ifdef CONFIG_DEBUG_ERRORS __backtrace(); -#endif } EXPORT_SYMBOL(dump_stack); @@ -204,12 +202,24 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) barrier(); } +#ifdef CONFIG_PREEMPT +#define S_PREEMPT " PREEMPT" +#else +#define S_PREEMPT "" +#endif +#ifdef CONFIG_SMP +#define S_SMP " SMP" +#else +#define S_SMP "" +#endif + static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) { struct task_struct *tsk = thread->task; static int die_counter; - printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); + printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", + str, err, ++die_counter); print_modules(); __show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", @@ -232,6 +242,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) { struct thread_info *thread = current_thread_info(); + oops_enter(); + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -239,9 +251,13 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) bust_spinlocks(0); spin_unlock_irq(&die_lock); + if (in_interrupt()) + panic("Fatal exception in interrupt"); + if (panic_on_oops) panic("Fatal exception"); + oops_exit(); do_exit(SIGSEGV); } |