Update of /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel In directory sc8-pr-cvs1:/tmp/cvs-serv23180/arch/s390/kernel Modified Files: debug.c entry.S init_task.c process.c ptrace.c s390_ksyms.c setup.c smp.c time.c traps.c Log Message: DA: sync to Marcelo 2.4.18 + remove init_mmap (no longer needed) Index: debug.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/debug.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- debug.c 9 Apr 2002 17:03:16 -0000 1.2 +++ debug.c 10 Jun 2003 01:46:08 -0000 1.3 @@ -228,8 +228,10 @@ strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))); rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0; memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *)); +#ifdef CONFIG_PROC_FS memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS * sizeof(struct proc_dir_entry*)); +#endif /* CONFIG_PROC_FS */ atomic_set(&(rc->ref_count), 0); return rc; @@ -346,8 +348,10 @@ if (!db_info) return; if (atomic_dec_and_test(&db_info->ref_count)) { +#ifdef DEBUG printk(KERN_INFO "debug: freeing debug area %p (%s)\n", db_info, db_info->name); +#endif for (i = 0; i < DEBUG_MAX_VIEWS; i++) { if (db_info->views[i] != NULL) debug_delete_proc_dir_entry @@ -541,14 +545,18 @@ debug_info_snapshot = debug_info_copy(debug_info); if(!debug_info_snapshot){ +#ifdef DEBUG printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n"); +#endif rc = -ENOMEM; goto out; } if ((file->private_data = kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) { +#ifdef DEBUG printk(KERN_ERR "debug_open: kmalloc failed\n"); +#endif debug_info_free(debug_info_snapshot); rc = -ENOMEM; goto out; @@ -602,6 +610,7 @@ { struct proc_dir_entry *rc = NULL; +#ifdef CONFIG_PROC_FS #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) const char *fn = name; int len; @@ -634,6 +643,7 @@ #endif out: +#endif /* CONFIG_PROC_FS */ return rc; } @@ -646,12 +656,14 @@ (struct proc_dir_entry *root, struct proc_dir_entry *proc_entry) { +#ifdef CONFIG_PROC_FS #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) proc_unregister(root, proc_entry->low_ino); kfree(proc_entry); #else remove_proc_entry(proc_entry->name, root); #endif +#endif /* CONFIG_PROC_FS */ } /* @@ -677,9 +689,11 @@ goto out; debug_register_view(rc, &debug_level_view); debug_register_view(rc, &debug_flush_view); +#ifdef DEBUG printk(KERN_INFO "debug: reserved %d areas of %d pages for debugging %s\n", nr_areas, 1 << page_order, rc->name); +#endif out: if (rc == NULL){ printk(KERN_ERR "debug: debug_register failed for %s\n",name); @@ -699,7 +713,9 @@ if (!id) goto out; down(&debug_lock); +#ifdef DEBUG printk(KERN_INFO "debug: unregistering %s\n", id->name); +#endif debug_info_put(id); up(&debug_lock); @@ -906,11 +922,13 @@ down(&debug_lock); if (!initialized) { +#ifdef CONFIG_PROC_FS debug_proc_root_entry = debug_create_proc_dir_entry(&proc_root, DEBUG_DIR_ROOT, S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, NULL, NULL); +#endif /* CONFIG_PROC_FS */ printk(KERN_INFO "debug: Initialization complete\n"); initialized = 1; } @@ -1271,7 +1289,9 @@ #ifdef DEBUG printk("debug_cleanup_module: \n"); #endif +#ifdef CONFIG_PROC_FS debug_delete_proc_dir_entry(&proc_root, debug_proc_root_entry); +#endif /* CONFIG_PROC_FS */ return; } Index: entry.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/entry.S,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- entry.S 9 Apr 2002 17:03:16 -0000 1.2 +++ entry.S 10 Jun 2003 01:46:08 -0000 1.3 @@ -79,7 +79,7 @@ sigpending = 8 need_resched = 24 tsk_ptrace = 28 -processor = 56 +processor = 52 /* * Base Address of this Module --- saved in __LC_ENTRY_BASE Index: init_task.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/init_task.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- init_task.c 14 Jan 2001 19:55:08 -0000 1.1.1.1 +++ init_task.c 10 Jun 2003 01:46:09 -0000 1.2 @@ -12,7 +12,6 @@ #include <asm/uaccess.h> #include <asm/pgtable.h> -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; Index: process.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/process.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- process.c 9 Apr 2002 17:03:17 -0000 1.2 +++ process.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -75,173 +75,24 @@ } } -/* - As all the register will only be made displayable to the root - user ( via printk ) or checking if the uid of the user is 0 from - the /proc filesystem please god this will be secure enough DJB. - The lines are given one at a time so as not to chew stack space in - printk on a crash & also for the proc filesystem when you get - 0 returned you know you've got all the lines - */ - -static int sprintf_regs(int line, char *buff, struct task_struct *task, struct pt_regs *regs) -{ - int linelen=0; - int regno,chaincnt; - u32 backchain,prev_backchain,endchain; - u32 ksp = 0; - char *mode = "???"; - - enum - { - sp_linefeed, - sp_psw, - sp_ksp, - sp_gprs, - sp_gprs1, - sp_gprs2, - sp_gprs3, - sp_gprs4, - sp_acrs, - sp_acrs1, - sp_acrs2, - sp_acrs3, - sp_acrs4, - sp_kern_backchain, - sp_kern_backchain1 - }; - - if (task) - ksp = task->thread.ksp; - if (regs && !(regs->psw.mask & PSW_PROBLEM_STATE)) - ksp = regs->gprs[15]; - - if (regs) - mode = (regs->psw.mask & PSW_PROBLEM_STATE)? - "User" : "Kernel"; - - switch(line) - { - case sp_linefeed: - linelen=sprintf(buff,"\n"); - break; - case sp_psw: - if(regs) - linelen=sprintf(buff, "%s PSW: %08lx %08lx %s\n", mode, - (unsigned long) regs->psw.mask, - (unsigned long) regs->psw.addr, - print_tainted()); - else - linelen=sprintf(buff,"pt_regs=NULL some info unavailable\n"); - break; - case sp_ksp: - linelen=sprintf(&buff[linelen], - "task: %08x ksp: %08x pt_regs: %08x\n", - (addr_t)task, (addr_t)ksp, (addr_t)regs); - break; - case sp_gprs: - if(regs) - linelen=sprintf(buff, "%s GPRS:\n", mode); - break; - case sp_gprs1 ... sp_gprs4: - if(regs) - { - regno=(line-sp_gprs1)*4; - linelen=sprintf(buff,"%08x %08x %08x %08x\n", - regs->gprs[regno], - regs->gprs[regno+1], - regs->gprs[regno+2], - regs->gprs[regno+3]); - } - break; - case sp_acrs: - if(regs) - linelen=sprintf(buff, "%s ACRS:\n", mode); - break; - case sp_acrs1 ... sp_acrs4: - if(regs) - { - regno=(line-sp_acrs1)*4; - linelen=sprintf(buff,"%08x %08x %08x %08x\n", - regs->acrs[regno], - regs->acrs[regno+1], - regs->acrs[regno+2], - regs->acrs[regno+3]); - } - break; - case sp_kern_backchain: - if (regs && (regs->psw.mask & PSW_PROBLEM_STATE)) - break; - if (ksp) - linelen=sprintf(buff, "Kernel BackChain CallChain\n"); - break; - default: - if (ksp) - { - - backchain=ksp&PSW_ADDR_MASK; - endchain=((backchain&(-8192))+8192); - prev_backchain=backchain-1; - line-=sp_kern_backchain1; - for(chaincnt=0;;chaincnt++) - { - if((backchain==0)||(backchain>=endchain) - ||(chaincnt>=8)||(prev_backchain>=backchain)) - break; - if(chaincnt==line) - { - linelen+=sprintf(&buff[linelen]," %08x [<%08lx>]\n", - backchain, - *(u32 *)(backchain+56)&PSW_ADDR_MASK); - break; - } - prev_backchain=backchain; - backchain=(*((u32 *)backchain))&PSW_ADDR_MASK; - } - } - } - return(linelen); -} - +extern void show_registers(struct pt_regs *regs); +extern void show_trace(unsigned long *sp); void show_regs(struct pt_regs *regs) { - char buff[80]; - int i, line; + struct task_struct *tsk = current; - printk("CPU: %d\n",smp_processor_id()); - printk("Process %s (pid: %d, stackpage=%08X)\n", - current->comm, current->pid, 4096+(addr_t)current); - - for (line = 0; sprintf_regs(line, buff, current, regs); line++) - printk(buff); - - if (regs->psw.mask & PSW_PROBLEM_STATE) - { - printk("User Code:\n"); - memset(buff, 0, 20); - copy_from_user(buff, - (char *) (regs->psw.addr & PSW_ADDR_MASK), 20); - for (i = 0; i < 20; i++) - printk("%02x ", buff[i]); - printk("\n"); - } + printk("CPU: %d %s\n", tsk->processor, print_tainted()); + printk("Process %s (pid: %d, task: %08lx, ksp: %08x)\n", + current->comm, current->pid, (unsigned long) tsk, + tsk->thread.ksp); + + show_registers(regs); + /* Show stack backtrace if pt_regs is from kernel mode */ + if (!(regs->psw.mask & PSW_PROBLEM_STATE)) + show_trace((unsigned long *) regs->gprs[15]); } -char *task_show_regs(struct task_struct *task, char *buffer) -{ - int line, len; - - for (line = 0; ; line++) - { - len = sprintf_regs(line, buffer, task, task->thread.regs); - if (!len) break; - buffer += len; - } - return buffer; -} - - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { int clone_arg = flags | CLONE_VM; @@ -301,16 +152,10 @@ unsigned long gprs[10]; /* gprs 6 -15 */ unsigned long fprs[4]; /* fpr 4 and 6 */ unsigned long empty[4]; -#if CONFIG_REMOTE_DEBUG - struct gdb_pt_regs childregs; -#else struct pt_regs childregs; -#endif } *frame; frame = (struct stack_frame *) (2*PAGE_SIZE + (unsigned long) p) -1; - frame = (struct stack_frame *) (((unsigned long) frame)&-8L); - p->thread.regs = (struct pt_regs *)&frame->childregs; p->thread.ksp = (unsigned long) frame; memcpy(&frame->childregs,regs,sizeof(struct pt_regs)); frame->childregs.gprs[15] = new_stackp; Index: ptrace.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/ptrace.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ptrace.c 9 Apr 2002 17:03:17 -0000 1.2 +++ ptrace.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -41,7 +41,7 @@ void FixPerRegisters(struct task_struct *task) { - struct pt_regs *regs = task->thread.regs; + struct pt_regs *regs = __KSTK_PTREGS(task); per_struct *per_info= (per_struct *)&task->thread.per_info; @@ -155,7 +155,7 @@ mask=0xffffffff; if(useraddr<PT_FPC) { - realuseraddr=(addr_t)&(((u8 *)task->thread.regs)[useraddr]); + realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr; if(useraddr<PT_PSWMASK) { copymax=PT_PSWMASK; @@ -217,7 +217,6 @@ { struct task_struct *child; int ret = -EPERM; - unsigned long flags; unsigned long tmp; int copied; ptrace_area parea; Index: s390_ksyms.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/s390_ksyms.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- s390_ksyms.c 9 Apr 2002 17:03:17 -0000 1.2 +++ s390_ksyms.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -18,8 +18,9 @@ EXPORT_SYMBOL_NOVERS(_oi_bitmap); EXPORT_SYMBOL_NOVERS(_ni_bitmap); EXPORT_SYMBOL_NOVERS(_zb_findmap); -EXPORT_SYMBOL_NOVERS(__copy_from_user_fixup); -EXPORT_SYMBOL_NOVERS(__copy_to_user_fixup); +EXPORT_SYMBOL_NOVERS(__copy_from_user_asm); +EXPORT_SYMBOL_NOVERS(__copy_to_user_asm); +EXPORT_SYMBOL_NOVERS(__clear_user_asm); /* * semaphore ops @@ -35,6 +36,7 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(memscan); EXPORT_SYMBOL_NOVERS(strlen); EXPORT_SYMBOL_NOVERS(strchr); EXPORT_SYMBOL_NOVERS(strcmp); @@ -57,5 +59,3 @@ EXPORT_SYMBOL(console_mode); EXPORT_SYMBOL(console_device); EXPORT_SYMBOL_NOVERS(do_call_softirq); - - Index: setup.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/setup.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- setup.c 9 Apr 2002 17:03:17 -0000 1.2 +++ setup.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -439,6 +439,7 @@ lowcore->kernel_stack = ((__u32) &init_task_union) + 8192; lowcore->async_stack = (__u32) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0) + 8192; + lowcore->jiffy_timer = -1LL; set_prefix((__u32) lowcore); cpu_init(); boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; @@ -485,15 +486,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_S390 *cpuinfo; - unsigned n = v; + unsigned long n = (unsigned long) v - 1; - if (!n--) { + if (!n) { seq_printf(m, "vendor_id : IBM/S390\n" "# processors : %i\n" "bogomips per cpu: %lu.%02lu\n", smp_num_cpus, loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); - } else if (cpu_online_map & (1 << n)) { + } + if (cpu_online_map & (1 << n)) { cpuinfo = &safe_get_cpu_lowcore(n).cpu_data; seq_printf(m, "processor %i: " "version = %02X, " @@ -508,7 +510,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) { - return *pos <= NR_CPUS ? (void)(*pos+1) : NULL; + return *pos <= NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { Index: smp.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/smp.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- smp.c 10 Jun 2003 01:13:15 -0000 1.3 +++ smp.c 10 Jun 2003 01:46:09 -0000 1.4 @@ -49,9 +49,6 @@ static int max_cpus = NR_CPUS; /* Setup configured maximum number of CPUs to activate */ int smp_num_cpus; struct _lowcore *lowcore_ptr[NR_CPUS]; -unsigned int prof_multiplier[NR_CPUS]; -unsigned int prof_old_multiplier[NR_CPUS]; -unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time=0; int smp_threads_ready=0; /* Set when the idlers are all forked. */ static atomic_t smp_commenced = ATOMIC_INIT(0); @@ -473,7 +470,7 @@ /* * Activate a secondary processor. */ -extern void init_100hz_timer(void); +extern void init_cpu_timer(void); extern int pfault_init(void); extern int pfault_token(void); @@ -486,8 +483,8 @@ /* Wait for completion of smp startup */ while (!atomic_read(&smp_commenced)) /* nothing */ ; - /* init per CPU 100 hz timer */ - init_100hz_timer(); + /* init per CPU timer */ + init_cpu_timer(); #ifdef CONFIG_PFAULT /* Enable pfault pseudo page faults on this cpu. */ pfault_init(); @@ -540,7 +537,7 @@ cpu_lowcore=&get_cpu_lowcore(cpu); cpu_lowcore->save_area[15] = idle->thread.ksp; - cpu_lowcore->kernel_stack = (idle->thread.ksp | 8191) + 1; + cpu_lowcore->kernel_stack = (__u32) idle + 8192; __asm__ __volatile__("la 1,%0\n\t" "stctl 0,15,0(1)\n\t" "la 1,%1\n\t" @@ -591,15 +588,7 @@ /* * Initialize the logical to physical CPU number mapping - * and the per-CPU profiling counter/multiplier */ - - for (i = 0; i < NR_CPUS; i++) { - prof_counter[i] = 1; - prof_old_multiplier[i] = 1; - prof_multiplier[i] = 1; - } - print_cpu_info(&safe_get_cpu_lowcore(0).cpu_data); for(i = 0; i < smp_num_cpus; i++) @@ -646,58 +635,6 @@ int setup_profiling_timer(unsigned int multiplier) { return 0; -} - -/* - * Local timer interrupt handler. It does both profiling and - * process statistics/rescheduling. - * - * We do profiling in every local tick, statistics/rescheduling - * happen only every 'profiling multiplier' ticks. The default - * multiplier is 1 and it can be changed by writing the new multiplier - * value into /proc/profile. - */ - -void smp_local_timer_interrupt(struct pt_regs * regs) -{ - int user = (user_mode(regs) != 0); - int cpu = smp_processor_id(); - - /* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ - if (!user_mode(regs)) - s390_do_profile(regs->psw.addr); - - if (!--prof_counter[cpu]) { - - /* - * The multiplier may have changed since the last time we got - * to this point as a result of the user writing to - * /proc/profile. In this case we need to adjust the APIC - * timer accordingly. - * - * Interrupts are already masked off at this point. - */ - prof_counter[cpu] = prof_multiplier[cpu]; - if (prof_counter[cpu] != prof_old_multiplier[cpu]) { - /* FIXME setup_APIC_timer(calibration_result/prof_counter[cpu] - ); */ - prof_old_multiplier[cpu] = prof_counter[cpu]; - } - - /* - * After doing the above, we need to make like - * a normal interrupt - otherwise timer interrupts - * ignore the global interrupt lock, which is the - * WrongThing (tm) to do. - */ - - update_process_times(user); - } } EXPORT_SYMBOL(lowcore_ptr); Index: time.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/time.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- time.c 9 Apr 2002 17:03:17 -0000 1.2 +++ time.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -33,19 +33,18 @@ #include <asm/irq.h> - /* change this if you have some constant time drift */ -#define USECS_PER_JIFFY ((signed long)1000000/HZ) -#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12) +#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) +#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) #define TICK_SIZE tick -static uint64_t init_timer_cc, last_timer_cc; +static uint64_t init_timer_cc; extern rwlock_t xtime_lock; extern unsigned long wall_jiffies; -void tod_to_timeval(uint64_t todval, struct timeval *xtime) +void tod_to_timeval(__u64 todval, struct timeval *xtime) { const int high_bit = 0x80000000L; const int c_f4240 = 0xf4240L; @@ -79,13 +78,15 @@ : "cc", "memory", "2", "3", "4" ); } -unsigned long do_gettimeoffset(void) +static inline unsigned long do_gettimeoffset(void) { - __u64 timer_cc; + __u64 now; - asm volatile ("STCK %0" : "=m" (timer_cc)); - /* We require the offset from the previous interrupt */ - return ((unsigned long)((timer_cc - last_timer_cc)>>12)); + asm ("STCK %0" : "=m" (now)); + now = (now - init_timer_cc) >> 12; + /* We require the offset from the latest update of xtime */ + now -= (__u64) wall_jiffies*USECS_PER_JIFFY; + return (unsigned long) now; } /* @@ -95,15 +96,10 @@ { unsigned long flags; unsigned long usec, sec; - unsigned long lost_ticks; read_lock_irqsave(&xtime_lock, flags); - lost_ticks = jiffies - wall_jiffies; - usec = do_gettimeoffset(); - if (lost_ticks) - usec +=(USECS_PER_JIFFY*lost_ticks); sec = xtime.tv_sec; - usec += xtime.tv_usec; + usec = xtime.tv_usec + do_gettimeoffset(); read_unlock_irqrestore(&xtime_lock, flags); while (usec >= 1000000) { @@ -149,51 +145,31 @@ extern __u16 boot_cpu_addr; #endif -void do_timer_interrupt(struct pt_regs *regs, __u16 error_code) +static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code) { int cpu = smp_processor_id(); irq_enter(cpu, 0); - /* - * reset timer to 10ms minus time already elapsed - * since timer-interrupt pending - */ + /* + * set clock comparator for next tick + */ + S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; + asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); + #ifdef CONFIG_SMP - if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) { + if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) write_lock(&xtime_lock); - last_timer_cc = S390_lowcore.jiffy_timer_cc; - } -#else - last_timer_cc = S390_lowcore.jiffy_timer_cc; -#endif - /* set clock comparator */ - S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc)); -/* - * In the SMP case we use the local timer interrupt to do the - * profiling, except when we simulate SMP mode on a uniprocessor - * system, in that case we have to call the local interrupt handler. - */ -#ifdef CONFIG_SMP - /* when SMP, do smp_local_timer_interrupt for *all* CPUs, - but only do the rest for the boot CPU */ - smp_local_timer_interrupt(regs); -#else - if (!user_mode(regs)) - s390_do_profile(regs->psw.addr); -#endif + update_process_times(user_mode(regs)); -#ifdef CONFIG_SMP - if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) -#endif - { + if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) { do_timer(regs); -#ifdef CONFIG_SMP write_unlock(&xtime_lock); -#endif } +#else + do_timer(regs); +#endif irq_exit(cpu, 0); } @@ -201,19 +177,17 @@ /* * Start the clock comparator on the current CPU */ -static long cr0 __attribute__ ((aligned (8))); - -void init_100hz_timer(void) +void init_cpu_timer(void) { + unsigned long cr0; + /* allow clock comparator timer interrupt */ asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory"); cr0 |= 0x800; asm volatile ("LCTL 0,0,%0" : : "m" (cr0) : "memory"); - /* set clock comparator */ - /* read the TOD clock */ - asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc)); - S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc)); + S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY; + S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY; + asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); } /* @@ -222,6 +196,7 @@ */ void __init time_init(void) { + __u64 set_time_cc; int cc; /* kick the TOD clock */ @@ -241,15 +216,16 @@ printk("time_init: TOD clock stopped/non-operational\n"); break; } + + /* set xtime */ + set_time_cc = init_timer_cc - 0x8126d60e46000000LL + + (0x3c26700LL*1000000*4096); + tod_to_timeval(set_time_cc, &xtime); + /* request the 0x1004 external interrupt */ - if (register_external_interrupt(0x1004, do_timer_interrupt) != 0) - panic("Couldn't request external interrupts 0x1004"); - init_100hz_timer(); - init_timer_cc = S390_lowcore.jiffy_timer_cc; - init_timer_cc -= 0x8126d60e46000000LL - - (0x3c26700LL*1000000*4096); - tod_to_timeval(init_timer_cc, &xtime); + if (register_external_interrupt(0x1004, do_comparator_interrupt) != 0) + panic("Couldn't request external interrupt 0x1004"); - /* Set do_get_fast_time function pointer. */ - do_get_fast_time = do_gettimeofday; + /* init CPU timer */ + init_cpu_timer(); } Index: traps.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/s390/kernel/traps.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- traps.c 9 Apr 2002 17:03:17 -0000 1.2 +++ traps.c 10 Jun 2003 01:46:09 -0000 1.3 @@ -26,15 +26,13 @@ #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/module.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/atomic.h> #include <asm/mathemu.h> -#if CONFIG_REMOTE_DEBUG -#include <asm/gdb-stub.h> -#endif #include <asm/cpcmd.h> #include <asm/s390_ext.h> @@ -60,6 +58,203 @@ extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code); #endif +int kstack_depth_to_print = 12; + +/* + * If the address is either in the .text section of the + * kernel, or in the vmalloc'ed module regions, it *may* + * be the address of a calling routine + */ +extern char _stext, _etext; + +#ifdef CONFIG_MODULES + +extern struct module *module_list; +extern struct module kernel_module; + +static inline int kernel_text_address(unsigned long addr) +{ + int retval = 0; + struct module *mod; + + if (addr >= (unsigned long) &_stext && + addr <= (unsigned long) &_etext) + return 1; + + for (mod = module_list; mod != &kernel_module; mod = mod->next) { + /* mod_bound tests for addr being inside the vmalloc'ed + * module area. Of course it'd be better to test only + * for the .text subset... */ + if (mod_bound(addr, 0, mod)) { + retval = 1; + break; + } + } + + return retval; +} + +#else + +static inline int kernel_text_address(unsigned long addr) +{ + return (addr >= (unsigned long) &_stext && + addr <= (unsigned long) &_etext); +} + +#endif + +void show_trace(unsigned long * stack) +{ + unsigned long backchain, low_addr, high_addr, ret_addr; + int i; + + if (!stack) + stack = (unsigned long*)&stack; + + printk("Call Trace: "); + low_addr = ((unsigned long) stack) & PSW_ADDR_MASK; + high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE; + /* Skip the first frame (biased stack) */ + backchain = *((unsigned long *) low_addr) & PSW_ADDR_MASK; + /* Print up to 8 lines */ + for (i = 0; i < 8; i++) { + if (backchain < low_addr || backchain >= high_addr) + break; + ret_addr = *((unsigned long *) (backchain+56)) & PSW_ADDR_MASK; + if (!kernel_text_address(ret_addr)) + break; + if (i && ((i % 6) == 0)) + printk("\n "); + printk("[<%08lx>] ", ret_addr); + low_addr = backchain; + backchain = *((unsigned long *) backchain) & PSW_ADDR_MASK; + } + printk("\n"); +} + +void show_trace_task(struct task_struct *tsk) +{ + /* + * We can't print the backtrace of a running process. It is + * unreliable at best and can cause kernel oopses. + */ + if (task_has_cpu(tsk)) + return; + show_trace((unsigned long *) tsk->thread.ksp); +} + +void show_stack(unsigned long *sp) +{ + unsigned long *stack; + int i; + + // debugging aid: "show_stack(NULL);" prints the + // back trace for this cpu. + + if(sp == NULL) + sp = (unsigned long*) &sp; + + stack = sp; + for (i = 0; i < kstack_depth_to_print; i++) { + if (((addr_t) stack & (THREAD_SIZE-1)) == 0) + break; + if (i && ((i % 8) == 0)) + printk("\n "); + printk("%08lx ", *stack++); + } + printk("\n"); + show_trace(sp); +} + +void show_registers(struct pt_regs *regs) +{ + mm_segment_t old_fs; + char *mode; + int i; + + mode = (regs->psw.mask & PSW_PROBLEM_STATE) ? "User" : "Krnl"; + printk("%s PSW : %08lx %08lx\n", + mode, (unsigned long) regs->psw.mask, + (unsigned long) regs->psw.addr); + printk("%s GPRS: %08x %08x %08x %08x\n", mode, + regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); + printk(" %08x %08x %08x %08x\n", + regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]); + printk(" %08x %08x %08x %08x\n", + regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]); + printk(" %08x %08x %08x %08x\n", + regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]); + printk("%s ACRS: %08x %08x %08x %08x\n", mode, + regs->acrs[0], regs->acrs[1], regs->acrs[2], regs->acrs[3]); + printk(" %08x %08x %08x %08x\n", + regs->acrs[4], regs->acrs[5], regs->acrs[6], regs->acrs[7]); + printk(" %08x %08x %08x %08x\n", + regs->acrs[8], regs->acrs[9], regs->acrs[10], regs->acrs[11]); + printk(" %08x %08x %08x %08x\n", + regs->acrs[12], regs->acrs[13], regs->acrs[14], regs->acrs[15]); + + /* + * Print the first 20 byte of the instruction stream at the + * time of the fault. + */ + old_fs = get_fs(); + if (regs->psw.mask & PSW_PROBLEM_STATE) + set_fs(USER_DS); + else + set_fs(KERNEL_DS); + printk("%s Code: ", mode); + for (i = 0; i < 20; i++) { + unsigned char c; + if (__get_user(c, (char *)(regs->psw.addr + i))) { + printk(" Bad PSW."); + break; + } + printk("%02x ", c); + } + set_fs(old_fs); + + printk("\n"); +} + +/* This is called from fs/proc/array.c */ +char *task_show_regs(struct task_struct *task, char *buffer) +{ + struct pt_regs *regs; + + regs = __KSTK_PTREGS(task); + buffer += sprintf(buffer, "task: %08lx, ksp: %08x\n", + (unsigned long) task, task->thread.ksp); + buffer += sprintf(buffer, "User PSW : %08lx %08lx\n", + (unsigned long) regs->psw.mask, + (unsigned long) regs->psw.addr); + buffer += sprintf(buffer, "User GPRS: %08x %08x %08x %08x\n", + regs->gprs[0], regs->gprs[1], + regs->gprs[2], regs->gprs[3]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->gprs[4], regs->gprs[5], + regs->gprs[6], regs->gprs[7]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->gprs[8], regs->gprs[9], + regs->gprs[10], regs->gprs[11]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->gprs[12], regs->gprs[13], + regs->gprs[14], regs->gprs[15]); + buffer += sprintf(buffer, "User ACRS: %08x %08x %08x %08x\n", + regs->acrs[0], regs->acrs[1], + regs->acrs[2], regs->acrs[3]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->acrs[4], regs->acrs[5], + regs->acrs[6], regs->acrs[7]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->acrs[8], regs->acrs[9], + regs->acrs[10], regs->acrs[11]); + buffer += sprintf(buffer, " %08x %08x %08x %08x\n", + regs->acrs[12], regs->acrs[13], + regs->acrs[14], regs->acrs[15]); + return buffer; +} + spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) @@ -145,7 +340,7 @@ #if CONFIG_REMOTE_DEBUG if(gdb_stub_initialised) { - gdb_stub_handle_exception((struct gdb_pt_regs *)regs,signal); + gdb_stub_handle_exception(regs, signal); return 0; } #endif |