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 unsigned long 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 #define xnarch_user_task(tcb) (NULL)
00169 #define xnarch_user_pid(tcb) 0
00170
00171 struct xnthread;
00172
00173 typedef struct xnarchtcb {
00174
00175 const char *name;
00176 struct xnthread *thread;
00177 void *khandle;
00178 void (*entry)(void *);
00179 void *cookie;
00180 int imask;
00181 jmp_buf rstenv;
00182 pthread_t thid;
00183 xncompletion_t completion;
00184
00185
00186
00187 unsigned stacksize;
00188 unsigned long *stackbase;
00189
00190 } xnarchtcb_t;
00191
00192 extern xnarchtcb_t *uvm_root;
00193
00194 extern xnarchtcb_t *uvm_current;
00195
00196 typedef void *xnarch_fltinfo_t;
00197
00198 #define xnarch_fault_trap(fi) 0
00199 #define xnarch_fault_code(fi) 0
00200 #define xnarch_fault_pc(fi) 0L
00201 #define xnarch_fault_notify(fi) 1
00202
00203 typedef struct xnarch_heapcb {
00204
00205 #if (__GNUC__ <= 2)
00206 int old_gcc_dislikes_emptiness;
00207 #endif
00208
00209 } xnarch_heapcb_t;
00210
00211 static inline void xnarch_init_heapcb (xnarch_heapcb_t *cb) {
00212 }
00213
00214 static inline int __attribute__ ((unused))
00215 xnarch_read_environ (const char *name, const char **ptype, void *pvar)
00216
00217 {
00218 char *value;
00219
00220 if (*ptype == NULL)
00221 return 0;
00222
00223 value = getenv(name);
00224
00225 if (!value)
00226 return -1;
00227
00228 if (**ptype == 's')
00229 *((char **)pvar) = value;
00230 else if (strstr(*ptype,"int"))
00231 *((int *)pvar) = atoi(value);
00232 else if (strstr(*ptype,"long"))
00233 *((u_long *)pvar) = (u_long)atol(value);
00234
00235 *ptype = NULL;
00236
00237 return 1;
00238 }
00239
00240 static int inline xnarch_lock_irq (void)
00241 {
00242 return xnarch_atomic_xchg(&uvm_irqlock,1);
00243 }
00244
00245 static inline void xnarch_unlock_irq (int x)
00246 {
00247 extern unsigned long uvm_irqpend;
00248
00249 if (!x && uvm_irqlock)
00250 {
00251 if (xnarch_atomic_xchg(&uvm_irqpend,0))
00252 uvm_thread_release(&uvm_irqlock);
00253 else
00254 uvm_irqlock = 0;
00255 }
00256 }
00257
00258 void xnarch_sync_irq(void);
00259
00260 int xnarch_setimask(int imask);
00261
00262 #ifdef __cplusplus
00263 extern "C" {
00264 #endif
00265
00266 void xnpod_welcome_thread(struct xnthread *);
00267
00268 #ifdef XENO_INTR_MODULE
00269
00270 unsigned long uvm_irqlock = 0;
00271
00272 unsigned long uvm_irqpend = 0;
00273
00274 void xnarch_sync_irq (void)
00275
00276 {
00277 if (uvm_irqlock)
00278
00279
00280 uvm_thread_hold(&uvm_irqpend);
00281 }
00282
00283 static inline int xnarch_hook_irq (unsigned irq,
00284 void (*handler)(unsigned irq,
00285 void *cookie),
00286 int (*ackfn)(unsigned irq),
00287 void *cookie)
00288 {
00289 return -ENOSYS;
00290 }
00291
00292 static inline int xnarch_release_irq (unsigned irq)
00293
00294 {
00295 return -ENOSYS;
00296 }
00297
00298 static inline int xnarch_enable_irq (unsigned irq)
00299
00300 {
00301 return -ENOSYS;
00302 }
00303
00304 static inline int xnarch_disable_irq (unsigned irq)
00305
00306 {
00307 return -ENOSYS;
00308 }
00309
00310 static inline void xnarch_chain_irq (unsigned irq)
00311
00312 { }
00313
00314 static inline unsigned long xnarch_set_irq_affinity (unsigned irq,
00315 unsigned long affinity)
00316 {
00317 return 0;
00318 }
00319
00320 #define xnarch_relay_tick()
00321
00322 #endif
00323
00324 #ifdef XENO_MAIN_MODULE
00325
00326 int __fusion_sys_init(void);
00327
00328 void __fusion_sys_exit(void);
00329
00330 int __fusion_skin_init(void);
00331
00332 void __fusion_skin_exit(void);
00333
00334 int __fusion_user_init(void);
00335
00336 void __fusion_user_exit(void);
00337
00338 static inline int xnarch_init (void) {
00339 return 0;
00340 }
00341
00342 static inline void xnarch_exit (void) {
00343 }
00344
00345 static void xnarch_restart_handler (int sig) {
00346
00347 longjmp(uvm_current->rstenv,1);
00348 }
00349
00350 int main (int argc, char *argv[])
00351
00352 {
00353 struct sigaction sa;
00354 int err;
00355
00356 if (geteuid() != 0)
00357 {
00358 fprintf(stderr,"This program must be run with root privileges.\n");
00359 exit(1);
00360 }
00361
00362 err = __fusion_sys_init();
00363
00364 if (err)
00365 {
00366 fprintf(stderr,"sys_init() failed: %s\n",strerror(-err));
00367 exit(2);
00368 }
00369
00370 err = __fusion_skin_init();
00371
00372 if (err)
00373 {
00374 fprintf(stderr,"skin_init() failed: %s\n",strerror(-err));
00375 exit(3);
00376 }
00377
00378 err = __fusion_user_init();
00379
00380 if (err)
00381 {
00382 fprintf(stderr,"user_init() failed: %s\n",strerror(-err));
00383 exit(4);
00384 }
00385
00386 mlockall(MCL_CURRENT|MCL_FUTURE);
00387
00388 sa.sa_handler = &xnarch_restart_handler;
00389 sigemptyset(&sa.sa_mask);
00390 sa.sa_flags = SA_RESTART;
00391 sigaction(XNARCH_SIG_RESTART,&sa,NULL);
00392
00393 for (;;)
00394 uvm_thread_idle(&uvm_irqlock);
00395
00396 __fusion_user_exit();
00397 __fusion_skin_exit();
00398 __fusion_sys_exit();
00399
00400 exit(0);
00401 }
00402
00403 #endif
00404
00405 #ifdef XENO_TIMER_MODULE
00406
00407 void *uvm_timer_handle;
00408
00409 static inline void xnarch_program_timer_shot (unsigned long delay) {
00410
00411 }
00412
00413 static inline void xnarch_stop_timer (void) {
00414 uvm_thread_cancel(uvm_timer_handle,NULL);
00415 }
00416
00417 static inline int xnarch_send_timer_ipi (xnarch_cpumask_t mask) {
00418
00419 return 0;
00420 }
00421
00422 #endif
00423
00424 #ifdef XENO_POD_MODULE
00425
00426 extern void *uvm_timer_handle;
00427
00428 xnsysinfo_t uvm_info;
00429
00430 xnarchtcb_t *uvm_root;
00431
00432 xnarchtcb_t *uvm_current;
00433
00434 struct xnarch_tick_parms {
00435 unsigned long nstick;
00436 void (*tickhandler)(void);
00437 xncompletion_t completion;
00438 };
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 static void *xnarch_timer_thread (void *cookie)
00450
00451 {
00452 struct xnarch_tick_parms *p = (struct xnarch_tick_parms *)cookie;
00453 void (*tickhandler)(void);
00454 struct sched_param param;
00455 unsigned long nstick;
00456 long err;
00457
00458 param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 2;
00459 sched_setscheduler(0,SCHED_FIFO,¶m);
00460
00461
00462
00463 tickhandler = p->tickhandler;
00464 nstick = p->nstick;
00465
00466 uvm_thread_create("uvm-timer",NULL,&p->completion,&uvm_timer_handle);
00467
00468 err = uvm_thread_barrier();
00469
00470 if (!err)
00471 err = uvm_thread_set_periodic(0,nstick);
00472
00473 if (err)
00474 pthread_exit((void *)err);
00475
00476 for (;;)
00477 {
00478 if (uvm_thread_wait_period() == -EWOULDBLOCK)
00479 break;
00480
00481 xnarch_sync_irq();
00482 tickhandler();
00483 }
00484
00485 pthread_exit(NULL);
00486 }
00487
00488 static inline int xnarch_start_timer (unsigned long nstick,
00489 void (*tickhandler)(void))
00490 {
00491 struct xnarch_tick_parms parms;
00492 pthread_attr_t thattr;
00493 pthread_t thid;
00494 int err;
00495
00496 if (nstick == 0)
00497 return -ENODEV;
00498
00499
00500
00501
00502
00503 err = uvm_timer_start(0);
00504
00505 if (err)
00506 return err;
00507
00508 parms.nstick = nstick;
00509 parms.tickhandler = tickhandler;
00510 parms.completion.syncflag = 0;
00511 parms.completion.pid = -1;
00512
00513 pthread_attr_init(&thattr);
00514 pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED);
00515 pthread_create(&thid,&thattr,&xnarch_timer_thread,&parms);
00516
00517 err = uvm_thread_sync(&parms.completion);
00518
00519 if (err == 0)
00520 uvm_thread_start(uvm_timer_handle);
00521
00522 return err;
00523 }
00524
00525 static inline void xnarch_leave_root(xnarchtcb_t *rootcb) {
00526 }
00527
00528 static inline void xnarch_enter_root(xnarchtcb_t *rootcb) {
00529 }
00530
00531 static inline void xnarch_switch_to (xnarchtcb_t *out_tcb,
00532 xnarchtcb_t *in_tcb)
00533 {
00534 uvm_current = in_tcb;
00535 uvm_thread_activate(in_tcb->khandle,out_tcb->khandle);
00536 }
00537
00538 static inline void xnarch_finalize_and_switch (xnarchtcb_t *dead_tcb,
00539 xnarchtcb_t *next_tcb)
00540 {
00541 uvm_current = next_tcb;
00542 uvm_thread_cancel(dead_tcb->khandle,next_tcb->khandle);
00543 }
00544
00545 static inline void xnarch_finalize_no_switch (xnarchtcb_t *dead_tcb)
00546
00547 {
00548 uvm_thread_cancel(dead_tcb->khandle,NULL);
00549 }
00550
00551 static inline void xnarch_init_root_tcb (xnarchtcb_t *tcb,
00552 struct xnthread *thread,
00553 const char *name)
00554 {
00555 struct sched_param param;
00556 int err;
00557
00558 param.sched_priority = sched_get_priority_min(SCHED_FIFO);
00559 sched_setscheduler(0,SCHED_FIFO,¶m);
00560 err = uvm_system_info(&uvm_info);
00561
00562 if (err)
00563 {
00564 fprintf(stderr,"UVM init failed: %s\n",strerror(-err));
00565 exit(1);
00566 }
00567
00568 uvm_thread_shadow("uvm-root",tcb,&tcb->khandle);
00569 tcb->name = name;
00570 uvm_root = uvm_current = tcb;
00571 }
00572
00573 static void *xnarch_thread_trampoline (void *cookie)
00574
00575 {
00576 xnarchtcb_t *tcb = (xnarchtcb_t *)cookie;
00577 struct sched_param param;
00578 long err;
00579
00580 if (!setjmp(tcb->rstenv))
00581 {
00582 param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
00583 sched_setscheduler(0,SCHED_FIFO,¶m);
00584 uvm_thread_create(tcb->name,tcb,&tcb->completion,&tcb->khandle);
00585 err = uvm_thread_barrier();
00586 if (err)
00587 pthread_exit((void *)err);
00588 }
00589
00590 xnarch_setimask(tcb->imask);
00591
00592 xnpod_welcome_thread(tcb->thread);
00593
00594 tcb->entry(tcb->cookie);
00595
00596 pthread_exit(NULL);
00597 }
00598
00599 static inline void xnarch_init_thread (xnarchtcb_t *tcb,
00600 void (*entry)(void *),
00601 void *cookie,
00602 int imask,
00603 struct xnthread *thread,
00604 char *name)
00605 {
00606 pthread_attr_t thattr;
00607
00608 if (tcb->khandle)
00609 {
00610 pthread_kill(tcb->thid,XNARCH_SIG_RESTART);
00611 return;
00612 }
00613
00614 tcb->imask = imask;
00615 tcb->entry = entry;
00616 tcb->cookie = cookie;
00617 tcb->thread = thread;
00618 tcb->name = name;
00619 tcb->completion.syncflag = 0;
00620 tcb->completion.pid = -1;
00621
00622 pthread_attr_init(&thattr);
00623 pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED);
00624 pthread_create(&tcb->thid,&thattr,&xnarch_thread_trampoline,tcb);
00625 uvm_thread_sync(&tcb->completion);
00626 }
00627
00628 static inline void xnarch_enable_fpu(xnarchtcb_t *current_tcb) {
00629
00630 }
00631
00632 static inline void xnarch_init_fpu(xnarchtcb_t *tcb) {
00633
00634 }
00635
00636 static inline void xnarch_save_fpu(xnarchtcb_t *tcb) {
00637
00638 }
00639
00640 static inline void xnarch_restore_fpu(xnarchtcb_t *tcb) {
00641
00642 }
00643
00644 int xnarch_setimask (int imask)
00645
00646 {
00647 spl_t s;
00648 splhigh(s);
00649 splexit(!!imask);
00650 return !!s;
00651 }
00652
00653 static inline int xnarch_send_ipi (cpumask_t cpumask) {
00654
00655 return 0;
00656 }
00657
00658 static inline int xnarch_hook_ipi (void (*handler)(void)) {
00659
00660 return 0;
00661 }
00662
00663 static inline int xnarch_release_ipi (void) {
00664
00665 return 0;
00666 }
00667
00668 #define xnarch_notify_ready()
00669 #define xnarch_notify_shutdown()
00670 #define xnarch_notify_halt()
00671
00672 static inline unsigned long long xnarch_get_sys_time(void)
00673 {
00674 struct timeval tv;
00675
00676 if(gettimeofday(&tv, NULL))
00677 {
00678 printf("Warning, gettimeofday failed, error %d\n", errno);
00679 return 0;
00680 }
00681
00682 return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
00683 }
00684
00685 #endif
00686
00687 #ifdef XENO_THREAD_MODULE
00688
00689 static inline void xnarch_init_tcb (xnarchtcb_t *tcb) {
00690
00691 tcb->khandle = NULL;
00692 }
00693
00694 #endif
00695
00696 extern xnsysinfo_t uvm_info;
00697
00698 static inline unsigned long long xnarch_tsc_to_ns (unsigned long long tsc) {
00699
00700 nanostime_t ns;
00701 return uvm_timer_tsc2ns(tsc,&ns) ? 0 : ns;
00702 }
00703
00704 static inline unsigned long long xnarch_ns_to_tsc (unsigned long long ns) {
00705
00706 nanostime_t tsc;
00707 return uvm_timer_ns2tsc(ns,&tsc) ? 0 : tsc;
00708 }
00709
00710 static inline unsigned long long xnarch_get_cpu_time (void)
00711
00712 {
00713 nanotime_t t;
00714 uvm_timer_read(&t);
00715 return t;
00716 }
00717
00718 static inline unsigned long long xnarch_get_cpu_tsc (void)
00719
00720 {
00721 nanotime_t t;
00722 uvm_timer_tsc(&t);
00723 return t;
00724 }
00725
00726 static inline unsigned long long xnarch_get_cpu_freq (void) {
00727 return uvm_info.cpufreq;
00728 }
00729
00730 static inline void xnarch_halt (const char *emsg) {
00731 fprintf(stderr,"UVM fatal: %s\n",emsg);
00732 fflush(stderr);
00733 exit(99);
00734 }
00735
00736 static inline void *xnarch_sysalloc (u_long bytes) {
00737 return malloc(bytes);
00738 }
00739
00740 static inline void xnarch_sysfree (void *chunk, u_long bytes) {
00741 free(chunk);
00742 }
00743
00744 #define xnarch_current_cpu() 0
00745 #define xnarch_declare_cpuid const int cpuid = 0
00746 #define xnarch_get_cpu(x) do { (x) = (x); } while(0)
00747 #define xnarch_put_cpu(x) do { } while(0)
00748
00749 #define xnarch_alloc_stack xnmalloc
00750 #define xnarch_free_stack xnfree
00751
00752 #ifdef __cplusplus
00753 }
00754 #endif
00755
00756
00757 #define XNARCH_DECL_DISPLAY_CONTEXT();
00758 #define xnarch_init_display_context(obj)
00759 #define xnarch_create_display(obj,name,tag)
00760 #define xnarch_delete_display(obj)
00761 #define xnarch_post_graph(obj,state)
00762 #define xnarch_post_graph_if(obj,state,cond)
00763
00764 #endif