diff options
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/.gitignore | 1 | ||||
-rw-r--r-- | arch/arc/kernel/devtree.c | 6 | ||||
-rw-r--r-- | arch/arc/kernel/entry.S | 66 | ||||
-rw-r--r-- | arch/arc/kernel/head.S | 5 | ||||
-rw-r--r-- | arch/arc/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/arc/kernel/ptrace.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 5 | ||||
-rw-r--r-- | arch/arc/kernel/signal.c | 25 | ||||
-rw-r--r-- | arch/arc/kernel/time.c | 7 | ||||
-rw-r--r-- | arch/arc/kernel/unaligned.c | 32 |
10 files changed, 65 insertions, 85 deletions
diff --git a/arch/arc/kernel/.gitignore b/arch/arc/kernel/.gitignore new file mode 100644 index 00000000000..c5f676c3c22 --- /dev/null +++ b/arch/arc/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index bdee3a81205..2340af0e1d6 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -18,12 +18,6 @@ #include <asm/clk.h> #include <asm/mach_desc.h> -/* called from unflatten_device_tree() to bootstrap devicetree itself */ -void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) -{ - return __va(memblock_alloc(size, align)); -} - /** * setup_machine_fdt - Machine setup when an dtb was passed to the kernel * @dt: virtual address pointer to dt blob diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 1d7165156e1..b908dde8a33 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -267,12 +267,7 @@ ARC_EXIT handle_interrupt_level1 ARC_ENTRY instr_service - EXCPN_PROLOG_FREEUP_REG r9 - - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE lr r0, [efa] mov r1, sp @@ -289,15 +284,13 @@ ARC_EXIT instr_service ARC_ENTRY mem_service - EXCPN_PROLOG_FREEUP_REG r9 - - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE lr r0, [efa] mov r1, sp + + FAKE_RET_FROM_EXCPN r9 + bl do_memory_error b ret_from_exception ARC_EXIT mem_service @@ -308,11 +301,7 @@ ARC_EXIT mem_service ARC_ENTRY EV_MachineCheck - EXCPN_PROLOG_FREEUP_REG r9 - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE lr r2, [ecr] lr r0, [efa] @@ -342,13 +331,7 @@ ARC_EXIT EV_MachineCheck ARC_ENTRY EV_TLBProtV - EXCPN_PROLOG_FREEUP_REG r9 - - ;Which mode (user/kernel) was the system in when Exception occured - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE ;---------(3) Save some more regs----------------- ; vineetg: Mar 6th: Random Seg Fault issue #1 @@ -406,12 +389,7 @@ ARC_EXIT EV_TLBProtV ; --------------------------------------------- ARC_ENTRY EV_PrivilegeV - EXCPN_PROLOG_FREEUP_REG r9 - - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE lr r0, [efa] mov r1, sp @@ -427,14 +405,13 @@ ARC_EXIT EV_PrivilegeV ; --------------------------------------------- ARC_ENTRY EV_Extension - EXCPN_PROLOG_FREEUP_REG r9 - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE lr r0, [efa] mov r1, sp + + FAKE_RET_FROM_EXCPN r9 + bl do_extension_fault b ret_from_exception ARC_EXIT EV_Extension @@ -526,14 +503,7 @@ trap_with_param: ARC_ENTRY EV_Trap - ; Need at least 1 reg to code the early exception prolog - EXCPN_PROLOG_FREEUP_REG r9 - - ;Which mode (user/kernel) was the system in when intr occured - lr r9, [erstatus] - - SWITCH_TO_KERNEL_STK - SAVE_ALL_SYS + EXCEPTION_PROLOGUE ;------- (4) What caused the Trap -------------- lr r12, [ecr] @@ -642,6 +612,9 @@ resume_kernel_mode: #ifdef CONFIG_PREEMPT + ; This is a must for preempt_schedule_irq() + IRQ_DISABLE r9 + ; Can't preempt if preemption disabled GET_CURR_THR_INFO_FROM_SP r10 ld r8, [r10, THREAD_INFO_PREEMPT_COUNT] @@ -651,8 +624,6 @@ resume_kernel_mode: ld r9, [r10, THREAD_INFO_FLAGS] bbit0 r9, TIF_NEED_RESCHED, restore_regs - IRQ_DISABLE r9 - ; Invoke PREEMPTION bl preempt_schedule_irq @@ -665,12 +636,11 @@ resume_kernel_mode: ; ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap) ; IRQ shd definitely not happen between now and rtie +; All 2 entry points to here already disable interrupts restore_regs : - ; Disable Interrupts while restoring reg-file back - ; XXX can this be optimised out - IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy + lr r10, [status32] ; Restore REG File. In case multiple Events outstanding, ; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 2a913f85a74..0f944f02451 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S @@ -34,6 +34,9 @@ stext: ; IDENTITY Reg [ 3 2 1 0 ] ; (cpu-id) ^^^ => Zero for UP ARC700 ; => #Core-ID if SMP (Master 0) + ; Note that non-boot CPUs might not land here if halt-on-reset and + ; instead breath life from @first_lines_of_secondary, but we still + ; need to make sure only boot cpu takes this path. GET_CPU_ID r5 cmp r5, 0 jnz arc_platform_smp_wait_to_boot @@ -98,6 +101,8 @@ stext: first_lines_of_secondary: + sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] + ; setup per-cpu idle task as "current" on this CPU ld r0, [@secondary_idle_tsk] SET_CURR_TASK_ON_CPU r0, r1 diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index 305b3f866aa..5fc92455da3 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -24,7 +24,6 @@ * -Needed for each CPU (hence not foldable into init_IRQ) * * what it does ? - * -setup Vector Table Base Reg - in case Linux not linked at 0x8000_0000 * -Disable all IRQs (on CPU side) * -Optionally, setup the High priority Interrupts as Level 2 IRQs */ diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 333238564b6..5d76706139d 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -102,7 +102,7 @@ static int genregs_set(struct task_struct *target, REG_IGNORE_ONE(pad2); REG_IN_CHUNK(callee, efa, cregs); /* callee_regs[r25..r13] */ REG_IGNORE_ONE(efa); /* efa update invalid */ - REG_IN_ONE(stop_pc, &ptregs->ret); /* stop_pc: PC update */ + REG_IGNORE_ONE(stop_pc); /* PC updated via @ret */ return ret; } diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 6b083454d03..2c68bc7e6a7 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -47,10 +47,7 @@ void read_arc_build_cfg_regs(void) READ_BCR(AUX_IDENTITY, cpu->core); cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR); - cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE); - if (cpu->vec_base == 0) - cpu->vec_base = (unsigned int)_int_vec_base_lds; READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space); cpu->uncached_base = uncached_space.start << 24; @@ -357,8 +354,6 @@ void __init setup_arch(char **cmdline_p) */ root_mountflags &= ~MS_RDONLY; - console_verbose(); - #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index ee6ef2f60a2..7e95e1a8651 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -101,7 +101,6 @@ SYSCALL_DEFINE0(rt_sigreturn) { struct rt_sigframe __user *sf; unsigned int magic; - int err; struct pt_regs *regs = current_pt_regs(); /* Always make any pending restarted system calls return -EINTR */ @@ -119,15 +118,16 @@ SYSCALL_DEFINE0(rt_sigreturn) if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) goto badframe; - err = restore_usr_regs(regs, sf); - err |= __get_user(magic, &sf->sigret_magic); - if (err) + if (__get_user(magic, &sf->sigret_magic)) goto badframe; if (unlikely(is_do_ss_needed(magic))) if (restore_altstack(&sf->uc.uc_stack)) goto badframe; + if (restore_usr_regs(regs, sf)) + goto badframe; + /* Don't restart from sigreturn */ syscall_wont_restart(regs); @@ -191,6 +191,15 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, return 1; /* + * w/o SA_SIGINFO, struct ucontext is partially populated (only + * uc_mcontext/uc_sigmask) for kernel's normal user state preservation + * during signal handler execution. This works for SA_SIGINFO as well + * although the semantics are now overloaded (the same reg state can be + * inspected by userland: but are they allowed to fiddle with it ? + */ + err |= stash_usr_regs(sf, regs, set); + + /* * SA_SIGINFO requires 3 args to signal handler: * #1: sig-no (common to any handler) * #2: struct siginfo @@ -213,14 +222,6 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, magic = MAGIC_SIGALTSTK; } - /* - * w/o SA_SIGINFO, struct ucontext is partially populated (only - * uc_mcontext/uc_sigmask) for kernel's normal user state preservation - * during signal handler execution. This works for SA_SIGINFO as well - * although the semantics are now overloaded (the same reg state can be - * inspected by userland: but are they allowed to fiddle with it ? - */ - err |= stash_usr_regs(sf, regs, set); err |= __put_user(magic, &sf->sigret_magic); if (err) return err; diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 0e51e69cf30..3fde7de3ea6 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -227,12 +227,9 @@ void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu) { struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); - clockevents_calc_mult_shift(clk, arc_get_core_freq(), 5); - - clk->max_delta_ns = clockevent_delta2ns(ARC_TIMER_MAX, clk); clk->cpumask = cpumask_of(cpu); - - clockevents_register_device(clk); + clockevents_config_and_register(clk, arc_get_core_freq(), + 0, ARC_TIMER_MAX); /* * setup the per-cpu timer IRQ handler - for all cpus diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c index c0f832f595d..7ff5b5c183b 100644 --- a/arch/arc/kernel/unaligned.c +++ b/arch/arc/kernel/unaligned.c @@ -16,6 +16,16 @@ #include <linux/uaccess.h> #include <asm/disasm.h> +#ifdef CONFIG_CPU_BIG_ENDIAN +#define BE 1 +#define FIRST_BYTE_16 "swap %1, %1\n swape %1, %1\n" +#define FIRST_BYTE_32 "swape %1, %1\n" +#else +#define BE 0 +#define FIRST_BYTE_16 +#define FIRST_BYTE_32 +#endif + #define __get8_unaligned_check(val, addr, err) \ __asm__( \ "1: ldb.ab %1, [%2, 1]\n" \ @@ -36,9 +46,9 @@ do { \ unsigned int err = 0, v, a = addr; \ __get8_unaligned_check(v, a, err); \ - val = v ; \ + val = v << ((BE) ? 8 : 0); \ __get8_unaligned_check(v, a, err); \ - val |= v << 8; \ + val |= v << ((BE) ? 0 : 8); \ if (err) \ goto fault; \ } while (0) @@ -47,13 +57,13 @@ do { \ unsigned int err = 0, v, a = addr; \ __get8_unaligned_check(v, a, err); \ - val = v << 0; \ + val = v << ((BE) ? 24 : 0); \ __get8_unaligned_check(v, a, err); \ - val |= v << 8; \ + val |= v << ((BE) ? 16 : 8); \ __get8_unaligned_check(v, a, err); \ - val |= v << 16; \ + val |= v << ((BE) ? 8 : 16); \ __get8_unaligned_check(v, a, err); \ - val |= v << 24; \ + val |= v << ((BE) ? 0 : 24); \ if (err) \ goto fault; \ } while (0) @@ -63,6 +73,7 @@ unsigned int err = 0, v = val, a = addr;\ \ __asm__( \ + FIRST_BYTE_16 \ "1: stb.ab %1, [%2, 1]\n" \ " lsr %1, %1, 8\n" \ "2: stb %1, [%2]\n" \ @@ -87,8 +98,9 @@ #define put32_unaligned_check(val, addr) \ do { \ unsigned int err = 0, v = val, a = addr;\ - __asm__( \ \ + __asm__( \ + FIRST_BYTE_32 \ "1: stb.ab %1, [%2, 1]\n" \ " lsr %1, %1, 8\n" \ "2: stb.ab %1, [%2, 1]\n" \ @@ -233,6 +245,12 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs, regs->status32 &= ~STATUS_DE_MASK; } else { regs->ret += state.instr_len; + + /* handle zero-overhead-loop */ + if ((regs->ret == regs->lp_end) && (regs->lp_count)) { + regs->ret = regs->lp_start; + regs->lp_count--; + } } return 0; |