···1717 select GENERIC_FIND_FIRST_BIT1818 # for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP1919 select GENERIC_IRQ_SHOW2020+ select GENERIC_KERNEL_EXECVE2121+ select GENERIC_KERNEL_THREAD2022 select GENERIC_PENDING_IRQ if SMP2123 select GENERIC_SMP_IDLE_THREAD2224 select HAVE_GENERIC_HARDIRQS
+20
arch/arc/include/asm/arcregs.h
···4747#define AUX_ITRIGGER 0x40d4848#define AUX_IPULSE 0x41549495050+/*5151+ * Floating Pt Registers5252+ * Status regs are read-only (build-time) so need not be saved/restored5353+ */5454+#define ARC_AUX_FP_STAT 0x3005555+#define ARC_AUX_DPFP_1L 0x3015656+#define ARC_AUX_DPFP_1H 0x3025757+#define ARC_AUX_DPFP_2L 0x3035858+#define ARC_AUX_DPFP_2H 0x3045959+#define ARC_AUX_DPFP_STAT 0x3056060+5061#ifndef __ASSEMBLY__51625263/*···119108 : "r"(val), "memory"(®_in_var)); \120109})121110111111+#endif112112+113113+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE114114+/* These DPFP regs need to be saved/restored across ctx-sw */115115+struct arc_fpu {116116+ struct {117117+ unsigned int l, h;118118+ } aux_dpfp[2];119119+};122120#endif123121124122#endif /* __ASEMBLY__ */
+3-6
arch/arc/include/asm/processor.h
···2929 unsigned long callee_reg; /* pointer to callee regs */3030 unsigned long fault_address; /* dbls as brkpt holder as well */3131 unsigned long cause_code; /* Exception Cause Code (ECR) */3232+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE3333+ struct arc_fpu fpu;3434+#endif3235};33363437#define INIT_THREAD { \···5653#define prepare_to_copy(tsk) do { } while (0)57545855#define cpu_relax() do { } while (0)5959-6060-/*6161- * Create a new kernel thread6262- */6363-6464-extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);65566657#define copy_segments(tsk, mm) do { } while (0)6758#define release_segments(mm) do { } while (0)
···11+/*22+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)33+ *44+ * This program is free software; you can redistribute it and/or modify55+ * it under the terms of the GNU General Public License version 2 as66+ * published by the Free Software Foundation.77+ */88+99+#ifndef _ASM_ARC_SWITCH_TO_H1010+#define _ASM_ARC_SWITCH_TO_H1111+1212+#ifndef __ASSEMBLY__1313+1414+#include <linux/sched.h>1515+1616+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE1717+1818+extern void fpu_save_restore(struct task_struct *p, struct task_struct *n);1919+#define ARC_FPU_PREV(p, n) fpu_save_restore(p, n)2020+#define ARC_FPU_NEXT(t)2121+2222+#else2323+2424+#define ARC_FPU_PREV(p, n)2525+#define ARC_FPU_NEXT(n)2626+2727+#endif /* !CONFIG_ARC_FPU_SAVE_RESTORE */2828+2929+struct task_struct *__switch_to(struct task_struct *p, struct task_struct *n);3030+3131+#define switch_to(prev, next, last) \3232+do { \3333+ ARC_FPU_PREV(prev, next); \3434+ last = __switch_to(prev, next);\3535+ ARC_FPU_NEXT(next); \3636+ mb(); \3737+} while (0)3838+3939+#endif4040+4141+#endif
+91
arch/arc/kernel/ctx_sw.c
···11+/*22+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)33+ *44+ * This program is free software; you can redistribute it and/or modify55+ * it under the terms of the GNU General Public License version 2 as66+ * published by the Free Software Foundation.77+ *88+ * Vineetg: Aug 200999+ * -"C" version of lowest level context switch asm macro called by schedular1010+ * gcc doesn't generate the dward CFI info for hand written asm, hence can't1111+ * backtrace out of it (e.g. tasks sleeping in kernel).1212+ * So we cheat a bit by writing almost similar code in inline-asm.1313+ * -This is a hacky way of doing things, but there is no other simple way.1414+ * I don't want/intend to extend unwinding code to understand raw asm1515+ */1616+1717+#include <asm/asm-offsets.h>1818+#include <linux/sched.h>1919+2020+struct task_struct *__sched2121+__switch_to(struct task_struct *prev_task, struct task_struct *next_task)2222+{2323+ unsigned int tmp;2424+ unsigned int prev = (unsigned int)prev_task;2525+ unsigned int next = (unsigned int)next_task;2626+ int num_words_to_skip = 1;2727+2828+ __asm__ __volatile__(2929+ /* FP/BLINK save generated by gcc (standard function prologue */3030+ "st.a r13, [sp, -4] \n\t"3131+ "st.a r14, [sp, -4] \n\t"3232+ "st.a r15, [sp, -4] \n\t"3333+ "st.a r16, [sp, -4] \n\t"3434+ "st.a r17, [sp, -4] \n\t"3535+ "st.a r18, [sp, -4] \n\t"3636+ "st.a r19, [sp, -4] \n\t"3737+ "st.a r20, [sp, -4] \n\t"3838+ "st.a r21, [sp, -4] \n\t"3939+ "st.a r22, [sp, -4] \n\t"4040+ "st.a r23, [sp, -4] \n\t"4141+ "st.a r24, [sp, -4] \n\t"4242+ "st.a r25, [sp, -4] \n\t"4343+ "sub sp, sp, %4 \n\t" /* create gutter at top */4444+4545+ /* set ksp of outgoing task in tsk->thread.ksp */4646+ "st.as sp, [%3, %1] \n\t"4747+4848+ "sync \n\t"4949+5050+ /*5151+ * setup _current_task with incoming tsk.5252+ * optionally, set r25 to that as well5353+ * For SMP extra work to get to &_current_task[cpu]5454+ * (open coded SET_CURR_TASK_ON_CPU)5555+ */5656+ "st %2, [@_current_task] \n\t"5757+5858+ /* get ksp of incoming task from tsk->thread.ksp */5959+ "ld.as sp, [%2, %1] \n\t"6060+6161+ /* start loading it's CALLEE reg file */6262+6363+ "add sp, sp, %4 \n\t" /* skip gutter at top */6464+6565+ "ld.ab r25, [sp, 4] \n\t"6666+ "ld.ab r24, [sp, 4] \n\t"6767+ "ld.ab r23, [sp, 4] \n\t"6868+ "ld.ab r22, [sp, 4] \n\t"6969+ "ld.ab r21, [sp, 4] \n\t"7070+ "ld.ab r20, [sp, 4] \n\t"7171+ "ld.ab r19, [sp, 4] \n\t"7272+ "ld.ab r18, [sp, 4] \n\t"7373+ "ld.ab r17, [sp, 4] \n\t"7474+ "ld.ab r16, [sp, 4] \n\t"7575+ "ld.ab r15, [sp, 4] \n\t"7676+ "ld.ab r14, [sp, 4] \n\t"7777+ "ld.ab r13, [sp, 4] \n\t"7878+7979+ /* last (ret value) = prev : although for ARC it mov r0, r0 */8080+ "mov %0, %3 \n\t"8181+8282+ /* FP/BLINK restore generated by gcc (standard func epilogue */8383+8484+ : "=r"(tmp)8585+ : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev),8686+ "n"(num_words_to_skip * 4)8787+ : "blink"8888+ );8989+9090+ return (struct task_struct *)tmp;9191+}
+58
arch/arc/kernel/ctx_sw_asm.S
···11+/*22+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)33+ *44+ * This program is free software; you can redistribute it and/or modify55+ * it under the terms of the GNU General Public License version 2 as66+ * published by the Free Software Foundation.77+ *88+ * Vineetg: Aug 200999+ * -Moved core context switch macro out of entry.S into this file.1010+ * -This is the more "natural" hand written assembler1111+ */1212+1313+#include <asm/entry.h> /* For the SAVE_* macros */1414+#include <asm/asm-offsets.h>1515+#include <asm/linkage.h>1616+1717+;################### Low Level Context Switch ##########################1818+1919+ .section .sched.text,"ax",@progbits2020+ .align 42121+ .global __switch_to2222+ .type __switch_to, @function2323+__switch_to:2424+2525+ /* Save regs on kernel mode stack of task */2626+ st.a blink, [sp, -4]2727+ st.a fp, [sp, -4]2828+ SAVE_CALLEE_SAVED_KERNEL2929+3030+ /* Save the now KSP in task->thread.ksp */3131+ st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4]3232+3333+ /*3434+ * Return last task in r0 (return reg)3535+ * On ARC, Return reg = First Arg reg = r0.3636+ * Since we already have last task in r0,3737+ * don't need to do anything special to return it3838+ */3939+4040+ /* hardware memory barrier */4141+ sync4242+4343+ /*4444+ * switch to new task, contained in r14545+ * Temp reg r3 is required to get the ptr to store val4646+ */4747+ SET_CURR_TASK_ON_CPU r1, r34848+4949+ /* reload SP with kernel mode stack pointer in task->thread.ksp */5050+ ld.as sp, [r1, (TASK_THREAD + THREAD_KSP)/4]5151+5252+ /* restore the registers */5353+ RESTORE_CALLEE_SAVED_KERNEL5454+ ld.ab fp, [sp, 4]5555+ ld.ab blink, [sp, 4]5656+ j [blink]5757+5858+ARC_EXIT __switch_to
+13-2
arch/arc/kernel/entry.S
···566566 ; when the forked child comes here from the __switch_to function567567 ; r0 has the last task pointer.568568 ; put last task in scheduler queue569569- bl @schedule_tail570570- b @ret_from_exception569569+ bl @schedule_tail570570+571571+ ; If kernel thread, jump to it's entry-point572572+ ld r9, [sp, PT_status32]573573+ brne r9, 0, 1f574574+575575+ jl.d [r14]576576+ mov r0, r13 ; arg to payload577577+578578+1:579579+ ; special case of kernel_thread entry point returning back due to580580+ ; kernel_execve() - pretend return from syscall to ret to userland581581+ b ret_from_exception571582ARC_EXIT ret_from_fork572583573584;################### Special Sys Call Wrappers ##########################
+55
arch/arc/kernel/fpu.c
···11+/*22+ * fpu.c - save/restore of Floating Point Unit Registers on task switch33+ *44+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License version 2 as88+ * published by the Free Software Foundation.99+ */1010+1111+#include <linux/sched.h>1212+#include <asm/switch_to.h>1313+1414+/*1515+ * To save/restore FPU regs, simplest scheme would use LR/SR insns.1616+ * However since SR serializes the pipeline, an alternate "hack" can be used1717+ * which uses the FPU Exchange insn (DEXCL) to r/w FPU regs.1818+ *1919+ * Store to 64bit dpfp1 reg from a pair of core regs:2020+ * dexcl1 0, r1, r0 ; where r1:r0 is the 64 bit val2121+ *2222+ * Read from dpfp1 into pair of core regs (w/o clobbering dpfp1)2323+ * mov_s r3, 02424+ * daddh11 r1, r3, r3 ; get "hi" into r1 (dpfp1 unchanged)2525+ * dexcl1 r0, r1, r3 ; get "low" into r0 (dpfp1 low clobbered)2626+ * dexcl1 0, r1, r0 ; restore dpfp1 to orig value2727+ *2828+ * However we can tweak the read, so that read-out of outgoing task's FPU regs2929+ * and write of incoming task's regs happen in one shot. So all the work is3030+ * done before context switch3131+ */3232+3333+void fpu_save_restore(struct task_struct *prev, struct task_struct *next)3434+{3535+ unsigned int *saveto = &prev->thread.fpu.aux_dpfp[0].l;3636+ unsigned int *readfrom = &next->thread.fpu.aux_dpfp[0].l;3737+3838+ const unsigned int zero = 0;3939+4040+ __asm__ __volatile__(4141+ "daddh11 %0, %2, %2\n"4242+ "dexcl1 %1, %3, %4\n"4343+ : "=&r" (*(saveto + 1)), /* early clobber must here */4444+ "=&r" (*(saveto))4545+ : "r" (zero), "r" (*(readfrom + 1)), "r" (*(readfrom))4646+ );4747+4848+ __asm__ __volatile__(4949+ "daddh22 %0, %2, %2\n"5050+ "dexcl2 %1, %3, %4\n"5151+ : "=&r"(*(saveto + 3)), /* early clobber must here */5252+ "=&r"(*(saveto + 2))5353+ : "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2))5454+ );5555+}
+193
arch/arc/kernel/process.c
···4040{4141 return task_thread_info(current)->thr_ptr;4242}4343+4444+static inline void arch_idle(void)4545+{4646+ /* sleep, but enable all interrupts before committing */4747+ __asm__("sleep 0x3");4848+}4949+5050+void cpu_idle(void)5151+{5252+ /* Since we SLEEP in idle loop, TIF_POLLING_NRFLAG can't be set */5353+5454+ /* endless idle loop with no priority at all */5555+ while (1) {5656+ tick_nohz_idle_enter();5757+ rcu_idle_enter();5858+5959+doze:6060+ local_irq_disable();6161+ if (!need_resched()) {6262+ arch_idle();6363+ goto doze;6464+ } else {6565+ local_irq_enable();6666+ }6767+6868+ rcu_idle_exit();6969+ tick_nohz_idle_exit();7070+7171+ schedule_preempt_disabled();7272+ }7373+}7474+7575+asmlinkage void ret_from_fork(void);7676+7777+/* Layout of Child kernel mode stack as setup at the end of this function is7878+ *7979+ * | ... |8080+ * | ... |8181+ * | unused |8282+ * | |8383+ * ------------------ <==== top of Stack (thread.ksp)8484+ * | UNUSED 1 word|8585+ * ------------------8686+ * | r25 |8787+ * ~ ~8888+ * | --to-- | (CALLEE Regs of user mode)8989+ * | r13 |9090+ * ------------------9191+ * | fp |9292+ * | blink | @ret_from_fork9393+ * ------------------9494+ * | |9595+ * ~ ~9696+ * ~ ~9797+ * | |9898+ * ------------------9999+ * | r12 |100100+ * ~ ~101101+ * | --to-- | (scratch Regs of user mode)102102+ * | r0 |103103+ * ------------------104104+ * | UNUSED 1 word|105105+ * ------------------ <===== END of PAGE106106+ */107107+int copy_thread(unsigned long clone_flags,108108+ unsigned long usp, unsigned long arg,109109+ struct task_struct *p)110110+{111111+ struct pt_regs *c_regs; /* child's pt_regs */112112+ unsigned long *childksp; /* to unwind out of __switch_to() */113113+ struct callee_regs *c_callee; /* child's callee regs */114114+ struct callee_regs *parent_callee; /* paren't callee */115115+ struct pt_regs *regs = current_pt_regs();116116+117117+ /* Mark the specific anchors to begin with (see pic above) */118118+ c_regs = task_pt_regs(p);119119+ childksp = (unsigned long *)c_regs - 2; /* 2 words for FP/BLINK */120120+ c_callee = ((struct callee_regs *)childksp) - 1;121121+122122+ /*123123+ * __switch_to() uses thread.ksp to start unwinding stack124124+ * For kernel threads we don't need to create callee regs, the125125+ * stack layout nevertheless needs to remain the same.126126+ * Also, since __switch_to anyways unwinds callee regs, we use127127+ * this to populate kernel thread entry-pt/args into callee regs,128128+ * so that ret_from_kernel_thread() becomes simpler.129129+ */130130+ p->thread.ksp = (unsigned long)c_callee; /* THREAD_KSP */131131+132132+ /* __switch_to expects FP(0), BLINK(return addr) at top */133133+ childksp[0] = 0; /* fp */134134+ childksp[1] = (unsigned long)ret_from_fork; /* blink */135135+136136+ if (unlikely(p->flags & PF_KTHREAD)) {137137+ memset(c_regs, 0, sizeof(struct pt_regs));138138+139139+ c_callee->r13 = arg; /* argument to kernel thread */140140+ c_callee->r14 = usp; /* function */141141+142142+ return 0;143143+ }144144+145145+ /*--------- User Task Only --------------*/146146+147147+ /* __switch_to expects FP(0), BLINK(return addr) at top of stack */148148+ childksp[0] = 0; /* for POP fp */149149+ childksp[1] = (unsigned long)ret_from_fork; /* for POP blink */150150+151151+ /* Copy parents pt regs on child's kernel mode stack */152152+ *c_regs = *regs;153153+154154+ if (usp)155155+ c_regs->sp = usp;156156+157157+ c_regs->r0 = 0; /* fork returns 0 in child */158158+159159+ parent_callee = ((struct callee_regs *)regs) - 1;160160+ *c_callee = *parent_callee;161161+162162+ if (unlikely(clone_flags & CLONE_SETTLS)) {163163+ /*164164+ * set task's userland tls data ptr from 4th arg165165+ * clone C-lib call is difft from clone sys-call166166+ */167167+ task_thread_info(p)->thr_ptr = regs->r3;168168+ } else {169169+ /* Normal fork case: set parent's TLS ptr in child */170170+ task_thread_info(p)->thr_ptr =171171+ task_thread_info(current)->thr_ptr;172172+ }173173+174174+ return 0;175175+}176176+177177+/*178178+ * Some archs flush debug and FPU info here179179+ */180180+void flush_thread(void)181181+{182182+}183183+184184+/*185185+ * Free any architecture-specific thread data structures, etc.186186+ */187187+void exit_thread(void)188188+{189189+}190190+191191+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)192192+{193193+ return 0;194194+}195195+196196+/*197197+ * API: expected by schedular Code: If thread is sleeping where is that.198198+ * What is this good for? it will be always the scheduler or ret_from_fork.199199+ * So we hard code that anyways.200200+ */201201+unsigned long thread_saved_pc(struct task_struct *t)202202+{203203+ struct pt_regs *regs = task_pt_regs(t);204204+ unsigned long blink = 0;205205+206206+ /*207207+ * If the thread being queried for in not itself calling this, then it208208+ * implies it is not executing, which in turn implies it is sleeping,209209+ * which in turn implies it got switched OUT by the schedular.210210+ * In that case, it's kernel mode blink can reliably retrieved as per211211+ * the picture above (right above pt_regs).212212+ */213213+ if (t != current && t->state != TASK_RUNNING)214214+ blink = *((unsigned int *)regs - 1);215215+216216+ return blink;217217+}218218+219219+int elf_check_arch(const struct elf32_hdr *x)220220+{221221+ unsigned int eflags;222222+223223+ if (x->e_machine != EM_ARCOMPACT)224224+ return 0;225225+226226+ eflags = x->e_flags;227227+ if ((eflags & EF_ARC_OSABI_MSK) < EF_ARC_OSABI_V2) {228228+ pr_err("ABI mismatch - you need newer toolchain\n");229229+ force_sigsegv(SIGSEGV, current);230230+ return 0;231231+ }232232+233233+ return 1;234234+}235235+EXPORT_SYMBOL(elf_check_arch);