xref: /linux/arch/sh/kernel/process.c (revision 4a6feab0ee5240c4bd5378d9f8a46b85718c68a7)
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