00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _RTAI_ASM_UVM_SYSTEM_H
00021 #define _RTAI_ASM_UVM_SYSTEM_H
00022
00023 #include <sys/time.h>
00024 #include <sys/mman.h>
00025 #include <errno.h>
00026 #include <malloc.h>
00027 #include <stdlib.h>
00028 #include <unistd.h>
00029 #include <string.h>
00030 #include <signal.h>
00031 #include <stdio.h>
00032 #include <limits.h>
00033 #include <setjmp.h>
00034 #include <pthread.h>
00035 #include <rtai_config.h>
00036 #include <nucleus/asm/atomic.h>
00037 #include <nucleus/asm/syscall.h>
00038 #include <uvm/uvm.h>
00039
00040
00041 #define vartype(var) var ## _ ## tYpE
00042 #define MODULE_DESCRIPTION(s);
00043 #define MODULE_LICENSE(s);
00044 #define MODULE_AUTHOR(s);
00045 #define MODULE_PARM_DESC(name,desc);
00046 #define module_param_named(name,var,type,perm) static const char *vartype(var) = #type
00047 #define module_param_value(var) ({ xnarch_read_environ(#var,&vartype(var),&var); var; })
00048
00049
00050 #define EXPORT_SYMBOL(sym);
00051 #define module_init(sym);
00052 #define module_exit(sym);
00053 #define __init
00054 #define __exit
00055
00056 typedef int spl_t;
00057
00058 typedef unsigned long cpumask_t;
00059
00060 #ifdef CONFIG_SMP
00061 #error "UVM over SMP not supported yet -- CONFIG_RTAI_OPT_UVM needs to be switched off"
00062 #endif
00063
00064 extern int uvm_irqlock;
00065
00066 #define splhigh(x) ((x) = xnarch_lock_irq())
00067 #define splexit(x) xnarch_unlock_irq(x)
00068 #define splnone() xnarch_unlock_irq(0)
00069
00070 typedef unsigned long xnlock_t;
00071
00072 #define XNARCH_LOCK_UNLOCKED 0
00073
00074 #define xnlock_init(lock) do { } while(0)
00075 #define xnlock_get_irqsave(lock,x) ((x) = xnarch_lock_irq())
00076 #define xnlock_put_irqrestore(lock,x) xnarch_unlock_irq(x)
00077 #define xnlock_clear_irqoff(lock) xnarch_lock_irq()
00078 #define xnlock_clear_irqon(lock) xnarch_unlock_irq(0)
00079
00080 #define XNARCH_NR_CPUS 1
00081
00082 #define XNARCH_DEFAULT_TICK 1000000
00083 #define XNARCH_SIG_RESTART SIGUSR1
00084 #define XNARCH_HOST_TICK 0
00085
00086 #define XNARCH_THREAD_STACKSZ 0
00087 #define XNARCH_ROOT_STACKSZ 0
00088
00089 #define xnarch_alloc_stack xnmalloc
00090 #define xnarch_free_stack xnfree
00091
00092 #define XNARCH_PROMPT "RTAI/uvm: "
00093 #define xnarch_loginfo(fmt,args...) fprintf(stdout, XNARCH_PROMPT fmt , ##args)
00094 #define xnarch_logwarn(fmt,args...) fprintf(stderr, XNARCH_PROMPT fmt , ##args)
00095 #define xnarch_logerr(fmt,args...) fprintf(stderr, XNARCH_PROMPT fmt , ##args)
00096 #define xnarch_printf(fmt,args...) fprintf(stdout, fmt, ##args)
00097 #define printk(fmt,args...) xnarch_loginfo(fmt, ##args)
00098
00099 typedef unsigned long xnarch_cpumask_t;
00100 #define xnarch_num_online_cpus() XNARCH_NR_CPUS
00101 #define xnarch_cpu_online_map ((1<<xnarch_num_online_cpus()) - 1)
00102 #define xnarch_cpu_set(cpu, mask) ((mask) |= 1 << (cpu))
00103 #define xnarch_cpu_clear(cpu, mask) ((mask) &= 1 << (cpu))
00104 #define xnarch_cpus_clear(mask) ((mask) = 0UL)
00105 #define xnarch_cpu_isset(cpu, mask) (!!((mask) & (1 << (cpu))))
00106 #define xnarch_cpus_and(dst, src1, src2) ((dst) = (src1) & (src2))
00107 #define xnarch_cpus_equal(mask1, mask2) ((mask1) == (mask2))
00108 #define xnarch_cpus_empty(mask) ((mask) == 0UL)
00109 #define xnarch_cpumask_of_cpu(cpu) (1 << (cpu))
00110 #define xnarch_first_cpu(mask) (ffnz(mask))
00111 #define XNARCH_CPU_MASK_ALL (~0UL)
00112
00113 #define xnarch_ullmod(ull,uld,rem) ((*rem) = ((ull) % (uld)))
00114 #define xnarch_uldivrem(ull,uld,rem) ((u_long)xnarch_ulldiv((ull),(uld),(rem)))
00115 #define xnarch_uldiv(ull, d) xnarch_uldivrem(ull, d, NULL)
00116 #define xnarch_ulmod(ull, d) ({ u_long _rem; \
00117 xnarch_uldivrem(ull,d,&_rem); _rem; })
00118
00119 static inline int xnarch_imuldiv(int i, int mult, int div)
00120 {
00121 unsigned long long ull = (unsigned long long) (unsigned) i * (unsigned) mult;
00122 return ull / (unsigned) div;
00123 }
00124
00125 static inline unsigned long long __xnarch_ullimd(unsigned long long ull,
00126 u_long m,
00127 u_long d) {
00128
00129 unsigned long long mh, ml;
00130 u_long h, l, mlh, mll, qh, r, ql;
00131
00132 h = ull >> 32; l = ull & 0xffffffff;
00133 mh = (unsigned long long) h * m;
00134 ml = (unsigned long long) l * m;
00135 mlh = ml >> 32; mll = ml & 0xffffffff;
00136 mh += mlh;
00137 qh = mh / d;
00138 r = mh % d;
00139 ml = (((unsigned long long) r) << 32) + mll;
00140 ql = ml / d;
00141
00142 return (((unsigned long long) qh) << 32) + ql;
00143 }
00144
00145 static inline long long xnarch_llimd(long long ll, u_long m, u_long d) {
00146 if(ll < 0)
00147 return -__xnarch_ullimd(-ll, m, d);
00148 return __xnarch_ullimd(ll, m, d);
00149 }
00150
00151 static inline unsigned long long xnarch_ullmul(unsigned long m1,
00152 unsigned long m2) {
00153 return (unsigned long long) m1 * m2;
00154 }
00155
00156 static inline unsigned long long xnarch_ulldiv (unsigned long long ull,
00157 unsigned long uld,
00158 unsigned long *rem)
00159 {
00160 if (rem)
00161 *rem = ull % uld;
00162
00163 return ull / uld;
00164 }
00165
00166 #define xnarch_stack_size(tcb) ((tcb)->stacksize)
00167 #define xnarch_fpu_ptr(tcb) (NULL)
00168
00169 struct xnthread;
00170
00171 typedef struct xnarchtcb {
00172
00173 const char *name;
00174 struct xnthread *thread;
00175 void *khandle;
00176 void (*entry)(void *);
00177 void *cookie;
00178 int imask;
00179 jmp_buf rstenv;
00180 pthread_t thid;
00181 xncompletion_t completion;
00182
00183
00184
00185 unsigned stacksize;
00186 unsigned long *stackbase;
00187
00188 } xnarchtcb_t;
00189
00190 extern xnarchtcb_t *uvm_root;
00191
00192 extern xnarchtcb_t *uvm_current;
00193
00194 typedef void *xnarch_fltinfo_t;
00195
00196 #define xnarch_fault_trap(fi) 0
00197 #define xnarch_fault_code(fi) 0
00198 #define xnarch_fault_pc(fi) 0L
00199 #define xnarch_fault_notify(fi) 1
00200
00201 typedef struct xnarch_heapcb {
00202
00203 #if (__GNUC__ <= 2)
00204 int old_gcc_dislikes_emptiness;
00205 #endif
00206
00207 } xnarch_heapcb_t;
00208
00209 static inline void xnarch_init_heapcb (xnarch_heapcb_t *cb) {
00210 }
00211
00212 static inline int __attribute__ ((unused))
00213 xnarch_read_environ (const char *name, const char **ptype, void *pvar)
00214
00215 {
00216 char *value;
00217
00218 if (*ptype == NULL)
00219 return 0;
00220
00221 value = getenv(name);
00222
00223 if (!value)
00224 return -1;
00225
00226 if (**ptype == 's')
00227 *((char **)pvar) = value;
00228 else if (strstr(*ptype,"int"))
00229 *((int *)pvar) = atoi(value);
00230 else if (strstr(*ptype,"long"))
00231 *((u_long *)pvar) = (u_long)atol(value);
00232
00233 *ptype = NULL;
00234
00235 return 1;
00236 }
00237
00238 static int inline xnarch_lock_irq (void)
00239 {
00240 return xnarch_atomic_xchg(&uvm_irqlock,1);
00241 }
00242
00243 static inline void xnarch_unlock_irq (int x)
00244 {
00245 extern int uvm_irqpend;
00246
00247 if (!x && uvm_irqlock)
00248 {
00249 if (xnarch_atomic_xchg(&uvm_irqpend,0))
00250 uvm_thread_release(&uvm_irqlock);
00251 else
00252 uvm_irqlock = 0;
00253 }
00254 }
00255
00256 void xnarch_sync_irq(void);
00257
00258 int xnarch_setimask(int imask);
00259
00260 #ifdef __cplusplus
00261 extern "C" {
00262 #endif
00263
00264 void xnpod_welcome_thread(struct xnthread *);
00265
00266 #ifdef XENO_INTR_MODULE
00267
00268 int uvm_irqlock = 0;
00269
00270 int uvm_irqpend = 0;
00271
00272 void xnarch_sync_irq (void)
00273
00274 {
00275 if (uvm_irqlock)
00276
00277
00278 uvm_thread_hold(&uvm_irqpend);
00279 }
00280
00281 static inline int xnarch_hook_irq (unsigned irq,
00282 void (*handler)(unsigned irq,
00283 void *cookie),
00284 void *cookie)
00285 {
00286 return -ENOSYS;
00287 }
00288
00289 static inline int xnarch_release_irq (unsigned irq)
00290
00291 {
00292 return -ENOSYS;
00293 }
00294
00295 static inline int xnarch_enable_irq (unsigned irq)
00296
00297 {
00298 return -ENOSYS;
00299 }
00300
00301 static inline int xnarch_disable_irq (unsigned irq)
00302
00303 {
00304 return -ENOSYS;
00305 }
00306
00307 static inline void xnarch_chain_irq (unsigned irq)
00308
00309 { }
00310
00311 static inline unsigned long xnarch_set_irq_affinity (unsigned irq,
00312 unsigned long affinity)
00313 {
00314 return 0;
00315 }
00316
00317 #define xnarch_relay_tick()
00318
00319 #endif
00320
00321 #ifdef XENO_MAIN_MODULE
00322
00323 int __fusion_sys_init(void);
00324
00325 void __fusion_sys_exit(void);
00326
00327 int __fusion_skin_init(void);
00328
00329 void __fusion_skin_exit(void);
00330
00331 int __fusion_user_init(void);
00332
00333 void __fusion_user_exit(void);
00334
00335 static inline int xnarch_init (void) {
00336 return 0;
00337 }
00338
00339 static inline void xnarch_exit (void) {
00340 }
00341
00342 static void xnarch_restart_handler (int sig) {
00343
00344 longjmp(uvm_current->rstenv,1);
00345 }
00346
00347 int main (int argc, char *argv[])
00348
00349 {
00350 struct sigaction sa;
00351 int err;
00352
00353 if (geteuid() !=0)
00354 {
00355 fprintf(stderr,"This program must be run with root privileges.\n");
00356 exit(1);
00357 }
00358
00359 err = __fusion_sys_init();
00360
00361 if (err)
00362 {
00363 fprintf(stderr,"sys_init() failed: %s\n",strerror(-err));
00364 exit(2);
00365 }
00366
00367 err = __fusion_skin_init();
00368
00369 if (err)
00370 {
00371 fprintf(stderr,"skin_init() failed: %s\n",strerror(-err));
00372 exit(3);
00373 }
00374
00375 err = __fusion_user_init();
00376
00377 if (err)
00378 {
00379 fprintf(stderr,"user_init() failed: %s\n",strerror(-err));
00380 exit(4);
00381 }
00382
00383
00384
00385
00386
00387
00388 mlockall(MCL_CURRENT);
00389
00390 sa.sa_handler = &xnarch_restart_handler;
00391 sigemptyset(&sa.sa_mask);
00392 sa.sa_flags = SA_RESTART;
00393 sigaction(XNARCH_SIG_RESTART,&sa,NULL);
00394
00395 for (;;)
00396 uvm_thread_idle(&uvm_irqlock);
00397
00398 __fusion_user_exit();
00399 __fusion_skin_exit();
00400 __fusion_sys_exit();
00401
00402 exit(0);
00403 }
00404
00405 #endif
00406
00407 #ifdef XENO_TIMER_MODULE
00408
00409 void *uvm_timer_handle;
00410
00411 static inline void xnarch_program_timer_shot (unsigned long delay) {
00412
00413 }
00414
00415 static inline void xnarch_stop_timer (void) {
00416 uvm_thread_cancel(uvm_timer_handle,NULL);
00417 }
00418
00419 static inline int xnarch_send_timer_ipi (xnarch_cpumask_t mask) {
00420
00421 return 0;
00422 }
00423
00424 static inline void xnarch_read_timings (unsigned long long *shot,
00425 unsigned long long *delivery,
00426 unsigned long long defval)
00427 {
00428 *shot = defval;
00429 *delivery = defval;
00430 }
00431
00432 #endif
00433
00434 #ifdef XENO_POD_MODULE
00435
00436 extern void *uvm_timer_handle;
00437
00438 xnsysinfo_t uvm_info;
00439
00440 xnarchtcb_t *uvm_root;
00441
00442 xnarchtcb_t *uvm_current;
00443
00444 struct xnarch_tick_parms {
00445 unsigned long nstick;
00446 void (*tickhandler)(void);
00447 xncompletion_t completion;
00448 };
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 static void *xnarch_timer_thread (void *cookie)
00460
00461 {
00462 struct xnarch_tick_parms *p = (struct xnarch_tick_parms *)cookie;
00463 void (*tickhandler)(void);
00464 struct sched_param param;
00465 unsigned long nstick;
00466 long err;
00467
00468 param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 2;
00469 sched_setscheduler(0,SCHED_FIFO,¶m);
00470
00471
00472
00473 tickhandler = p->tickhandler;
00474 nstick = p->nstick;
00475
00476 uvm_thread_create("uvm-timer",NULL,&p->completion,&uvm_timer_handle);
00477
00478 err = uvm_thread_barrier();
00479
00480 if (!err)
00481 err = uvm_thread_set_periodic(0,nstick);
00482
00483 if (err)
00484 pthread_exit((void *)err);
00485
00486 for (;;)
00487 {
00488 if (uvm_thread_wait_period() == -EWOULDBLOCK)
00489 break;
00490
00491 xnarch_sync_irq();
00492 tickhandler();
00493 }
00494
00495 pthread_exit(NULL);
00496 }
00497
00498 static inline int xnarch_start_timer (unsigned long nstick,
00499 void (*tickhandler)(void))
00500 {
00501 struct xnarch_tick_parms parms;
00502 pthread_attr_t thattr;
00503 pthread_t thid;
00504 int err;
00505
00506 if (nstick == 0)
00507 return -ENODEV;
00508
00509
00510
00511
00512
00513
00514
00515 #ifdef CONFIG_RTAI_HW_APERIODIC_TIMER
00516 err = uvm_timer_start(0);
00517 #else
00518 err = uvm_timer_start(nstick);
00519 #endif
00520
00521 if (err)
00522 return err;
00523
00524 parms.nstick = nstick;
00525 parms.tickhandler = tickhandler;
00526 parms.completion.syncflag = 0;
00527 parms.completion.pid = -1;
00528
00529 pthread_attr_init(&thattr);
00530 pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED);
00531 pthread_create(&thid,&thattr,&xnarch_timer_thread,&parms);
00532
00533 err = uvm_thread_sync(&parms.completion);
00534
00535 if (err == 0)
00536 uvm_thread_start(uvm_timer_handle);
00537
00538 return err;
00539 }
00540
00541 static inline void xnarch_leave_root(xnarchtcb_t *rootcb) {
00542 }
00543
00544 static inline void xnarch_enter_root(xnarchtcb_t *rootcb) {
00545 }
00546
00547 static inline void xnarch_switch_to (xnarchtcb_t *out_tcb,
00548 xnarchtcb_t *in_tcb)
00549 {
00550 uvm_current = in_tcb;
00551 uvm_thread_activate(in_tcb->khandle,out_tcb->khandle);
00552 }
00553
00554 static inline void xnarch_finalize_and_switch (xnarchtcb_t *dead_tcb,
00555 xnarchtcb_t *next_tcb)
00556 {
00557 uvm_current = next_tcb;
00558 uvm_thread_cancel(dead_tcb->khandle,next_tcb->khandle);
00559 }
00560
00561 static inline void xnarch_finalize_no_switch (xnarchtcb_t *dead_tcb)
00562
00563 {
00564 uvm_thread_cancel(dead_tcb->khandle,NULL);
00565 }
00566
00567 static inline void xnarch_init_root_tcb (xnarchtcb_t *tcb,
00568 struct xnthread *thread,
00569 const char *name)
00570 {
00571 struct sched_param param;
00572 int err;
00573
00574 param.sched_priority = sched_get_priority_min(SCHED_FIFO);
00575 sched_setscheduler(0,SCHED_FIFO,¶m);
00576 err = uvm_system_info(&uvm_info);
00577
00578 if (err)
00579 {
00580 fprintf(stderr,"UVM init failed: %s\n",strerror(-err));
00581 exit(1);
00582 }
00583
00584 uvm_thread_shadow("uvm-root",tcb,&tcb->khandle);
00585 tcb->name = name;
00586 uvm_root = uvm_current = tcb;
00587 }
00588
00589 static void *xnarch_thread_trampoline (void *cookie)
00590
00591 {
00592 xnarchtcb_t *tcb = (xnarchtcb_t *)cookie;
00593 struct sched_param param;
00594 long err;
00595
00596 if (!setjmp(tcb->rstenv))
00597 {
00598 param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
00599 sched_setscheduler(0,SCHED_FIFO,¶m);
00600 uvm_thread_create(tcb->name,tcb,&tcb->completion,&tcb->khandle);
00601 err = uvm_thread_barrier();
00602 if (err)
00603 pthread_exit((void *)err);
00604 }
00605
00606 xnarch_setimask(tcb->imask);
00607
00608 xnpod_welcome_thread(tcb->thread);
00609
00610 tcb->entry(tcb->cookie);
00611
00612 pthread_exit(NULL);
00613 }
00614
00615 static inline void xnarch_init_thread (xnarchtcb_t *tcb,
00616 void (*entry)(void *),
00617 void *cookie,
00618 int imask,
00619 struct xnthread *thread,
00620 char *name)
00621 {
00622 pthread_attr_t thattr;
00623
00624 if (tcb->khandle)
00625 {
00626 pthread_kill(tcb->thid,XNARCH_SIG_RESTART);
00627 return;
00628 }
00629
00630 tcb->imask = imask;
00631 tcb->entry = entry;
00632 tcb->cookie = cookie;
00633 tcb->thread = thread;
00634 tcb->name = name;
00635 tcb->completion.syncflag = 0;
00636 tcb->completion.pid = -1;
00637
00638 pthread_attr_init(&thattr);
00639 pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED);
00640 pthread_create(&tcb->thid,&thattr,&xnarch_thread_trampoline,tcb);
00641 uvm_thread_sync(&tcb->completion);
00642 }
00643
00644 static inline void xnarch_enable_fpu(xnarchtcb_t *current_tcb) {
00645
00646 }
00647
00648 static inline void xnarch_init_fpu(xnarchtcb_t *tcb) {
00649
00650 }
00651
00652 static inline void xnarch_save_fpu(xnarchtcb_t *tcb) {
00653
00654 }
00655
00656 static inline void xnarch_restore_fpu(xnarchtcb_t *tcb) {
00657
00658 }
00659
00660 int xnarch_setimask (int imask)
00661
00662 {
00663 spl_t s;
00664 splhigh(s);
00665 splexit(!!imask);
00666 return !!s;
00667 }
00668
00669 static inline int xnarch_send_ipi (cpumask_t cpumask) {
00670
00671 return 0;
00672 }
00673
00674 static inline int xnarch_hook_ipi (void (*handler)(void)) {
00675
00676 return 0;
00677 }
00678
00679 static inline int xnarch_release_ipi (void) {
00680
00681 return 0;
00682 }
00683
00684 #define xnarch_notify_ready()
00685 #define xnarch_notify_shutdown()
00686 #define xnarch_notify_halt()
00687
00688 #endif
00689
00690 #ifdef XENO_THREAD_MODULE
00691
00692 static inline void xnarch_init_tcb (xnarchtcb_t *tcb) {
00693
00694 tcb->khandle = NULL;
00695 }
00696
00697 #endif
00698
00699 extern xnsysinfo_t uvm_info;
00700
00701 static inline unsigned long long xnarch_tsc_to_ns (unsigned long long tsc) {
00702
00703 nanostime_t ns;
00704 return uvm_timer_tsc2ns(tsc,&ns) ? 0 : ns;
00705 }
00706
00707 static inline unsigned long long xnarch_ns_to_tsc (unsigned long long ns) {
00708
00709 nanostime_t tsc;
00710 return uvm_timer_ns2tsc(ns,&tsc) ? 0 : tsc;
00711 }
00712
00713 static inline unsigned long long xnarch_get_cpu_time (void)
00714
00715 {
00716 nanotime_t t;
00717 uvm_timer_read(&t);
00718 return t;
00719 }
00720
00721 static inline unsigned long long xnarch_get_cpu_tsc (void)
00722
00723 {
00724 nanotime_t t;
00725 uvm_timer_tsc(&t);
00726 return t;
00727 }
00728
00729 static inline unsigned long long xnarch_get_cpu_freq (void) {
00730 return uvm_info.cpufreq;
00731 }
00732
00733 static inline void xnarch_halt (const char *emsg) {
00734 fprintf(stderr,"UVM fatal: %s\n",emsg);
00735 fflush(stderr);
00736 exit(99);
00737 }
00738
00739 static inline void *xnarch_sysalloc (u_long bytes) {
00740 return malloc(bytes);
00741 }
00742
00743 static inline void xnarch_sysfree (void *chunk, u_long bytes) {
00744 free(chunk);
00745 }
00746
00747 #define xnarch_current_cpu() 0
00748 #define xnarch_declare_cpuid const int cpuid = 0
00749 #define xnarch_get_cpu(x) do { (x) = (x); } while(0)
00750 #define xnarch_put_cpu(x) do { } while(0)
00751
00752 #define xnarch_alloc_stack xnmalloc
00753 #define xnarch_free_stack xnfree
00754
00755 #ifdef __cplusplus
00756 }
00757 #endif
00758
00759
00760 #define XNARCH_DECL_DISPLAY_CONTEXT();
00761 #define xnarch_init_display_context(obj)
00762 #define xnarch_create_display(obj,name,tag)
00763 #define xnarch_delete_display(obj)
00764 #define xnarch_post_graph(obj,state)
00765 #define xnarch_post_graph_if(obj,state,cond)
00766
00767 #endif