summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/process.c')
-rw-r--r--arch/sparc64/kernel/process.c126
1 files changed, 54 insertions, 72 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index c0058afd9..373d122c3 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,9 +1,9 @@
-/* $Id: process.c,v 1.52 1998/03/29 12:57:53 ecd Exp $
+/* $Id: process.c,v 1.70 1998/08/04 20:49:15 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
/*
@@ -52,8 +52,8 @@ asmlinkage int sys_idle(void)
return -EPERM;
/* endless idle loop with no priority at all */
- current->priority = -100;
- current->counter = -100;
+ current->priority = 0;
+ current->counter = 0;
for (;;) {
check_pgt_cache();
run_task_queue(&tq_scheduler);
@@ -69,17 +69,13 @@ asmlinkage int sys_idle(void)
*/
asmlinkage int cpu_idle(void)
{
- current->priority = -100;
+ current->priority = 0;
while(1) {
check_pgt_cache();
- if(tq_scheduler) {
- lock_kernel();
- run_task_queue(&tq_scheduler);
- unlock_kernel();
- }
+ run_task_queue(&tq_scheduler);
barrier();
- current->counter = -100;
- if(need_resched)
+ current->counter = 0;
+ if(current->need_resched)
schedule();
barrier();
}
@@ -99,18 +95,18 @@ asmlinkage int sys_idle(void)
extern char reboot_command [];
#ifdef CONFIG_SUN_CONSOLE
-extern void console_restore_palette (void);
+extern void (*prom_palette)(int);
extern int serial_console;
#endif
void machine_halt(void)
{
sti();
- udelay(8000);
+ mdelay(8);
cli();
#ifdef CONFIG_SUN_CONSOLE
- if (!serial_console)
- console_restore_palette ();
+ if (!serial_console && prom_palette)
+ prom_palette (1);
#endif
prom_halt();
panic("Halt failed!");
@@ -121,14 +117,14 @@ void machine_restart(char * cmd)
char *p;
sti();
- udelay(8000);
+ mdelay(8);
cli();
p = strchr (reboot_command, '\n');
if (p) *p = 0;
#ifdef CONFIG_SUN_CONSOLE
- if (!serial_console)
- console_restore_palette ();
+ if (!serial_console && prom_palette)
+ prom_palette (1);
#endif
if (cmd)
prom_reboot(cmd);
@@ -272,7 +268,7 @@ void __show_regs(struct pt_regs * regs)
smp_processor_id(), local_irq_count,
atomic_read(&global_irq_count));
#endif
- printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate,
+ printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate,
regs->tpc, regs->tnpc, regs->y);
printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
@@ -295,22 +291,22 @@ void __show_regs(struct pt_regs * regs)
#ifdef VERBOSE_SHOWREGS
static void idump_from_user (unsigned int *pc)
{
- int i;
- int code;
-
- if((((unsigned long) pc) & 3))
- return;
-
- pc -= 3;
- for(i = -3; i < 6; i++) {
- get_user(code, pc);
- printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
- pc++;
- }
- printk("\n");
+ int i;
+ int code;
+
+ if((((unsigned long) pc) & 3))
+ return;
+
+ pc -= 3;
+ for(i = -3; i < 6; i++) {
+ get_user(code, pc);
+ printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
+ pc++;
+ }
+ printk("\n");
}
#endif
-
+
void show_regs(struct pt_regs *regs)
{
#ifdef VERBOSE_SHOWREGS
@@ -339,7 +335,7 @@ void show_regs(struct pt_regs *regs)
void show_regs32(struct pt_regs32 *regs)
{
- printk("PSR: %08x PC: %08x NPC: %08x Y: %08x\n", regs->psr,
+ printk("PSR: %08x PC: %08x NPC: %08x Y: %08x\n", regs->psr,
regs->pc, regs->npc, regs->y);
printk("g0: %08x g1: %08x g2: %08x g3: %08x\n",
regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
@@ -366,7 +362,6 @@ void show_thread(struct thread_struct *tss)
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("kpc: 0x%08x\n", tss->kpc);
if (tss->w_saved) {
for (i = 0; i < NSWINS; i++) {
@@ -378,10 +373,6 @@ void show_thread(struct thread_struct *tss)
printk("w_saved: 0x%04x\n", tss->w_saved);
}
- printk("sstk_info.stack: 0x%016lx\n",
- (unsigned long)tss->sstk_info.the_stack);
- printk("sstk_info.status: 0x%016lx\n",
- (unsigned long)tss->sstk_info.cur_status);
printk("flags: 0x%08x\n", tss->flags);
printk("current_ds: 0x%016lx\n", tss->current_ds.seg);
}
@@ -400,13 +391,10 @@ void exit_thread(void)
void flush_thread(void)
{
current->tss.w_saved = 0;
- current->tss.sstk_info.cur_status = 0;
- current->tss.sstk_info.the_stack = 0;
/* No new signal delivery by default. */
current->tss.new_signal = 0;
- current->tss.flags &= ~(SPARC_FLAG_USEDFPU | SPARC_FLAG_USEDFPUL |
- SPARC_FLAG_USEDFPUU);
+ current->tss.fpsaved[0] = 0;
/* Now, this task is no longer a kernel thread. */
current->tss.current_ds = USER_DS;
@@ -422,7 +410,9 @@ void flush_thread(void)
get_mmu_context(current);
spin_unlock(&scheduler_lock);
}
- current->tss.ctx = current->mm->context & 0x1fff;
+ if (current->tss.flags & SPARC_FLAG_32BIT)
+ __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r"(TSB_REG), "i"(ASI_DMMU));
+ current->tss.ctx = current->mm->context & 0x3ff;
spitfire_set_secondary_context (current->tss.ctx);
__asm__ __volatile__("flush %g6");
}
@@ -438,6 +428,13 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
__get_user(fp, &(((struct reg_window *)psp)->ins[6]));
} else
__get_user(fp, &(((struct reg_window32 *)psp)->ins[6]));
+
+ /* Now 8-byte align the stack as this is mandatory in the
+ * Sparc ABI due to how register windows work. This hides
+ * the restriction from thread libraries etc. -DaveM
+ */
+ csp &= ~7UL;
+
distance = fp - psp;
rval = (csp - distance);
if(copy_in_user(rval, psp, distance))
@@ -537,38 +534,21 @@ barf:
* allocate the task_struct and kernel stack in
* do_fork().
*/
-#ifdef __SMP__
-extern void ret_from_smpfork(void);
-#else
-extern void ret_from_syscall(void);
-#endif
-
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct task_struct *p, struct pt_regs *regs)
{
- unsigned long stack_offset;
char *child_trap_frame;
- int tframe_size;
/* Calculate offset to stack_frame & pt_regs */
- stack_offset = (((PAGE_SIZE << 1) -
- ((sizeof(unsigned int)*64) + (2*sizeof(unsigned long)))) &
- ~(64 - 1)) - (TRACEREG_SZ+REGWIN_SZ);
- tframe_size = (TRACEREG_SZ + REGWIN_SZ) +
- (sizeof(unsigned int) * 64) + (2 * sizeof(unsigned long));
- child_trap_frame = ((char *)p) + stack_offset;
- memcpy(child_trap_frame, (((struct reg_window *)regs)-1), tframe_size);
+ 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;
-#ifdef __SMP__
- p->tss.kpc = ((unsigned int) ((unsigned long) ret_from_smpfork)) - 0x8;
-#else
- p->tss.kpc = ((unsigned int) ((unsigned long) ret_from_syscall)) - 0x8;
-#endif
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;
if(regs->tstate & TSTATE_PRIV) {
p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
- p->tss.flags |= SPARC_FLAG_KTHREAD;
+ p->tss.flags |= (SPARC_FLAG_KTHREAD | SPARC_FLAG_NEWCHILD);
p->tss.current_ds = KERNEL_DS;
p->tss.ctx = 0;
__asm__ __volatile__("flushw");
@@ -578,13 +558,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
} else {
if(current->tss.flags & SPARC_FLAG_32BIT) {
- sp &= 0x00000000ffffffff;
- regs->u_regs[UREG_FP] &= 0x00000000ffffffff;
+ sp &= 0x00000000ffffffffUL;
+ regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
}
p->tss.kregs->u_regs[UREG_FP] = sp;
- p->tss.flags &= ~SPARC_FLAG_KTHREAD;
+ p->tss.flags = (p->tss.flags & ~SPARC_FLAG_KTHREAD) |
+ SPARC_FLAG_NEWCHILD;
p->tss.current_ds = USER_DS;
- p->tss.ctx = (p->mm->context & 0x1fff);
+ p->tss.ctx = (p->mm->context & 0x3ff);
if (sp != regs->u_regs[UREG_FP]) {
unsigned long csp;
@@ -667,7 +648,8 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
putname(filename);
if(!error) {
fprs_write(0);
- regs->fprs = 0;
+ current->tss.xfsr[0] = 0;
+ current->tss.fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF;
}
out: