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