00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _RTAI_ASM_GENERIC_SYSTEM_H
00022 #define _RTAI_ASM_GENERIC_SYSTEM_H
00023
00024 #ifdef __KERNEL__
00025
00026 #include <linux/kernel.h>
00027 #include <linux/version.h>
00028 #include <linux/module.h>
00029 #include <linux/slab.h>
00030 #include <linux/errno.h>
00031 #include <linux/vmalloc.h>
00032 #include <asm/uaccess.h>
00033 #include <asm/param.h>
00034 #include <asm/mmu_context.h>
00035 #include <rtai_config.h>
00036 #include <nucleus/asm/hal.h>
00037 #include <nucleus/asm/atomic.h>
00038 #include <nucleus/shadow.h>
00039
00040 #define module_param_value(parm) (parm)
00041
00042 typedef unsigned long spl_t;
00043
00044 #define splhigh(x) rthal_local_irq_save(x)
00045 #ifdef CONFIG_SMP
00046 #define splexit(x) rthal_local_irq_restore((x) & 1)
00047 #else
00048 #define splexit(x) rthal_local_irq_restore(x)
00049 #endif
00050 #define splnone() rthal_local_irq_enable()
00051 #define spltest() rthal_local_irq_test()
00052 #define splget(x) rthal_local_irq_flags(x)
00053 #define splsync(x) rthal_local_irq_sync(x)
00054
00055 #if defined(CONFIG_SMP) && \
00056 (defined(CONFIG_RTAI_OPT_STATS) || defined(CONFIG_RTAI_OPT_DEBUG))
00057
00058 typedef struct {
00059
00060 unsigned long long spin_time;
00061 unsigned long long lock_time;
00062 const char *file;
00063 const char *function;
00064 unsigned line;
00065
00066 } xnlockinfo_t;
00067
00068 typedef struct {
00069
00070 volatile unsigned long lock;
00071 const char *file;
00072 const char *function;
00073 unsigned line;
00074 int cpu;
00075 unsigned long long spin_time;
00076 unsigned long long lock_date;
00077
00078 } xnlock_t;
00079
00080 #define XNARCH_LOCK_UNLOCKED (xnlock_t) { \
00081 0, \
00082 NULL, \
00083 NULL, \
00084 0, \
00085 -1, \
00086 0LL, \
00087 0LL, \
00088 }
00089
00090 #define CONFIG_RTAI_SPINLOCK_DEBUG 1
00091
00092 #else
00093
00094 typedef struct { volatile unsigned long lock; } xnlock_t;
00095
00096 #define XNARCH_LOCK_UNLOCKED (xnlock_t) { 0 }
00097
00098 #endif
00099
00100 #define XNARCH_NR_CPUS RTHAL_NR_CPUS
00101
00102 #define XNARCH_ROOT_STACKSZ 0
00103
00104 #define XNARCH_PROMPT "RTAI: "
00105 #define xnarch_loginfo(fmt,args...) printk(KERN_INFO XNARCH_PROMPT fmt , ##args)
00106 #define xnarch_logwarn(fmt,args...) printk(KERN_WARNING XNARCH_PROMPT fmt , ##args)
00107 #define xnarch_logerr(fmt,args...) printk(KERN_ERR XNARCH_PROMPT fmt , ##args)
00108 #define xnarch_printf(fmt,args...) printk(KERN_INFO XNARCH_PROMPT fmt , ##args)
00109
00110 #define xnarch_ullmod(ull,uld,rem) ({ xnarch_ulldiv(ull,uld,rem); (*rem); })
00111 #define xnarch_uldiv(ull, d) rthal_uldivrem(ull, d, NULL)
00112 #define xnarch_ulmod(ull, d) ({ u_long _rem; \
00113 rthal_uldivrem(ull,d,&_rem); _rem; })
00114
00115 #define xnarch_ullmul rthal_ullmul
00116 #define xnarch_uldivrem rthal_uldivrem
00117 #define xnarch_ulldiv rthal_ulldiv
00118 #define xnarch_imuldiv rthal_imuldiv
00119 #define xnarch_llimd rthal_llimd
00120 #define xnarch_get_cpu_tsc rthal_rdtsc
00121
00122 typedef cpumask_t xnarch_cpumask_t;
00123
00124 #ifdef CONFIG_SMP
00125 #define xnarch_cpu_online_map cpu_online_map
00126 #else
00127 #define xnarch_cpu_online_map cpumask_of_cpu(0)
00128 #endif
00129 #define xnarch_num_online_cpus() num_online_cpus()
00130 #define xnarch_cpu_set(cpu, mask) cpu_set(cpu, mask)
00131 #define xnarch_cpu_clear(cpu, mask) cpu_clear(cpu, mask)
00132 #define xnarch_cpus_clear(mask) cpus_clear(mask)
00133 #define xnarch_cpu_isset(cpu, mask) cpu_isset(cpu, mask)
00134 #define xnarch_cpus_and(dst, src1, src2) cpus_and(dst, src1, src2)
00135 #define xnarch_cpus_equal(mask1, mask2) cpus_equal(mask1, mask2)
00136 #define xnarch_cpus_empty(mask) cpus_empty(mask)
00137 #define xnarch_cpumask_of_cpu(cpu) cpumask_of_cpu(cpu)
00138 #define xnarch_cpu_test_and_set(cpu,mask) cpu_test_and_set(cpu,mask)
00139
00140 #define xnarch_first_cpu(mask) first_cpu(mask)
00141 #define XNARCH_CPU_MASK_ALL CPU_MASK_ALL
00142
00143 typedef struct xnarch_heapcb {
00144
00145 atomic_t numaps;
00146
00147 int kmflags;
00148
00149 void *heapbase;
00150
00151 } xnarch_heapcb_t;
00152
00153 #ifdef __cplusplus
00154 extern "C" {
00155 #endif
00156
00157 static inline long long xnarch_tsc_to_ns (long long ts) {
00158 return xnarch_llimd(ts,1000000000,RTHAL_CPU_FREQ);
00159 }
00160
00161 static inline long long xnarch_ns_to_tsc (long long ns) {
00162 return xnarch_llimd(ns,RTHAL_CPU_FREQ,1000000000);
00163 }
00164
00165 static inline unsigned long long xnarch_get_cpu_time (void) {
00166 return xnarch_tsc_to_ns(xnarch_get_cpu_tsc());
00167 }
00168
00169 static inline unsigned long long xnarch_get_cpu_freq (void) {
00170 return RTHAL_CPU_FREQ;
00171 }
00172
00173 static inline unsigned xnarch_current_cpu (void) {
00174 return rthal_processor_id();
00175 }
00176
00177 #define xnarch_declare_cpuid rthal_declare_cpuid
00178 #define xnarch_get_cpu(flags) rthal_get_cpu(flags)
00179 #define xnarch_put_cpu(flags) rthal_put_cpu(flags)
00180
00181 #define xnarch_halt(emsg) \
00182 do { \
00183 rthal_emergency_console(); \
00184 xnarch_logerr("fatal: %s\n",emsg); \
00185 show_stack(NULL,NULL); \
00186 for (;;) cpu_relax(); \
00187 } while(0)
00188
00189 static inline int xnarch_setimask (int imask)
00190
00191 {
00192 spl_t s;
00193 splhigh(s);
00194 splexit(!!imask);
00195 return !!s;
00196 }
00197
00198 #ifdef CONFIG_SMP
00199
00200 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00201 #define xnlock_get_irqsave(lock,x) \
00202 ((x) = __xnlock_get_irqsave(lock, __FILE__, __LINE__,__FUNCTION__))
00203 #else
00204 #define xnlock_get_irqsave(lock,x) ((x) = __xnlock_get_irqsave(lock))
00205 #endif
00206 #define xnlock_clear_irqoff(lock) xnlock_put_irqrestore(lock,1)
00207 #define xnlock_clear_irqon(lock) xnlock_put_irqrestore(lock,0)
00208
00209 static inline void xnlock_init (xnlock_t *lock) {
00210
00211 *lock = XNARCH_LOCK_UNLOCKED;
00212 }
00213
00214 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00215
00216 #define XNARCH_DEBUG_SPIN_LIMIT 3000000
00217
00218 static inline spl_t __xnlock_get_irqsave (xnlock_t *lock,
00219 const char *file,
00220 unsigned line,
00221 const char *function)
00222 {
00223 unsigned spin_count = 0;
00224 #else
00225 static inline spl_t __xnlock_get_irqsave (xnlock_t *lock)
00226 {
00227 #endif
00228 rthal_declare_cpuid;
00229 unsigned long flags;
00230
00231 rthal_local_irq_save(flags);
00232
00233 rthal_load_cpuid();
00234
00235 if (!test_and_set_bit(cpuid,&lock->lock))
00236 {
00237 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00238 unsigned long long lock_date = rthal_rdtsc();
00239 #endif
00240 while (test_and_set_bit(BITS_PER_LONG - 1,&lock->lock))
00241
00242
00243 while (test_bit(BITS_PER_LONG - 1,&lock->lock))
00244 {
00245 cpu_relax();
00246
00247 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00248 if (++spin_count == XNARCH_DEBUG_SPIN_LIMIT)
00249 {
00250 rthal_emergency_console();
00251 printk(KERN_ERR
00252 "RTAI: stuck on nucleus lock %p\n"
00253 " waiter = %s:%u (%s(), CPU #%d)\n"
00254 " owner = %s:%u (%s(), CPU #%d)\n",
00255 lock,file,line,function,cpuid,
00256 lock->file,lock->line,lock->function,lock->cpu);
00257 show_stack(NULL,NULL);
00258 for (;;)
00259 cpu_relax();
00260 }
00261 #endif
00262 }
00263
00264 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00265 lock->spin_time = rthal_rdtsc() - lock_date;
00266 lock->lock_date = lock_date;
00267 lock->file = file;
00268 lock->function = function;
00269 lock->line = line;
00270 lock->cpu = cpuid;
00271 #endif
00272 }
00273 else
00274 flags |= 2;
00275
00276 return flags;
00277 }
00278
00279 static inline void xnlock_put_irqrestore (xnlock_t *lock, spl_t flags)
00280
00281 {
00282 if (!(flags & 2))
00283 {
00284 rthal_declare_cpuid;
00285
00286 rthal_local_irq_disable();
00287
00288 rthal_load_cpuid();
00289
00290 if (test_and_clear_bit(cpuid,&lock->lock))
00291 {
00292 #ifdef CONFIG_RTAI_OPT_STATS
00293 extern xnlockinfo_t xnlock_stats[];
00294
00295 unsigned long long lock_time = rthal_rdtsc() - lock->lock_date;
00296
00297 if (lock_time > xnlock_stats[cpuid].lock_time)
00298 {
00299 xnlock_stats[cpuid].lock_time = lock_time;
00300 xnlock_stats[cpuid].spin_time = lock->spin_time;
00301 xnlock_stats[cpuid].file = lock->file;
00302 xnlock_stats[cpuid].function = lock->function;
00303 xnlock_stats[cpuid].line = lock->line;
00304 }
00305 #endif
00306
00307 clear_bit(BITS_PER_LONG - 1,&lock->lock);
00308 }
00309 }
00310
00311 rthal_local_irq_restore(flags & 1);
00312 }
00313
00314 #else
00315
00316 #define xnlock_init(lock) do { } while(0)
00317 #define xnlock_get_irqsave(lock,x) rthal_local_irq_save(x)
00318 #define xnlock_put_irqrestore(lock,x) rthal_local_irq_restore(x)
00319 #define xnlock_clear_irqoff(lock) rthal_local_irq_disable()
00320 #define xnlock_clear_irqon(lock) rthal_local_irq_enable()
00321
00322 #endif
00323
00324 #ifdef XENO_POD_MODULE
00325
00326 #ifdef CONFIG_SMP
00327
00328 static inline int xnarch_send_ipi (xnarch_cpumask_t cpumask) {
00329
00330 return rthal_send_ipi(RTHAL_SERVICE_IPI0, cpumask);
00331 }
00332
00333 static inline int xnarch_hook_ipi (void (*handler)(void))
00334
00335 {
00336 return rthal_virtualize_irq(&rthal_domain,
00337 RTHAL_SERVICE_IPI0,
00338 (void (*)(unsigned)) handler,
00339 NULL,
00340 IPIPE_HANDLE_MASK);
00341 }
00342
00343 static inline int xnarch_release_ipi (void)
00344
00345 {
00346 return rthal_virtualize_irq(&rthal_domain,
00347 RTHAL_SERVICE_IPI0,
00348 NULL,
00349 NULL,
00350 IPIPE_PASS_MASK);
00351 }
00352
00353 static struct linux_semaphore xnarch_finalize_sync;
00354
00355 static void xnarch_finalize_cpu(unsigned irq)
00356 {
00357 up(&xnarch_finalize_sync);
00358 }
00359
00360 static inline void xnarch_notify_halt(void)
00361
00362 {
00363 xnarch_cpumask_t other_cpus = cpu_online_map;
00364 unsigned cpu, nr_cpus = num_online_cpus();
00365 unsigned long flags;
00366 rthal_declare_cpuid;
00367
00368 sema_init(&xnarch_finalize_sync,0);
00369
00370
00371
00372
00373
00374 rthal_virtualize_irq(rthal_current_domain,
00375 RTHAL_SERVICE_IPI2,
00376 xnarch_finalize_cpu,
00377 NULL,
00378 IPIPE_HANDLE_MASK);
00379
00380 rthal_lock_cpu(flags);
00381 cpu_clear(cpuid, other_cpus);
00382 rthal_send_ipi(RTHAL_SERVICE_IPI2, other_cpus);
00383 rthal_unlock_cpu(flags);
00384
00385 for(cpu=0; cpu < nr_cpus-1; ++cpu)
00386 down(&xnarch_finalize_sync);
00387
00388 rthal_virtualize_irq(rthal_current_domain,
00389 RTHAL_SERVICE_IPI2,
00390 NULL,
00391 NULL,
00392 IPIPE_PASS_MASK);
00393 }
00394
00395 #else
00396
00397 static inline int xnarch_send_ipi (xnarch_cpumask_t cpumask) {
00398
00399 return 0;
00400 }
00401
00402 static inline int xnarch_hook_ipi (void (*handler)(void)) {
00403
00404 return 0;
00405 }
00406
00407 static inline int xnarch_release_ipi (void) {
00408
00409 return 0;
00410 }
00411
00412 #define xnarch_notify_halt()
00413
00414 #endif
00415
00416 static inline void xnarch_notify_shutdown(void)
00417
00418 {
00419 #ifdef CONFIG_SMP
00420
00421
00422 set_cpus_allowed(current,cpumask_of_cpu(0));
00423 #endif
00424 #ifdef CONFIG_RTAI_OPT_FUSION
00425 xnshadow_release_events();
00426 #endif
00427
00428 set_current_state(TASK_UNINTERRUPTIBLE);
00429 schedule_timeout(50);
00430 xnarch_release_ipi();
00431 }
00432
00433 static inline int xnarch_escalate (void)
00434
00435 {
00436 extern int xnarch_escalation_virq;
00437
00438 if (rthal_current_domain == rthal_root_domain)
00439 {
00440 spl_t s;
00441 splsync(s);
00442 rthal_trigger_irq(xnarch_escalation_virq);
00443 splexit(s);
00444 return 1;
00445 }
00446
00447 return 0;
00448 }
00449
00450 static void xnarch_notify_ready (void)
00451
00452 {
00453 #ifdef CONFIG_RTAI_OPT_FUSION
00454 xnshadow_grab_events();
00455 #endif
00456 }
00457
00458 static inline unsigned long long xnarch_get_sys_time(void)
00459 {
00460 struct timeval tv;
00461 do_gettimeofday(&tv);
00462 return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
00463 }
00464
00465 #endif
00466
00467 #ifdef XENO_INTR_MODULE
00468
00469 static inline int xnarch_hook_irq (unsigned irq,
00470 void (*handler)(unsigned irq,
00471 void *cookie),
00472 int (*ackfn)(unsigned irq),
00473 void *cookie)
00474 {
00475 return rthal_irq_request(irq,handler,ackfn,cookie);
00476 }
00477
00478 static inline int xnarch_release_irq (unsigned irq)
00479
00480 {
00481 return rthal_irq_release(irq);
00482 }
00483
00484 static inline int xnarch_enable_irq (unsigned irq)
00485
00486 {
00487 return rthal_irq_enable(irq);
00488 }
00489
00490 static inline int xnarch_disable_irq (unsigned irq)
00491
00492 {
00493 return rthal_irq_disable(irq);
00494 }
00495
00496 static inline void xnarch_chain_irq (unsigned irq)
00497
00498 {
00499 rthal_irq_host_pend(irq);
00500 }
00501
00502 static inline cpumask_t xnarch_set_irq_affinity (unsigned irq,
00503 xnarch_cpumask_t affinity)
00504 {
00505 return rthal_set_irq_affinity(irq,affinity);
00506 }
00507
00508 #endif
00509
00510 #ifdef XENO_HEAP_MODULE
00511
00512 #include <linux/mm.h>
00513
00514 static inline void xnarch_init_heapcb (xnarch_heapcb_t *hcb)
00515
00516 {
00517 atomic_set(&hcb->numaps,0);
00518 hcb->kmflags = 0;
00519 hcb->heapbase = NULL;
00520 }
00521
00522 static inline int xnarch_remap_page_range(struct vm_area_struct *vma,
00523 unsigned long uvaddr,
00524 unsigned long paddr,
00525 unsigned long size,
00526 pgprot_t prot)
00527 {
00528 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
00529 return remap_pfn_range(vma,uvaddr,paddr >> PAGE_SHIFT,size,prot);
00530 #else
00531 return remap_page_range(vma,uvaddr,paddr,size,prot);
00532 #endif
00533 }
00534
00535 #endif
00536
00537 #ifdef __cplusplus
00538 }
00539 #endif
00540
00541
00542 #define XNARCH_DECL_DISPLAY_CONTEXT();
00543 #define xnarch_init_display_context(obj)
00544 #define xnarch_create_display(obj,name,tag)
00545 #define xnarch_delete_display(obj)
00546 #define xnarch_post_graph(obj,state)
00547 #define xnarch_post_graph_if(obj,state,cond)
00548
00549 #else
00550
00551 #include <nucleus/system.h>
00552
00553 #endif
00554
00555 #endif