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
- Lines: 480
- Date:
Wed Aug 4 15:39:46 1999
- Orig file:
v2.3.12/linux/arch/sparc64/kernel/process.c
- Orig date:
Wed Jun 30 13:38:19 1999
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 = ¤t->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 = ¤t->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(¤t->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(¤t->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 = ¤t->tss;
+ struct thread_struct *t = ¤t->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 = ¤t->tss;
+ struct thread_struct *t = ¤t->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], ¤t->tss.float_regs[0], (sizeof(unsigned long) * 32));
- dump->fpu.fpstatus.fsr = current->tss.fsr;
+ memcpy(&dump->fpu.fpstatus.fregs.regs[0], ¤t->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)