Module: xenomai-forge Branch: master Commit: 567e3faf056d1f79b0a4d5ef0878460a18a5e9b5 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=567e3faf056d1f79b0a4d5ef0878460a18a5e9b5
Author: Philippe Gerum <r...@xenomai.org> Date: Mon Jan 7 17:53:16 2013 +0100 cobalt/powerpc: convert to native linux kthreads --- include/asm-powerpc/thread.h | 116 ++++----------- kernel/cobalt/arch/powerpc/Kconfig | 4 - kernel/cobalt/arch/powerpc/switch_32.S | 12 -- kernel/cobalt/arch/powerpc/switch_64.S | 16 +-- kernel/cobalt/arch/powerpc/thread.c | 265 +++++--------------------------- 5 files changed, 67 insertions(+), 346 deletions(-) diff --git a/include/asm-powerpc/thread.h b/include/asm-powerpc/thread.h index a968a7b..2e87281 100644 --- a/include/asm-powerpc/thread.h +++ b/include/asm-powerpc/thread.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2006 Philippe Gerum. + * Copyright (C) 2004-2013 Philippe Gerum. * * Xenomai is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -20,62 +20,20 @@ #ifndef _XENO_ASM_POWERPC_THREAD_H #define _XENO_ASM_POWERPC_THREAD_H -#ifndef __KERNEL__ -#error "Pure kernel header included from user-space!" -#endif - -#include <asm/ptrace.h> -#include <asm/processor.h> - -struct xnthread; -struct task_struct; +#include <asm-generic/xenomai/thread.h> struct xnarchtcb { - - /* User mode side */ - struct task_struct *user_task; /* Shadowed user-space task */ - struct task_struct *active_task; /* Active user-space task */ - struct thread_struct *tsp; /* Pointer to the active thread struct (&ts or &user->thread). */ - struct mm_struct *mm; - struct mm_struct *active_mm; - struct { - unsigned long nip; - unsigned long r0; - } mayday; - - /* Kernel mode side */ - struct thread_struct ts; /* Holds kernel-based thread context. */ -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - struct thread_info *tip; /* Pointer to the active thread info (ti or user->thread_info). */ - struct thread_info ti; /* Holds kernel-based thread info */ -#endif + struct xntcb core; #ifdef CONFIG_XENO_HW_FPU - /* - * We only care for basic FPU handling in kernel-space; Altivec - * and SPE are not available to kernel-based nucleus threads. - */ - struct thread_struct *fpup; /* Pointer to the FPU backup container */ - struct task_struct *user_fpu_owner; - /* - * Pointer to the FPU owner in userspace: - * - NULL for RT K threads, - * - last_task_used_math for Linux US threads (current or NULL when SMP) - * - current for RT US threads. - */ + struct thread_struct *fpup; #define xnarch_fpu_ptr(tcb) ((tcb)->fpup) #else #define xnarch_fpu_ptr(tcb) NULL #endif - - unsigned stacksize; /* Aligned size of stack (bytes) */ - unsigned long *stackbase; /* Stack space */ - - /* Init block */ - struct xnthread *self; - int imask; - const char *name; - void (*entry) (void *cookie); - void *cookie; + struct { + unsigned long nip; + unsigned long r0; + } mayday; }; #define xnarch_fault_regs(d) ((d)->regs) @@ -85,63 +43,45 @@ struct xnarchtcb { #define xnarch_fault_pc(d) ((d)->regs->nip) #define xnarch_fault_fpu_p(d) 0 #define xnarch_fault_pf_p(d) ((d)->exception == IPIPE_TRAP_ACCESS) -#ifdef CONFIG_PPC64 -#define XNARCH_THREAD_STACKSZ 8182 -#define xnarch_fault_bp_p(d) ((current->ptrace & PT_PTRACED) && \ - ((d)->exception == IPIPE_TRAP_IABR || \ - (d)->exception == IPIPE_TRAP_SSTEP)) -#else /* !CONFIG_PPC64 */ -#define XNARCH_THREAD_STACKSZ 4096 #define xnarch_fault_bp_p(d) ((current->ptrace & PT_PTRACED) && \ ((d)->exception == IPIPE_TRAP_IABR || \ (d)->exception == IPIPE_TRAP_SSTEP || \ (d)->exception == IPIPE_TRAP_DEBUG)) -#endif /* CONFIG_PPC64 */ #define xnarch_fault_notify(d) (xnarch_fault_bp_p(d) == 0) -#define xnarch_stack_size(tcb) ((tcb)->stacksize) -#define xnarch_stack_base(tcb) ((tcb)->stackbase) -#define xnarch_stack_end(tcb) ((caddr_t)(tcb)->stackbase - (tcb)->stacksize) -#define xnarch_user_task(tcb) ((tcb)->user_task) -#define xnarch_user_pid(tcb) ((tcb)->user_task->pid) +static inline void xnarch_enter_root(struct xnarchtcb *rootcb) { } -void xnarch_switch_to(struct xnarchtcb *out_tcb, struct xnarchtcb *in_tcb); +#ifdef CONFIG_XENO_HW_FPU -void xnarch_init_thread(struct xnarchtcb *tcb, - void (*entry)(void *), - void *cookie, - int imask, - struct xnthread *thread, char *name); +static inline void xnarch_init_root_tcb(struct xnarchtcb *tcb) +{ + tcb->fpup = NULL; +} -void xnarch_enter_root(struct xnarchtcb *rootcb); +static inline void xnarch_init_shadow_tcb(struct xnarchtcb *tcb) +{ + tcb->fpup = &tcb->core.host_task->thread; +} void xnarch_leave_root(struct xnarchtcb *rootcb); -int xnarch_escalate(void); - -void xnarch_init_root_tcb(struct xnarchtcb *tcb, - struct xnthread *thread, - const char *name); - -void xnarch_init_shadow_tcb(struct xnarchtcb *tcb, - struct xnthread *thread, - const char *name); +#else /* !CONFIG_XENO_HW_FPU */ -void xnarch_init_tcb(struct xnarchtcb *tcb); +static inline void xnarch_init_root_tcb(struct xnarchtcb *tcb) { } +static inline void xnarch_init_shadow_tcb(struct xnarchtcb *tcb) { } -int xnarch_alloc_stack(struct xnarchtcb *tcb, size_t stacksize); +#endif /* !CONFIG_XENO_HW_FPU */ -void xnarch_free_stack(struct xnarchtcb *tcb); - -static inline int xnarch_fpu_init_p(struct task_struct *task) +static inline int xnarch_handle_fpu_fault(struct xnarchtcb *tcb) { - /* No lazy FPU init on PowerPC. */ - return 1; + return 0; } -void xnarch_enable_fpu(struct xnarchtcb *current_tcb); +void xnarch_switch_to(struct xnarchtcb *out_tcb, struct xnarchtcb *in_tcb); + +int xnarch_escalate(void); -void xnarch_init_fpu(struct xnarchtcb *tcb); +void xnarch_enable_fpu(struct xnarchtcb *current_tcb); void xnarch_save_fpu(struct xnarchtcb *tcb); diff --git a/kernel/cobalt/arch/powerpc/Kconfig b/kernel/cobalt/arch/powerpc/Kconfig index 7eafffc..d964fa2 100644 --- a/kernel/cobalt/arch/powerpc/Kconfig +++ b/kernel/cobalt/arch/powerpc/Kconfig @@ -1,7 +1,3 @@ -config XENO_GENERIC_STACKPOOL - bool - default y - config XENO_HW_MATH_EMU bool default y if MATH_EMU || 8XX_MINIMAL_FPEMU diff --git a/kernel/cobalt/arch/powerpc/switch_32.S b/kernel/cobalt/arch/powerpc/switch_32.S index 97fea44..a9165ef 100644 --- a/kernel/cobalt/arch/powerpc/switch_32.S +++ b/kernel/cobalt/arch/powerpc/switch_32.S @@ -78,12 +78,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPE) #endif /* CONFIG_SMP */ lwz r1,KSP(r4) /* Load new stack pointer */ - mr r3,r2 lwz r0,PGDIR(r4) - cmpwi r0, 0 - beq- same_current - tophys(r0,r4) CLR_TOP32(r0) mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */ @@ -106,8 +102,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPE) #endif #endif /* CONFIG_SPE */ -same_current: - lwz r0,_CCR(r1) mtcrf 0xFF,r0 REST_NVGPRS(r1) @@ -116,9 +110,3 @@ same_current: mtlr r4 addi r1,r1,INT_FRAME_SIZE blr - -_GLOBAL(__asm_thread_trampoline) - stwu r1,-STACK_FRAME_OVERHEAD(r1) - mr r3,r22 - mtlr r23 - blr diff --git a/kernel/cobalt/arch/powerpc/switch_64.S b/kernel/cobalt/arch/powerpc/switch_64.S index 7da7ff5..4deb982 100644 --- a/kernel/cobalt/arch/powerpc/switch_64.S +++ b/kernel/cobalt/arch/powerpc/switch_64.S @@ -36,7 +36,8 @@ #include <asm/ptrace.h> /* - * void __asm_thread_switch(struct thread_struct *prev, struct thread_struct *next, int kthreadp) + * struct task_struct * + * __asm_thread_switch(struct thread_struct *prev, struct thread_struct *next) */ _GLOBAL(__asm_thread_switch) mflr r0 @@ -89,12 +90,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) ld r8,KSP(r4) /* new stack pointer */ ld r3,PACACURRENT(r13) /* we must return "prev" when paired to switch_to() */ - cmpwi cr5,r5,0 /* is it a kernel thread */ - bne- cr5,10f /* if so, don't touch 'current' */ - addi r6,r4,-THREAD /* Convert THREAD to 'current' */ std r6,PACACURRENT(r13) /* Set new 'current' */ -10: #ifdef CONFIG_PPC_BOOK3S BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(95) @@ -144,8 +141,6 @@ END_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) isync 2: #endif /* !CONFIG_PPC_BOOK3S */ - bne- cr5,11f /* kernel thread: don't update KSAVE */ - clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE because we don't need to leave the 288-byte ABI gap at the @@ -173,10 +168,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) mtlr r7 addi r1,r1,SWITCH_FRAME_SIZE blr - -_GLOBAL(__asm_thread_trampoline) - stdu r1,-STACK_FRAME_OVERHEAD(r1) - mr r3,r22 - mr r2,r24 - mtlr r23 - blr diff --git a/kernel/cobalt/arch/powerpc/thread.c b/kernel/cobalt/arch/powerpc/thread.c index b72334a..56f953f 100644 --- a/kernel/cobalt/arch/powerpc/thread.c +++ b/kernel/cobalt/arch/powerpc/thread.c @@ -24,127 +24,39 @@ #include <linux/ipipe.h> #include <linux/mm.h> #include <asm/mmu_context.h> -#include <nucleus/pod.h> -#include <nucleus/heap.h> - -#ifdef CONFIG_PPC64 - -asmlinkage struct task_struct * -__asm_thread_switch(struct thread_struct *prev_t, - struct thread_struct *next_t, - int kthreadp); - -/* from process.c/copy_thread */ -static unsigned long get_stack_vsid(unsigned long ksp) -{ - unsigned long vsid; - unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; - - if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) - vsid = get_kernel_vsid(ksp, MMU_SEGSIZE_1T) - << SLB_VSID_SHIFT_1T; - else - vsid = get_kernel_vsid(ksp, MMU_SEGSIZE_256M) - << SLB_VSID_SHIFT; - - vsid |= SLB_VSID_KERNEL | llp; - - return vsid; -} - -#else /* !CONFIG_PPC64 */ +#include <nucleus/thread.h> asmlinkage struct task_struct * __asm_thread_switch(struct thread_struct *prev, struct thread_struct *next); -#endif /* !CONFIG_PPC64 */ - -asmlinkage void __asm_thread_trampoline(void); - -void xnarch_enter_root(struct xnarchtcb *rootcb) -{ -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - if (!rootcb->mm) - set_ti_thread_flag(rootcb->tip, TIF_MMSWITCH_INT); -#endif - ipipe_unmute_pic(); -} - void xnarch_switch_to(struct xnarchtcb *out_tcb, struct xnarchtcb *in_tcb) { - struct mm_struct *prev_mm = out_tcb->active_mm, *next_mm; - struct task_struct *prev = out_tcb->active_task; - struct task_struct *next = in_tcb->user_task; + struct mm_struct *prev_mm, *next_mm; + struct task_struct *next; + + next = in_tcb->core.host_task; + prev_mm = out_tcb->core.active_mm; - if (likely(next != NULL)) { - in_tcb->active_task = next; - in_tcb->active_mm = in_tcb->mm; - ipipe_clear_foreign_stack(&xnarch_machdata.domain); + next_mm = in_tcb->core.mm; + if (next_mm == NULL) { + in_tcb->core.active_mm = prev_mm; + enter_lazy_tlb(prev_mm, next); } else { - in_tcb->active_task = prev; - in_tcb->active_mm = prev_mm; - ipipe_set_foreign_stack(&xnarch_machdata.domain); + ipipe_switch_mm_head(prev_mm, next_mm, next); + /* + * We might be switching back to the root thread, + * which we preempted earlier, shortly after "current" + * dropped its mm context in the do_exit() path + * (next->mm == NULL). In that particular case, the + * kernel expects a lazy TLB state for leaving the mm. + */ + if (next->mm == NULL) + enter_lazy_tlb(prev_mm, next); } - next_mm = in_tcb->active_mm; - if (next_mm && likely(prev_mm != next_mm)) - __switch_mm(prev_mm, next_mm, next); - -#ifdef CONFIG_PPC64 - __asm_thread_switch(out_tcb->tsp, in_tcb->tsp, next == NULL); -#else - __asm_thread_switch(out_tcb->tsp, in_tcb->tsp); -#endif -} - -asmlinkage static void thread_trampoline(struct xnarchtcb *tcb) -{ - xnpod_welcome_thread(tcb->self, tcb->imask); - tcb->entry(tcb->cookie); - xnpod_delete_thread(tcb->self); -} - -void xnarch_init_thread(struct xnarchtcb *tcb, - void (*entry)(void *), - void *cookie, - int imask, - struct xnthread *thread, char *name) -{ - struct pt_regs *childregs; - unsigned long sp; - - /* - * Stack space is guaranteed to have been fully zeroed. We do - * this earlier in xnthread_init() which runs with interrupts - * on, to reduce latency. - */ - sp = (unsigned long)tcb->stackbase + tcb->stacksize; - sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *)sp; - sp -= STACK_FRAME_OVERHEAD; - - tcb->ts.ksp = sp; - tcb->entry = entry; - tcb->cookie = cookie; - tcb->self = thread; - tcb->imask = imask; - tcb->name = name; - -#ifdef CONFIG_PPC64 - childregs->nip = ((unsigned long *)__asm_thread_trampoline)[0]; - childregs->gpr[2] = ((unsigned long *)__asm_thread_trampoline)[1]; - childregs->gpr[22] = (unsigned long)tcb; - childregs->gpr[23] = ((unsigned long *)thread_trampoline)[0]; /* lr = entry addr. */ - childregs->gpr[24] = ((unsigned long *)thread_trampoline)[1]; /* r2 = TOC base. */ - if (mmu_has_feature(MMU_FTR_SLB)) - tcb->ts.ksp_vsid = get_stack_vsid(tcb->ts.ksp); -#else /* !CONFIG_PPC64 */ - childregs->nip = (unsigned long)__asm_thread_trampoline; - childregs->gpr[22] = (unsigned long)tcb; - childregs->gpr[23] = (unsigned long)thread_trampoline; -#endif /* !CONFIG_PPC64 */ + __asm_thread_switch(out_tcb->core.tsp, in_tcb->core.tsp); } #ifdef CONFIG_XENO_HW_FPU @@ -206,19 +118,17 @@ asmlinkage void __asm_restore_fpu(struct thread_struct *ts); void xnarch_init_fpu(struct xnarchtcb *tcb) { /* - * Initialize the FPU for an emerging kernel-based RT - * thread. This must be run on behalf of the emerging thread. - * xnarch_init_tcb() guarantees that all FPU regs are zeroed - * in tcb. + * This must run on behalf of the thread we initialize the FPU + * for. All FPU regs are guaranteed zero. */ - __asm_init_fpu(&tcb->ts); + __asm_init_fpu(&tcb->core.ts); } void xnarch_enable_fpu(struct xnarchtcb *tcb) { - struct task_struct *task = tcb->user_task; + struct task_struct *task = tcb->core.host_task; - if (task && task != tcb->user_fpu_owner) + if (task && task != tcb->core.user_fpu_owner) do_disable_fpu(); else do_enable_fpu(); @@ -229,9 +139,9 @@ void xnarch_save_fpu(struct xnarchtcb *tcb) if (tcb->fpup) { __asm_save_fpu(tcb->fpup); - if (tcb->user_fpu_owner && - tcb->user_fpu_owner->thread.regs) - tcb->user_fpu_owner->thread.regs->msr &= ~(MSR_FP|MSR_FE0|MSR_FE1); + if (tcb->core.user_fpu_owner && + tcb->core.user_fpu_owner->thread.regs) + tcb->core.user_fpu_owner->thread.regs->msr &= ~(MSR_FP|MSR_FE0|MSR_FE1); } } @@ -246,8 +156,8 @@ void xnarch_restore_fpu(struct xnarchtcb *tcb) * Note: Only enable FP in MSR, if it was enabled when * we saved the fpu state. */ - if (tcb->user_fpu_owner) { - ts = &tcb->user_fpu_owner->thread; + if (tcb->core.user_fpu_owner) { + ts = &tcb->core.user_fpu_owner->thread; regs = ts->regs; if (regs) { regs->msr &= ~(MSR_FE0|MSR_FE1); @@ -259,32 +169,20 @@ void xnarch_restore_fpu(struct xnarchtcb *tcb) * FIXME: We restore FPU "as it was" when Xenomai preempted Linux, * whereas we could be much lazier. */ - if (tcb->user_task && tcb->user_task != tcb->user_fpu_owner) + if (tcb->core.host_task && tcb->core.host_task != tcb->core.user_fpu_owner) do_disable_fpu(); } -#endif /* CONFIG_XENO_HW_FPU */ - void xnarch_leave_root(struct xnarchtcb *rootcb) { - struct task_struct *p = current; - - ipipe_mute_pic(); - /* Remember the preempted Linux task pointer. */ - rootcb->user_task = rootcb->active_task = p; - rootcb->tsp = &p->thread; - rootcb->mm = rootcb->active_mm = ipipe_get_active_mm(); -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - rootcb->tip = task_thread_info(p); -#endif -#ifdef CONFIG_XENO_HW_FPU - rootcb->user_fpu_owner = get_fpu_owner(rootcb->user_task); + rootcb->core.user_fpu_owner = get_fpu_owner(rootcb->core.host_task); /* So that xnarch_save_fpu() will operate on the right FPU area. */ - rootcb->fpup = rootcb->user_fpu_owner ? - &rootcb->user_fpu_owner->thread : NULL; -#endif /* CONFIG_XENO_HW_FPU */ + rootcb->fpup = rootcb->core.user_fpu_owner ? + &rootcb->core.user_fpu_owner->thread : NULL; } +#endif /* CONFIG_XENO_HW_FPU */ + int xnarch_escalate(void) { if (ipipe_root_p) { @@ -294,92 +192,3 @@ int xnarch_escalate(void) return 0; } - -void xnarch_init_tcb(struct xnarchtcb *tcb) -{ - tcb->user_task = NULL; - tcb->active_task = NULL; - tcb->tsp = &tcb->ts; - tcb->mm = NULL; - tcb->active_mm = NULL; -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - tcb->tip = &tcb->ti; -#endif - /* Note: .pgdir(ppc32) == NULL for a Xenomai kthread. */ - memset(&tcb->ts, 0, sizeof(tcb->ts)); -#ifdef CONFIG_XENO_HW_FPU - tcb->user_fpu_owner = NULL; - tcb->fpup = &tcb->ts; -#endif /* CONFIG_XENO_HW_FPU */ - /* Must be followed by xnarch_init_thread(). */ -} - -void xnarch_init_root_tcb(struct xnarchtcb *tcb, - struct xnthread *thread, - const char *name) -{ - tcb->user_task = current; - tcb->active_task = NULL; - tcb->tsp = &tcb->ts; - tcb->mm = current->mm; - tcb->active_mm = NULL; -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - tcb->tip = &tcb->ti; -#endif -#ifdef CONFIG_XENO_HW_FPU - tcb->user_fpu_owner = NULL; - tcb->fpup = NULL; -#endif /* CONFIG_XENO_HW_FPU */ - tcb->entry = NULL; - tcb->cookie = NULL; - tcb->self = thread; - tcb->imask = 0; - tcb->name = name; -} - -void xnarch_init_shadow_tcb(struct xnarchtcb *tcb, - struct xnthread *thread, - const char *name) -{ - struct task_struct *task = current; - - tcb->user_task = task; - tcb->active_task = NULL; - tcb->tsp = &task->thread; - tcb->mm = task->mm; - tcb->active_mm = NULL; -#ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH - tcb->tip = task_thread_info(task); -#endif -#ifdef CONFIG_XENO_HW_FPU - tcb->user_fpu_owner = task; - tcb->fpup = &task->thread; -#endif /* CONFIG_XENO_HW_FPU */ - tcb->entry = NULL; - tcb->cookie = NULL; - tcb->self = thread; - tcb->imask = 0; - tcb->name = name; -} - -int xnarch_alloc_stack(struct xnarchtcb *tcb, size_t stacksize) -{ - int ret = 0; - - tcb->stacksize = stacksize; - if (stacksize == 0) - tcb->stackbase = NULL; - else { - tcb->stackbase = xnheap_alloc(&kstacks, stacksize); - if (tcb->stackbase == NULL) - ret = -ENOMEM; - } - - return ret; -} - -void xnarch_free_stack(struct xnarchtcb *tcb) -{ - if (tcb->stackbase) - xnheap_free(&kstacks, tcb->stackbase); -} _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git