diff -urN linux-2.4.15-pre6-rmk2-rtai/Documentation/Configure.help linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/Documentation/Configure.help --- linux-2.4.15-pre6-rmk2-rtai/Documentation/Configure.help Tue Nov 20 17:33:56 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/Documentation/Configure.help Tue Nov 26 12:05:24 2002 @@ -239,6 +239,14 @@ You will need a new lynxer.elf file to flash your firmware with - send email to Martin.Bligh@us.ibm.com + +Real-Time Harware Abstraction +CONFIG_RTHAL + The Real-Time Hardware Abstraction Layer (RTHAL) is used by + the Real-Time Application Interface (RTAI) to provide a + hard real-time environment as part of Linux. This feature + cannot be turned off, so say Y. + IO-APIC Support on Uniprocessors CONFIG_X86_UP_IOAPIC An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/arm/kernel/armksyms.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/arm/kernel/armksyms.c --- linux-2.4.15-pre6-rmk2-rtai/arch/arm/kernel/armksyms.c Thu Dec 5 15:02:37 2002 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/arm/kernel/armksyms.c Thu Nov 21 16:30:40 2002 @@ -206,6 +206,7 @@ EXPORT_SYMBOL(__arch_copy_to_user); EXPORT_SYMBOL(__arch_clear_user); EXPORT_SYMBOL(__arch_strnlen_user); +EXPORT_SYMBOL(__arch_strncpy_from_user); /* consistent area handling */ EXPORT_SYMBOL(pci_alloc_consistent); diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/arm/kernel/irq.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/arm/kernel/irq.c --- linux-2.4.15-pre6-rmk2-rtai/arch/arm/kernel/irq.c Thu Dec 5 15:02:37 2002 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/arm/kernel/irq.c Thu Nov 28 16:37:49 2002 @@ -575,6 +575,9 @@ hard_stf(); } +extern int idle_weight; +extern void switch_mem(struct task_struct *, struct task_struct *, int); + struct rt_hal rthal = { do_IRQ, /* irq-dispatcher */ NULL, /* srq-dispatcher */ @@ -586,6 +589,11 @@ linux_save_flags_and_cli, linux_fcli, linux_fsti, + &idle_weight, + 0, + switch_mem, + init_tasks, + __switch_to, }; #endif diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/ppc/config.in linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/config.in --- linux-2.4.15-pre6-rmk2-rtai/arch/ppc/config.in Tue Nov 20 17:23:06 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/config.in Tue Nov 26 12:05:24 2002 @@ -110,6 +110,9 @@ bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS fi +#bool 'Real-Time Hardware Abstraction Layer' CONFIG_RTHAL +define_bool CONFIG_RTHAL y + if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then bool 'AltiVec Support' CONFIG_ALTIVEC bool 'Thermal Management Support' CONFIG_TAU diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/entry.S linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/entry.S --- linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/entry.S Mon Oct 29 19:52:33 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/entry.S Tue Nov 26 12:05:24 2002 @@ -291,6 +291,7 @@ bl do_signal .globl do_signal_ret do_signal_ret: + bl do_soft_sti .globl ret_to_user_hook ret_to_user_hook: nop diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/irq.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/irq.c --- linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/irq.c Mon Oct 29 19:52:33 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/irq.c Tue Nov 26 12:05:24 2002 @@ -534,6 +534,29 @@ spin_unlock(&desc->lock); } +void do_soft_cli(void) +{ +} + +void (*rtai_soft_sti)(void); + +void do_soft_sti(void) +{ + if(rtai_soft_sti)rtai_soft_sti(); +} + + +void do_soft_cli(void) +{ +} + +void (*rtai_soft_sti)(void); + +void do_soft_sti(void) +{ + if(rtai_soft_sti)rtai_soft_sti(); +} + int do_IRQ(struct pt_regs *regs) { int cpu = smp_processor_id(); diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/ppc_ksyms.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/ppc_ksyms.c --- linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/ppc_ksyms.c Tue Nov 20 17:23:09 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/ppc_ksyms.c Tue Nov 26 11:49:40 2002 @@ -217,6 +217,12 @@ EXPORT_SYMBOL(synchronize_irq); #endif +extern int (*rtai_srq_bckdr)(struct pt_regs *); +EXPORT_SYMBOL(rtai_srq_bckdr); + +extern void (*rtai_soft_sti)(void); +EXPORT_SYMBOL(rtai_soft_sti); + EXPORT_SYMBOL(ppc_md); #ifdef CONFIG_ADB diff -urN linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/traps.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/traps.c --- linux-2.4.15-pre6-rmk2-rtai/arch/ppc/kernel/traps.c Tue Nov 20 17:23:09 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/arch/ppc/kernel/traps.c Tue Nov 26 12:05:31 2002 @@ -269,9 +269,16 @@ return(retval); } +int (*rtai_srq_bckdr)(struct pt_regs *regs) = NULL; + + void ProgramCheckException(struct pt_regs *regs) { + if (rtai_srq_bckdr && !rtai_srq_bckdr(regs)) { + return; + } + #if defined(CONFIG_4xx) unsigned int esr = mfspr(SPRN_ESR); diff -urN linux-2.4.15-pre6-rmk2-rtai/include/asm-arm/proc-armv/system.h linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-arm/proc-armv/system.h --- linux-2.4.15-pre6-rmk2-rtai/include/asm-arm/proc-armv/system.h Thu Dec 5 15:02:38 2002 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-arm/proc-armv/system.h Fri Nov 29 13:43:51 2002 @@ -67,6 +67,11 @@ unsigned int (*getflags_and_cli)(void); void (*fdisint)(void); void (*fenint)(void); + int *idle_weight; + void (*lxrt_global_cli)(void); + void (*switch_mem)(struct task_struct *, struct task_struct *, int); + struct task_struct **init_tasks; + struct task_struct * (*__switch_to)(struct task_struct *, struct task_struct *); } __attribute__ ((__aligned__ (32))); extern struct rt_hal rthal; diff -urN linux-2.4.15-pre6-rmk2-rtai/include/asm-arm/system.h linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-arm/system.h --- linux-2.4.15-pre6-rmk2-rtai/include/asm-arm/system.h Thu Dec 5 15:02:38 2002 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-arm/system.h Wed Dec 4 15:21:34 2002 @@ -41,7 +41,17 @@ #define wmb() mb() #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); -#define prepare_to_switch() do { } while(0) + +#define prepare_to_switch() do { } while(0) +/* Is a call to cli() necessary here? */ +#if 0 +#define prepare_to_switch() do { \ + if (rthal.lxrt_global_cli) { \ + rthal.lxrt_global_cli(); \ + } \ +} while(0) +#endif +/* Probably need to sti() in end_switch if prepare_to_switch has a cli() (?) */ #define end_switch() do { } while(0) /* diff -urN linux-2.4.15-pre6-rmk2-rtai/include/asm-ppc/system.h linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-ppc/system.h --- linux-2.4.15-pre6-rmk2-rtai/include/asm-ppc/system.h Mon Oct 29 19:45:41 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/asm-ppc/system.h Tue Nov 26 12:05:31 2002 @@ -81,6 +81,7 @@ struct task_struct; #define prepare_to_switch() do { } while(0) +#define end_switch() do { } while(0) #define switch_to(prev,next,last) _switch_to((prev),(next),&(last)) extern void _switch_to(struct task_struct *, struct task_struct *, struct task_struct **); diff -urN linux-2.4.15-pre6-rmk2-rtai/include/linux/sched.h linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/linux/sched.h --- linux-2.4.15-pre6-rmk2-rtai/include/linux/sched.h Fri Nov 23 11:34:43 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/include/linux/sched.h Wed Dec 4 15:21:40 2002 @@ -403,6 +403,8 @@ /* journalling filesystem info */ void *journal_info; + + void *this_rt_task[2]; /* RTHAL */ }; /* @@ -492,6 +494,7 @@ blocked: {{0}}, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + this_rt_task: {0,0}, \ } diff -urN linux-2.4.15-pre6-rmk2-rtai/kernel/exit.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/exit.c --- linux-2.4.15-pre6-rmk2-rtai/kernel/exit.c Tue Nov 20 17:35:55 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/exit.c Tue Nov 26 12:05:31 2002 @@ -416,6 +416,71 @@ write_unlock_irq(&tasklist_lock); } +// +// PGGC added these lines to callback rtai when a task dies. +// A list of functions allows different rt_modules to be informed. +// +static struct t_callback { + void (*rtai_callback)(struct task_struct *tsk); + struct t_callback *next; + } *rtai_callback_list; + +extern int set_rtai_callback( void (*fun)(struct task_struct *tsk)); +extern void remove_rtai_callback( void (*fun)(struct task_struct *tsk)); + +void inform_rtai(void) +{ + struct t_callback *pt; + + pt = rtai_callback_list; + while (pt) { + (*(pt->rtai_callback))(current); + pt = pt->next; + } +//printk( "Task pid %d going down\n", current->pid); +} + +int set_rtai_callback( void (*pt)(struct task_struct *tsk)) +{ + struct t_callback *ptn; + + ptn = kmalloc(sizeof(struct t_callback), GFP_KERNEL); + if (!ptn) { + return -ENOMEM; + } + ptn->rtai_callback = pt; + ptn->next = rtai_callback_list ? rtai_callback_list : 0; + rtai_callback_list = ptn; + return 0; +} + +void remove_rtai_callback(void (*pt)(struct task_struct *tsk)) +{ + struct t_callback *pto, *ptoo, *ptd; + + pto = rtai_callback_list; + ptoo = 0; + while (pto) { + if (pto->rtai_callback == pt) { + if (!ptoo) { + rtai_callback_list = pto->next; + } else { + ptoo->next = pto->next; + } + ptd = pto; + pto = pto->next; + kfree(ptd); + } else { + ptoo = pto; + pto = pto->next; + } + } +//printk("rtai_callback_list %X\n", rtai_callback_list); +} +// +// +// + NORET_TYPE void do_exit(long code) { struct task_struct *tsk = current; @@ -433,6 +498,18 @@ #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif + +/* + * PGGC added these lines to callback rtai when a task dies. + * This assumes that a LXRT task should/will always set its + * scheduling police to SCHED_FIFO or SCHED_RR. + * We may want to enforce this in rt_task_init(...). + * (For the moment it is not so, thus let's inform LXRT anyhow (Paolo)) + */ + if(tsk->this_rt_task[0]) { + inform_rtai(); + } + __exit_mm(tsk); lock_kernel(); diff -urN linux-2.4.15-pre6-rmk2-rtai/kernel/fork.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/fork.c --- linux-2.4.15-pre6-rmk2-rtai/kernel/fork.c Tue Nov 20 17:35:56 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/fork.c Tue Nov 26 12:05:31 2002 @@ -223,7 +223,9 @@ atomic_set(&mm->mm_count, 1); init_rwsem(&mm->mmap_sem); mm->page_table_lock = SPIN_LOCK_UNLOCKED; + lock_kernel(); mm->pgd = pgd_alloc(mm); + unlock_kernel(); if (mm->pgd) return mm; free_mm(mm); @@ -254,7 +256,9 @@ inline void __mmdrop(struct mm_struct *mm) { if (mm == &init_mm) BUG(); + lock_kernel(); pgd_free(mm->pgd); + unlock_kernel(); destroy_context(mm); free_mm(mm); } diff -urN linux-2.4.15-pre6-rmk2-rtai/kernel/ksyms.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/ksyms.c --- linux-2.4.15-pre6-rmk2-rtai/kernel/ksyms.c Tue Nov 20 17:35:56 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/ksyms.c Tue Nov 26 12:05:31 2002 @@ -553,3 +553,44 @@ EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(pidhash); + +/* + * used to inform rtai a task is about to die. + */ +extern int set_rtai_callback( void (*fun)(struct task_struct *tsk)); +extern void remove_rtai_callback(void (*fun)(struct task_struct *tsk)); +extern NORET_TYPE void do_exit(long code); +EXPORT_SYMBOL(set_rtai_callback); +EXPORT_SYMBOL(remove_rtai_callback); +EXPORT_SYMBOL(do_exit); + +/* + * used to inform RTAI LXRT a task should deal with a Linux signal, and for rt_lxrt_fork() + */ +extern int (*rtai_signal_handler)(struct task_struct *lnxt, int sig); +EXPORT_SYMBOL(rtai_signal_handler); +extern int do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size); +EXPORT_SYMBOL(do_fork); + +/* + * used to provide async io support (aio) to RTAI LXRT. + */ +extern ssize_t sys_read(unsigned int fd, char * buf, size_t count); +extern ssize_t sys_write(unsigned int fd, const char * buf, size_t count); +extern ssize_t sys_pread(unsigned int fd, char * buf, + size_t count, loff_t pos); +extern ssize_t sys_pwrite(unsigned int fd, const char * buf, + size_t count, loff_t pos); +extern long sys_fsync(unsigned int fd); +extern long sys_fdatasync(unsigned int fd); +extern long sys_open(const char * filename, int flags, int mode); +extern long sys_close(unsigned int fd); + +EXPORT_SYMBOL(sys_read); +EXPORT_SYMBOL(sys_write); +EXPORT_SYMBOL(sys_open); +//EXPORT_SYMBOL(sys_close); +EXPORT_SYMBOL(sys_pread); +EXPORT_SYMBOL(sys_pwrite); +EXPORT_SYMBOL(sys_fsync); +EXPORT_SYMBOL(sys_fdatasync); diff -urN linux-2.4.15-pre6-rmk2-rtai/kernel/sched.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/sched.c --- linux-2.4.15-pre6-rmk2-rtai/kernel/sched.c Tue Nov 20 17:35:56 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/sched.c Fri Nov 29 12:20:37 2002 @@ -530,6 +530,96 @@ * tasks can run. It can not be killed, and it cannot sleep. The 'state' * information in task[0] is never used. */ + +int idle_weight = -1000; +#define MAX_MM 4096 // How large should it be? +static struct smm_t { int in, out; struct mm_struct *mm[MAX_MM]; } smm[NR_CPUS]; +#define incpnd(x) do { x = (x + 1) & (MAX_MM - 1); } while(0) + +static inline void pend_mm(struct mm_struct *mm, int cpu) +{ + if (rthal.lxrt_global_cli) { + struct smm_t *p = smm + cpu; + p->mm[p->in] = mm; + incpnd(p->in); + } else { + mmdrop(mm); + } +} + +static inline void drop_mm(void) +{ + if (rthal.lxrt_global_cli) { + struct smm_t *p = smm + smp_processor_id(); + while (p->out != p->in) { + mmdrop(p->mm[p->out]); + incpnd(p->out); + } + } +} +#ifdef CONFIG_X86 +void switch_mem(struct task_struct *prevp, struct task_struct *nextp, int cpuid) +{ + if (cpuid < 0) { + struct mm_struct *next = nextp->active_mm; + if (prevp->active_mm != next || (cpuid & 0x40000000)) { + if ((prevp->active_mm)->context.segments != next->context.segments) { + load_LDT(next); + } + set_bit(cpuid & 0xFFFFFFF, &next->context.cpuvalid); + asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd))); + } +#ifdef CONFIG_SMP + else if (!test_and_set_bit(cpuid & 0xFFFFFFF, &next->context.cpuvalid)) { + load_LDT(next); + } +#endif + } else { + struct mm_struct *oldmm = prevp->active_mm; + if (nextp->mm) { + switch_mm(oldmm, nextp->mm, nextp, cpuid); + } else { + nextp->active_mm = oldmm; + atomic_inc(&oldmm->mm_count); + enter_lazy_tlb(oldmm, nextp, cpuid); + } + if (!prevp->mm) { + prevp->active_mm = NULL; + pend_mm(oldmm, cpuid); + } + } +} +#endif + +#ifdef CONFIG_ARM +void switch_mem(struct task_struct *prevp, struct task_struct *nextp, int cpuid) +{ + if (cpuid < 0) { + /* This code is inspired by switch_mm in arch */ + struct mm_struct *next = nextp->active_mm; + struct mm_struct *prev = prevp->active_mm; + if (prev != next) { + /* Second parameter for cpu_switch_mm is unused on ARM, + it points to a task_struct */ + cpu_switch_mm(next->pgd, NULL); + } + } else { + struct mm_struct *oldmm = prevp->active_mm; + if (nextp->mm) { + switch_mm(oldmm, nextp->mm, nextp, cpuid); + } else { + nextp->active_mm = oldmm; + atomic_inc(&oldmm->mm_count); + enter_lazy_tlb(oldmm, nextp, cpuid); + } + if (!prevp->mm) { + prevp->active_mm = NULL; + pend_mm(oldmm, cpuid); + } + } +} +#endif + asmlinkage void schedule(void) { struct schedule_data * sched_data; @@ -584,7 +674,7 @@ * Default process to select.. */ next = idle_task(this_cpu); - c = -1000; + c = idle_weight; if (prev->state == TASK_RUNNING) goto still_running; @@ -663,7 +753,7 @@ if (!prev->mm) { prev->active_mm = NULL; - mmdrop(oldmm); + pend_mm(oldmm, this_cpu); } } @@ -672,6 +762,7 @@ * stack. */ switch_to(prev, next, prev); + drop_mm(); __schedule_tail(prev); same_process: diff -urN linux-2.4.15-pre6-rmk2-rtai/kernel/signal.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/signal.c --- linux-2.4.15-pre6-rmk2-rtai/kernel/signal.c Tue Nov 20 17:35:56 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/kernel/signal.c Tue Nov 26 12:05:31 2002 @@ -974,9 +974,30 @@ return ret; } +// +// Add this pointer to the RTAI signal handler. +// +int (*rtai_signal_handler)(struct task_struct *lnxt, int sig); + asmlinkage long sys_kill(int pid, int sig) { +// Add this section to call the RTAI signal handler. +// + { + struct task_struct *p; + int ret; + + if (rtai_signal_handler) { + p = find_task_by_pid(pid); + if(p && (p->policy == SCHED_FIFO || p->policy == SCHED_RR) && p->this_rt_task[0]) { + ret = rtai_signal_handler(p, sig); + if(!ret) return 0; //let Linux deal with it. + } + } + } + + { struct siginfo info; info.si_signo = sig; @@ -986,6 +1007,7 @@ info.si_uid = current->uid; return kill_something_info(sig, &info, pid); + } } asmlinkage long diff -urN linux-2.4.15-pre6-rmk2-rtai/mm/vmalloc.c linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/mm/vmalloc.c --- linux-2.4.15-pre6-rmk2-rtai/mm/vmalloc.c Tue Nov 20 17:36:03 2001 +++ linux-2.4.15-pre6-rmk2-rtai-arm-newlxrt/mm/vmalloc.c Tue Nov 26 12:05:31 2002 @@ -147,6 +147,9 @@ spin_lock(&init_mm.page_table_lock); do { pmd_t *pmd; +#ifdef CONFIG_X86 + pgd_t olddir = *dir; +#endif pmd = pmd_alloc(&init_mm, dir, address); ret = -ENOMEM; @@ -156,6 +159,10 @@ ret = -ENOMEM; if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot)) break; +#ifdef CONFIG_X86 + if (pgd_val(olddir) != pgd_val(*dir)) + set_pgdir(address, *dir); +#endif address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++;