patch-2.3.26 linux/arch/ppc/kernel/process.c

Next file: linux/arch/ppc/kernel/setup.c
Previous file: linux/arch/ppc/kernel/ppc_ksyms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.25/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
@@ -45,6 +45,7 @@
 extern unsigned long _get_SP(void);
 
 struct task_struct *last_task_used_math = NULL;
+struct task_struct *last_task_used_altivec = NULL;
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
@@ -60,6 +61,7 @@
 #undef SHOW_TASK_SWITCHES 1
 #undef CHECK_STACK 1
 
+#if defined(CHECK_STACK)
 unsigned long
 kernel_stack_top(struct task_struct *tsk)
 {
@@ -72,28 +74,6 @@
 	return ((unsigned long)tsk) + sizeof(struct task_struct);
 }
 
-int
-dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
-{
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
-	memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
-	return 1;
-}
-
-void
-enable_kernel_fp(void)
-{
-#ifdef __SMP__
-	if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
-		giveup_fpu(current);
-	else
-		giveup_fpu(NULL);	/* just enables FP for kernel */
-#else
-	giveup_fpu(last_task_used_math);
-#endif /* __SMP__ */
-}
-
 /* check to make sure the kernel stack is healthy */
 int check_stack(struct task_struct *tsk)
 {
@@ -156,6 +136,29 @@
 	}
 	return(ret);
 }
+#endif /* defined(CHECK_STACK) */
+
+int
+dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+	if (regs->msr & MSR_FP)
+		giveup_fpu(current);
+	memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
+	return 1;
+}
+
+void
+enable_kernel_fp(void)
+{
+#ifdef __SMP__
+	if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
+		giveup_fpu(current);
+	else
+		giveup_fpu(NULL);	/* just enables FP for kernel */
+#else
+	giveup_fpu(last_task_used_math);
+#endif /* __SMP__ */
+}
 
 void
 _switch_to(struct task_struct *prev, struct task_struct *new,
@@ -187,9 +190,23 @@
 	 * every switch, just a save.
 	 *  -- Cort
 	 */
-	if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
+	if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) )
 		giveup_fpu(prev);
-
+	/*
+	 * If the previous thread 1) has some altivec regs it wants saved
+	 * (has bits in vrsave set) and 2) used altivec in the last quantum
+	 * (thus changing altivec regs) then save them.
+	 *
+	 * On SMP we always save/restore altivec regs just to avoid the
+	 * complexity of changing processors.
+	 *  -- Cort
+	 */
+	if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) &&
+	     prev->thread.vrsave )
+		giveup_altivec(prev);
+	if ( (new->last_processor != NO_PROC_ID) &&
+	     (new->last_processor != new->processor) && new->mm )
+		flush_tlb_mm(new->mm);
 	prev->last_processor = prev->processor;
 	current_set[smp_processor_id()] = new;
 #endif /* __SMP__ */
@@ -213,7 +230,8 @@
 	printk("TASK = %p[%d] '%s' ",
 	       current, current->pid, current->comm);
 	printk("Last syscall: %ld ", current->thread.last_syscall);
-	printk("\nlast math %p", last_task_used_math);
+	printk("\nlast math %p last altivec %p", last_task_used_math,
+	       last_task_used_altivec);
 	
 #ifdef __SMP__	
 	printk(" CPU: %d last CPU: %d", current->processor,current->last_processor);
@@ -243,12 +261,16 @@
 {
 	if (last_task_used_math == current)
 		last_task_used_math = NULL;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = NULL;
 }
 
 void flush_thread(void)
 {
 	if (last_task_used_math == current)
 		last_task_used_math = NULL;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = NULL;
 }
 
 void
@@ -305,11 +327,18 @@
 	 */
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
-
 	memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
 	p->thread.fpscr = current->thread.fpscr;
 	childregs->msr &= ~MSR_FP;
 
+	if (regs->msr & MSR_VEC)
+		giveup_altivec(current);
+	if ( p->thread.vrsave )
+		memcpy(&p->thread.vrf, &current->thread.vrf, sizeof(p->thread.vrf));
+	p->thread.vscr = current->thread.vscr;
+	p->thread.vrsave = current->thread.vrsave;
+	childregs->msr &= ~MSR_VEC;
+
 #ifdef __SMP__
 	p->last_processor = NO_PROC_ID;
 #endif /* __SMP__ */
@@ -367,6 +396,8 @@
 	shove_aux_table(sp);
 	if (last_task_used_math == current)
 		last_task_used_math = 0;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = 0;
 	current->thread.fpscr = 0;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)