00001 /* 00002 * Architecture specific scheduler support. 00003 * 00004 * Original RTAI/x86 layer implementation: 00005 * Copyright (c) 2000 Paolo Mantegazza (mantegazza@aero.polimi.it) 00006 * Copyright (c) 2000 Steve Papacharalambous (stevep@zentropix.com) 00007 * Copyright (c) 2000 Stuart Hughes 00008 * and others. 00009 * 00010 * RTAI/x86 rewrite over Adeos: 00011 * Copyright (c) 2002 Philippe Gerum (rpm@xenomai.org) 00012 * 00013 * Original RTAI/ARM RTHAL implementation: 00014 * Copyright (c) 2000 Pierre Cloutier (pcloutier@poseidoncontrols.com) 00015 * Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de) 00016 * Copyright (c) 2002 Guennadi Liakhovetski DSA GmbH (gl@dsa-ac.de) 00017 * Copyright (c) 2002 Steve Papacharalambous (stevep@zentropix.com) 00018 * Copyright (c) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de) 00019 * Copyright (c) 2003 Bernard Haible, Marconi Communications 00020 * Copyright (c) 2003 Thomas Gleixner (tglx@linutronix.de) 00021 * Copyright (c) 2003 Philippe Gerum (rpm@xenomai.org) 00022 * 00023 * RTAI/ARM over Adeos rewrite: 00024 * Copyright (c) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at) 00025 * 00026 * RTAI/ARM over Adeos rewrite for PXA255_2.6.7: 00027 * Copyright (c) 2005 Stefano Gafforelli (stefano.gafforelli@tiscali.it) 00028 * Copyright (c) 2005 Luca Pizzi (lucapizzi@hotmail.com) 00029 * 00030 * 00031 * This program is free software; you can redistribute it and/or modify it under 00032 * the terms of the GNU General Public License as published by the Free Software 00033 * Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, USA; either version 2 of 00034 * the License, or (at your option) any later version. 00035 * 00036 * This program is distributed in the hope that it will be useful, but WITHOUT 00037 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00038 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00039 * details. 00040 * 00041 * You should have received a copy of the GNU General Public License along with 00042 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00043 * Place - Suite 330, Boston, MA 02111-1307, USA. 00044 */ 00045 #ifndef _RTAI_ASM_ARM_RTAI_SCHED_H 00046 #define _RTAI_ASM_ARM_RTAI_SCHED_H 00047 00048 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) 00049 # include <asm/proc/ptrace.h> 00050 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ 00051 # include <asm/ptrace.h> 00052 # define I_BIT PSR_I_BIT 00053 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */ 00054 00055 #include <rtai_schedcore.h> 00056 00057 /* 00058 * Registers according to the ARM procedure call standard: 00059 * Reg Description 00060 * r0-r3 argument/scratch registers 00061 * r4-r9 variable register 00062 * r10=sl stack limit/variable register 00063 * r11=fp frame pointer/variable register 00064 * r12=ip intra-procedure-call scratch register 00065 * r13=sp stack pointer (auto preserved) 00066 * r14=lr link register 00067 * r15=pc program counter (auto preserved) 00068 * 00069 * Take special care to restore r0/r1 for startup of new task (-> 00070 * init_arch_stack, rt_startup)! 00071 * 00072 * Stack layout: 00073 * 00074 * Offset Content 00075 * 00076 * 12 r14=lr (i.e. resume point for task) 00077 * 11 r11=fp 00078 * 10 r10=sl 00079 * 9 r9 00080 * 8 r8 00081 * 7 r7 00082 * 6 r6 00083 * 5 r5 00084 * 4 r4 00085 * 3 cpsr 00086 * 2 domain_access_control 00087 * 1 r1 (startup: data) 00088 * 0 r0 (startup: rt_thread) 00089 */ 00090 00091 #define rt_exchange_tasks(old_task, new_task) \ 00092 asm volatile( \ 00093 "mrc p15, 0, r2, c3, c0\n\t" /* get current domain_access_control */ \ 00094 "adr lr, 1f\n\t" /* get address of resume point */ \ 00095 "mrs r3, cpsr\n\t" /* get current cpsr */ \ 00096 "ldr ip, [%[oldp]]\n\t" /* get pointer to old task */ \ 00097 "stmfd sp!, {r0 - fp, lr}\n\t" /* push registers on stack */ \ 00098 "str %[new], [%[oldp]]\n\t" /* *oldp = new */ \ 00099 "str sp, [ip]\n\t" /* save current stack-pointer to old task */ \ 00100 "ldr sp, [%[new]]\n\t" /* get stack-pointer of new task */ \ 00101 "ldmfd sp!, {r0-r3}\n\t" /* pop new tasks' r0, r1, cpsr & d.a.c from stack */ \ 00102 "mcr p15, 0, r2, c3, c0\n\t" /* restore previous domain_access_control */ \ 00103 "msr cpsr_c, %[psr]\n\t" /* disable hw-irqs */ \ 00104 "msr spsr, r3\n\t" /* set spsr to previous cpsr */ \ 00105 "ldmfd sp!, {r4 - fp, pc}^\n\t" /* pop registers, pc = resume point, cpsr = spsr */ \ 00106 "1:" /* resume point (except for startup) */ \ 00107 : /* output */ /* none */ \ 00108 : /* input */ [oldp] "r" (&old_task), \ 00109 [new] "r" (new_task), \ 00110 [psr] "i" (SVC_MODE|I_BIT) \ 00111 : /* clobber */ "lr", "ip", "r2", "r3", "memory" \ 00112 ) 00113 00114 extern inline unsigned long 00115 current_domain_access_control(void) 00116 { 00117 unsigned long domain_access_control; 00118 asm("mrc p15, 0, %0, c3, c0" : "=r" (domain_access_control)); 00119 return domain_access_control; 00120 } 00121 00122 /* 00123 * Set up stack for new proper RTAI task (i.e. kernel task without 00124 * kernel-thread). This is called in rt_task_init_cpuid() where the following 00125 * variables are used (should be arguments to macro!): 00126 * rt_thread pointer to tasks function 00127 * data integer to pass to rt_thread 00128 * 00129 * The stack needs to be set-up so that a rt_exchange_tasks() on the newly 00130 * created task will call rt_startup(rt_thread = r0, data = r1). 00131 * 00132 * See rt_exchange_tasks() above for the stack layout. 00133 * 00134 */ 00135 #define init_arch_stack() \ 00136 do { \ 00137 task->stack -= 13; /* make room on stack */ \ 00138 task->stack[12] = (int)rt_startup; /* entry point */ \ 00139 task->stack[ 3] = SVC_MODE; /* cpsr */ \ 00140 task->stack[ 2] = (int)current_domain_access_control(); \ 00141 task->stack[ 1] = (int)data; /* arg 2 of rt_startup() */ \ 00142 task->stack[ 0] = (int)rt_thread; /* arg 1 " " */ \ 00143 } while (0) 00144 00145 #define DEFINE_LINUX_CR0 00146 #define DEFINE_LINUX_SMP_CR0 00147 00148 #ifdef CONFIG_RTAI_FP_SUPPORT 00149 #define init_fp_env() \ 00150 do { \ 00151 memset(&task->fpu_reg, 0, sizeof(task->fpu_reg)); \ 00152 }while(0) 00153 #else 00154 #define init_fp_env() 00155 #endif 00156 00157 #define init_task_fpenv(task) do { init_fpenv((task)->fpu_reg); } while(0) 00158 00159 extern inline void * 00160 get_stack_pointer(void) 00161 { 00162 void *sp; 00163 asm("mov %0, sp" : "=r" (sp)); 00164 return sp; 00165 } 00166 00167 /* acknowledge timer interrupt in scheduler's timer-handler (using the 00168 * arch-specific rtai_timer_irq_ack()) also allows to bail out of timer irq 00169 * handler (because of spurious interrupt or whatever) */ 00170 #ifndef CONFIG_ARCH_AT91 00171 #define DO_TIMER_PROPER_OP() \ 00172 do { \ 00173 rtai_timer_irq_ack(); \ 00174 } while (0) 00175 #else 00176 /* since we are using extern_timer_isr in __ipipe_grab_irq 00177 * we need to update tsc manually in periodic mode*/ 00178 #define DO_TIMER_PROPER_OP() \ 00179 do { \ 00180 if(rt_periodic) { \ 00181 rtai_at91_update_tsc(); \ 00182 } \ 00183 } while (0) 00184 #endif 00185 00186 #endif /* _RTAI_ASM_ARM_RTAI_SCHED_H */