diff --git a/sys/arch/acorn26/acorn26/cpuswitch.c b/sys/arch/acorn26/acorn26/cpuswitch.c index 4b14db675a8e..9dbeeb5216b4 100644 --- a/sys/arch/acorn26/acorn26/cpuswitch.c +++ b/sys/arch/acorn26/acorn26/cpuswitch.c @@ -1,4 +1,4 @@ -/* $NetBSD: cpuswitch.c,v 1.10 2007/03/04 05:59:03 christos Exp $ */ +/* $NetBSD: cpuswitch.c,v 1.11 2007/06/01 07:04:53 skrll Exp $ */ /* * Copyright (c) 2000 Ben Harris. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cpuswitch.c,v 1.10 2007/03/04 05:59:03 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpuswitch.c,v 1.11 2007/06/01 07:04:53 skrll Exp $"); #include "opt_lockdebug.h" @@ -48,100 +48,24 @@ __KERNEL_RCSID(0, "$NetBSD: cpuswitch.c,v 1.10 2007/03/04 05:59:03 christos Exp #include #include #include +#include #include #include #include -void idle(void); - struct pcb *curpcb; -/* - * Idle - */ -void -idle() -{ - - sched_unlock_idle(); - spl0(); - while (sched_whichqs == 0) - continue; - splhigh(); - sched_lock_idle(); -} - extern int want_resched; /* XXX should be in */ -/* - * Find the highest-priority runnable process and switch to it. - * - * If l1 is NULL, we're switching away from a dying process. We hope it's - * safe to run on its stack until the switch. - */ -int -cpu_switch(struct lwp *l1, struct lwp *newl) -{ - int which; - struct prochd *q; - struct lwp *l2; - struct proc *p2; - struct switchframe *dummy; - /* - * We enter here with interrupts blocked and sched_lock held. - */ - -#if 0 - printf("cpu_switch: %p ->", l1); -#endif - curlwp = NULL; - curpcb = NULL; - while (sched_whichqs == 0) - idle(); - which = ffs(sched_whichqs) - 1; - q = &sched_qs[which]; - l2 = q->ph_link; - remrunqueue(l2); - want_resched = 0; - sched_unlock_idle(); - /* p->p_cpu initialized in fork1() for single-processor */ - l2->l_stat = LSONPROC; - curlwp = l2; - curpcb = &curlwp->l_addr->u_pcb; -#if 0 - printf(" %p\n", l2); -#endif - if (l2 == l1) - return (0); - if (l1 != NULL) - pmap_deactivate(l1); - pmap_activate(l2); - - /* Check for Restartable Atomic Sequences. */ - p2 = l2->l_proc; - if (!LIST_EMPTY(&p2->p_raslist)) { - struct trapframe *tf = l2->l_addr->u_pcb.pcb_tf; - void *pc; - - pc = ras_lookup(p2, (void *)(tf->tf_r15 & R15_PC)); - if (pc != (void *) -1) - tf->tf_r15 = (tf->tf_r15 & ~R15_PC) | (register_t) pc; - } - - cpu_loswitch(l1 ? &l1->l_addr->u_pcb.pcb_sf : &dummy, - l2->l_addr->u_pcb.pcb_sf); - /* We only get back here after the other process has run. */ - return (1); -} - /* * Switch to the indicated lwp. */ -void -cpu_switchto(struct lwp *old, struct lwp *new) +lwp_t * +cpu_switchto(lwp_t *old, lwp_t *new) { + struct proc *p2; /* * We enter here with interrupts blocked and sched_lock held. @@ -150,14 +74,23 @@ cpu_switchto(struct lwp *old, struct lwp *new) #if 0 printf("cpu_switchto: %p -> %p", old, new); #endif - want_resched = 0; - /* p->p_cpu initialized in fork1() for single-processor */ - new->l_stat = LSONPROC; + curlwp = new; curpcb = &curlwp->l_addr->u_pcb; - sched_unlock_idle(); - pmap_deactivate(old); - pmap_activate(new); - cpu_loswitch(&old->l_addr->u_pcb.pcb_sf, new->l_addr->u_pcb.pcb_sf); - /* We only get back here after the other process has run. */ + + if ((new->l_flag & LW_SYSTEM) == 0) { + /* Check for Restartable Atomic Sequences. */ + p2 = new->l_proc; + if (!LIST_EMPTY(&p2->p_raslist)) { + struct trapframe *tf = new->l_addr->u_pcb.pcb_tf; + void *pc; + + pc = ras_lookup(p2, (void *)(tf->tf_r15 & R15_PC)); + if (pc != (void *) -1) + tf->tf_r15 = (tf->tf_r15 & ~R15_PC) | + (register_t) pc; + } + } + + return cpu_loswitch(old, new); } diff --git a/sys/arch/acorn26/acorn26/genassym.cf b/sys/arch/acorn26/acorn26/genassym.cf index 9fff8758839d..9214f9eff699 100644 --- a/sys/arch/acorn26/acorn26/genassym.cf +++ b/sys/arch/acorn26/acorn26/genassym.cf @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.7 2006/10/08 12:22:35 bjh21 Exp $ +# $NetBSD: genassym.cf,v 1.8 2007/06/01 07:04:53 skrll Exp $ # # Copyright (c) 1999 Ben Harris # All rights reserved. @@ -47,6 +47,7 @@ endif define __PROG26 1 define U_PCB offsetof(struct user, u_pcb) +define PCB_SF offsetof(struct pcb, pcb_sf) define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) define L_ADDR offsetof(struct lwp, l_addr) @@ -73,4 +74,3 @@ define EFS_RX_FLAGS offsetof(struct eca_fiqstate, efs_rx_flags) define EFS_RX_MYADDR offsetof(struct eca_fiqstate, efs_rx_myaddr) define EFS_TX_CURMBUF offsetof(struct eca_fiqstate, efs_tx_curmbuf) endif - diff --git a/sys/arch/acorn26/acorn26/locore.S b/sys/arch/acorn26/acorn26/locore.S index dae12eb4d48f..04d83bff2cec 100644 --- a/sys/arch/acorn26/acorn26/locore.S +++ b/sys/arch/acorn26/acorn26/locore.S @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.11 2007/02/28 23:47:09 bjh21 Exp $ */ +/* $NetBSD: locore.S,v 1.12 2007/06/01 07:04:54 skrll Exp $ */ /* * Copyright (c) 1998, 1999, 2000 Ben Harris * Copyright (C) 1994-1997 Mark Brinicombe @@ -383,44 +383,62 @@ ENTRY_NP(get_r15) mov r0, r14 mov r15, lr - /* - * Low-level context-switch operation. cpu_switch() is in C -- this - * just handles the bits that can't be done in C. - * - * void cpu_loswitch(struct switchframe **fromp, - * struct switchframe *to) - * - * We leave a switchframe on the stack pointed to by fromp, - * and return to the context in to. This should be called in - * splhigh(); - */ -/* LINTSTUB: Func: void cpu_loswitch(struct switchframe **fromp, struct switchframe *to) */ +/* + * Low-level context-switch operation. cpu_switchto() is in C -- this + * just handles the bits that can't be done in C. + * + * struct lwp *cpu_loswitch(struct lwp *oldl, struct lwp *newl) + * + * We leave a switchframe on the stack pointed to by and save this in + * oldl's PCB, and return to the context in newl. This should be called at + * splhigh(); + * + * r0 and r1 must be left intact as they're needed by lwp_startup in + * lwp_trampoline + */ +/* LINTSTUB: Func: struct lwp *cpu_loswitch(struct lwp *oldl, struct lwp *newl) */ ENTRY(cpu_loswitch) + teq r0, #0x00000000 + beq Lswitch_exited + + ldr r3, [r0, #(L_ADDR)] + add r3, r3, #PCB_SF /* r3 = &old->l_addr->u_pcb.pcb_sf */ + mov r2, sp /* Temporary stack pointer */ stmfd r2!, {r4-r11, r13-r14} /* Save all relevant registers */ - str r2, [r0] /* Save switchframe pointer */ - ldmfd r1, {r4-r11, r13-r14} /* Restore from old switchframe */ + str r2, [r3] /* Save switchframe pointer */ + +Lswitch_exited: + + ldr r2, [r1, #(L_ADDR)] + ldr r3, [r2, #(PCB_SF)] /* r3 = new->l_addr->u_pcb.pcb_sf; */ + + ldmfd r3, {r4-r11, r13-r14} /* Restore from old switchframe */ mov pc, r14 /* and return */ - /* - * This funny little routine implements starting a process. - * It's called by cpu_loswitch returning from a faked - * switchframe set up by cpu_fork(), and gets - * the function it's meant to enter passed in R4 with its - * argument in R5. If that function's NULL, or if it returns, - * we hope there's a trapframe on the stack that'll take us - * back to userland. - */ -ENTRY(proc_trampoline) +/* + * This funny little routine implements starting a process. + * It's called by cpu_loswitch returning from a faked + * switchframe set up by cpu_lwp_fork(), and gets + * the function it's meant to enter passed in R4 with its + * argument in R5. If that function's NULL, or if it returns, + * we hope there's a trapframe on the stack that'll take us + * back to userland. + * + * cpu_loswitch also ensures that r0 is oldl and r1 is newl + * for our call to lwp_startup. + */ +ENTRY(lwp_trampoline) mov fp, #0 /* Tie knot in top of stack */ + bl _C_LABEL(lwp_startup) mov r0, #0 - bl _C_LABEL(lowerspl) /* spl0() */ + bl _C_LABEL(lowerspl) /* spl0() */ cmp r4, #0 /* Function to call? */ - beq Lproc_trampoline_nofunc + beq Llwp_trampoline_nofunc mov r0, r5 mov r14, pc /* Save return address */ mov pc, r4 /* Call function */ -Lproc_trampoline_nofunc: +Llwp_trampoline_nofunc: b pull_trapframe /* LINTSTUB: Func: int setjmp(label_t *l) */ @@ -444,4 +462,4 @@ ENTRY(cpu_Debugger) ldmfd r13!, {pc} #endif -RCSID("$NetBSD: locore.S,v 1.11 2007/02/28 23:47:09 bjh21 Exp $") +RCSID("$NetBSD: locore.S,v 1.12 2007/06/01 07:04:54 skrll Exp $") diff --git a/sys/arch/acorn26/acorn26/machdep.c b/sys/arch/acorn26/acorn26/machdep.c index 4607ff495eb4..c4f9a5b531e0 100644 --- a/sys/arch/acorn26/acorn26/machdep.c +++ b/sys/arch/acorn26/acorn26/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.19 2007/02/22 04:47:28 thorpej Exp $ */ +/* $NetBSD: machdep.c,v 1.20 2007/06/01 07:04:54 skrll Exp $ */ /*- * Copyright (c) 1998 Ben Harris @@ -32,7 +32,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.19 2007/02/22 04:47:28 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.20 2007/06/01 07:04:54 skrll Exp $"); #include #include @@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.19 2007/02/22 04:47:28 thorpej Exp $") #include #include #include +#include #include #include @@ -214,3 +215,16 @@ cmos_write(int location, int value) return (pcfrtc_bootstrap_write(acorn26_i2c_tag, 0x50, location, &val, 1)); } + +void +cpu_need_resched(struct cpu_info *ci, int flags) +{ + bool immed = (flags & RESCHED_IMMED) != 0; + + if (want_resched && !immed) + return; + + want_resched = 1; + if (curlwp != ci->ci_data.cpu_idlelwp) + setsoftast(); +} diff --git a/sys/arch/acorn26/include/machdep.h b/sys/arch/acorn26/include/machdep.h index 2da8ee66fe7e..2beccc294be2 100644 --- a/sys/arch/acorn26/include/machdep.h +++ b/sys/arch/acorn26/include/machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.h,v 1.2 2002/03/24 23:37:43 bjh21 Exp $ */ +/* $NetBSD: machdep.h,v 1.3 2007/06/01 07:04:54 skrll Exp $ */ /*- * Copyright (c) 1998 Ben Harris * All rights reserved. @@ -55,8 +55,8 @@ extern void int_on __P((void)); extern void int_off __P((void)); extern void fiq_on __P((void)); extern void fiq_off __P((void)); -extern void cpu_loswitch(struct switchframe **, struct switchframe *); -extern void proc_trampoline(void); /* not quite true */ +extern struct lwp *cpu_loswitch(struct lwp *, struct lwp *); +extern void lwp_trampoline(void); /* not quite true */ /* pmap.c */ extern register_t update_memc __P((register_t, register_t));