patch-2.3.13 linux/arch/sparc64/kernel/process.c

Next file: linux/arch/sparc64/kernel/psycho.c
Previous file: linux/arch/sparc64/kernel/ioctl32.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.95 1999/06/28 08:48:51 davem Exp $
+/*  $Id: process.c,v 1.99 1999/08/04 03:19:20 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -46,7 +46,7 @@
 /*
  * the idle loop on a Sparc... ;)
  */
-asmlinkage int sys_idle(void)
+int cpu_idle(void)
 {
 	if (current->pid != 0)
 		return -EPERM;
@@ -77,7 +77,7 @@
  */
 #define idle_me_harder()	(cpu_data[current->processor].idle_volume += 1)
 #define unidle_me()		(cpu_data[current->processor].idle_volume = 0)
-asmlinkage int cpu_idle(void)
+int cpu_idle(void)
 {
 	current->priority = 0;
 	current->counter = -100;
@@ -99,15 +99,6 @@
 	}
 }
 
-asmlinkage int sys_idle(void)
-{
-	if(current->pid != 0)
-		return -EPERM;
-
-	cpu_idle();
-	return 0;
-}
-
 #endif
 
 extern char reboot_command [];
@@ -189,7 +180,7 @@
 	struct reg_window r_w;
 	mm_segment_t old_fs;
 
-	if ((regs->tstate & TSTATE_PRIV) || !(current->tss.flags & SPARC_FLAG_32BIT)) {
+	if ((regs->tstate & TSTATE_PRIV) || !(current->thread.flags & SPARC_FLAG_32BIT)) {
 		__asm__ __volatile__ ("flushw");
 		rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
 		if (!(regs->tstate & TSTATE_PRIV)) {
@@ -369,90 +360,96 @@
 	       regs->u_regs[15]);
 }
 
-void show_thread(struct thread_struct *tss)
+void show_thread(struct thread_struct *thread)
 {
 	int i;
 
 #if 0
-	printk("kregs:             0x%016lx\n", (unsigned long)tss->kregs);
-	show_regs(tss->kregs);
+	printk("kregs:             0x%016lx\n", (unsigned long)thread->kregs);
+	show_regs(thread->kregs);
 #endif	
-	printk("sig_address:       0x%016lx\n", tss->sig_address);
-	printk("sig_desc:          0x%016lx\n", tss->sig_desc);
-	printk("ksp:               0x%016lx\n", tss->ksp);
+	printk("sig_address:       0x%016lx\n", thread->sig_address);
+	printk("sig_desc:          0x%016lx\n", thread->sig_desc);
+	printk("ksp:               0x%016lx\n", thread->ksp);
 
-	if (tss->w_saved) {
+	if (thread->w_saved) {
 		for (i = 0; i < NSWINS; i++) {
-			if (!tss->rwbuf_stkptrs[i])
+			if (!thread->rwbuf_stkptrs[i])
 				continue;
 			printk("reg_window[%d]:\n", i);
-			printk("stack ptr:         0x%016lx\n", tss->rwbuf_stkptrs[i]);
+			printk("stack ptr:         0x%016lx\n", thread->rwbuf_stkptrs[i]);
 		}
-		printk("w_saved:           0x%04x\n", tss->w_saved);
+		printk("w_saved:           0x%04x\n", thread->w_saved);
 	}
 
-	printk("flags:             0x%08x\n", tss->flags);
-	printk("current_ds:        0x%x\n", tss->current_ds.seg);
+	printk("flags:             0x%08x\n", thread->flags);
+	printk("current_ds:        0x%x\n", thread->current_ds.seg);
 }
 
 /* Free current thread data structures etc.. */
 void exit_thread(void)
 {
-	if (current->tss.utraps) {
-		if (current->tss.utraps[0] < 2)
-			kfree (current->tss.utraps);
+	struct thread_struct *t = &current->thread;
+
+	if (t->utraps) {
+		if (t->utraps[0] < 2)
+			kfree (t->utraps);
 		else
-			current->tss.utraps[0]--;
+			t->utraps[0]--;
 	}
 
 	/* Turn off performance counters if on. */
-	if (current->tss.flags & SPARC_FLAG_PERFCTR) {
-		current->tss.user_cntd0 =
-			current->tss.user_cntd1 = NULL;
-		current->tss.pcr_reg = 0;
-		current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+	if (t->flags & SPARC_FLAG_PERFCTR) {
+		t->user_cntd0 = t->user_cntd1 = NULL;
+		t->pcr_reg = 0;
+		t->flags &= ~(SPARC_FLAG_PERFCTR);
 		write_pcr(0);
 	}
 }
 
 void flush_thread(void)
 {
-	if (!(current->tss.flags & SPARC_FLAG_KTHREAD))
-		flush_user_windows();
-	current->tss.w_saved = 0;
+	struct thread_struct *t = &current->thread;
+
+	if (current->mm) {
+		if (t->flags & SPARC_FLAG_32BIT) {
+			struct mm_struct *mm = current->mm;
+			pgd_t *pgd0 = &mm->pgd[0];
+			unsigned long pgd_cache;
+
+			if (pgd_none(*pgd0)) {
+				pmd_t *page = get_pmd_fast();
+				if (!page)
+					(void) get_pmd_slow(pgd0, 0);
+				else
+					pgd_set(pgd0, page);
+			}
+			pgd_cache = pgd_val(*pgd0) << 11UL;
+			__asm__ __volatile__("stxa %0, [%1] %2"
+					     : /* no outputs */
+					     : "r" (pgd_cache),
+					       "r" (TSB_REG),
+					       "i" (ASI_DMMU));
+		}
+	}
+	t->w_saved = 0;
 
 	/* Turn off performance counters if on. */
-	if (current->tss.flags & SPARC_FLAG_PERFCTR) {
-		current->tss.user_cntd0 =
-			current->tss.user_cntd1 = NULL;
-		current->tss.pcr_reg = 0;
-		current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+	if (t->flags & SPARC_FLAG_PERFCTR) {
+		t->user_cntd0 = t->user_cntd1 = NULL;
+		t->pcr_reg = 0;
+		t->flags &= ~(SPARC_FLAG_PERFCTR);
 		write_pcr(0);
 	}
 
-	/* No new signal delivery by default. */
-	current->tss.new_signal = 0;
-	current->tss.fpsaved[0] = 0;
+	/* Clear FPU register state. */
+	t->fpsaved[0] = 0;
 	
-	/* Now, this task is no longer a kernel thread. */
-	current->tss.current_ds = USER_DS;
-	if(current->tss.flags & SPARC_FLAG_KTHREAD) {
-		current->tss.flags &= ~SPARC_FLAG_KTHREAD;
+	if (t->current_ds.seg != ASI_AIUS)
+		set_fs(USER_DS);
 
-		/* exec_mmap() set context to NO_CONTEXT, here is
-		 * where we grab a new one.
-		 */
-		activate_context(current);
-	}
-	if (current->tss.flags & SPARC_FLAG_32BIT)
-		__asm__ __volatile__("stxa %%g0, [%0] %1"
-				     : /* no outputs */
-				     : "r"(TSB_REG), "i"(ASI_DMMU));
-	__cli();
-	current->tss.ctx = current->mm->context & 0x3ff;
-	spitfire_set_secondary_context (current->tss.ctx);
-	__asm__ __volatile__("flush %g6");
-	__sti();
+	/* Init new signal delivery disposition. */
+	t->flags &= ~SPARC_FLAG_NEWSIGNALS;
 }
 
 /* It's a bit more tricky when 64-bit tasks are involved... */
@@ -460,12 +457,7 @@
 {
 	unsigned long fp, distance, rval;
 
-	/* do_fork() grabs the parent semaphore, we must release it
-	 * temporarily so we can build the child clone stack frame
-	 * without deadlocking.
-	 */
-	up(&current->mm->mmap_sem);
-	if(!(current->tss.flags & SPARC_FLAG_32BIT)) {
+	if(!(current->thread.flags & SPARC_FLAG_32BIT)) {
 		csp += STACK_BIAS;
 		psp += STACK_BIAS;
 		__get_user(fp, &(((struct reg_window *)psp)->ins[6]));
@@ -482,7 +474,7 @@
 	rval = (csp - distance);
 	if(copy_in_user(rval, psp, distance))
 		rval = 0;
-	else if(current->tss.flags & SPARC_FLAG_32BIT) {
+	else if(current->thread.flags & SPARC_FLAG_32BIT) {
 		if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
 			rval = 0;
 	} else {
@@ -492,47 +484,46 @@
 		else
 			rval = rval - STACK_BIAS;
 	}
-	down(&current->mm->mmap_sem);
 
 	return rval;
 }
 
 /* Standard stuff. */
 static inline void shift_window_buffer(int first_win, int last_win,
-				       struct thread_struct *tp)
+				       struct thread_struct *t)
 {
 	int i;
 
 	for(i = first_win; i < last_win; i++) {
-		tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
-		memcpy(&tp->reg_window[i], &tp->reg_window[i+1],
+		t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
+		memcpy(&t->reg_window[i], &t->reg_window[i+1],
 		       sizeof(struct reg_window));
 	}
 }
 
 void synchronize_user_stack(void)
 {
-	struct thread_struct *tp = &current->tss;
+	struct thread_struct *t = &current->thread;
 	unsigned long window;
 
 	flush_user_windows();
-	if((window = tp->w_saved) != 0) {
+	if((window = t->w_saved) != 0) {
 		int winsize = REGWIN_SZ;
 		int bias = 0;
 
-		if(tp->flags & SPARC_FLAG_32BIT)
+		if(t->flags & SPARC_FLAG_32BIT)
 			winsize = REGWIN32_SZ;
 		else
 			bias = STACK_BIAS;
 
 		window -= 1;
 		do {
-			unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
-			struct reg_window *rwin = &tp->reg_window[window];
+			unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
+			struct reg_window *rwin = &t->reg_window[window];
 
 			if(!copy_to_user((char *)sp, rwin, winsize)) {
-				shift_window_buffer(window, tp->w_saved - 1, tp);
-				tp->w_saved--;
+				shift_window_buffer(window, t->w_saved - 1, t);
+				t->w_saved--;
 			}
 		} while(window--);
 	}
@@ -540,28 +531,28 @@
 
 void fault_in_user_windows(struct pt_regs *regs)
 {
-	struct thread_struct *tp = &current->tss;
+	struct thread_struct *t = &current->thread;
 	unsigned long window;
 	int winsize = REGWIN_SZ;
 	int bias = 0;
 
-	if(tp->flags & SPARC_FLAG_32BIT)
+	if(t->flags & SPARC_FLAG_32BIT)
 		winsize = REGWIN32_SZ;
 	else
 		bias = STACK_BIAS;
 	flush_user_windows();
-	window = tp->w_saved;
+	window = t->w_saved;
 	if(window != 0) {
 		window -= 1;
 		do {
-			unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
-			struct reg_window *rwin = &tp->reg_window[window];
+			unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
+			struct reg_window *rwin = &t->reg_window[window];
 
 			if(copy_to_user((char *)sp, rwin, winsize))
 				goto barf;
 		} while(window--);
 	}
-	current->tss.w_saved = 0;
+	t->w_saved = 0;
 	return;
 barf:
 	do_exit(SIGILL);
@@ -582,65 +573,73 @@
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		struct task_struct *p, struct pt_regs *regs)
 {
+	struct thread_struct *t = &p->thread;
 	char *child_trap_frame;
 
 	/* Calculate offset to stack_frame & pt_regs */
 	child_trap_frame = ((char *)p) + ((PAGE_SIZE << 1) - (TRACEREG_SZ+REGWIN_SZ));
 	memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
-	p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
-	p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
-	p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP;
-	p->tss.fpsaved[0] = 0;
-	p->mm->segments = (void *) 0;
+	t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
+	t->flags |= SPARC_FLAG_NEWCHILD;
+	t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
+	t->cwp = (regs->tstate + 1) & TSTATE_CWP;
+	t->fpsaved[0] = 0;
 	if(regs->tstate & TSTATE_PRIV) {
 		/* Special case, if we are spawning a kernel thread from
 		 * a userspace task (via KMOD, NFS, or similar) we must
 		 * disable performance counters in the child because the
 		 * address space and protection realm are changing.
 		 */
-		if (current->tss.flags & SPARC_FLAG_PERFCTR) {
-			p->tss.user_cntd0 =
-				p->tss.user_cntd1 = NULL;
-			p->tss.pcr_reg = 0;
-			p->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+		if (t->flags & SPARC_FLAG_PERFCTR) {
+			t->user_cntd0 = t->user_cntd1 = NULL;
+			t->pcr_reg = 0;
+			t->flags &= ~(SPARC_FLAG_PERFCTR);
 		}
-		p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
-		p->tss.flags |= (SPARC_FLAG_KTHREAD | SPARC_FLAG_NEWCHILD);
-		p->tss.current_ds = KERNEL_DS;
-		p->tss.ctx = 0;
-		__asm__ __volatile__("flushw");
-		memcpy((void *)(p->tss.ksp + STACK_BIAS),
+		t->kregs->u_regs[UREG_FP] = p->thread.ksp;
+		t->current_ds = KERNEL_DS;
+		flush_register_windows();
+		memcpy((void *)(t->ksp + STACK_BIAS),
 		       (void *)(regs->u_regs[UREG_FP] + STACK_BIAS),
 		       sizeof(struct reg_window));
-		p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
+		t->kregs->u_regs[UREG_G6] = (unsigned long) p;
 	} else {
-		if(current->tss.flags & SPARC_FLAG_32BIT) {
+		if(t->flags & SPARC_FLAG_32BIT) {
 			sp &= 0x00000000ffffffffUL;
 			regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 		}
-		p->tss.kregs->u_regs[UREG_FP] = sp;
-		p->tss.flags = (p->tss.flags & ~SPARC_FLAG_KTHREAD) |
-			SPARC_FLAG_NEWCHILD;
-		p->tss.current_ds = USER_DS;
-		p->tss.ctx = (p->mm->context & 0x3ff);
+		t->kregs->u_regs[UREG_FP] = sp;
+		t->current_ds = USER_DS;
 		if (sp != regs->u_regs[UREG_FP]) {
 			unsigned long csp;
 
 			csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
 			if(!csp)
 				return -EFAULT;
-			p->tss.kregs->u_regs[UREG_FP] = csp;
+			t->kregs->u_regs[UREG_FP] = csp;
 		}
-		if (p->tss.utraps)
-			p->tss.utraps[0]++;
+		if (t->utraps)
+			t->utraps[0]++;
 	}
 
 	/* Set the return value for the child. */
-	p->tss.kregs->u_regs[UREG_I0] = current->pid;
-	p->tss.kregs->u_regs[UREG_I1] = 1;
+	t->kregs->u_regs[UREG_I0] = current->pid;
+	t->kregs->u_regs[UREG_I1] = 1;
 
 	/* Set the second return value for the parent. */
 	regs->u_regs[UREG_I1] = 0;
+#if 0
+	printk("\ncopy_thread: c(%p[mm(%p:%p)]) p(%p[mm(%p:%p)])\n",
+	       current, current->mm, current->active_mm,
+	       p, p->mm, p->active_mm);
+	printk("copy_thread: c MM_ctx(%016lx) MM_pgd(%016lx)\n",
+	       (current->mm ? current->mm->context : 0),
+	       (current->mm ? pgd_val(current->mm->pgd[0]) : 0));
+	printk("copy_thread: p MM_ctx(%016lx) MM_pgd(%08x)\n",
+	       (p->mm ? p->mm->context : 0),
+	       (p->mm ? pgd_val(p->mm->pgd[0]) : 0));
+	printk("copy_thread: c->flags(%x) p->flags(%x) ",
+	       current->thread.flags, p->thread.flags);
+#endif
 	return 0;
 }
 
@@ -703,10 +702,10 @@
 	dump->u_dsize &= ~(PAGE_SIZE - 1);
 	first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
 	dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
-	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->tss.float_regs[0], (sizeof(unsigned long) * 32));
-	dump->fpu.fpstatus.fsr = current->tss.fsr;
+	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
+	dump->fpu.fpstatus.fsr = current->thread.fsr;
 	dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
-	dump->sigcode = current->tss.sig_desc;
+	dump->sigcode = current->thread.sig_desc;
 #endif	
 }
 
@@ -729,9 +728,9 @@
 int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 {
 	unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
-	unsigned long fprs = current->tss.fpsaved[0];
+	unsigned long fprs = current->thread.fpsaved[0];
 
-	if ((current->tss.flags & SPARC_FLAG_32BIT) != 0) {
+	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
 		elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
 
 		if (fprs & FPRS_DL)
@@ -745,7 +744,7 @@
 		memset(&fpregs32->pr_q[0], 0,
 		       (sizeof(unsigned int) * 64));
 		if (fprs & FPRS_FEF) {
-			fpregs32->pr_fsr = (unsigned int) current->tss.xfsr[0];
+			fpregs32->pr_fsr = (unsigned int) current->thread.xfsr[0];
 			fpregs32->pr_en = 1;
 		} else {
 			fpregs32->pr_fsr = 0;
@@ -765,8 +764,8 @@
 			memset(&fpregs->pr_regs[16], 0,
 			       sizeof(unsigned int) * 32);
 		if(fprs & FPRS_FEF) {
-			fpregs->pr_fsr = current->tss.xfsr[0];
-			fpregs->pr_gsr = current->tss.gsr[0];
+			fpregs->pr_fsr = current->thread.xfsr[0];
+			fpregs->pr_gsr = current->thread.gsr[0];
 		} else {
 			fpregs->pr_fsr = fpregs->pr_gsr = 0;
 		}
@@ -784,6 +783,8 @@
 	int error, base = 0;
 	char *filename;
 
+	/* User register window flush is done by entry.S */
+
 	/* Check for indirect call. */
 	if(regs->u_regs[UREG_G1] == 0)
 		base = 1;
@@ -798,8 +799,8 @@
 	putname(filename);
 	if(!error) {
 		fprs_write(0);
-		current->tss.xfsr[0] = 0;
-		current->tss.fpsaved[0] = 0;
+		current->thread.xfsr[0] = 0;
+		current->thread.fpsaved[0] = 0;
 		regs->tstate &= ~TSTATE_PEF;
 	}
 out:

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