From: Kenn H. <ke...@us...> - 2003-08-23 00:20:50
|
Update of /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel In directory sc8-pr-cvs1:/tmp/cvs-serv13334/arch/vax/kernel Modified Files: entry.S process.c syscall.c Log Message: Scheduler changes in 2.5.63 mean that we need to return the 'prev' pointer properly after context switching. We also need a separate path for newly-created processes (ret_from_fork, rather than ret_from_syscall, and we've probably needed this for a long time). Also NR_syscalls disappears in 2.5.63 Index: entry.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel/entry.S,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- entry.S 26 Jun 2003 23:27:41 -0000 1.11 +++ entry.S 23 Aug 2003 00:20:46 -0000 1.12 @@ -193,6 +193,15 @@ mtpr $31, $PR_IPL rei +.globl ret_from_fork +ret_from_fork: + /* A newly-created thread starts here when it is first + scheduled. R0 will contain the previous task (the one + that we just scheduled away from on this CPU). */ + pushl %r0 + calls $1, schedule_tail + brb ret_from_syscall + /* irqvec_stray is the generic handler for all exceptions and interrupts for which there is no registered handler. We just save all registers, and call unhandled_exception(), passing it the return address saved @@ -253,6 +262,8 @@ .data .globl sys_call_table sys_call_table: +.globl first_syscall +first_syscall: .long sys_ni_syscall /* 0 - old "setup()" system call*/ .long sys_exit .long sys_fork @@ -476,14 +487,5 @@ .long sys_getdents64 /* 220 */ .long sys_fcntl64 .long sys_tkill - /* - - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - .rept NR_syscalls-221 - .long sys_ni_syscall - .endr - +.globl last_syscall +last_syscall: Index: process.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel/process.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- process.c 26 Jun 2003 22:15:06 -0000 1.17 +++ process.c 23 Aug 2003 00:20:47 -0000 1.18 @@ -46,13 +46,13 @@ /* nothing */ } -void __switch_to(struct task_struct* prev, struct task_struct* next) +struct task_struct *__switch_to(struct task_struct* prev, struct task_struct* next) { unsigned long pcbb; /* physical address of new pcb */ #ifdef VAX_PROCESS_DEBUG - printk("vax_switch_to: switching %p, pid %d, state %ld -> %p, pid %d, state %ld\n", - prev, prev->pid, prev->state, next, next->pid, next->state); + printk("vax_switch_to: switching %p, pid %d, state %ld -> %p, pid %d, state %ld, pc %08lx\n", + prev, prev->pid, prev->state, next, next->pid, next->state, next->thread.pcb.pc); #endif /* We should check that __pa((prev)->thread.pcb) == PR_PCBB */ @@ -60,22 +60,34 @@ /* Get phys address of next process pcb */ pcbb = virt_to_phys(&next->thread.pcb); + /* When 'next' starts running, R0 will hold the task pointer + for the process we just switched away from. This will end + up in R0 at ret_from_fork, for new processes and will be + the return value from this function for existing processes */ + next->thread.pcb.r0 = (unsigned long) prev; + /* svpctx should deal with writing the stuff into *prev */ - asm(" movpsl -(%%sp) \n - pushab 1f \n - mtpr %3, %4 \n - svpctx \n - mtpr %1, %2 \n - ldpctx \n - rei \n - 1: " + asm(" movpsl -(%%sp) + pushab 1f + mtpr %2, %3 /* Raise IPL to 31 */ + svpctx /* Causes switch to interrupt stack */ + mtpr %0, %1 /* Load pcbb into PR_PCCB */ + ldpctx /* Loads registers and switches back to + kernel stack. Also leaves PC/PSL of + new process on kernel stack for an + immediate REI */ + rei + 1: + ret /* return now before anything munges R0 */ " : /* no outputs */ - : "g"(prev), - "r"(pcbb), "g"(PR_PCBB), + : "r"(pcbb), "g"(PR_PCBB), "g"(31), "g"(PR_IPL) /* no clobbers */ ); + + /* Never get to here because of the RET instruction above */ + return NULL; } /* This _must_ match the stack layout in effect at ret_from_syscall @@ -99,7 +111,7 @@ }; /* Defined in entry.S */ -extern void ret_from_syscall(void); +extern void ret_from_fork(void); int copy_thread(int unused1, unsigned long clone_flags, unsigned long usp, unsigned long unused2, @@ -129,9 +141,16 @@ p->thread.pcb.ksp = (unsigned long)child_stack; p->thread.pcb.usp = usp; - p->thread.pcb.pc = (unsigned long)ret_from_syscall; + p->thread.pcb.pc = (unsigned long)ret_from_fork; p->thread.pcb.psl = __psl; - + + /* New thread must start with IPL 31 to prevent any interrupts + from occuring between the time it is first scheduled (in __switch_to + above) and when ret_from_fork calls schedule_tail(). If an + interrupt comes in during this time, schedule() might get called + from do_irq_excep() before schedule_tail() has released the + runqueue lock (in finish_task_switch) */ + p->thread.pcb.psl.ipl = 31; /* We could speed this up by loading the register values into the PCB and start the new thread just before the REI in Index: syscall.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel/syscall.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- syscall.c 15 Jun 2003 22:33:56 -0000 1.6 +++ syscall.c 23 Aug 2003 00:20:47 -0000 1.7 @@ -31,6 +31,8 @@ Later we'll probably re-write this in asm. */ extern unsigned long *sys_call_table[256]; +extern unsigned long first_syscall; +extern unsigned long last_syscall; void syscall_handler(struct pt_regs *regs, void *excep_info) { @@ -40,7 +42,7 @@ chmk_arg = *(unsigned int *)(excep_info); - if (chmk_arg >= NR_syscalls) { + if (chmk_arg >= (&last_syscall - &first_syscall)) { regs->r0 = -ENOSYS; return; } |