1cbf6b1baSPaul Mundt #include <linux/mm.h> 2cbf6b1baSPaul Mundt #include <linux/kernel.h> 35a0e3ad6STejun Heo #include <linux/slab.h> 4cbf6b1baSPaul Mundt #include <linux/sched.h> 5cbf6b1baSPaul Mundt 60ea820cfSPaul Mundt struct kmem_cache *task_xstate_cachep = NULL; 70ea820cfSPaul Mundt unsigned int xstate_size; 80ea820cfSPaul Mundt 90ea820cfSPaul Mundt int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 100ea820cfSPaul Mundt { 110ea820cfSPaul Mundt *dst = *src; 120ea820cfSPaul Mundt 130ea820cfSPaul Mundt if (src->thread.xstate) { 140ea820cfSPaul Mundt dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep, 150ea820cfSPaul Mundt GFP_KERNEL); 160ea820cfSPaul Mundt if (!dst->thread.xstate) 170ea820cfSPaul Mundt return -ENOMEM; 180ea820cfSPaul Mundt memcpy(dst->thread.xstate, src->thread.xstate, xstate_size); 190ea820cfSPaul Mundt } 200ea820cfSPaul Mundt 210ea820cfSPaul Mundt return 0; 220ea820cfSPaul Mundt } 230ea820cfSPaul Mundt 240ea820cfSPaul Mundt void free_thread_xstate(struct task_struct *tsk) 250ea820cfSPaul Mundt { 260ea820cfSPaul Mundt if (tsk->thread.xstate) { 270ea820cfSPaul Mundt kmem_cache_free(task_xstate_cachep, tsk->thread.xstate); 280ea820cfSPaul Mundt tsk->thread.xstate = NULL; 290ea820cfSPaul Mundt } 300ea820cfSPaul Mundt } 310ea820cfSPaul Mundt 32cbf6b1baSPaul Mundt #if THREAD_SHIFT < PAGE_SHIFT 33cbf6b1baSPaul Mundt static struct kmem_cache *thread_info_cache; 34cbf6b1baSPaul Mundt 35*b6a84016SEric Dumazet struct thread_info *alloc_thread_info(struct task_struct *tsk, int node) 36cbf6b1baSPaul Mundt { 37cbf6b1baSPaul Mundt struct thread_info *ti; 38cbf6b1baSPaul Mundt #ifdef CONFIG_DEBUG_STACK_USAGE 39*b6a84016SEric Dumazet gfp_t mask = GFP_KERNEL | __GFP_ZERO; 40*b6a84016SEric Dumazet #else 41*b6a84016SEric Dumazet gfp_t mask = GFP_KERNEL; 42cbf6b1baSPaul Mundt #endif 43*b6a84016SEric Dumazet 44*b6a84016SEric Dumazet ti = kmem_cache_alloc_node(thread_info_cache, mask, node); 45cbf6b1baSPaul Mundt return ti; 46cbf6b1baSPaul Mundt } 47cbf6b1baSPaul Mundt 48cbf6b1baSPaul Mundt void free_thread_info(struct thread_info *ti) 49cbf6b1baSPaul Mundt { 500ea820cfSPaul Mundt free_thread_xstate(ti->task); 51cbf6b1baSPaul Mundt kmem_cache_free(thread_info_cache, ti); 52cbf6b1baSPaul Mundt } 53cbf6b1baSPaul Mundt 54cbf6b1baSPaul Mundt void thread_info_cache_init(void) 55cbf6b1baSPaul Mundt { 56cbf6b1baSPaul Mundt thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, 57a3705799SPaul Mundt THREAD_SIZE, SLAB_PANIC, NULL); 58cbf6b1baSPaul Mundt } 59cbf6b1baSPaul Mundt #else 60cbf6b1baSPaul Mundt struct thread_info *alloc_thread_info(struct task_struct *tsk) 61cbf6b1baSPaul Mundt { 62cbf6b1baSPaul Mundt #ifdef CONFIG_DEBUG_STACK_USAGE 63cbf6b1baSPaul Mundt gfp_t mask = GFP_KERNEL | __GFP_ZERO; 64cbf6b1baSPaul Mundt #else 65cbf6b1baSPaul Mundt gfp_t mask = GFP_KERNEL; 66cbf6b1baSPaul Mundt #endif 67*b6a84016SEric Dumazet struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER); 68*b6a84016SEric Dumazet 69*b6a84016SEric Dumazet return page ? page_address(page) : NULL; 70cbf6b1baSPaul Mundt } 71cbf6b1baSPaul Mundt 72cbf6b1baSPaul Mundt void free_thread_info(struct thread_info *ti) 73cbf6b1baSPaul Mundt { 740ea820cfSPaul Mundt free_thread_xstate(ti->task); 75cbf6b1baSPaul Mundt free_pages((unsigned long)ti, THREAD_SIZE_ORDER); 76cbf6b1baSPaul Mundt } 77cbf6b1baSPaul Mundt #endif /* THREAD_SHIFT < PAGE_SHIFT */ 780ea820cfSPaul Mundt 790ea820cfSPaul Mundt void arch_task_cache_init(void) 800ea820cfSPaul Mundt { 810ea820cfSPaul Mundt if (!xstate_size) 820ea820cfSPaul Mundt return; 830ea820cfSPaul Mundt 840ea820cfSPaul Mundt task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size, 850ea820cfSPaul Mundt __alignof__(union thread_xstate), 860ea820cfSPaul Mundt SLAB_PANIC | SLAB_NOTRACK, NULL); 870ea820cfSPaul Mundt } 880ea820cfSPaul Mundt 890ea820cfSPaul Mundt #ifdef CONFIG_SH_FPU_EMU 900ea820cfSPaul Mundt # define HAVE_SOFTFP 1 910ea820cfSPaul Mundt #else 920ea820cfSPaul Mundt # define HAVE_SOFTFP 0 930ea820cfSPaul Mundt #endif 940ea820cfSPaul Mundt 954a6feab0SPaul Mundt void __cpuinit init_thread_xstate(void) 960ea820cfSPaul Mundt { 970ea820cfSPaul Mundt if (boot_cpu_data.flags & CPU_HAS_FPU) 980ea820cfSPaul Mundt xstate_size = sizeof(struct sh_fpu_hard_struct); 990ea820cfSPaul Mundt else if (HAVE_SOFTFP) 1000ea820cfSPaul Mundt xstate_size = sizeof(struct sh_fpu_soft_struct); 1010ea820cfSPaul Mundt else 1020ea820cfSPaul Mundt xstate_size = 0; 1030ea820cfSPaul Mundt } 104