diff options
Diffstat (limited to 'arch')
433 files changed, 4605 insertions, 5035 deletions
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index f3e98f83778..1898ea79d0e 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -40,7 +40,6 @@ #include <asm/unistd.h> extern struct hwrpb_struct *hwrpb; -extern void dump_thread(struct pt_regs *, struct user *); extern spinlock_t rtc_lock; /* these are C runtime functions with special calling conventions: */ diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index 9903e3a7910..fff5cf93e81 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c @@ -7,6 +7,7 @@ #include <linux/pci.h> #include <linux/init.h> #include <linux/bootmem.h> +#include <linux/capability.h> #include <linux/mm.h> #include <linux/errno.h> #include <linux/sched.h> diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index abb739b88ed..9924fd07743 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -276,7 +276,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { extern void ret_from_fork(void); - struct thread_info *childti = p->thread_info; + struct thread_info *childti = task_thread_info(p); struct pt_regs * childregs; struct switch_stack * childstack, *stack; unsigned long stack_offset, settls; @@ -285,7 +285,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, if (!(regs->ps & 8)) stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; childregs = (struct pt_regs *) - (stack_offset + PAGE_SIZE + (long) childti); + (stack_offset + PAGE_SIZE + task_stack_page(p)); *childregs = *regs; settls = regs->r20; @@ -428,30 +428,15 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) int dump_elf_task(elf_greg_t *dest, struct task_struct *task) { - struct thread_info *ti; - struct pt_regs *pt; - - ti = task->thread_info; - pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1; - - dump_elf_thread(dest, pt, ti); - + dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task)); return 1; } int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) { - struct thread_info *ti; - struct pt_regs *pt; - struct switch_stack *sw; - - ti = task->thread_info; - pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1; - sw = (struct switch_stack *)pt - 1; - + struct switch_stack *sw = (struct switch_stack *)task_pt_regs(task) - 1; memcpy(dest, sw->fp, 32 * 8); - return 1; } @@ -492,8 +477,8 @@ out: unsigned long thread_saved_pc(task_t *t) { - unsigned long base = (unsigned long)t->thread_info; - unsigned long fp, sp = t->thread_info->pcb.ksp; + unsigned long base = (unsigned long)task_stack_page(t); + unsigned long fp, sp = task_thread_info(t)->pcb.ksp; if (sp > base && sp+6*8 < base + 16*1024) { fp = ((unsigned long*)sp)[6]; @@ -523,7 +508,7 @@ get_wchan(struct task_struct *p) pc = thread_saved_pc(p); if (in_sched_functions(pc)) { - schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6]; + schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6]; return ((unsigned long *)schedule_frame)[12]; } return pc; diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 9969d212e94..0cd060598f9 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -72,6 +72,13 @@ enum { REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64 }; +#define PT_REG(reg) \ + (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg)) + +#define SW_REG(reg) \ + (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \ + + offsetof(struct switch_stack, reg)) + static int regoff[] = { PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3), PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7), @@ -103,14 +110,14 @@ get_reg_addr(struct task_struct * task, unsigned long regno) unsigned long *addr; if (regno == 30) { - addr = &task->thread_info->pcb.usp; + addr = &task_thread_info(task)->pcb.usp; } else if (regno == 65) { - addr = &task->thread_info->pcb.unique; + addr = &task_thread_info(task)->pcb.unique; } else if (regno == 31 || regno > 65) { zero = 0; addr = &zero; } else { - addr = (void *)task->thread_info + regoff[regno]; + addr = task_stack_page(task) + regoff[regno]; } return addr; } @@ -125,7 +132,7 @@ get_reg(struct task_struct * task, unsigned long regno) if (regno == 63) { unsigned long fpcr = *get_reg_addr(task, regno); unsigned long swcr - = task->thread_info->ieee_state & IEEE_SW_MASK; + = task_thread_info(task)->ieee_state & IEEE_SW_MASK; swcr = swcr_update_status(swcr, fpcr); return fpcr | swcr; } @@ -139,8 +146,8 @@ static int put_reg(struct task_struct *task, unsigned long regno, unsigned long data) { if (regno == 63) { - task->thread_info->ieee_state - = ((task->thread_info->ieee_state & ~IEEE_SW_MASK) + task_thread_info(task)->ieee_state + = ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK) | (data & IEEE_SW_MASK)); data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data); } @@ -188,35 +195,35 @@ ptrace_set_bpt(struct task_struct * child) * branch (emulation can be tricky for fp branches). */ displ = ((s32)(insn << 11)) >> 9; - child->thread_info->bpt_addr[nsaved++] = pc + 4; + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4; if (displ) /* guard against unoptimized code */ - child->thread_info->bpt_addr[nsaved++] + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4 + displ; DBG(DBG_BPT, ("execing branch\n")); } else if (op_code == 0x1a) { reg_b = (insn >> 16) & 0x1f; - child->thread_info->bpt_addr[nsaved++] = get_reg(child, reg_b); + task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b); DBG(DBG_BPT, ("execing jump\n")); } else { - child->thread_info->bpt_addr[nsaved++] = pc + 4; + task_thread_info(child)->bpt_addr[nsaved++] = pc + 4; DBG(DBG_BPT, ("execing normal insn\n")); } /* install breakpoints: */ for (i = 0; i < nsaved; ++i) { - res = read_int(child, child->thread_info->bpt_addr[i], + res = read_int(child, task_thread_info(child)->bpt_addr[i], (int *) &insn); if (res < 0) return res; - child->thread_info->bpt_insn[i] = insn; + task_thread_info(child)->bpt_insn[i] = insn; DBG(DBG_BPT, (" -> next_pc=%lx\n", - child->thread_info->bpt_addr[i])); - res = write_int(child, child->thread_info->bpt_addr[i], + task_thread_info(child)->bpt_addr[i])); + res = write_int(child, task_thread_info(child)->bpt_addr[i], BREAKINST); if (res < 0) return res; } - child->thread_info->bpt_nsaved = nsaved; + task_thread_info(child)->bpt_nsaved = nsaved; return 0; } @@ -227,9 +234,9 @@ ptrace_set_bpt(struct task_struct * child) int ptrace_cancel_bpt(struct task_struct * child) { - int i, nsaved = child->thread_info->bpt_nsaved; + int i, nsaved = task_thread_info(child)->bpt_nsaved; - child->thread_info->bpt_nsaved = 0; + task_thread_info(child)->bpt_nsaved = 0; if (nsaved > 2) { printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); @@ -237,8 +244,8 @@ ptrace_cancel_bpt(struct task_struct * child) } for (i = 0; i < nsaved; ++i) { - write_int(child, child->thread_info->bpt_addr[i], - child->thread_info->bpt_insn[i]); + write_int(child, task_thread_info(child)->bpt_addr[i], + task_thread_info(child)->bpt_insn[i]); } return (nsaved != 0); } @@ -355,7 +362,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, if (!valid_signal(data)) break; /* Mark single stepping. */ - child->thread_info->bpt_nsaved = -1; + task_thread_info(child)->bpt_nsaved = -1; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; wake_up_process(child); diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index da0be346579..4b873527ce1 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -302,7 +302,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) + hwrpb->processor_offset + cpuid * hwrpb->processor_size); hwpcb = (struct pcb_struct *) cpu->hwpcb; - ipcb = &idle->thread_info->pcb; + ipcb = &task_thread_info(idle)->pcb; /* Initialize the CPU's HWPCB to something just good enough for us to get started. Immediately after starting, we'll swpctx diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 90752f6d886..486d7945583 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -7,6 +7,7 @@ /* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */ #include <linux/config.h> +#include <linux/pagemap.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/kernel.h> diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c index 00f6278f42b..48b1e19b131 100644 --- a/arch/arm/common/rtctime.c +++ b/arch/arm/common/rtctime.c @@ -17,6 +17,7 @@ #include <linux/proc_fs.h> #include <linux/miscdevice.h> #include <linux/spinlock.h> +#include <linux/capability.h> #include <linux/device.h> #include <linux/mutex.h> diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index b9df1b782bb..766b6c05c6d 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c @@ -18,6 +18,7 @@ #include <linux/proc_fs.h> #include <linux/miscdevice.h> #include <linux/apm_bios.h> +#include <linux/capability.h> #include <linux/sched.h> #include <linux/pm.h> #include <linux/device.h> diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 54a21bdcba5..4b4e4cf79c8 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -342,10 +342,10 @@ void flush_thread(void) void release_thread(struct task_struct *dead_task) { #if defined(CONFIG_VFP) - vfp_release_thread(&dead_task->thread_info->vfpstate); + vfp_release_thread(&task_thread_info(dead_task)->vfpstate); #endif #if defined(CONFIG_IWMMXT) - iwmmxt_task_release(dead_task->thread_info); + iwmmxt_task_release(task_thread_info(dead_task)); #endif } @@ -355,10 +355,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *thread = p->thread_info; - struct pt_regs *childregs; + struct thread_info *thread = task_thread_info(p); + struct pt_regs *childregs = task_pt_regs(p); - childregs = (void *)thread + THREAD_START_SP - sizeof(*regs); *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; @@ -460,8 +459,8 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_start = (unsigned long)(p->thread_info + 1); - stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE; + stack_start = (unsigned long)end_of_stack(p); + stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE; fp = thread_saved_fp(p); do { diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 2b84f78d7b0..e591f72bcde 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -55,23 +55,6 @@ #endif /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return (struct pt_regs *) - ((unsigned long)task->thread_info + THREAD_SIZE - - 8 - sizeof(struct pt_regs)); -} - -/* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our @@ -79,7 +62,7 @@ get_user_regs(struct task_struct *task) */ static inline long get_user_reg(struct task_struct *task, int offset) { - return get_user_regs(task)->uregs[offset]; + return task_pt_regs(task)->uregs[offset]; } /* @@ -91,7 +74,7 @@ static inline long get_user_reg(struct task_struct *task, int offset) static inline int put_user_reg(struct task_struct *task, int offset, long data) { - struct pt_regs newregs, *regs = get_user_regs(task); + struct pt_regs newregs, *regs = task_pt_regs(task); int ret = -EINVAL; newregs = *regs; @@ -421,7 +404,7 @@ void ptrace_set_bpt(struct task_struct *child) u32 insn; int res; - regs = get_user_regs(child); + regs = task_pt_regs(child); pc = instruction_pointer(regs); if (thumb_mode(regs)) { @@ -572,7 +555,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -587,7 +570,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); ret = -EINVAL; if (valid_user_regs(&newregs)) { @@ -604,7 +587,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) */ static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp) { - return copy_to_user(ufp, &tsk->thread_info->fpstate, + return copy_to_user(ufp, &task_thread_info(tsk)->fpstate, sizeof(struct user_fp)) ? -EFAULT : 0; } @@ -613,7 +596,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); thread->used_cp[1] = thread->used_cp[2] = 1; return copy_from_user(&thread->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; @@ -626,7 +609,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); void *ptr = &thread->fpstate; if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) @@ -643,7 +626,7 @@ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) */ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) { - struct thread_info *thread = tsk->thread_info; + struct thread_info *thread = task_thread_info(tsk); void *ptr = &thread->fpstate; if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) @@ -779,7 +762,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); break; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 373c0959bc2..7338948bd7d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -114,7 +114,7 @@ int __cpuinit __cpu_up(unsigned int cpu) * We need to tell the secondary core where to find * its stack and the page tables. */ - secondary_data.stack = (void *)idle->thread_info + THREAD_START_SP; + secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; secondary_data.pgdir = virt_to_phys(pgd); wmb(); @@ -245,7 +245,7 @@ void __cpuexit cpu_die(void) __asm__("mov sp, %0\n" " b secondary_start_kernel" : - : "r" ((void *)current->thread_info + THREAD_SIZE - 8)); + : "r" (task_stack_page(current) + THREAD_SIZE - 8)); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index c9fe6f5f7ee..93cfd3ffcc7 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -164,7 +164,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } else if (verify_stack(fp)) { printk("invalid frame pointer 0x%08x", fp); ok = 0; - } else if (fp < (unsigned long)(tsk->thread_info + 1)) + } else if (fp < (unsigned long)end_of_stack(tsk)) printk("frame pointer underflow"); printk("\n"); @@ -210,7 +210,7 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p if (!user_mode(regs) || in_interrupt()) { dump_mem("Stack: ", regs->ARM_sp, - THREAD_SIZE + (unsigned long)tsk->thread_info); + THREAD_SIZE + (unsigned long)task_stack_page(tsk)); dump_backtrace(regs, tsk); dump_instr(regs); } diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index f5cc21ad095..a4e5ac77f6d 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -64,7 +64,7 @@ static int dma_chan_count; static spinlock_t dma_chan_lock; static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT]; -const static u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { +static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c index 35514b398e2..811a6376c62 100644 --- a/arch/arm26/kernel/armksyms.c +++ b/arch/arm26/kernel/armksyms.c @@ -35,7 +35,6 @@ #include <asm/checksum.h> #include <asm/mach-types.h> -extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, struct user_fp_struct *); extern void inswb(unsigned int port, void *to, int len); extern void outswb(unsigned int port, const void *to, int len); diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c index 15833a0057d..38630565917 100644 --- a/arch/arm26/kernel/process.c +++ b/arch/arm26/kernel/process.c @@ -277,10 +277,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *thread = p->thread_info; - struct pt_regs *childregs; + struct thread_info *thread = task_thread_info(p); + struct pt_regs *childregs = task_pt_regs(p); - childregs = __get_user_regs(thread); *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 4e6b7356a72..3c3371d4683 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -40,21 +40,6 @@ #define BREAKINST_ARM 0xef9f0001 /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return __get_user_regs(task->thread_info); -} - -/* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our @@ -62,7 +47,7 @@ get_user_regs(struct task_struct *task) */ static inline long get_user_reg(struct task_struct *task, int offset) { - return get_user_regs(task)->uregs[offset]; + return task_pt_regs(task)->uregs[offset]; } /* @@ -74,7 +59,7 @@ static inline long get_user_reg(struct task_struct *task, int offset) static inline int put_user_reg(struct task_struct *task, int offset, long data) { - struct pt_regs newregs, *regs = get_user_regs(task); + struct pt_regs newregs, *regs = task_pt_regs(task); int ret = -EINVAL; newregs = *regs; @@ -377,7 +362,7 @@ void ptrace_set_bpt(struct task_struct *child) u32 insn; int res; - regs = get_user_regs(child); + regs = task_pt_regs(child); pc = instruction_pointer(regs); res = read_instr(child, pc, &insn); @@ -500,7 +485,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -515,7 +500,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); ret = -EINVAL; if (valid_user_regs(&newregs)) { @@ -532,7 +517,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs) */ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) { - return copy_to_user(ufp, &tsk->thread_info->fpstate, + return copy_to_user(ufp, &task_thread_info(tsk)->fpstate, sizeof(struct user_fp)) ? -EFAULT : 0; } @@ -542,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { set_stopped_child_used_math(tsk); - return copy_from_user(&tsk->thread_info->fpstate, ufp, + return copy_from_user(&task_threas_info(tsk)->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index f64f5902239..5847ea5d774 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c @@ -132,7 +132,7 @@ static void dump_instr(struct pt_regs *regs) /*static*/ void __dump_stack(struct task_struct *tsk, unsigned long sp) { - dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info); + dump_mem("Stack: ", sp, 8192+(unsigned long)task_stack_page(tsk)); } void dump_stack(void) @@ -158,7 +158,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } else if (verify_stack(fp)) { printk("invalid frame pointer 0x%08x", fp); ok = 0; - } else if (fp < (unsigned long)(tsk->thread_info + 1)) + } else if (fp < (unsigned long)end_of_stack(tsk)) printk("frame pointer underflow"); printk("\n"); @@ -168,7 +168,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) /* FIXME - this is probably wrong.. */ void show_stack(struct task_struct *task, unsigned long *sp) { - dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info); + dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task_stack_page(task)); } DEFINE_SPINLOCK(die_lock); @@ -187,7 +187,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) printk("CPU: %d\n", smp_processor_id()); show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", - current->comm, current->pid, tsk->thread_info + 1); + current->comm, current->pid, end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { __dump_stack(tsk, (unsigned long)(regs + 1)); diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c index 10795f67f68..b100f26497c 100644 --- a/arch/cris/arch-v10/drivers/ds1302.c +++ b/arch/cris/arch-v10/drivers/ds1302.c @@ -148,6 +148,7 @@ #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/bcd.h> +#include <linux/capability.h> #include <asm/uaccess.h> #include <asm/system.h> diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index f2c55742e90..af517c21038 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -28,6 +28,7 @@ #include <linux/ioctl.h> #include <linux/delay.h> #include <linux/bcd.h> +#include <linux/capability.h> #include <asm/uaccess.h> #include <asm/system.h> diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 69e28b4057e..0a675ce9e09 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c @@ -79,7 +79,7 @@ void hard_reset_now (void) */ unsigned long thread_saved_pc(struct task_struct *t) { - return (unsigned long)user_regs(t->thread_info)->irp; + return task_pt_regs(t)->irp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) @@ -128,7 +128,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * remember that the task_struct doubles as the kernel stack for the task */ - childregs = user_regs(p->thread_info); + childregs = task_pt_regs(p); *childregs = *regs; /* struct copy of pt_regs */ diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 6cbd34a27b9..f214f74f264 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -37,7 +37,7 @@ inline long get_reg(struct task_struct *task, unsigned int regno) if (regno == PT_USP) return task->thread.usp; else if (regno < PT_MAX) - return ((unsigned long *)user_regs(task->thread_info))[regno]; + return ((unsigned long *)task_pt_regs(task))[regno]; else return 0; } @@ -51,7 +51,7 @@ inline int put_reg(struct task_struct *task, unsigned int regno, if (regno == PT_USP) task->thread.usp = data; else if (regno < PT_MAX) - ((unsigned long *)user_regs(task->thread_info))[regno] = data; + ((unsigned long *)task_pt_regs(task))[regno] = data; else return -1; return 0; diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 882be42114f..843513102d3 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c @@ -96,7 +96,7 @@ hard_reset_now(void) */ unsigned long thread_saved_pc(struct task_struct *t) { - return (unsigned long)user_regs(t->thread_info)->erp; + return task_pt_regs(t)->erp; } static void @@ -148,7 +148,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * fix it up. Note: the task_struct doubles as the kernel stack for the * task. */ - childregs = user_regs(p->thread_info); + childregs = task_pt_regs(p); *childregs = *regs; /* Struct copy of pt_regs. */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ @@ -157,7 +157,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * The TLS is in $mof beacuse it is the 5th argument to sys_clone. */ if (p->mm && (clone_flags & CLONE_SETTLS)) { - p->thread_info->tls = regs->mof; + task_thread_info(p)->tls = regs->mof; } /* Put the switch stack right below the pt_regs. */ diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 5528b83a622..82cf2e3624a 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -46,7 +46,7 @@ long get_reg(struct task_struct *task, unsigned int regno) unsigned long ret; if (regno <= PT_EDA) - ret = ((unsigned long *)user_regs(task->thread_info))[regno]; + ret = ((unsigned long *)task_pt_regs(task))[regno]; else if (regno == PT_USP) ret = task->thread.usp; else if (regno == PT_PPC) @@ -65,13 +65,13 @@ long get_reg(struct task_struct *task, unsigned int regno) int put_reg(struct task_struct *task, unsigned int regno, unsigned long data) { if (regno <= PT_EDA) - ((unsigned long *)user_regs(task->thread_info))[regno] = data; + ((unsigned long *)task_pt_regs(task))[regno] = data; else if (regno == PT_USP) task->thread.usp = data; else if (regno == PT_PPC) { /* Write pseudo-PC to ERP only if changed. */ if (data != get_pseudo_pc(task)) - ((unsigned long *)user_regs(task->thread_info))[PT_ERP] = data; + task_pt_regs(task)->erp = data; } else if (regno <= PT_MAX) return put_debugreg(task->pid, regno, data); else diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 13867f4fad1..da40d19a151 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -113,10 +113,10 @@ smp_boot_one_cpu(int cpuid) if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - idle->thread_info->cpu = cpuid; + task_thread_info(idle)->cpu = cpuid; /* Information to the CPU that is about to boot */ - smp_init_current_idle_thread = idle->thread_info; + smp_init_current_idle_thread = task_thread_info(idle); cpu_now_booting = cpuid; /* Wait for CPU to come online */ diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c index b08a28bb58a..9d75d769230 100644 --- a/arch/cris/arch-v32/mm/tlb.c +++ b/arch/cris/arch-v32/mm/tlb.c @@ -198,9 +198,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, per_cpu(current_pgd, cpu) = next->pgd; /* Switch context in the MMU. */ - if (tsk && tsk->thread_info) + if (tsk && task_thread_info(tsk)) { - SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | tsk->thread_info->tls); + SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | task_thread_info(tsk)->tls); } else { diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 85833d704eb..de39725da92 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c @@ -21,7 +21,6 @@ #include <asm/pgtable.h> #include <asm/fasttimer.h> -extern void dump_thread(struct pt_regs *, struct user *); extern unsigned long get_cmos_time(void); extern void __Udiv(void); extern void __Umod(void); @@ -33,7 +32,6 @@ extern void __lshrdi3(void); extern void iounmap(volatile void * __iomem); /* Platform dependent support */ -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(loops_per_usec); diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 7c80afb1046..4ab3e87115b 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -257,34 +257,6 @@ void flush_thread(void) { } -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ -#if 0 - int i; - - /* changed the size calculations - should hopefully work better. lbt */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = regs->esp & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - for (i = 0; i < 8; i++) - dump->u_debugreg[i] = current->debugreg[i]; - - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; - - dump->regs = *regs; - - dump->u_fpvalid = dump_fpu (regs, &dump->i387); -#endif -} - /* Fill in the fpu structure for a core dump. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) { diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index 61261b78ced..60a617aff8b 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -6,10 +6,6 @@ config FRV bool default y -config UID16 - bool - default y - config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index d75e0d77136..5dfc93fd945 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile @@ -57,10 +57,10 @@ initrd: # installation # install: $(CONFIGURE) Image - sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" + sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" zinstall: $(CONFIGURE) zImage - sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" + sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" # # miscellany diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 5f118c89d09..0f1c6cbc4f5 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -18,7 +18,6 @@ #include <asm/hardirq.h> #include <asm/cacheflush.h> -extern void dump_thread(struct pt_regs *, struct user *); extern long __memcpy_user(void *dst, const void *src, size_t count); extern long __memset_user(void *dst, const void *src, size_t count); @@ -27,7 +26,6 @@ extern long __memset_user(void *dst, const void *src, size_t count); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 54a452136f0..0fff8a61ef2 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -204,7 +204,7 @@ int copy_thread(int nr, unsigned long clone_flags, regs0 = __kernel_frame0_ptr; childregs0 = (struct pt_regs *) - ((unsigned long) p->thread_info + THREAD_SIZE - USER_CONTEXT_SIZE); + (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); childregs = childregs0; /* set up the userspace frame (the only place that the USP is stored) */ @@ -220,7 +220,7 @@ int copy_thread(int nr, unsigned long clone_flags, *childregs = *regs; childregs->sp = (unsigned long) childregs0; childregs->next_frame = childregs0; - childregs->gr15 = (unsigned long) p->thread_info; + childregs->gr15 = (unsigned long) task_thread_info(p); childregs->gr29 = (unsigned long) p; } @@ -244,28 +244,6 @@ int copy_thread(int nr, unsigned long clone_flags, } /* end copy_thread() */ /* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs *regs, struct user *dump) -{ -#if 0 - /* changed the size calculations - should hopefully work better. lbt */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = user_stack(regs) & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; - - dump->regs = *(struct user_context *) regs; -#endif -} - -/* * sys_execve() executes a new program. */ asmlinkage int sys_execve(char *name, char **argv, char **envp) diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c index 795682b873e..d195568ca8a 100644 --- a/arch/h8300/kernel/gpio.c +++ b/arch/h8300/kernel/gpio.c @@ -122,7 +122,7 @@ int h8300_get_gpio_dir(int port_bit) static char *port_status(int portno) { static char result[10]; - const static char io[2]={'I','O'}; + static const char io[2]={'I','O'}; char *rp; int c; unsigned char used,ddr; @@ -143,7 +143,7 @@ static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int *unused_i, void *unused_v) { int c,outlen; - const static char port_name[]="123456789ABCDEFGH"; + static const char port_name[]="123456789ABCDEFGH"; outlen = 0; for (c = 0; c < MAX_PORT; c++) { if (ddrs[c] == NULL) diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c index 5a630233112..5cc76efaf7a 100644 --- a/arch/h8300/kernel/h8300_ksyms.c +++ b/arch/h8300/kernel/h8300_ksyms.c @@ -22,11 +22,8 @@ //asmlinkage long long __lshrdi3 (long long, int); extern char h8300_debug_device[]; -extern void dump_thread(struct pt_regs *, struct user *); - /* platform dependent support */ -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); @@ -103,10 +100,6 @@ EXPORT_SYMBOL(__udivsi3); EXPORT_SYMBOL(__umoddi3); EXPORT_SYMBOL(__umodsi3); -#ifdef MAGIC_ROM_PTR -EXPORT_SYMBOL(is_in_rom); -#endif - EXPORT_SYMBOL(h8300_reserved_gpio); EXPORT_SYMBOL(h8300_free_gpio); EXPORT_SYMBOL(h8300_set_gpio_dir); diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index fe21adf3e75..ed79ae20e88 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -195,7 +195,7 @@ int copy_thread(int nr, unsigned long clone_flags, { struct pt_regs * childregs; - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; *childregs = *regs; childregs->retpc = (unsigned long) ret_from_fork; @@ -208,34 +208,6 @@ int copy_thread(int nr, unsigned long clone_flags, } /* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ -/* changed the size calculations - should hopefully work better. lbt */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + - (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - - dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump))); - dump->regs.er0 = regs->er0; - dump->regs.er1 = regs->er1; - dump->regs.er2 = regs->er2; - dump->regs.er3 = regs->er3; - dump->regs.er4 = regs->er4; - dump->regs.er5 = regs->er5; - dump->regs.er6 = regs->er6; - dump->regs.orig_er0 = regs->orig_er0; - dump->regs.ccr = regs->ccr; - dump->regs.pc = regs->pc; -} - -/* * sys_execve() executes a new program. */ asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...) diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c index f4ddece3216..81eace93f86 100644 --- a/arch/h8300/mm/memory.c +++ b/arch/h8300/mm/memory.c @@ -55,16 +55,3 @@ unsigned long kernel_map(unsigned long paddr, unsigned long size, return paddr; } -#ifdef MAGIC_ROM_PTR - -int is_in_rom(unsigned long addr) -{ - /* Anything not in operational RAM is returned as in rom! */ - if (addr < _ramstart || addr >= _ramend) - return 1; - else - return 0; -} - -#endif - diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c index 6ac93c05a1a..746b1ae672a 100644 --- a/arch/h8300/platform/h8300h/ptrace_h8300h.c +++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c @@ -98,7 +98,7 @@ struct optable { .type = jmp, \ } -const static struct optable optable_0[] = { +static const struct optable optable_0[] = { OPTABLE(0x00,0xff, 1,none), /* 0x00 */ OPTABLE(0x01,0xff,-1,none), /* 0x01 */ OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */ @@ -131,31 +131,31 @@ const static struct optable optable_0[] = { OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */ }; -const static struct optable optable_1[] = { +static const struct optable optable_1[] = { OPTABLE(0x00,0xff,-3,none), /* 0x0100 */ OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */ OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */ OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */ }; -const static struct optable optable_2[] = { +static const struct optable optable_2[] = { OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */ OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */ }; -const static struct optable optable_3[] = { +static const struct optable optable_3[] = { OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */ OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */ OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */ OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */ }; -const static struct optable optable_4[] = { +static const struct optable optable_4[] = { OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */ OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */ }; -const static struct optables_list { +static const struct optables_list { const struct optable *ptr; int size; } optables[] = { diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c index 5441cdd12a3..f6ed663bdde 100644 --- a/arch/h8300/platform/h8s/ints.c +++ b/arch/h8300/platform/h8s/ints.c @@ -52,7 +52,7 @@ struct irq_pins { unsigned char bit_no; }; /* ISTR = 0 */ -const static struct irq_pins irq_assign_table0[16]={ +static const struct irq_pins irq_assign_table0[16]={ {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, @@ -63,7 +63,7 @@ const static struct irq_pins irq_assign_table0[16]={ {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, }; /* ISTR = 1 */ -const static struct irq_pins irq_assign_table1[16]={ +static const struct irq_pins irq_assign_table1[16]={ {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, diff --git a/arch/h8300/platform/h8s/ints_h8s.c b/arch/h8300/platform/h8s/ints_h8s.c index f53de493e3e..8268dfd12f1 100644 --- a/arch/h8300/platform/h8s/ints_h8s.c +++ b/arch/h8300/platform/h8s/ints_h8s.c @@ -42,7 +42,7 @@ struct irq_pins { unsigned char bit_no; } __attribute__((aligned(1),packed)); /* ISTR = 0 */ -const static struct irq_pins irq_assign_table0[16]={ +static const struct irq_pins irq_assign_table0[16]={ {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, @@ -53,7 +53,7 @@ const static struct irq_pins irq_assign_table0[16]={ {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, }; /* ISTR = 1 */ -const static struct irq_pins irq_assign_table1[16]={ +static const struct irq_pins irq_assign_table1[16]={ {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index d849c6870e3..d5d0df7f04f 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -41,8 +41,21 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config DMI + bool + default y + source "init/Kconfig" +config DOUBLEFAULT + default y + bool "Enable doublefault exception handler" if EMBEDDED + help + This option allows trapping of rare doublefault exceptions that + would otherwise cause a system to silently reboot. Disabling this + option saves about 4k and might cause you much additional grey + hair. + menu "Processor type and features" choice @@ -645,17 +658,6 @@ config SECCOMP source kernel/Kconfig.hz -config PHYSICAL_START - hex "Physical address where the kernel is loaded" if EMBEDDED - default "0x100000" - help - This gives the physical address where the kernel is loaded. - Primarily used in the case of kexec on panic where the - fail safe kernel needs to run at a different address than - the panic-ed kernel. - - Don't change this unless you know what you are doing. - config KEXEC bool "kexec system call (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -675,11 +677,31 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps (EXPERIMENTAL)" - depends on EMBEDDED depends on EXPERIMENTAL depends on HIGHMEM help Generate crash dump after being started by kexec. + +config PHYSICAL_START + hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) + + default "0x1000000" if CRASH_DUMP + default "0x100000" + help + This gives the physical address where the kernel is loaded. Normally + for regular kernels this value is 0x100000 (1MB). But in the case + of kexec on panic the fail safe kernel needs to run at a different + address than the panic-ed kernel. This option is used to set the load + address for kernels used to capture crash dump on being kexec'ed + after panic. The default value for crash dump kernels is + 0x1000000 (16MB). This can also be set based on the "X" value as + specified in the "crashkernel=YM@XM" command line boot parameter + passed to the panic-ed kernel. Typically this parameter is set as + crashkernel=64M@16M. Please take a look at + Documentation/kdump/kdump.txt for more details about crash dumps. + + Don't change this unless you know what you are doing. + endmenu @@ -1051,3 +1073,7 @@ config X86_TRAMPOLINE bool depends on X86_SMP || (X86_VOYAGER && SMP) default y + +config KTIME_SCALAR + bool + default y diff --git a/arch/i386/Makefile b/arch/i386/Makefile index b84119f9cc6..d3c0409d201 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -37,7 +37,10 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -cflags-$(CONFIG_REGPARM) += -mregparm=3 +# -mregparm=3 works ok on gcc-3.0 and later +# +cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ + echo "-mregparm=3"; fi ;) # Disable unit-at-a-time mode, it makes gcc use a lot more stack # due to the lack of sharing of stacklots. @@ -100,7 +103,7 @@ AFLAGS += $(mflags-y) boot := arch/i386/boot .PHONY: zImage bzImage compressed zlilo bzlilo \ - zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install + zdisk bzdisk fdimage fdimage144 fdimage288 install all: bzImage @@ -122,8 +125,7 @@ zdisk bzdisk: vmlinux fdimage fdimage144 fdimage288: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ -install: vmlinux -install kernel_install: +install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install archclean: diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 1e71382d413..f136752563b 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -100,5 +100,5 @@ zlilo: $(BOOTIMAGE) cp System.map $(INSTALL_PATH)/ if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi -install: $(BOOTIMAGE) - sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" +install: + sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/arch/i386/boot/install.sh b/arch/i386/boot/install.sh index f17b40dfc0f..5e44c736eea 100644 --- a/arch/i386/boot/install.sh +++ b/arch/i386/boot/install.sh @@ -19,6 +19,20 @@ # $4 - default install path (blank if root directory) # +verify () { + if [ ! -f "$1" ]; then + echo "" 1>&2 + echo " *** Missing file: $1" 1>&2 + echo ' *** You need to run "make" before "make install".' 1>&2 + echo "" 1>&2 + exit 1 + fi +} + +# Make sure the files actually exist +verify "$2" +verify "$3" + # User may have a custom install script if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 92f66947014..2ac40c8244c 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -97,7 +97,6 @@ #define PARAM_VESAPM_OFF 0x30 #define PARAM_LFB_PAGES 0x32 #define PARAM_VESA_ATTRIB 0x34 -#define PARAM_CAPABILITIES 0x36 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN @@ -234,10 +233,6 @@ mopar_gr: movw 18(%di), %ax movl %eax, %fs:(PARAM_LFB_SIZE) -# store mode capabilities - movl 10(%di), %eax - movl %eax, %fs:(PARAM_CAPABILITIES) - # switching the DAC to 8-bit is for <= 8 bpp only movw %fs:(PARAM_LFB_DEPTH), %ax cmpw $8, %ax diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index be1880bb75b..60c3f76dfca 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 447fa9e33ff..2111529dea7 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -108,7 +108,7 @@ char *__acpi_map_table(unsigned long phys_addr, unsigned long size) if (!phys_addr || !size) return NULL; - if (phys_addr < (end_pfn_map << PAGE_SHIFT)) + if (phys_addr+size <= (end_pfn_map << PAGE_SHIFT) + PAGE_SIZE) return __va(phys_addr); return NULL; diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index d8f94e78de8..acd3f1e34ca 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -26,6 +26,7 @@ #include <linux/kernel_stat.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/module.h> #include <asm/atomic.h> #include <asm/smp.h> @@ -37,10 +38,17 @@ #include <asm/i8253.h> #include <mach_apic.h> +#include <mach_ipi.h> #include "io_ports.h" /* + * cpu_mask that denotes the CPUs that needs timer interrupt coming in as + * IPIs in place of local APIC timers + */ +static cpumask_t timer_bcast_ipi; + +/* * Knob to control our willingness to enable the local APIC. */ int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ @@ -92,10 +100,6 @@ void __init apic_intr_init(void) /* Using APIC to generate smp_local_timer_interrupt? */ int using_apic_timer = 0; -static DEFINE_PER_CPU(int, prof_multiplier) = 1; -static DEFINE_PER_CPU(int, prof_old_multiplier) = 1; -static DEFINE_PER_CPU(int, prof_counter) = 1; - static int enabled_via_apicbase; void enable_NMI_through_LVT0 (void * dummy) @@ -935,11 +939,16 @@ void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound; static void __setup_APIC_LVTT(unsigned int clocks) { unsigned int lvtt_value, tmp_value, ver; + int cpu = smp_processor_id(); ver = GET_APIC_VERSION(apic_read(APIC_LVR)); lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; if (!APIC_INTEGRATED(ver)) lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); + + if (cpu_isset(cpu, timer_bcast_ipi)) + lvtt_value |= APIC_LVT_MASKED; + apic_write_around(APIC_LVTT, lvtt_value); /* @@ -1072,7 +1081,7 @@ void __devinit setup_secondary_APIC_clock(void) setup_APIC_timer(calibration_result); } -void __devinit disable_APIC_timer(void) +void disable_APIC_timer(void) { if (using_apic_timer) { unsigned long v; @@ -1084,7 +1093,10 @@ void __devinit disable_APIC_timer(void) void enable_APIC_timer(void) { - if (using_apic_timer) { + int cpu = smp_processor_id(); + + if (using_apic_timer && + !cpu_isset(cpu, timer_bcast_ipi)) { unsigned long v; v = apic_read(APIC_LVTT); @@ -1092,33 +1104,31 @@ void enable_APIC_timer(void) } } -/* - * the frequency of the profiling timer can be changed - * by writing a multiplier value into /proc/profile. - */ -int setup_profiling_timer(unsigned int multiplier) +void switch_APIC_timer_to_ipi(void *cpumask) { - int i; + cpumask_t mask = *(cpumask_t *)cpumask; + int cpu = smp_processor_id(); - /* - * Sanity check. [at least 500 APIC cycles should be - * between APIC interrupts as a rule of thumb, to avoid - * irqs flooding us] - */ - if ( (!multiplier) || (calibration_result/multiplier < 500)) - return -EINVAL; - - /* - * Set the new multiplier for each CPU. CPUs don't start using the - * new values until the next timer interrupt in which they do process - * accounting. At that time they also adjust their APIC timers - * accordingly. - */ - for (i = 0; i < NR_CPUS; ++i) - per_cpu(prof_multiplier, i) = multiplier; + if (cpu_isset(cpu, mask) && + !cpu_isset(cpu, timer_bcast_ipi)) { + disable_APIC_timer(); + cpu_set(cpu, timer_bcast_ipi); + } +} +EXPORT_SYMBOL(switch_APIC_timer_to_ipi); - return 0; +void switch_ipi_to_APIC_timer(void *cpumask) +{ + cpumask_t mask = *(cpumask_t *)cpumask; + int cpu = smp_processor_id(); + + if (cpu_isset(cpu, mask) && + cpu_isset(cpu, timer_bcast_ipi)) { + cpu_clear(cpu, timer_bcast_ipi); + enable_APIC_timer(); + } } +EXPORT_SYMBOL(switch_ipi_to_APIC_timer); #undef APIC_DIVISOR @@ -1134,32 +1144,10 @@ int setup_profiling_timer(unsigned int multiplier) inline void smp_local_timer_interrupt(struct pt_regs * regs) { - int cpu = smp_processor_id(); - profile_tick(CPU_PROFILING, regs); - if (--per_cpu(prof_counter, cpu) <= 0) { - /* - * 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. - */ - per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu); - if (per_cpu(prof_counter, cpu) != - per_cpu(prof_old_multiplier, cpu)) { - __setup_APIC_LVTT( - calibration_result/ - per_cpu(prof_counter, cpu)); - per_cpu(prof_old_multiplier, cpu) = - per_cpu(prof_counter, cpu); - } - #ifdef CONFIG_SMP - update_process_times(user_mode_vm(regs)); + update_process_times(user_mode_vm(regs)); #endif - } /* * We take the 'long' return path, and there every subsystem @@ -1206,6 +1194,43 @@ fastcall void smp_apic_timer_interrupt(struct pt_regs *regs) irq_exit(); } +#ifndef CONFIG_SMP +static void up_apic_timer_interrupt_call(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * the NMI deadlock-detector uses this. + */ + per_cpu(irq_stat, cpu).apic_timer_irqs++; + + smp_local_timer_interrupt(regs); +} +#endif + +void smp_send_timer_broadcast_ipi(struct pt_regs *regs) +{ + cpumask_t mask; + + cpus_and(mask, cpu_online_map, timer_bcast_ipi); + if (!cpus_empty(mask)) { +#ifdef CONFIG_SMP + send_IPI_mask(mask, LOCAL_TIMER_VECTOR); +#else + /* + * We can directly call the apic timer interrupt handler + * in UP case. Minus all irq related functions + */ + up_apic_timer_interrupt_call(regs); +#endif + } +} + +int setup_profiling_timer(unsigned int multiplier) +{ + return -EINVAL; +} + /* * This interrupt should _never_ happen with our APIC/SMP architecture */ diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 9d8827156e5..05312a8abb8 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -219,6 +219,7 @@ #include <linux/sched.h> #include <linux/pm.h> #include <linux/pm_legacy.h> +#include <linux/capability.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/smp.h> diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index e7697e077f6..333578a4e91 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -216,6 +216,12 @@ static void __init init_amd(struct cpuinfo_x86 *c) c->x86_max_cores = 1; } + if (cpuid_eax(0x80000000) >= 0x80000007) { + c->x86_power = cpuid_edx(0x80000007); + if (c->x86_power & (1<<8)) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + } + #ifdef CONFIG_X86_HT /* * On a AMD dual core setup the lower bits of the APIC id @@ -233,6 +239,7 @@ static void __init init_amd(struct cpuinfo_x86 *c) cpu, c->x86_max_cores, cpu_core_id[cpu]); } #endif + } static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 170400879f4..15aee26ec2b 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -204,7 +204,10 @@ static int __devinit have_cpuid_p(void) /* Do minimum CPU detection early. Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. - The others are not touched to avoid unwanted side effects. */ + The others are not touched to avoid unwanted side effects. + + WARNING: this function is only called on the BP. Don't add code here + that is supposed to run on all CPUs. */ static void __init early_cpu_detect(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -236,12 +239,6 @@ static void __init early_cpu_detect(void) if (cap0 & (1<<19)) c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; } - - early_intel_workaround(c); - -#ifdef CONFIG_X86_HT - phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; -#endif } void __devinit generic_identify(struct cpuinfo_x86 * c) @@ -289,6 +286,12 @@ void __devinit generic_identify(struct cpuinfo_x86 * c) get_model_name(c); /* Default name */ } } + + early_intel_workaround(c); + +#ifdef CONFIG_X86_HT + phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; +#endif } static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 871366b83b3..7975e79d5fa 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -40,8 +40,6 @@ #include <linux/acpi.h> #include <acpi/processor.h> -#include "speedstep-est-common.h" - #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg) MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); @@ -367,6 +365,7 @@ acpi_cpufreq_cpu_init ( unsigned int cpu = policy->cpu; struct cpufreq_acpi_io *data; unsigned int result = 0; + struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; union acpi_object arg0 = {ACPI_TYPE_BUFFER}; u32 arg0_buf[3]; @@ -390,7 +389,7 @@ acpi_cpufreq_cpu_init ( if (result) goto err_free; - if (is_const_loops_cpu(cpu)) { + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; } diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index edb9873e27e..9a826cde4fd 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -35,8 +35,6 @@ #include <asm/processor.h> #include <asm/cpufeature.h> -#include "speedstep-est-common.h" - #define PFX "speedstep-centrino: " #define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>" @@ -493,12 +491,13 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) unsigned l, h; int ret; int i; + struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; /* Only Intel makes Enhanced Speedstep-capable CPUs */ if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; - if (is_const_loops_cpu(policy->cpu)) { + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { centrino_driver.flags |= CPUFREQ_CONST_LOOPS; } diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h b/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h deleted file mode 100644 index 5ce995c9d86..00000000000 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Routines common for drivers handling Enhanced Speedstep Technology - * Copyright (C) 2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> - * - * Licensed under the terms of the GNU GPL License version 2 -- see - * COPYING for details. - */ - -static inline int is_const_loops_cpu(unsigned int cpu) -{ - struct cpuinfo_x86 *c = cpu_data + cpu; - - if (c->x86_vendor != X86_VENDOR_INTEL || !cpu_has(c, X86_FEATURE_EST)) - return 0; - - /* - * on P-4s, the TSC runs with constant frequency independent of cpu freq - * when we use EST - */ - if (c->x86 == 0xf) - return 1; - - return 0; -} - diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 5e2da704f0f..8c0120186b9 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -183,10 +183,13 @@ static void __devinit init_intel(struct cpuinfo_x86 *c) } #endif - if (c->x86 == 15) + if (c->x86 == 15) set_bit(X86_FEATURE_P4, c->x86_capability); if (c->x86 == 6) set_bit(X86_FEATURE_P3, c->x86_capability); + if ((c->x86 == 0xf && c->x86_model >= 0x03) || + (c->x86 == 0x6 && c->x86_model >= 0x0e)) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); } diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c index cf39e205d33..5ac051bb9d5 100644 --- a/arch/i386/kernel/cpu/mtrr/if.c +++ b/arch/i386/kernel/cpu/mtrr/if.c @@ -1,5 +1,6 @@ #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/capability.h> #include <linux/ctype.h> #include <linux/module.h> #include <linux/seq_file.h> diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 6d91b274589..89a85af33d2 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -29,7 +29,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -40,7 +40,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Other (Linux-defined) */ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "constant_tsc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -57,11 +57,21 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, + "lahf_lm", "cmp_legacy", "svm", NULL, "cr8legacy", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; + static char *x86_power_flags[] = { + "ts", /* temperature sensor */ + "fid", /* frequency id control */ + "vid", /* voltage id control */ + "ttp", /* thermal trip */ + "tm", + "stc", + NULL, + /* nothing */ /* constant_tsc - moved to flags */ + }; struct cpuinfo_x86 *c = v; int i, n = c - cpu_data; int fpu_exception; @@ -131,6 +141,17 @@ static int show_cpuinfo(struct seq_file *m, void *v) x86_cap_flags[i] != NULL ) seq_printf(m, " %s", x86_cap_flags[i]); + for (i = 0; i < 32; i++) + if (c->x86_power & (1 << i)) { + if (i < ARRAY_SIZE(x86_power_flags) && + x86_power_flags[i]) + seq_printf(m, "%s%s", + x86_power_flags[i][0]?" ":"", + x86_power_flags[i]); + else + seq_printf(m, " [%d]", i); + } + seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 0248e084017..d49dbe8dc96 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -25,7 +25,6 @@ #include <mach_ipi.h> -note_buf_t crash_notes[NR_CPUS]; /* This keeps a track of which one is crashing cpu. */ static int crashing_cpu; @@ -72,7 +71,9 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) * squirrelled away. ELF notes happen to provide * all of that that no need to invent something new. */ - buf = &crash_notes[cpu][0]; + buf = (u32*)per_cpu_ptr(crash_notes, cpu); + if (!buf) + return; memset(&prstatus, 0, sizeof(prstatus)); prstatus.pr_pid = current->pid; elf_core_copy_regs(&prstatus.pr_reg, regs); @@ -81,51 +82,12 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) final_note(buf); } -static void crash_get_current_regs(struct pt_regs *regs) -{ - __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx)); - __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx)); - __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx)); - __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi)); - __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi)); - __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp)); - __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax)); - __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp)); - __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss)); - __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs)); - __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds)); - __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes)); - __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags)); - - regs->eip = (unsigned long)current_text_addr(); -} - -/* CPU does not save ss and esp on stack if execution is already - * running in kernel mode at the time of NMI occurrence. This code - * fixes it. - */ -static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs) -{ - memcpy(newregs, oldregs, sizeof(*newregs)); - newregs->esp = (unsigned long)&(oldregs->esp); - __asm__ __volatile__("xorl %eax, %eax;"); - __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss)); -} - -/* We may have saved_regs from where the error came from - * or it is NULL if via a direct panic(). - */ -static void crash_save_self(struct pt_regs *saved_regs) +static void crash_save_self(struct pt_regs *regs) { - struct pt_regs regs; int cpu; cpu = smp_processor_id(); - if (saved_regs) - crash_setup_regs(®s, saved_regs); - else - crash_get_current_regs(®s); - crash_save_this_cpu(®s, cpu); + crash_save_this_cpu(regs, cpu); } #ifdef CONFIG_SMP @@ -144,7 +106,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu) local_irq_disable(); if (!user_mode(regs)) { - crash_setup_regs(&fixed_regs, regs); + crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } crash_save_this_cpu(regs, cpu); diff --git a/arch/i386/kernel/crash_dump.c b/arch/i386/kernel/crash_dump.c new file mode 100644 index 00000000000..3f532df488b --- /dev/null +++ b/arch/i386/kernel/crash_dump.c @@ -0,0 +1,74 @@ +/* + * kernel/crash_dump.c - Memory preserving reboot related code. + * + * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) + * Copyright (C) IBM Corporation, 2004. All rights reserved + */ + +#include <linux/errno.h> +#include <linux/highmem.h> +#include <linux/crash_dump.h> + +#include <asm/uaccess.h> + +static void *kdump_buf_page; + +/** + * copy_oldmem_page - copy one page from "oldmem" + * @pfn: page frame number to be copied + * @buf: target memory address for the copy; this can be in kernel address + * space or user address space (see @userbuf) + * @csize: number of bytes to copy + * @offset: offset in bytes into the page (based on pfn) to begin the copy + * @userbuf: if set, @buf is in user address space, use copy_to_user(), + * otherwise @buf is in kernel address space, use memcpy(). + * + * Copy a page from "oldmem". For this page, there is no pte mapped + * in the current kernel. We stitch up a pte, similar to kmap_atomic. + * + * Calling copy_to_user() in atomic context is not desirable. Hence first + * copying the data to a pre-allocated kernel page and then copying to user + * space in non-atomic context. + */ +ssize_t copy_oldmem_page(unsigned long pfn, char *buf, + size_t csize, unsigned long offset, int userbuf) +{ + void *vaddr; + + if (!csize) + return 0; + + vaddr = kmap_atomic_pfn(pfn, KM_PTE0); + + if (!userbuf) { + memcpy(buf, (vaddr + offset), csize); + kunmap_atomic(vaddr, KM_PTE0); + } else { + if (!kdump_buf_page) { + printk(KERN_WARNING "Kdump: Kdump buffer page not" + " allocated\n"); + return -EFAULT; + } + copy_page(kdump_buf_page, vaddr); + kunmap_atomic(vaddr, KM_PTE0); + if (copy_to_user(buf, (kdump_buf_page + offset), csize)) + return -EFAULT; + } + + return csize; +} + +static int __init kdump_buf_page_init(void) +{ + int ret = 0; + + kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!kdump_buf_page) { + printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer" + " page\n"); + ret = -ENOMEM; + } + + return ret; +} +arch_initcall(kdump_buf_page_init); diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index 58516e2ac17..6a93d75db43 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -4,7 +4,7 @@ #include <linux/module.h> #include <linux/dmi.h> #include <linux/bootmem.h> - +#include <linux/slab.h> static char * __init dmi_string(struct dmi_header *dm, u8 s) { @@ -19,7 +19,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s) } if (*bp != 0) { - str = alloc_bootmem(strlen(bp) + 1); + str = dmi_alloc(strlen(bp) + 1); if (str != NULL) strcpy(str, bp); else @@ -40,7 +40,7 @@ static int __init dmi_table(u32 base, int len, int num, u8 *buf, *data; int i = 0; - buf = bt_ioremap(base, len); + buf = dmi_ioremap(base, len); if (buf == NULL) return -1; @@ -65,7 +65,7 @@ static int __init dmi_table(u32 base, int len, int num, data += 2; i++; } - bt_iounmap(buf, len); + dmi_iounmap(buf, len); return 0; } @@ -112,7 +112,7 @@ static void __init dmi_save_devices(struct dmi_header *dm) if ((*d & 0x80) == 0) continue; - dev = alloc_bootmem(sizeof(*dev)); + dev = dmi_alloc(sizeof(*dev)); if (!dev) { printk(KERN_ERR "dmi_save_devices: out of memory.\n"); break; @@ -131,7 +131,7 @@ static void __init dmi_save_ipmi_device(struct dmi_header *dm) struct dmi_device *dev; void * data; - data = alloc_bootmem(dm->length); + data = dmi_alloc(dm->length); if (data == NULL) { printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); return; @@ -139,7 +139,7 @@ static void __init dmi_save_ipmi_device(struct dmi_header *dm) memcpy(data, dm, dm->length); - dev = alloc_bootmem(sizeof(*dev)); + dev = dmi_alloc(sizeof(*dev)); if (!dev) { printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n"); return; @@ -221,7 +221,7 @@ void __init dmi_scan_machine(void) } } -out: printk(KERN_INFO "DMI not present.\n"); +out: printk(KERN_INFO "DMI not present or invalid.\n"); } diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 7554f8fd874..f2dd218d88c 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1649,7 +1649,7 @@ static void __init enable_IO_APIC(void) for(apic = 0; apic < nr_ioapics; apic++) { int pin; /* See if any of the pins is in ExtINT mode */ - for(pin = 0; pin < nr_ioapic_registers[i]; pin++) { + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { struct IO_APIC_route_entry entry; spin_lock_irqsave(&ioapic_lock, flags); *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index b59a34dbe26..79026f026b8 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -7,6 +7,7 @@ #include <linux/sched.h> #include <linux/kernel.h> +#include <linux/capability.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 19edcd526ba..6483eeb1a4e 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -58,13 +58,9 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode) int __kprobes arch_prepare_kprobe(struct kprobe *p) { - return 0; -} - -void __kprobes arch_copy_kprobe(struct kprobe *p) -{ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; + return 0; } void __kprobes arch_arm_kprobe(struct kprobe *p) @@ -81,10 +77,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void __kprobes arch_remove_kprobe(struct kprobe *p) -{ -} - static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { kcb->prev_kprobe.kp = kprobe_running(); @@ -196,6 +188,19 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) kcb->kprobe_status = KPROBE_REENTER; return 1; } else { + if (regs->eflags & VM_MASK) { + /* We are in virtual-8086 mode. Return 0 */ + goto no_kprobe; + } + if (*addr != BREAKPOINT_INSTRUCTION) { + /* The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + regs->eip -= sizeof(kprobe_opcode_t); + ret = 1; + goto no_kprobe; + } p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 165f13158c6..d3fdf0057d8 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -70,6 +70,7 @@ */ //#define DEBUG /* pr_debug */ +#include <linux/capability.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/sched.h> @@ -165,7 +166,7 @@ static void collect_cpu_info (void *unused) wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ - serialize_cpu(); + sync_core(); /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", @@ -379,7 +380,7 @@ static void do_update_one (void * unused) wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ - serialize_cpu(); + sync_core(); /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 035928f3f6c..2185377fdde 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct task_struct *tsk; int err; - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; - /* - * The below -8 is to reserve 8 bytes on top of the ring0 stack. - * This is necessary to guarantee that the entire "struct pt_regs" - * is accessable even if the CPU haven't stored the SS/ESP registers - * on the stack (interrupt gate does not save these registers - * when switching to the same priv ring). - * Therefore beware: accessing the xss/esp fields of the - * "struct pt_regs" is possible, but they may contain the - * completely wrong values. - */ - childregs = (struct pt_regs *) ((unsigned long) childregs - 8); + childregs = task_pt_regs(p); *childregs = *regs; childregs->eax = 0; childregs->esp = esp; @@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread); */ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs ptregs; - - ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info + - /* see comments in copy_thread() about -8 */ - THREAD_SIZE - sizeof(ptregs) - 8); + struct pt_regs ptregs = *task_pt_regs(tsk); ptregs.xcs &= 0xffff; ptregs.xds &= 0xffff; ptregs.xes &= 0xffff; @@ -601,8 +585,8 @@ static inline void disable_tsc(struct task_struct *prev_p, * gcc should eliminate the ->thread_info dereference if * has_secure_computing returns 0 at compile time (SECCOMP=n). */ - prev = prev_p->thread_info; - next = next_p->thread_info; + prev = task_thread_info(prev_p); + next = task_thread_info(next_p); if (has_secure_computing(prev) || has_secure_computing(next)) { /* slow path here */ @@ -787,7 +771,7 @@ unsigned long get_wchan(struct task_struct *p) int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p->thread_info; + stack_page = (unsigned long)task_stack_page(p); esp = p->thread.esp; if (!stack_page || esp < stack_page || esp > top_esp+stack_page) return 0; diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 2fa5803a759..d207242976d 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -12,6 +12,7 @@ #include <linux/efi.h> #include <linux/dmi.h> #include <linux/ctype.h> +#include <linux/pm.h> #include <asm/uaccess.h> #include <asm/apic.h> #include <asm/desc.h> @@ -355,10 +356,10 @@ void machine_halt(void) void machine_power_off(void) { - machine_shutdown(); - - if (pm_power_off) + if (pm_power_off) { + machine_shutdown(); pm_power_off(); + } } diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 27c956db046..51e513b4f72 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -45,6 +45,7 @@ #include <linux/nodemask.h> #include <linux/kexec.h> #include <linux/crash_dump.h> +#include <linux/dmi.h> #include <video/edid.h> @@ -146,7 +147,6 @@ EXPORT_SYMBOL(ist_info); struct e820map e820; extern void early_cpu_init(void); -extern void dmi_scan_machine(void); extern void generic_apic_probe(char *); extern int root_mountflags; @@ -898,7 +898,7 @@ static void __init parse_cmdline_early (char ** cmdline_p) } } #endif -#ifdef CONFIG_CRASH_DUMP +#ifdef CONFIG_PROC_VMCORE /* elfcorehdr= specifies the location of elf core header * stored by the crashed kernel. */ @@ -1584,7 +1584,7 @@ void __init setup_arch(char **cmdline_p) if (s) { extern void setup_early_printk(char *); - setup_early_printk(s); + setup_early_printk(strchr(s, '=') + 1); printk("early console enabled\n"); } } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index b3c2e2c2674..255adb49826 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu) /* initialize thread_struct. we really want to avoid destroy * idle tread */ - idle->thread.esp = (unsigned long)(((struct pt_regs *) - (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); + idle->thread.esp = (unsigned long)task_pt_regs(idle); init_idle(idle, cpu); return idle; } @@ -1096,6 +1095,7 @@ static void smp_tune_scheduling (void) cachesize = 16; /* Pentiums, 2x8kB cache */ bandwidth = 100; } + max_cache_size = cachesize * 1024; } } diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 41c5b2dc620..a14d594bfbe 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -302,6 +302,12 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) do_timer_interrupt(irq, regs); write_sequnlock(&xtime_lock); + +#ifdef CONFIG_X86_LOCAL_APIC + if (using_apic_timer) + smp_send_timer_broadcast_ipi(regs); +#endif + return IRQ_HANDLED; } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 53ad954e3ba..b9f0030a2eb 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -120,7 +120,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); - printk(" [<%08lx>] ", addr); + printk(KERN_EMERG " [<%08lx>] ", addr); print_symbol("%s", addr); printk("\n"); ebp = *(unsigned long *)ebp; @@ -129,7 +129,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; if (__kernel_text_address(addr)) { - printk(" [<%08lx>]", addr); + printk(KERN_EMERG " [<%08lx>]", addr); print_symbol(" %s", addr); printk("\n"); } @@ -161,7 +161,7 @@ void show_trace(struct task_struct *task, unsigned long * stack) stack = (unsigned long*)context->previous_esp; if (!stack) break; - printk(" =======================\n"); + printk(KERN_EMERG " =======================\n"); } } @@ -178,14 +178,15 @@ void show_stack(struct task_struct *task, unsigned long *esp) } stack = esp; + printk(KERN_EMERG); for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) - printk("\n "); + printk("\n" KERN_EMERG " "); printk("%08lx ", *stack++); } - printk("\nCall Trace:\n"); + printk("\n" KERN_EMERG "Call Trace:\n"); show_trace(task, esp); } @@ -216,18 +217,18 @@ void show_registers(struct pt_regs *regs) ss = regs->xss & 0xffff; } print_modules(); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx" - " (%s) \n", + printk(KERN_EMERG "CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\n" + "EFLAGS: %08lx (%s) \n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags, system_utsname.release); - print_symbol("EIP is at %s\n", regs->eip); - printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", + print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip); + printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); - printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", + printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", regs->esi, regs->edi, regs->ebp, esp); - printk("ds: %04x es: %04x ss: %04x\n", + printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); - printk("Process %s (pid: %d, threadinfo=%p task=%p)", + printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)", current->comm, current->pid, current_thread_info(), current); /* * When in-kernel, we also print out the stack and code at the @@ -236,10 +237,10 @@ void show_registers(struct pt_regs *regs) if (in_kernel) { u8 __user *eip; - printk("\nStack: "); + printk("\n" KERN_EMERG "Stack: "); show_stack(NULL, (unsigned long*)esp); - printk("Code: "); + printk(KERN_EMERG "Code: "); eip = (u8 __user *)regs->eip - 43; for (i = 0; i < 64; i++, eip++) { @@ -280,15 +281,15 @@ static void handle_BUG(struct pt_regs *regs) (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) file = "<bad filename>"; - printk("------------[ cut here ]------------\n"); - printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line); + printk(KERN_EMERG "------------[ cut here ]------------\n"); + printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); no_bug: return; /* Here we know it was a BUG but file-n-line is unavailable */ bug: - printk("Kernel BUG\n"); + printk(KERN_EMERG "Kernel BUG\n"); } /* This is gone through when something in the kernel @@ -321,16 +322,20 @@ void die(const char * str, struct pt_regs * regs, long err) if (++die.lock_owner_depth < 3) { int nl = 0; handle_BUG(regs); - printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); + printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk(KERN_EMERG "PREEMPT "); nl = 1; #endif #ifdef CONFIG_SMP + if (!nl) + printk(KERN_EMERG); printk("SMP "); nl = 1; #endif #ifdef CONFIG_DEBUG_PAGEALLOC + if (!nl) + printk(KERN_EMERG); printk("DEBUG_PAGEALLOC"); nl = 1; #endif @@ -339,7 +344,7 @@ void die(const char * str, struct pt_regs * regs, long err) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); show_registers(regs); } else - printk(KERN_ERR "Recursive die() failure, output suppressed\n"); + printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); bust_spinlocks(0); die.lock_owner = -1; @@ -527,8 +532,10 @@ gp_in_kernel: static void mem_parity_error(unsigned char reason, struct pt_regs * regs) { - printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); - printk("You probably have a hardware problem with your RAM chips\n"); + printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying " + "to continue\n"); + printk(KERN_EMERG "You probably have a hardware problem with your RAM " + "chips\n"); /* Clear and disable the memory parity error line. */ clear_mem_error(reason); @@ -538,7 +545,7 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) { unsigned long i; - printk("NMI: IOCK error (debug interrupt?)\n"); + printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); /* Re-enable the IOCK line, wait for a few seconds */ @@ -580,11 +587,11 @@ void die_nmi (struct pt_regs *regs, const char *msg) * to get a message out. */ bust_spinlocks(1); - printk(msg); + printk(KERN_EMERG "%s", msg); printk(" on CPU%d, eip %08lx, registers:\n", smp_processor_id(), regs->eip); show_registers(regs); - printk("console shuts up ...\n"); + printk(KERN_EMERG "console shuts up ...\n"); console_silent(); spin_unlock(&nmi_print_lock); bust_spinlocks(0); @@ -990,8 +997,8 @@ asmlinkage void math_state_restore(struct pt_regs regs) asmlinkage void math_emulate(long arg) { - printk("math-emulation not enabled and no coprocessor found.\n"); - printk("killing %s.\n",current->comm); + printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n"); + printk(KERN_EMERG "killing %s.\n",current->comm); force_sig(SIGFPE,current); schedule(); } diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index fc1993564f9..0c90ae54ddf 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -30,6 +30,7 @@ * */ +#include <linux/capability.h> #include <linux/config.h> #include <linux/errno.h> #include <linux/interrupt.h> @@ -310,7 +311,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk "movl %1,%%ebp\n\t" "jmp resume_userspace" : /* no outputs */ - :"r" (&info->regs), "r" (tsk->thread_info) : "ax"); + :"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax"); /* we never return here */ } diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index e8a53552b13..d0cadb33b54 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -224,7 +224,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable) return; if (!enable) mutex_debug_check_no_locks_freed(page_address(page), - page_address(page+numpages)); + numpages * PAGE_SIZE); /* the return value is ignored - the calls cannot fail, * large pages are disabled at boot time. diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 57b047c27e4..f722e1a2594 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -25,7 +25,6 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ -falign-functions=32 -frename-registers -fno-optimize-sibling-calls CFLAGS_KERNEL := -mconstant-gp -GCC_VERSION := $(call cc-version) GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)") CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") @@ -37,7 +36,7 @@ $(error Sorry, you need a newer version of the assember, one that is built from ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz) endif -ifeq ($(GCC_VERSION),0304) +ifeq ($(call cc-version),0304) cflags-$(CONFIG_ITANIUM) += -mtune=merced cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley endif diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 19ee635eeb7..a346e1833bf 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -26,6 +26,7 @@ #include <linux/fcntl.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/capability.h> #include <linux/console.h> #include <linux/module.h> #include <linux/serial.h> diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile index 2ed90da8116..61cb60affd9 100644 --- a/arch/ia64/ia32/Makefile +++ b/arch/ia64/ia32/Makefile @@ -2,11 +2,9 @@ # Makefile for the ia32 kernel emulation subsystem. # -obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o \ +obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \ ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o -CFLAGS_ia32_ioctl.o += -Ifs/ - # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and # restore_ia32_fpstate_live() can be sure the live register contain user-level state. CFLAGS_ia32_signal.o += -mfixed-range=f16-f31 diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h index b73b8b6b10c..a47f63b204f 100644 --- a/arch/ia64/ia32/elfcore32.h +++ b/arch/ia64/ia32/elfcore32.h @@ -95,8 +95,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { - struct pt_regs *pp = ia64_task_regs(t); - ELF_CORE_COPY_REGS((*elfregs), pp); + ELF_CORE_COPY_REGS((*elfregs), task_pt_regs(t)); return 1; } diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index 494fad6bf37..95fe04400f6 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -469,7 +469,7 @@ ia32_syscall_table: data8 sys32_epoll_wait data8 sys_remap_file_pages data8 sys_set_tid_address - data8 sys32_timer_create + data8 compat_sys_timer_create data8 compat_sys_timer_settime /* 260 */ data8 compat_sys_timer_gettime data8 sys_timer_getoverrun diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c deleted file mode 100644 index 88739394f6d..00000000000 --- a/arch/ia64/ia32/ia32_ioctl.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * IA32 Architecture-specific ioctl shim code - * - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> - * Copyright (C) 2001-2003 Hewlett-Packard Co - * David Mosberger-Tang <davidm@hpl.hp.com> - */ - -#include <linux/signal.h> /* argh, msdos_fs.h isn't self-contained... */ -#include <linux/syscalls.h> -#include "ia32priv.h" - -#define INCLUDES -#include "compat_ioctl.c" - -#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) - -#define DO_IOCTL(fd, cmd, arg) ({ \ - int _ret; \ - mm_segment_t _old_fs = get_fs(); \ - \ - set_fs(KERNEL_DS); \ - _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \ - set_fs(_old_fs); \ - _ret; \ -}) - -#define CODE -#include "compat_ioctl.c" - -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, -#define IOCTL_TABLE_START \ - struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END \ - }; - -IOCTL_TABLE_START -#define DECLARES -#include "compat_ioctl.c" -#include <linux/compat_ioctl.h> -IOCTL_TABLE_END - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index aa891c9bc9b..5856510210f 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -255,7 +255,7 @@ save_ia32_fpstate_live (struct _fpstate_ia32 __user *save) */ fp_tos = (fsr>>11)&0x7; fr8_st_map = (8-fp_tos)&0x7; - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); ia64f2ia32f(fpregp, &ptp->f8); copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); @@ -389,7 +389,7 @@ restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save) fr8_st_map = (8-fp_tos)&0x7; fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f8, fpregp); copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index 4f630043b3a..c187743965a 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -58,7 +58,7 @@ load_desc (u16 selector) void ia32_load_segment_descriptors (struct task_struct *task) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); /* Setup the segment descriptors */ regs->r24 = load_desc(regs->r16 >> 16); /* ESD */ @@ -113,7 +113,7 @@ void ia32_load_state (struct task_struct *t) { unsigned long eflag, fsr, fcr, fir, fdr, tssd; - struct pt_regs *regs = ia64_task_regs(t); + struct pt_regs *regs = task_pt_regs(t); eflag = t->thread.eflag; fsr = t->thread.fsr; diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 9f8e8d55887..3945d378bd7 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -48,6 +48,7 @@ #include <linux/ptrace.h> #include <linux/stat.h> #include <linux/ipc.h> +#include <linux/capability.h> #include <linux/compat.h> #include <linux/vfs.h> #include <linux/mman.h> @@ -1481,7 +1482,7 @@ getreg (struct task_struct *child, int regno) { struct pt_regs *child_regs; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); switch (regno / sizeof(int)) { case PT_EBX: return child_regs->r11; case PT_ECX: return child_regs->r9; @@ -1509,7 +1510,7 @@ putreg (struct task_struct *child, int regno, unsigned int value) { struct pt_regs *child_regs; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); switch (regno / sizeof(int)) { case PT_EBX: child_regs->r11 = value; break; case PT_ECX: child_regs->r9 = value; break; @@ -1625,7 +1626,7 @@ save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) put_fpreg(i, &save->st_space[i], ptp, swp, tos); @@ -1658,7 +1659,7 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __us * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) get_fpreg(i, &save->st_space[i], ptp, swp, tos); @@ -1689,7 +1690,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); @@ -1733,7 +1734,7 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __u * Stack frames start with 16-bytes of temp space */ swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = ia64_task_regs(tsk); + ptp = task_pt_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); @@ -2553,34 +2554,6 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info) return 0; } -asmlinkage long -sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) -{ - struct sigevent se; - mm_segment_t oldfs; - timer_t t; - long err; - - if (se32 == NULL) - return sys_timer_create(clock, NULL, timer_id); - - if (get_compat_sigevent(&se, se32)) - return -EFAULT; - - if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) - return -EFAULT; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t); - set_fs(oldfs); - - if (!err) - err = __put_user (t, timer_id); - - return err; -} - long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, __u32 len_low, __u32 len_high, int advice) { diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 89a70400c4f..346fedf9ea4 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -467,10 +467,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); } -void __kprobes arch_remove_kprobe(struct kprobe *p) -{ -} - /* * We are resuming execution after a single step fault, so the pt_regs * structure reflects the register state after we executed the instruction @@ -642,6 +638,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } + } else if (!is_ia64_break_inst(regs)) { + /* The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + ret = 1; + goto no_kprobe; } else { /* Not our break */ goto no_kprobe; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 355af15287c..ee7eec9ee57 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -766,7 +766,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, l = strlen(previous_current->comm); snprintf(comm, sizeof(comm), "%s %*s %d", current->comm, l, previous_current->comm, - previous_current->thread_info->cpu); + task_thread_info(previous_current)->cpu); } memcpy(current->comm, comm, sizeof(current->comm)); @@ -1423,7 +1423,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, struct task_struct *p = (struct task_struct *)((char *)mca_data + offset); struct thread_info *ti; memset(p, 0, KERNEL_STACK_SIZE); - ti = (struct thread_info *)((char *)p + IA64_TASK_SIZE); + ti = task_thread_info(p); ti->flags = _TIF_MCA_INIT; ti->preempt_count = 1; ti->task = p; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 410d4804fa6..bd87cb6b7a8 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -38,6 +38,7 @@ #include <linux/pagemap.h> #include <linux/mount.h> #include <linux/bitops.h> +#include <linux/capability.h> #include <linux/rcupdate.h> #include <asm/errno.h> @@ -1709,7 +1710,7 @@ static void pfm_syswide_force_stop(void *info) { pfm_context_t *ctx = (pfm_context_t *)info; - struct pt_regs *regs = ia64_task_regs(current); + struct pt_regs *regs = task_pt_regs(current); struct task_struct *owner; unsigned long flags; int ret; @@ -1814,7 +1815,7 @@ pfm_flush(struct file *filp) is_system = ctx->ctx_fl_system; task = PFM_CTX_TASK(ctx); - regs = ia64_task_regs(task); + regs = task_pt_regs(task); DPRINT(("ctx_state=%d is_current=%d\n", state, @@ -1944,7 +1945,7 @@ pfm_close(struct inode *inode, struct file *filp) is_system = ctx->ctx_fl_system; task = PFM_CTX_TASK(ctx); - regs = ia64_task_regs(task); + regs = task_pt_regs(task); DPRINT(("ctx_state=%d is_current=%d\n", state, @@ -4051,7 +4052,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) */ ia64_psr(regs)->up = 0; } else { - tregs = ia64_task_regs(task); + tregs = task_pt_regs(task); /* * stop monitoring at the user level @@ -4133,7 +4134,7 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) ia64_psr(regs)->up = 1; } else { - tregs = ia64_task_regs(ctx->ctx_task); + tregs = task_pt_regs(ctx->ctx_task); /* * start monitoring at the kernel level the next @@ -4403,7 +4404,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) /* * when not current, task MUST be stopped, so this is safe */ - regs = ia64_task_regs(task); + regs = task_pt_regs(task); /* force a full reload */ ctx->ctx_last_activation = PFM_INVALID_ACTIVATION; @@ -4529,7 +4530,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg /* * per-task mode */ - tregs = task == current ? regs : ia64_task_regs(task); + tregs = task == current ? regs : task_pt_regs(task); if (task == current) { /* @@ -4592,7 +4593,7 @@ pfm_exit_thread(struct task_struct *task) { pfm_context_t *ctx; unsigned long flags; - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); int ret, state; int free_ok = 0; @@ -4925,7 +4926,7 @@ restart_args: if (unlikely(ret)) goto abort_locked; skip_fd: - ret = (*func)(ctx, args_k, count, ia64_task_regs(current)); + ret = (*func)(ctx, args_k, count, task_pt_regs(current)); call_made = 1; @@ -5049,7 +5050,7 @@ pfm_handle_work(void) pfm_clear_task_notify(); - regs = ia64_task_regs(current); + regs = task_pt_regs(current); /* * extract reason for being here and clear @@ -5793,7 +5794,7 @@ pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_c * on every CPU, so we can rely on the pid to identify the idle task. */ if ((info & PFM_CPUINFO_EXCL_IDLE) == 0 || task->pid) { - regs = ia64_task_regs(task); + regs = task_pt_regs(task); ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0; return; } @@ -5876,7 +5877,7 @@ pfm_save_regs(struct task_struct *task) flags = pfm_protect_ctx_ctxsw(ctx); if (ctx->ctx_state == PFM_CTX_ZOMBIE) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); pfm_clear_psr_up(); @@ -6076,7 +6077,7 @@ pfm_load_regs (struct task_struct *task) BUG_ON(psr & IA64_PSR_I); if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) { - struct pt_regs *regs = ia64_task_regs(task); + struct pt_regs *regs = task_pt_regs(task); BUG_ON(ctx->ctx_smpl_hdr); @@ -6445,7 +6446,7 @@ pfm_alt_save_pmu_state(void *data) { struct pt_regs *regs; - regs = ia64_task_regs(current); + regs = task_pt_regs(current); DPRINT(("called\n")); @@ -6471,7 +6472,7 @@ pfm_alt_restore_pmu_state(void *data) { struct pt_regs *regs; - regs = ia64_task_regs(current); + regs = task_pt_regs(current); DPRINT(("called\n")); @@ -6753,7 +6754,7 @@ dump_pmu_state(const char *from) local_irq_save(flags); this_cpu = smp_processor_id(); - regs = ia64_task_regs(current); + regs = task_pt_regs(current); info = PFM_CPUINFO_GET(); dcr = ia64_getreg(_IA64_REG_CR_DCR); diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index e9904c74d2b..309d59658e5 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -328,7 +328,7 @@ ia64_save_extra (struct task_struct *task) #endif #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(task))) + if (IS_IA32_PROCESS(task_pt_regs(task))) ia32_save_state(task); #endif } @@ -353,7 +353,7 @@ ia64_load_extra (struct task_struct *task) #endif #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(task))) + if (IS_IA32_PROCESS(task_pt_regs(task))) ia32_load_state(task); #endif } @@ -488,7 +488,7 @@ copy_thread (int nr, unsigned long clone_flags, * If we're cloning an IA32 task then save the IA32 extra * state from the current task to the new task */ - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { ia32_save_state(p); if (clone_flags & CLONE_SETTLS) retval = ia32_clone_tls(p, child_ptregs); @@ -701,7 +701,7 @@ int kernel_thread_helper (int (*fn)(void *), void *arg) { #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { /* A kernel thread is always a 64-bit process. */ current->thread.map_base = DEFAULT_MAP_BASE; current->thread.task_size = DEFAULT_TASK_SIZE; @@ -722,7 +722,7 @@ flush_thread (void) current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { + if (IS_IA32_PROCESS(task_pt_regs(current))) { ia32_drop_partial_page_list(current); current->thread.task_size = IA32_PAGE_OFFSET; set_fs(USER_DS); @@ -755,7 +755,7 @@ exit_thread (void) if (current->thread.flags & IA64_THREAD_DBG_VALID) pfm_release_debug_registers(current); #endif - if (IS_IA32_PROCESS(ia64_task_regs(current))) + if (IS_IA32_PROCESS(task_pt_regs(current))) ia32_drop_partial_page_list(current); } diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 8d88eeea02d..eaed14aac6a 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -254,7 +254,7 @@ get_rnat (struct task_struct *task, struct switch_stack *sw, long num_regs, nbits; struct pt_regs *pt; - pt = ia64_task_regs(task); + pt = task_pt_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; @@ -314,7 +314,7 @@ put_rnat (struct task_struct *task, struct switch_stack *sw, struct pt_regs *pt; unsigned long cfm, *urbs_kargs; - pt = ia64_task_regs(task); + pt = task_pt_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; @@ -407,7 +407,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, urbs_end = (long *) user_rbs_end; laddr = (unsigned long *) addr; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); bspstore = (unsigned long *) child_regs->ar_bspstore; krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; if (on_kernel_rbs(addr, (unsigned long) bspstore, @@ -467,7 +467,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, struct pt_regs *child_regs; laddr = (unsigned long *) addr; - child_regs = ia64_task_regs(child); + child_regs = task_pt_regs(child); bspstore = (unsigned long *) child_regs->ar_bspstore; krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; if (on_kernel_rbs(addr, (unsigned long) bspstore, @@ -567,7 +567,7 @@ thread_matches (struct task_struct *thread, unsigned long addr) */ return 0; - thread_regs = ia64_task_regs(thread); + thread_regs = task_pt_regs(thread); thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL); if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end)) return 0; @@ -627,7 +627,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr) inline void ia64_flush_fph (struct task_struct *task) { - struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); + struct ia64_psr *psr = ia64_psr(task_pt_regs(task)); /* * Prevent migrating this task while @@ -653,7 +653,7 @@ ia64_flush_fph (struct task_struct *task) void ia64_sync_fph (struct task_struct *task) { - struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); + struct ia64_psr *psr = ia64_psr(task_pt_regs(task)); ia64_flush_fph(task); if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) { @@ -794,7 +794,7 @@ access_uarea (struct task_struct *child, unsigned long addr, + offsetof(struct pt_regs, reg))) - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); if ((addr & 0x7) != 0) { @@ -1120,7 +1120,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs))) return -EIO; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); unw_init_from_blocked_task(&info, child); if (unw_unwind_to_user(&info) < 0) { @@ -1265,7 +1265,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs))) return -EIO; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); unw_init_from_blocked_task(&info, child); if (unw_unwind_to_user(&info) < 0) { @@ -1403,7 +1403,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) void ptrace_disable (struct task_struct *child) { - struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child)); + struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child)); /* make sure the single step/taken-branch trap bits are not set: */ child_psr->ss = 0; @@ -1456,7 +1456,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) if (ret < 0) goto out_tsk; - pt = ia64_task_regs(child); + pt = task_pt_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); switch (request) { diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 1461dc660b4..a87a162a308 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -29,6 +29,7 @@ * Replace some NR_CPUS by cpus_online, for hotplug cpu. */ +#include <linux/capability.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/module.h> diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c33305d8e5e..c0766575a3a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -60,6 +60,7 @@ #include <asm/smp.h> #include <asm/system.h> #include <asm/unistd.h> +#include <asm/system.h> #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" @@ -695,6 +696,7 @@ static void get_max_cacheline_size (void) { unsigned long line_size, max = 1; + unsigned int cache_size = 0; u64 l, levels, unique_caches; pal_cache_config_info_t cci; s64 status; @@ -724,6 +726,8 @@ get_max_cacheline_size (void) line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; + if (cache_size < cci.pcci_cache_size) + cache_size = cci.pcci_cache_size; if (!cci.pcci_unified) { status = ia64_pal_cache_config_info(l, /* cache_type (instruction)= */ 1, @@ -740,6 +744,9 @@ get_max_cacheline_size (void) ia64_i_cache_stride_shift = cci.pcci_stride; } out: +#ifdef CONFIG_SMP + max_cache_size = max(max_cache_size, cache_size); +#endif if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; } @@ -794,7 +801,7 @@ cpu_init (void) #endif /* Clear the stack memory reserved for pt_regs: */ - memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); + memset(task_pt_regs(current), 0, sizeof(struct pt_regs)); ia64_set_kr(IA64_KR_FPU_OWNER, 0); @@ -870,6 +877,15 @@ cpu_init (void) pm_idle = default_idle; } +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible. + */ +void sched_cacheflush(void) +{ + ia64_sal_cache_flush(3); +} + void check_bugs (void) { diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 58ce07efc56..463f6bb44d0 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -655,11 +655,11 @@ set_sigdelayed(pid_t pid, int signo, int code, void __user *addr) if (!t) return; - t->thread_info->sigdelayed.signo = signo; - t->thread_info->sigdelayed.code = code; - t->thread_info->sigdelayed.addr = addr; - t->thread_info->sigdelayed.start_time = start_time; - t->thread_info->sigdelayed.pid = pid; + task_thread_info(t)->sigdelayed.signo = signo; + task_thread_info(t)->sigdelayed.code = code; + task_thread_info(t)->sigdelayed.addr = addr; + task_thread_info(t)->sigdelayed.start_time = start_time; + task_thread_info(t)->sigdelayed.pid = pid; wmb(); set_tsk_thread_flag(t, TIF_SIGDELAYED); } diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index f2dbcd1db0d..c7b943f1019 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -151,7 +151,7 @@ out: asmlinkage long sys_pipe (void) { - struct pt_regs *regs = ia64_task_regs(current); + struct pt_regs *regs = task_pt_regs(current); int fd[2]; int retval; diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 768c21deb2e..493fb3f38dc 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -11,6 +11,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/proc_fs.h> +#include <linux/capability.h> #include <linux/device.h> #include <linux/delay.h> #include <asm/system.h> diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index fae67bbb52f..a3dcc3fab4b 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -12,10 +12,6 @@ config M32R config SBUS bool -config UID16 - bool - default n - config GENERIC_ISA_DMA bool default y diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index e5ec134d81d..dbc8a392105 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c @@ -18,8 +18,6 @@ #include <asm/irq.h> #include <asm/tlbflush.h> -extern void dump_thread(struct pt_regs *, struct user *); - #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) extern struct drive_info_struct drive_info; EXPORT_SYMBOL(drive_info); @@ -27,7 +25,6 @@ EXPORT_SYMBOL(drive_info); /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 3bf55d92933..5dfc7ea45cf 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -242,13 +242,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) int copy_thread(int nr, unsigned long clone_flags, unsigned long spu, unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) { - struct pt_regs *childregs; - unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE; + struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); /* Copy registers */ - sp -= sizeof (struct pt_regs); - childregs = (struct pt_regs *)sp; *childregs = *regs; childregs->spu = spu; @@ -261,14 +258,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long spu, } /* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - /* M32R_FIXME */ -} - -/* * Capture the user space registers if the task is not running (in user space) */ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 9b75caaf5ce..340a3bf59b8 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -35,23 +35,6 @@ #include <asm/mmu_context.h> /* - * Get the address of the live pt_regs for the specified task. - * These are saved onto the top kernel stack when the process - * is not running. - * - * Note: if a user thread is execve'd from kernel space, the - * kernel stack will not be empty on entry to the kernel, so - * ptracing these tasks will fail. - */ -static inline struct pt_regs * -get_user_regs(struct task_struct *task) -{ - return (struct pt_regs *) - ((unsigned long)task->thread_info + THREAD_SIZE - - sizeof(struct pt_regs)); -} - -/* * This routine will get a word off of the process kernel stack. */ static inline unsigned long int @@ -59,7 +42,7 @@ get_stack_long(struct task_struct *task, int offset) { unsigned long *stack; - stack = (unsigned long *)get_user_regs(task); + stack = (unsigned long *)task_pt_regs(task); return stack[offset]; } @@ -72,7 +55,7 @@ put_stack_long(struct task_struct *task, int offset, unsigned long data) { unsigned long *stack; - stack = (unsigned long *)get_user_regs(task); + stack = (unsigned long *)task_pt_regs(task); stack[offset] = data; return 0; @@ -208,7 +191,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, */ static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; } @@ -223,7 +206,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) ret = -EFAULT; if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); + struct pt_regs *regs = task_pt_regs(tsk); *regs = newregs; ret = 0; } diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index b90c54169fa..d7ec16e7fb2 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -286,7 +286,7 @@ static void __init do_boot_cpu(int phys_id) /* So we see what's up */ printk("Booting processor %d/%d\n", phys_id, cpu_id); stack_start.spi = (void *)idle->thread.sp; - idle->thread_info->cpu = cpu_id; + task_thread_info(idle)->cpu = cpu_id; /* * Send Startup IPI diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index d9edf2d1a49..b0aa61bf870 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -126,9 +126,9 @@ void __init amiga_init_IRQ(void) gayle.inten = GAYLE_IRQ_IDE; /* turn off all interrupts and enable the master interrupt bit */ - custom.intena = 0x7fff; - custom.intreq = 0x7fff; - custom.intena = IF_SETCLR | IF_INTEN; + amiga_custom.intena = 0x7fff; + amiga_custom.intreq = 0x7fff; + amiga_custom.intena = IF_SETCLR | IF_INTEN; cia_init_IRQ(&ciaa_base); cia_init_IRQ(&ciab_base); @@ -245,7 +245,7 @@ int amiga_request_irq(unsigned int irq, /* enable the interrupt */ if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) - custom.intena = IF_SETCLR | amiga_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; return error; } @@ -274,7 +274,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id) amiga_delete_irq(&ami_irq_list[irq], dev_id); /* if server list empty, disable the interrupt */ if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } else { if (ami_irq_list[irq]->dev_id != dev_id) printk("%s: removing probably wrong IRQ %d from %s\n", @@ -283,7 +283,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id) ami_irq_list[irq]->flags = 0; ami_irq_list[irq]->dev_id = NULL; ami_irq_list[irq]->devname = NULL; - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } } @@ -327,7 +327,7 @@ void amiga_enable_irq(unsigned int irq) } /* enable the interrupt */ - custom.intena = IF_SETCLR | amiga_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; } void amiga_disable_irq(unsigned int irq) @@ -358,7 +358,7 @@ void amiga_disable_irq(unsigned int irq) } /* disable the interrupt */ - custom.intena = amiga_intena_vals[irq]; + amiga_custom.intena = amiga_intena_vals[irq]; } inline void amiga_do_irq(int irq, struct pt_regs *fp) @@ -373,7 +373,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) kstat_cpu(0).irqs[SYS_IRQS + irq]++; - custom.intreq = amiga_intena_vals[irq]; + amiga_custom.intreq = amiga_intena_vals[irq]; for (node = ami_irq_list[irq]; node; node = node->next) node->handler(irq, node->dev_id, fp); @@ -385,23 +385,23 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { - custom.intreq = IF_TBE; + amiga_custom.intreq = IF_TBE; amiga_do_irq(IRQ_AMIGA_TBE, fp); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { - custom.intreq = IF_DSKBLK; + amiga_custom.intreq = IF_DSKBLK; amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { - custom.intreq = IF_SOFT; + amiga_custom.intreq = IF_SOFT; amiga_do_irq(IRQ_AMIGA_SOFT, fp); } return IRQ_HANDLED; @@ -409,17 +409,17 @@ static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if a blitter interrupt */ if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; + amiga_custom.intreq = IF_BLIT; amiga_do_irq(IRQ_AMIGA_BLIT, fp); } /* if a copper interrupt */ if (ints & IF_COPER) { - custom.intreq = IF_COPER; + amiga_custom.intreq = IF_COPER; amiga_do_irq(IRQ_AMIGA_COPPER, fp); } @@ -431,29 +431,29 @@ static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if audio 0 interrupt */ if (ints & IF_AUD0) { - custom.intreq = IF_AUD0; + amiga_custom.intreq = IF_AUD0; amiga_do_irq(IRQ_AMIGA_AUD0, fp); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { - custom.intreq = IF_AUD1; + amiga_custom.intreq = IF_AUD1; amiga_do_irq(IRQ_AMIGA_AUD1, fp); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { - custom.intreq = IF_AUD2; + amiga_custom.intreq = IF_AUD2; amiga_do_irq(IRQ_AMIGA_AUD2, fp); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { - custom.intreq = IF_AUD3; + amiga_custom.intreq = IF_AUD3; amiga_do_irq(IRQ_AMIGA_AUD3, fp); } return IRQ_HANDLED; @@ -461,7 +461,7 @@ static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp) static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { @@ -471,7 +471,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp) /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { - custom.intreq = IF_DSKSYN; + amiga_custom.intreq = IF_DSKSYN; amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); } return IRQ_HANDLED; diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index bd5d134e9f1..ae94db5d93b 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c @@ -24,6 +24,8 @@ static const signed char sine_data[] = { }; #define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0])) +#define custom amiga_custom + /* * The minimum period for audio may be modified by the frame buffer * device since it depends on htotal (for OCS/ECS/AGA) diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 7d55682615e..9476eb9440f 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -60,7 +60,7 @@ unsigned char cia_set_irq(struct ciabase *base, unsigned char mask) else base->icr_data &= ~mask; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old & base->icr_mask; } @@ -89,7 +89,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) } } if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old; } @@ -133,7 +133,7 @@ static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp) mach_irq = base->cia_irq; irq = SYS_IRQS + mach_irq; ints = cia_set_irq(base, CIA_ICR_ALL); - custom.intreq = base->int_mask; + amiga_custom.intreq = base->int_mask; for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) { if (ints & 1) { kstat_cpu(0).irqs[irq]++; @@ -162,7 +162,7 @@ void __init cia_init_IRQ(struct ciabase *base) /* install CIA handler */ request_irq(base->handler_irq, cia_handler, 0, base->name, base); - custom.intena = IF_SETCLR | base->int_mask; + amiga_custom.intena = IF_SETCLR | base->int_mask; } int cia_get_irq_list(struct ciabase *base, struct seq_file *p) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 4775e18a78f..12e3706fe02 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -105,9 +105,6 @@ static int a2000_hwclk (int, struct rtc_time *); static int amiga_set_clock_mmss (unsigned long); static unsigned int amiga_get_ss (void); extern void amiga_mksound( unsigned int count, unsigned int ticks ); -#ifdef CONFIG_AMIGA_FLOPPY -extern void amiga_floppy_setup(char *, int *); -#endif static void amiga_reset (void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); @@ -290,7 +287,7 @@ static void __init amiga_identify(void) case CS_OCS: case CS_ECS: case CS_AGA: - switch (custom.deniseid & 0xf) { + switch (amiga_custom.deniseid & 0xf) { case 0x0c: AMIGAHW_SET(DENISE_HR); break; @@ -303,7 +300,7 @@ static void __init amiga_identify(void) AMIGAHW_SET(DENISE); break; } - switch ((custom.vposr>>8) & 0x7f) { + switch ((amiga_custom.vposr>>8) & 0x7f) { case 0x00: AMIGAHW_SET(AGNUS_PAL); break; @@ -427,13 +424,7 @@ void __init config_amiga(void) mach_set_clock_mmss = amiga_set_clock_mmss; mach_get_ss = amiga_get_ss; -#ifdef CONFIG_AMIGA_FLOPPY - mach_floppy_setup = amiga_floppy_setup; -#endif mach_reset = amiga_reset; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = amiga_mksound; #endif @@ -447,9 +438,9 @@ void __init config_amiga(void) amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ /* clear all DMA bits */ - custom.dmacon = DMAF_ALL; + amiga_custom.dmacon = DMAF_ALL; /* ensure that the DMA master bit is set */ - custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER; /* don't use Z2 RAM as system memory on Z3 capable machines */ if (AMIGAHW_PRESENT(ZORRO3)) { @@ -830,8 +821,8 @@ static void amiga_savekmsg_init(void) static void amiga_serial_putc(char c) { - custom.serdat = (unsigned char)c | 0x100; - while (!(custom.serdatr & 0x2000)) + amiga_custom.serdat = (unsigned char)c | 0x100; + while (!(amiga_custom.serdatr & 0x2000)) ; } @@ -855,11 +846,11 @@ int amiga_serial_console_wait_key(struct console *co) { int ch; - while (!(custom.intreqr & IF_RBF)) + while (!(amiga_custom.intreqr & IF_RBF)) barrier(); - ch = custom.serdatr & 0xff; + ch = amiga_custom.serdatr & 0xff; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return ch; } diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 26492947125..d401962d9b2 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -176,9 +176,6 @@ void config_apollo(void) { mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ mach_process_int = dn_process_int; mach_reset = dn_dummy_reset; /* */ -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_HEARTBEAT mach_heartbeat = dn_heartbeat; #endif diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 9261d2deeaf..1012b08e552 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -52,9 +52,6 @@ int atari_rtc_year_offset; /* local function prototypes */ static void atari_reset( void ); -#ifdef CONFIG_ATARI_FLOPPY -extern void atari_floppy_setup(char *, int *); -#endif static void atari_get_model(char *model); static int atari_get_hardware_list(char *buffer); @@ -244,12 +241,6 @@ void __init config_atari(void) mach_get_irq_list = show_atari_interrupts; mach_gettimeoffset = atari_gettimeoffset; mach_reset = atari_reset; -#ifdef CONFIG_ATARI_FLOPPY - mach_floppy_setup = atari_floppy_setup; -#endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffff; #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = atari_mksound; diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c index eb63ca6ed94..703cbc6dc9c 100644 --- a/arch/m68k/bvme6000/rtc.c +++ b/arch/m68k/bvme6000/rtc.c @@ -11,6 +11,7 @@ #include <linux/miscdevice.h> #include <linux/slab.h> #include <linux/ioport.h> +#include <linux/capability.h> #include <linux/fcntl.h> #include <linux/init.h> #include <linux/poll.h> @@ -46,6 +47,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned char msr; unsigned long flags; struct rtc_time wtime; + void __user *argp = (void __user *)arg; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ @@ -68,7 +70,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); rtc->msr = msr; local_irq_restore(flags); - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + return copy_to_user(argp, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ @@ -80,8 +82,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) + if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index a0b854f3f94..6d129eef370 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -261,9 +261,6 @@ void __init config_hp300(void) #ifdef CONFIG_HEARTBEAT mach_heartbeat = hp300_pulse; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffffff; if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) { diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index c787c5ba951..246a8820c22 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -92,7 +92,7 @@ int main(void) DEFINE(TRAP_TRACE, TRAP_TRACE); /* offsets into the custom struct */ - DEFINE(CUSTOMBASE, &custom); + DEFINE(CUSTOMBASE, &amiga_custom); DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index d4336d846df..70002c146ee 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -273,8 +273,10 @@ * Macintosh console support */ +#ifdef CONFIG_FRAMEBUFFER_CONSOLE #define CONSOLE #define CONSOLE_PENGUIN +#endif /* * Macintosh serial debug support; outputs boot info to the printer diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 73e2f5e168d..3d7f2000b71 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -23,8 +23,6 @@ asmlinkage long long __lshrdi3 (long long, int); asmlinkage long long __muldi3 (long long, long long); extern char m68k_debug_device[]; -extern void dump_thread(struct pt_regs *, struct user *); - /* platform dependent support */ EXPORT_SYMBOL(m68k_machtype); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 13d109328a4..3f9cb55d035 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -238,10 +238,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs * childregs; struct switch_stack * childstack, *stack; - unsigned long stack_offset, *retp; + unsigned long *retp; - stack_offset = THREAD_SIZE - sizeof(struct pt_regs); - childregs = (struct pt_regs *) ((unsigned long) (p->thread_info) + stack_offset); + childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; *childregs = *regs; childregs->d0 = 0; @@ -386,7 +385,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)(p->thread_info); + stack_page = (unsigned long)task_stack_page(p); fp = ((struct switch_stack *)p->thread.ksp)->a6; do { if (fp < stack_page+sizeof(struct thread_info) || diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index d6ca99242e5..750d5b3c971 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -84,9 +84,6 @@ void (*mach_reset)( void ); void (*mach_halt)( void ); void (*mach_power_off)( void ); long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) -void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -#endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int); EXPORT_SYMBOL(mach_heartbeat); @@ -100,6 +97,8 @@ void (*mach_beep)(unsigned int, unsigned int); #if defined(CONFIG_ISA) && defined(MULTI_ISA) int isa_type; int isa_sex; +EXPORT_SYMBOL(isa_type); +EXPORT_SYMBOL(isa_sex); #endif extern int amiga_parse_bootinfo(const struct bi_record *); @@ -280,6 +279,10 @@ void __init setup_arch(char **cmdline_p) } } +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + switch (m68k_machtype) { #ifdef CONFIG_AMIGA case MACH_AMIGA: @@ -521,16 +524,6 @@ int get_hardware_list(char *buffer) return(len); } - -#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) -void __init floppy_setup(char *str, int *ints) -{ - if (mach_floppy_setup) - mach_floppy_setup (str, ints); -} - -#endif - void check_bugs(void) { #ifndef CONFIG_M68KFPU_EMU diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 9c636a4c238..866917bfa02 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -96,7 +96,7 @@ asmlinkage int do_sigsuspend(struct pt_regs *regs) asmlinkage int do_rt_sigsuspend(struct pt_regs *regs) { - sigset_t *unewset = (sigset_t *)regs->d1; + sigset_t __user *unewset = (sigset_t __user *)regs->d1; size_t sigsetsize = (size_t)regs->d2; sigset_t saveset, newset; @@ -122,8 +122,8 @@ do_rt_sigsuspend(struct pt_regs *regs) } asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -154,7 +154,7 @@ sys_sigaction(int sig, const struct old_sigaction *act, } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return do_sigaltstack(uss, uoss, rdusp()); } @@ -169,10 +169,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss) struct sigframe { - char *pretcode; + char __user *pretcode; int sig; int code; - struct sigcontext *psc; + struct sigcontext __user *psc; char retcode[8]; unsigned long extramask[_NSIG_WORDS-1]; struct sigcontext sc; @@ -180,10 +180,10 @@ struct sigframe struct rt_sigframe { - char *pretcode; + char __user *pretcode; int sig; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; char retcode[8]; struct siginfo info; struct ucontext uc; @@ -248,7 +248,7 @@ out: #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] -static inline int rt_restore_fpu_state(struct ucontext *uc) +static inline int rt_restore_fpu_state(struct ucontext __user *uc) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; @@ -267,7 +267,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) return 0; } - if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) + if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) goto out; if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { if (!CPU_IS_060) @@ -306,7 +306,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) "m" (*fpregs.f_fpcntl)); } if (context_size && - __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, + __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, context_size)) goto out; __asm__ volatile (".chip 68k/68881\n\t" @@ -319,7 +319,7 @@ out: } static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, int *pd0) { int fsize, formatvec; @@ -404,10 +404,10 @@ badframe: static inline int rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, - struct ucontext *uc, int *pd0) + struct ucontext __user *uc, int *pd0) { int fsize, temp; - greg_t *gregs = uc->uc_mcontext.gregs; + greg_t __user *gregs = uc->uc_mcontext.gregs; unsigned long usp; int err; @@ -506,7 +506,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); - struct sigframe *frame = (struct sigframe *)(usp - 4); + struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); sigset_t set; int d0; @@ -536,7 +536,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); - struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); sigset_t set; int d0; @@ -596,7 +596,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) } } -static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; @@ -617,7 +617,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) ".chip 68k" : : "m" (*fpstate) : "memory"); - err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); + err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { fpregset_t fpregs; if (!CPU_IS_060) @@ -642,7 +642,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) sizeof(fpregs)); } if (context_size) - err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, + err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, context_size); return err; } @@ -662,10 +662,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, save_fpu_state(sc, regs); } -static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) { struct switch_stack *sw = (struct switch_stack *)regs - 1; - greg_t *gregs = uc->uc_mcontext.gregs; + greg_t __user *gregs = uc->uc_mcontext.gregs; int err = 0; err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); @@ -753,7 +753,7 @@ static inline void push_cache (unsigned long vaddr) } } -static inline void * +static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long usp; @@ -766,13 +766,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) if (!on_sig_stack(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } - return (void *)((usp - frame_size) & -8UL); + return (void __user *)((usp - frame_size) & -8UL); } static void setup_frame (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { - struct sigframe *frame; + struct sigframe __user *frame; int fsize = frame_extra_sizes[regs->format]; struct sigcontext context; int err = 0; @@ -813,7 +813,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, err |= __put_user(frame->retcode, &frame->pretcode); /* moveq #,d0; trap #0 */ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), - (long *)(frame->retcode)); + (long __user *)(frame->retcode)); if (err) goto give_sigsegv; @@ -849,7 +849,7 @@ give_sigsegv: static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { - struct rt_sigframe *frame; + struct rt_sigframe __user *frame; int fsize = frame_extra_sizes[regs->format]; int err = 0; @@ -880,8 +880,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, + err |= __put_user(NULL, &frame->uc.uc_link); + err |= __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags); @@ -893,8 +893,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(frame->retcode, &frame->pretcode); /* moveq #,d0; notb d0; trap #0 */ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), - (long *)(frame->retcode + 0)); - err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); + (long __user *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); if (err) goto give_sigsegv; diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 2ed7b783f65..143c552d38f 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -6,6 +6,7 @@ * platform. */ +#include <linux/capability.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/mm.h> @@ -31,7 +32,7 @@ * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(unsigned long __user * fildes) { int fd[2]; int error; @@ -93,7 +94,7 @@ struct mmap_arg_struct { unsigned long offset; }; -asmlinkage int old_mmap(struct mmap_arg_struct *arg) +asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int error = -EFAULT; @@ -159,11 +160,11 @@ out: struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp, *outp, *exp; + struct timeval __user *tvp; }; -asmlinkage int old_select(struct sel_arg_struct *arg) +asmlinkage int old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -179,7 +180,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg) * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void __user *ptr, long fifth) { int version, ret; @@ -189,14 +190,14 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (call <= SEMCTL) switch (call) { case SEMOP: - return sys_semop (first, (struct sembuf *)ptr, second); + return sys_semop (first, ptr, second); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) + if (get_user(fourth.__pad, (void __user *__user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } @@ -206,31 +207,26 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (call <= MSGCTL) switch (call) { case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); + return sys_msgsnd (first, ptr, second, third); case MSGRCV: switch (version) { case 0: { struct ipc_kludge tmp; if (!ptr) return -EINVAL; - if (copy_from_user (&tmp, - (struct ipc_kludge *)ptr, - sizeof (tmp))) + if (copy_from_user (&tmp, ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); } default: - return sys_msgrcv (first, - (struct msgbuf *) ptr, + return sys_msgrcv (first, ptr, second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: - return sys_msgctl (first, second, - (struct msqid_ds *) ptr); + return sys_msgctl (first, second, ptr); default: return -ENOSYS; } @@ -240,20 +236,18 @@ asmlinkage int sys_ipc (uint call, int first, int second, switch (version) { default: { ulong raddr; - ret = do_shmat (first, (char *) ptr, - second, &raddr); + ret = do_shmat (first, ptr, second, &raddr); if (ret) return ret; - return put_user (raddr, (ulong *) third); + return put_user (raddr, (ulong __user *) third); } } case SHMDT: - return sys_shmdt ((char *)ptr); + return sys_shmdt (ptr); case SHMGET: return sys_shmget (first, second, third); case SHMCTL: - return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + return sys_shmctl (first, second, ptr); default: return -ENOSYS; } diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index deb36e8b04a..cdf58fbb3e7 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -169,25 +169,25 @@ void __init trap_init (void) if (CPU_IS_060 && !FPU_IS_EMU) { /* set up IFPSP entry points */ - asmlinkage void snan_vec(void) asm ("_060_fpsp_snan"); - asmlinkage void operr_vec(void) asm ("_060_fpsp_operr"); - asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl"); - asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl"); - asmlinkage void dz_vec(void) asm ("_060_fpsp_dz"); - asmlinkage void inex_vec(void) asm ("_060_fpsp_inex"); - asmlinkage void fline_vec(void) asm ("_060_fpsp_fline"); - asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp"); - asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd"); - - vectors[VEC_FPNAN] = snan_vec; - vectors[VEC_FPOE] = operr_vec; - vectors[VEC_FPOVER] = ovfl_vec; - vectors[VEC_FPUNDER] = unfl_vec; - vectors[VEC_FPDIVZ] = dz_vec; - vectors[VEC_FPIR] = inex_vec; - vectors[VEC_LINE11] = fline_vec; - vectors[VEC_FPUNSUP] = unsupp_vec; - vectors[VEC_UNIMPEA] = effadd_vec; + asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); + asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); + asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); + asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); + asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); + asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); + asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); + asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); + asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); + + vectors[VEC_FPNAN] = snan_vec6; + vectors[VEC_FPOE] = operr_vec6; + vectors[VEC_FPOVER] = ovfl_vec6; + vectors[VEC_FPUNDER] = unfl_vec6; + vectors[VEC_FPDIVZ] = dz_vec6; + vectors[VEC_FPIR] = inex_vec6; + vectors[VEC_LINE11] = fline_vec6; + vectors[VEC_FPUNSUP] = unsupp_vec6; + vectors[VEC_UNIMPEA] = effadd_vec6; } /* if running on an amiga, make the NMI interrupt do nothing */ diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index e58654f3f8d..69d1d3d30c7 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -13,6 +13,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } :text = 0x4e75 diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index cc37e8d3c1e..65cc39c2418 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -14,6 +14,7 @@ SECTIONS *(.head) *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } :text = 0x4e75 @@ -66,7 +67,7 @@ __init_begin = .; __initramfs_end = .; . = ALIGN(8192); __init_end = .; - .init.task : { *(init_task) } + .data.init.task : { *(.data.init_task) } .bss : { *(.bss) } /* BSS */ diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 4a5c5445c61..cb13c6e3cca 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -134,7 +134,7 @@ EXPORT_SYMBOL(csum_partial); */ unsigned int -csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, +csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst, int len, int sum, int *csum_err) { /* diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index cd19cbb213e..14f8d3f4e19 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -212,9 +212,6 @@ void __init config_mac(void) mach_reset = mac_reset; mach_halt = mac_poweroff; mach_power_off = mac_poweroff; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif mach_max_dma_address = 0xffffffff; #if 0 mach_debug_init = mac_debug_init; diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index d889ba80ccd..9179a379840 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -293,8 +293,8 @@ void __init iop_init(void) } for (i = 0 ; i < NUM_IOP_CHAN ; i++) { - iop_send_queue[IOP_NUM_SCC][i] = 0; - iop_send_queue[IOP_NUM_ISM][i] = 0; + iop_send_queue[IOP_NUM_SCC][i] = NULL; + iop_send_queue[IOP_NUM_ISM][i] = NULL; iop_listeners[IOP_NUM_SCC][i].devname = NULL; iop_listeners[IOP_NUM_SCC][i].handler = NULL; iop_listeners[IOP_NUM_ISM][i].devname = NULL; diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 5b80d7cd954..bbb0c3b95e9 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -39,72 +39,163 @@ extern struct mac_booter_data mac_bi_data; static void (*rom_reset)(void); -#ifdef CONFIG_ADB -/* - * Return the current time as the number of seconds since January 1, 1904. - */ - -static long adb_read_time(void) +#ifdef CONFIG_ADB_CUDA +static long cuda_read_time(void) { - volatile struct adb_request req; + struct adb_request req; long time; - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_GET_TIME); + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) + return 0; + while (!req.complete) + cuda_poll(); time = (req.reply[3] << 24) | (req.reply[4] << 16) | (req.reply[5] << 8) | req.reply[6]; return time - RTC_OFFSET; } -/* - * Set the current system time - */ +static void cuda_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + (data >> 24) & 0xFF, (data >> 16) & 0xFF, + (data >> 8) & 0xFF, data & 0xFF) < 0) + return; + while (!req.complete) + cuda_poll(); +} -static void adb_write_time(long data) +static __u8 cuda_read_pram(int offset) { - volatile struct adb_request req; + struct adb_request req; + if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF) < 0) + return 0; + while (!req.complete) + cuda_poll(); + return req.reply[3]; +} - data += RTC_OFFSET; +static void cuda_write_pram(int offset, __u8 data) +{ + struct adb_request req; + if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) + return; + while (!req.complete) + cuda_poll(); +} +#else +#define cuda_read_time() 0 +#define cuda_write_time(n) +#define cuda_read_pram NULL +#define cuda_write_pram NULL +#endif + +#ifdef CONFIG_ADB_PMU68K +static long pmu_read_time(void) +{ + struct adb_request req; + long time; + + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return 0; + while (!req.complete) + pmu_poll(); - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 6, CUDA_PACKET, CUDA_SET_TIME, + time = (req.reply[0] << 24) | (req.reply[1] << 16) + | (req.reply[2] << 8) | req.reply[3]; + return time - RTC_OFFSET; +} + +static void pmu_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, (data >> 24) & 0xFF, (data >> 16) & 0xFF, - (data >> 8) & 0xFF, data & 0xFF); + (data >> 8) & 0xFF, data & 0xFF) < 0) + return; + while (!req.complete) + pmu_poll(); } -/* - * Get a byte from the NVRAM - */ +static __u8 pmu_read_pram(int offset) +{ + struct adb_request req; + if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, + (offset >> 8) & 0xFF, offset & 0xFF) < 0) + return 0; + while (!req.complete) + pmu_poll(); + return req.reply[3]; +} -static __u8 adb_read_pram(int offset) +static void pmu_write_pram(int offset, __u8 data) { - volatile struct adb_request req; + struct adb_request req; + if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) + return; + while (!req.complete) + pmu_poll(); +} +#else +#define pmu_read_time() 0 +#define pmu_write_time(n) +#define pmu_read_pram NULL +#define pmu_write_pram NULL +#endif - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 4, CUDA_PACKET, CUDA_GET_PRAM, - (offset >> 8) & 0xFF, offset & 0xFF); - return req.reply[3]; +#ifdef CONFIG_ADB_MACIISI +extern int maciisi_request(struct adb_request *req, + void (*done)(struct adb_request *), int nbytes, ...); + +static long maciisi_read_time(void) +{ + struct adb_request req; + long time; + + if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME)) + return 0; + + time = (req.reply[3] << 24) | (req.reply[4] << 16) + | (req.reply[5] << 8) | req.reply[6]; + return time - RTC_OFFSET; } -/* - * Write a byte to the NVRAM - */ +static void maciisi_write_time(long data) +{ + struct adb_request req; + data += RTC_OFFSET; + maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + (data >> 24) & 0xFF, (data >> 16) & 0xFF, + (data >> 8) & 0xFF, data & 0xFF); +} -static void adb_write_pram(int offset, __u8 data) +static __u8 maciisi_read_pram(int offset) { - volatile struct adb_request req; + struct adb_request req; + if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF)) + return 0; + return req.reply[3]; +} - adb_request((struct adb_request *) &req, NULL, - ADBREQ_RAW|ADBREQ_SYNC, - 5, CUDA_PACKET, CUDA_SET_PRAM, - (offset >> 8) & 0xFF, offset & 0xFF, - data); +static void maciisi_write_pram(int offset, __u8 data) +{ + struct adb_request req; + maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, + (offset >> 8) & 0xFF, offset & 0xFF, data); } -#endif /* CONFIG_ADB */ +#else +#define maciisi_read_time() 0 +#define maciisi_write_time(n) +#define maciisi_read_pram NULL +#define maciisi_write_pram NULL +#endif /* * VIA PRAM/RTC access routines @@ -305,42 +396,55 @@ static void oss_shutdown(void) static void cuda_restart(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_RESET_SYSTEM); + struct adb_request req; + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0) + return; + while (!req.complete) + cuda_poll(); } static void cuda_shutdown(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, CUDA_PACKET, CUDA_POWERDOWN); + struct adb_request req; + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0) + return; + while (!req.complete) + cuda_poll(); } #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K void pmu_restart(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 3, PMU_PACKET, PMU_SET_INTR_MASK, - PMU_INT_ADB|PMU_INT_TICK); - - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 2, PMU_PACKET, PMU_RESET); + struct adb_request req; + if (pmu_request(&req, NULL, + 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) + return; + while (!req.complete) + pmu_poll(); + if (pmu_request(&req, NULL, 1, PMU_RESET) < 0) + return; + while (!req.complete) + pmu_poll(); } void pmu_shutdown(void) { - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 3, PMU_PACKET, PMU_SET_INTR_MASK, - PMU_INT_ADB|PMU_INT_TICK); - - adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, - 6, PMU_PACKET, PMU_SHUTDOWN, - 'M', 'A', 'T', 'T'); + struct adb_request req; + if (pmu_request(&req, NULL, + 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) + return; + while (!req.complete) + pmu_poll(); + if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0) + return; + while (!req.complete) + pmu_poll(); } -#endif /* CONFIG_ADB_PMU */ +#endif /* *------------------------------------------------------------------- @@ -351,21 +455,22 @@ void pmu_shutdown(void) void mac_pram_read(int offset, __u8 *buffer, int len) { - __u8 (*func)(int) = NULL; + __u8 (*func)(int); int i; - if (macintosh_config->adb_type == MAC_ADB_IISI || - macintosh_config->adb_type == MAC_ADB_PB1 || - macintosh_config->adb_type == MAC_ADB_PB2 || - macintosh_config->adb_type == MAC_ADB_CUDA) { -#ifdef CONFIG_ADB - func = adb_read_pram; -#else - return; -#endif - } else { + switch(macintosh_config->adb_type) { + case MAC_ADB_IISI: + func = maciisi_read_pram; break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + func = pmu_read_pram; break; + case MAC_ADB_CUDA: + func = cuda_read_pram; break; + default: func = via_read_pram; } + if (!func) + return; for (i = 0 ; i < len ; i++) { buffer[i] = (*func)(offset++); } @@ -373,21 +478,22 @@ void mac_pram_read(int offset, __u8 *buffer, int len) void mac_pram_write(int offset, __u8 *buffer, int len) { - void (*func)(int, __u8) = NULL; + void (*func)(int, __u8); int i; - if (macintosh_config->adb_type == MAC_ADB_IISI || - macintosh_config->adb_type == MAC_ADB_PB1 || - macintosh_config->adb_type == MAC_ADB_PB2 || - macintosh_config->adb_type == MAC_ADB_CUDA) { -#ifdef CONFIG_ADB - func = adb_write_pram; -#else - return; -#endif - } else { + switch(macintosh_config->adb_type) { + case MAC_ADB_IISI: + func = maciisi_write_pram; break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + func = pmu_write_pram; break; + case MAC_ADB_CUDA: + func = cuda_write_pram; break; + default: func = via_write_pram; } + if (!func) + return; for (i = 0 ; i < len ; i++) { (*func)(offset++, buffer[i]); } @@ -408,7 +514,7 @@ void mac_poweroff(void) } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { cuda_shutdown(); #endif -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K } else if (macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2) { pmu_shutdown(); @@ -448,7 +554,7 @@ void mac_reset(void) } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { cuda_restart(); #endif -#ifdef CONFIG_ADB_PMU +#ifdef CONFIG_ADB_PMU68K } else if (macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2) { pmu_restart(); @@ -466,12 +572,13 @@ void mac_reset(void) /* make a 1-to-1 mapping, using the transparent tran. reg. */ unsigned long virt = (unsigned long) mac_reset; unsigned long phys = virt_to_phys(mac_reset); + unsigned long addr = (phys&0xFF000000)|0x8777; unsigned long offset = phys-virt; local_irq_disable(); /* lets not screw this up, ok? */ __asm__ __volatile__(".chip 68030\n\t" "pmove %0,%/tt0\n\t" ".chip 68k" - : : "m" ((phys&0xFF000000)|0x8777)); + : : "m" (addr)); /* Now jump to physical address so we can disable MMU */ __asm__ __volatile__( ".chip 68030\n\t" @@ -588,20 +695,22 @@ int mac_hwclk(int op, struct rtc_time *t) unsigned long now; if (!op) { /* read */ - if (macintosh_config->adb_type == MAC_ADB_II) { + switch (macintosh_config->adb_type) { + case MAC_ADB_II: + case MAC_ADB_IOP: now = via_read_time(); - } else -#ifdef CONFIG_ADB - if ((macintosh_config->adb_type == MAC_ADB_IISI) || - (macintosh_config->adb_type == MAC_ADB_PB1) || - (macintosh_config->adb_type == MAC_ADB_PB2) || - (macintosh_config->adb_type == MAC_ADB_CUDA)) { - now = adb_read_time(); - } else -#endif - if (macintosh_config->adb_type == MAC_ADB_IOP) { - now = via_read_time(); - } else { + break; + case MAC_ADB_IISI: + now = maciisi_read_time(); + break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + now = pmu_read_time(); + break; + case MAC_ADB_CUDA: + now = cuda_read_time(); + break; + default: now = 0; } @@ -619,15 +728,20 @@ int mac_hwclk(int op, struct rtc_time *t) now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - if (macintosh_config->adb_type == MAC_ADB_II) { - via_write_time(now); - } else if ((macintosh_config->adb_type == MAC_ADB_IISI) || - (macintosh_config->adb_type == MAC_ADB_PB1) || - (macintosh_config->adb_type == MAC_ADB_PB2) || - (macintosh_config->adb_type == MAC_ADB_CUDA)) { - adb_write_time(now); - } else if (macintosh_config->adb_type == MAC_ADB_IOP) { + switch (macintosh_config->adb_type) { + case MAC_ADB_II: + case MAC_ADB_IOP: via_write_time(now); + break; + case MAC_ADB_CUDA: + cuda_write_time(now); + break; + case MAC_ADB_PB1: + case MAC_ADB_PB2: + pmu_write_time(now); + break; + case MAC_ADB_IISI: + maciisi_write_time(now); } #endif } diff --git a/arch/m68k/math-emu/multi_arith.h b/arch/m68k/math-emu/multi_arith.h index 02251e5afd8..4ad0ca918e2 100644 --- a/arch/m68k/math-emu/multi_arith.h +++ b/arch/m68k/math-emu/multi_arith.h @@ -366,7 +366,7 @@ static inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, #define fp_mul64(desth, destl, src1, src2) ({ \ asm ("mulu.l %2,%1:%0" : "=d" (destl), "=d" (desth) \ - : "g" (src1), "0" (src2)); \ + : "dm" (src1), "0" (src2)); \ }) #define fp_div64(quot, rem, srch, srcl, div) \ asm ("divu.l %2,%1:%0" : "=d" (quot), "=d" (rem) \ diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index fe2383e36b0..85ad19a0ac7 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -102,7 +102,7 @@ static inline void free_io_area(void *addr) */ /* Rewritten by Andreas Schwab to remove all races. */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) { struct vm_struct *area; unsigned long virtaddr, retaddr; @@ -121,7 +121,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) if (MACH_IS_AMIGA) { if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) && (cacheflag == IOMAP_NOCACHE_SER)) - return (void *)physaddr; + return (void __iomem *)physaddr; } #endif @@ -218,21 +218,21 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) #endif flush_tlb_all(); - return (void *)retaddr; + return (void __iomem *)retaddr; } /* * Unmap a ioremap()ed region again */ -void iounmap(void *addr) +void iounmap(void __iomem *addr) { #ifdef CONFIG_AMIGA if ((!MACH_IS_AMIGA) || (((unsigned long)addr < 0x40000000) || ((unsigned long)addr > 0x60000000))) - free_io_area(addr); + free_io_area((__force void *)addr); #else - free_io_area(addr); + free_io_area((__force void *)addr); #endif } diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index 7977eae50af..a69fe3048ed 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c @@ -11,6 +11,7 @@ #include <linux/miscdevice.h> #include <linux/slab.h> #include <linux/ioport.h> +#include <linux/capability.h> #include <linux/fcntl.h> #include <linux/init.h> #include <linux/poll.h> @@ -44,6 +45,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; unsigned long flags; struct rtc_time wtime; + void __user *argp = (void __user *)arg; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ @@ -63,7 +65,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; rtc->ctrl = 0; local_irq_restore(flags); - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + return copy_to_user(argp, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ @@ -75,8 +77,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) + if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 02b626bae4a..5e0f9b04d45 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -36,8 +36,6 @@ #include <asm/machdep.h> #include <asm/q40_master.h> -extern void floppy_setup(char *str, int *ints); - extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ extern void q40_init_IRQ (void); @@ -194,9 +192,6 @@ void __init config_q40(void) mach_heartbeat = q40_heartbeat; #endif mach_halt = q40_halt; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif /* disable a few things that SMSQ might have left enabled */ q40_disable_irqs(); diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c index 77d05bcc322..f1ca0dfbaa6 100644 --- a/arch/m68k/sun3/config.c +++ b/arch/m68k/sun3/config.c @@ -160,9 +160,6 @@ void __init config_sun3(void) mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; mach_get_hardware_list = sun3_get_hardware_list; -#if defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif memory_start = ((((int)&_end) + 0x2000) & ~0x1fff); // PROM seems to want the last couple of physical pages. --m diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c index 0ef547f5494..0920f5d3360 100644 --- a/arch/m68k/sun3x/config.c +++ b/arch/m68k/sun3x/config.c @@ -71,10 +71,6 @@ void __init config_sun3x(void) mach_get_model = sun3_get_model; mach_get_hardware_list = sun3x_get_hardware_list; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - sun3_intreg = (unsigned char *)SUN3X_INTREG; /* only the serial console is known to work anyway... */ diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index b6b5c14e55f..6f880cbff1c 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -99,7 +99,6 @@ cflags-$(CONFIG_M68360) := -m68332 AFLAGS += $(cflags-y) CFLAGS += $(cflags-y) -CFLAGS += -O1 -g CFLAGS += -D__linux__ CFLAGS += -DUTS_SYSNAME=\"uClinux\" diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c index b2c62eeb3ba..eddb8d3e130 100644 --- a/arch/m68knommu/kernel/m68k_ksyms.c +++ b/arch/m68knommu/kernel/m68k_ksyms.c @@ -18,7 +18,6 @@ #include <asm/checksum.h> #include <asm/current.h> -extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); /* platform dependent support */ @@ -26,7 +25,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 82e7ec88880..99bf4382479 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -198,10 +198,9 @@ int copy_thread(int nr, unsigned long clone_flags, { struct pt_regs * childregs; struct switch_stack * childstack, *stack; - unsigned long stack_offset, *retp; + unsigned long *retp; - stack_offset = THREAD_SIZE - sizeof(struct pt_regs); - childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset); + childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; *childregs = *regs; childregs->d0 = 0; @@ -276,52 +275,6 @@ int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu) } /* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - struct switch_stack *sw; - - /* changed the size calculations - should hopefully work better. lbt */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + - (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; - - dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); - sw = ((struct switch_stack *)regs) - 1; - dump->regs.d1 = regs->d1; - dump->regs.d2 = regs->d2; - dump->regs.d3 = regs->d3; - dump->regs.d4 = regs->d4; - dump->regs.d5 = regs->d5; - dump->regs.d6 = sw->d6; - dump->regs.d7 = sw->d7; - dump->regs.a0 = regs->a0; - dump->regs.a1 = regs->a1; - dump->regs.a2 = regs->a2; - dump->regs.a3 = sw->a3; - dump->regs.a4 = sw->a4; - dump->regs.a5 = sw->a5; - dump->regs.a6 = sw->a6; - dump->regs.d0 = regs->d0; - dump->regs.orig_d0 = regs->orig_d0; - dump->regs.stkadj = regs->stkadj; - dump->regs.sr = regs->sr; - dump->regs.pc = regs->pc; - dump->regs.fmtvec = (regs->format << 12) | regs->vector; - /* dump floating point stuff */ - dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp); -} - -/* * Generic dumping code. Used for panic and debug. */ void dump(struct pt_regs *fp) diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 262ab8c72e5..382ca5797b9 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -101,7 +101,7 @@ void ptrace_disable(struct task_struct *child) put_reg(child, PT_SR, tmp); } -long arch_ptrace(truct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 43a2726c0d0..e1b3aa39e27 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -285,6 +285,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, regs->d1 = context.sc_d1; regs->a0 = context.sc_a0; regs->a1 = context.sc_a1; + ((struct switch_stack *)regs - 1)->a5 = context.sc_a5; regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); regs->pc = context.sc_pc; regs->orig_d0 = -1; /* disable syscall checks */ @@ -498,6 +499,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, sc->sc_d1 = regs->d1; sc->sc_a0 = regs->a0; sc->sc_a1 = regs->a1; + sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5; sc->sc_sr = regs->sr; sc->sc_pc = regs->pc; sc->sc_formatvec = regs->format << 12 | regs->vector; @@ -597,6 +599,9 @@ static void setup_frame (int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; + ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data; + regs->format = 0x4; /*set format byte to make stack appear modulo 4 + which it will be when doing the rte */ adjust_stack: /* Prepare to skip over the extra stuff in the exception frame. */ @@ -664,6 +669,9 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; + ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data; + regs->format = 0x4; /*set format byte to make stack appear modulo 4 + which it will be when doing the rte */ adjust_stack: /* Prepare to skip over the extra stuff in the exception frame. */ diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 0eab92ca4b9..ac9de2661c0 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -129,7 +129,7 @@ */ #if defined(CONFIG_M5208EVB) #define RAM_START 0x40020000 -#define RAM_LENGTH 0x01e00000 +#define RAM_LENGTH 0x01fe0000 #endif /* diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b50be449d3f..c3e852e9953 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1471,7 +1471,7 @@ config SB1_PASS_2_1_WORKAROUNDS config 64BIT_PHYS_ADDR bool "Support for 64-bit physical address space" - depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32_R1 || CPU_MIPS64_R1) && 32BIT + depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && 32BIT config CPU_ADVANCED bool "Override CPU Options" @@ -1492,14 +1492,6 @@ config CPU_HAS_LLSC for better performance, N if you don't know. You must say Y here for multiprocessor machines. -config CPU_HAS_LLDSCD - bool "lld/scd Instructions available" if CPU_ADVANCED - default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32_R1 - help - Say Y here if your CPU has the lld and scd instructions, the 64-bit - equivalents of ll and sc. Say Y here for better performance, N if - you don't know. You must say Y here for multiprocessor machines. - config CPU_HAS_WB bool "Writeback Buffer available" if CPU_ADVANCED default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION diff --git a/arch/mips/Makefile b/arch/mips/Makefile index e14ba5e01a3..2a9f2ef27b2 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -93,7 +93,6 @@ endif # cflags-y += -I $(TOPDIR)/include/asm/gcc cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -cflags-y += $(call cc-option, -finline-limit=100000) LDFLAGS_vmlinux += -G 0 -static -n -nostdlib MODFLAGS += -mlong-calls diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index 069f9d14983..6fd35377981 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -130,7 +130,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_SIBYTE_DMA_PAGEOPS is not set # CONFIG_MIPS_MT is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index 216f4023a81..1d3ee18ea8b 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -115,7 +115,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig index bea00a9e926..a81e2de6947 100644 --- a/arch/mips/configs/ddb5476_defconfig +++ b/arch/mips/configs/ddb5476_defconfig @@ -116,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig index 61f7171ca7e..f1c27c2fb03 100644 --- a/arch/mips/configs/ddb5477_defconfig +++ b/arch/mips/configs/ddb5477_defconfig @@ -116,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig index 14e3815f11e..aa24d85ea94 100644 --- a/arch/mips/configs/ev64120_defconfig +++ b/arch/mips/configs/ev64120_defconfig @@ -118,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig index 510819581d8..eeed0e5ad26 100644 --- a/arch/mips/configs/ev96100_defconfig +++ b/arch/mips/configs/ev96100_defconfig @@ -121,7 +121,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 67979e3e606..e56351abf87 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -123,7 +123,6 @@ CONFIG_IP22_CPU_SCACHE=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 03af44d1d84..e17d3adff02 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -119,7 +119,6 @@ CONFIG_PAGE_SIZE_4KB=y CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index cba2a49cceb..967e7acd8e1 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -121,7 +121,6 @@ CONFIG_R5000_CPU_SCACHE=y CONFIG_RM7000_CPU_SCACHE=y # CONFIG_MIPS_MT is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig index e7ee1679af9..b5fa9639db6 100644 --- a/arch/mips/configs/it8172_defconfig +++ b/arch/mips/configs/it8172_defconfig @@ -117,7 +117,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig index 138c8a60a4d..71386938d47 100644 --- a/arch/mips/configs/ivr_defconfig +++ b/arch/mips/configs/ivr_defconfig @@ -114,7 +114,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig index 6238e0d6a43..14fb4688670 100644 --- a/arch/mips/configs/jaguar-atx_defconfig +++ b/arch/mips/configs/jaguar-atx_defconfig @@ -124,7 +124,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig index a7ad99b12fe..6c5df76d48d 100644 --- a/arch/mips/configs/lasat200_defconfig +++ b/arch/mips/configs/lasat200_defconfig @@ -121,7 +121,6 @@ CONFIG_R5000_CPU_SCACHE=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index d1c44216f1c..da0677a03c1 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc2 -# Thu Nov 24 01:06:35 2005 +# Linux kernel version: 2.6.15-rc5 +# Fri Dec 23 02:21:03 2005 # CONFIG_MIPS=y @@ -87,8 +87,8 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y # # CPU selection # -CONFIG_CPU_MIPS32_R1=y -# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set # CONFIG_CPU_R3000 is not set @@ -112,7 +112,7 @@ CONFIG_SYS_HAS_CPU_MIPS64_R1=y CONFIG_SYS_HAS_CPU_NEVADA=y CONFIG_SYS_HAS_CPU_RM7000=y CONFIG_CPU_MIPS32=y -CONFIG_CPU_MIPSR1=y +CONFIG_CPU_MIPSR2=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig index 9081ea5a9db..7ad8718c1b6 100644 --- a/arch/mips/configs/ocelot_3_defconfig +++ b/arch/mips/configs/ocelot_3_defconfig @@ -122,7 +122,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig index 570fc4d1816..e8d6bb3551a 100644 --- a/arch/mips/configs/ocelot_c_defconfig +++ b/arch/mips/configs/ocelot_c_defconfig @@ -118,7 +118,6 @@ CONFIG_RM7000_CPU_SCACHE=y CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig index 6634ab24715..f3787b68bdd 100644 --- a/arch/mips/configs/ocelot_defconfig +++ b/arch/mips/configs/ocelot_defconfig @@ -123,7 +123,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig index 4c396e1e2f0..b6126ad4d06 100644 --- a/arch/mips/configs/ocelot_g_defconfig +++ b/arch/mips/configs/ocelot_g_defconfig @@ -121,7 +121,6 @@ CONFIG_RM7000_CPU_SCACHE=y CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig index d9a0d2fdba4..4c650e70813 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/mips/configs/pnx8550-v2pci_defconfig @@ -116,7 +116,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_ADVANCED=y CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set # CONFIG_CPU_HAS_WB is not set CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig index 1cc14502358..9aaa43024ae 100644 --- a/arch/mips/configs/rbhma4500_defconfig +++ b/arch/mips/configs/rbhma4500_defconfig @@ -124,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_MIPS_MT is not set CONFIG_CPU_ADVANCED=y CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_WB=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 30975b305ae..abf61095931 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -124,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 63f1be18e9b..52048c90607 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -133,7 +133,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set CONFIG_SB1_PASS_1_WORKAROUNDS=y CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig index d51d5d16297..468c2e443d7 100644 --- a/arch/mips/configs/yosemite_defconfig +++ b/arch/mips/configs/yosemite_defconfig @@ -118,7 +118,6 @@ CONFIG_CPU_HAS_PREFETCH=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 2a1b844da43..4f125e9e8e0 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -123,7 +123,6 @@ CONFIG_IP22_CPU_SCACHE=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 72f2126ad19..f36c4f20ee8 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -50,7 +50,7 @@ obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o -obj-$(CONFIG_MIPS32_COMPAT) += ioctl32.o linux32.o signal32.o +obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o @@ -60,6 +60,5 @@ obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_64BIT) += cpu-bugs64.o CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) -CFLAGS_ioctl32.o += -Ifs/ EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5e1b08b00a3..fac48ad27b3 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -435,6 +435,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c) } } +static char unknown_isa[] __initdata = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + static inline unsigned int decode_config0(struct cpuinfo_mips *c) { unsigned int config0; @@ -447,16 +450,37 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c) isa = (config0 & MIPS_CONF_AT) >> 13; switch (isa) { case 0: - c->isa_level = MIPS_CPU_ISA_M32; + switch ((config0 >> 10) & 7) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } break; case 2: - c->isa_level = MIPS_CPU_ISA_M64; + switch ((config0 >> 10) & 7) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } break; default: - panic("Unsupported ISA type, cp0.config0.at: %d.", isa); + goto unknown; } return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); } static inline unsigned int decode_config1(struct cpuinfo_mips *c) @@ -568,7 +592,6 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c) break; case PRID_IMP_34K: c->cputype = CPU_34K; - c->isa_level = MIPS_CPU_ISA_M32; break; } } @@ -647,7 +670,7 @@ static inline void cpu_probe_philips(struct cpuinfo_mips *c) switch (c->processor_id & 0xff00) { case PRID_IMP_PR4450: c->cputype = CPU_PR4450; - c->isa_level = MIPS_CPU_ISA_M32; + c->isa_level = MIPS_CPU_ISA_M32R1; break; default: panic("Unknown Philips Core!"); /* REVISIT: die? */ @@ -690,8 +713,10 @@ __init void cpu_probe(void) if (c->options & MIPS_CPU_FPU) { c->fpu_id = cpu_get_fpu_id(); - if (c->isa_level == MIPS_CPU_ISA_M32 || - c->isa_level == MIPS_CPU_ISA_M64) { + if (c->isa_level == MIPS_CPU_ISA_M32R1 || + c->isa_level == MIPS_CPU_ISA_M32R2 || + c->isa_level == MIPS_CPU_ISA_M64R1 || + c->isa_level == MIPS_CPU_ISA_M64R2) { if (c->fpu_id & MIPS_FPIR_3D) c->ases |= MIPS_ASE_MIPS3D; } diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c deleted file mode 100644 index 9ea1fc74886..00000000000 --- a/arch/mips/kernel/ioctl32.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * Copyright (C) 2000 Silicon Graphics, Inc. - * Written by Ulf Carlsson (ulfc@engr.sgi.com) - * Copyright (C) 2000, 2004 Ralf Baechle - * Copyright (C) 2002, 2003 Maciej W. Rozycki - */ -#define INCLUDES -#include "compat_ioctl.c" - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/compat.h> -#include <linux/ioctl32.h> -#include <linux/syscalls.h> - -#ifdef CONFIG_SIBYTE_TBPROF -#include <asm/sibyte/trace_prof.h> -#endif - -#define A(__x) ((unsigned long)(__x)) - -long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - -#define CODE -#include "compat_ioctl.c" - -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, -#define IOCTL_TABLE_START \ - struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END \ - }; - -IOCTL_TABLE_START - -#include <linux/compat_ioctl.h> -#define DECLARES -#include "compat_ioctl.c" - -/*HANDLE_IOCTL(RTC_IRQP_READ, w_long) -COMPATIBLE_IOCTL(RTC_IRQP_SET) -HANDLE_IOCTL(RTC_EPOCH_READ, w_long) -COMPATIBLE_IOCTL(RTC_EPOCH_SET) -*/ - -IOCTL_TABLE_END - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index dd725779d91..fa98f10d013 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -140,12 +140,12 @@ void flush_thread(void) int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *ti = p->thread_info; + struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; long childksp; p->set_child_tid = p->clear_child_tid = NULL; - childksp = (unsigned long)ti + THREAD_SIZE - 32; + childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; preempt_disable(); @@ -205,7 +205,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) return 1; } -void dump_regs(elf_greg_t *gp, struct pt_regs *regs) +void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs) { int i; @@ -229,9 +229,7 @@ void dump_regs(elf_greg_t *gp, struct pt_regs *regs) int dump_task_regs (struct task_struct *tsk, elf_gregset_t *regs) { - struct thread_info *ti = tsk->thread_info; - long ksp = (unsigned long)ti + THREAD_SIZE - 32; - dump_regs(&(*regs)[0], (struct pt_regs *) ksp - 1); + elf_dump_regs(*regs, task_pt_regs(tsk)); return 1; } @@ -409,7 +407,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p->thread_info; + stack_page = (unsigned long)task_stack_page(p); if (!stack_page || !mips_frame_info_initialized) return 0; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 510da5fda56..f838b36cc76 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -64,8 +64,7 @@ int ptrace_getregs (struct task_struct *child, __s64 __user *data) if (!access_ok(VERIFY_WRITE, data, 38 * 8)) return -EIO; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); for (i = 0; i < 32; i++) __put_user (regs->regs[i], data + i); @@ -92,8 +91,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data) if (!access_ok(VERIFY_READ, data, 38 * 8)) return -EIO; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); for (i = 0; i < 32; i++) __get_user (regs->regs[i], data + i); @@ -198,8 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct pt_regs *regs; unsigned long tmp = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); ret = 0; /* Default return value. */ switch (addr) { @@ -280,12 +277,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = -EIO; goto out; } - if (child->thread.dsp.used_dsp) { - dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); - } else { - tmp = -1; /* DSP registers yet used */ - } + dregs = __get_dsp_regs(child); + tmp = (unsigned long) (dregs[addr - DSP_BASE]); break; } case DSP_CONTROL: @@ -318,8 +311,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); switch (addr) { case 0 ... 31: @@ -446,7 +438,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); break; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 7e55457a491..0c82b25d8c6 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -126,8 +126,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) struct pt_regs *regs; unsigned int tmp; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); ret = 0; /* Default return value. */ switch (addr) { @@ -201,12 +200,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO; goto out_tsk; } - if (child->thread.dsp.used_dsp) { - dspreg_t *dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); - } else { - tmp = -1; /* DSP registers yet used */ - } + dspreg_t *dregs = __get_dsp_regs(child); + tmp = (unsigned long) (dregs[addr - DSP_BASE]); break; case DSP_CONTROL: if (!cpu_has_dsp) { @@ -263,8 +258,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child->thread_info + - THREAD_SIZE - 32 - sizeof(struct pt_regs)); + regs = task_pt_regs(child); switch (addr) { case 0 ... 31: @@ -381,7 +375,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) break; case PTRACE_GET_THREAD_AREA: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned int __user *) (unsigned long) data); break; @@ -395,7 +389,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) break; case PTRACE_GET_THREAD_AREA_3264: - ret = put_user(child->thread_info->tp_value, + ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) (unsigned long) data); break; diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index c856dbc52ab..98b185bbc94 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -588,7 +588,7 @@ static inline int setup_sigcontext32(struct pt_regs *regs, err |= __put_user(regs->hi, &sc->sc_mdhi); err |= __put_user(regs->lo, &sc->sc_mdlo); if (cpu_has_dsp) { - err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1); + err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); err |= __put_user(mfhi1(), &sc->sc_hi1); err |= __put_user(mflo1(), &sc->sc_lo1); err |= __put_user(mfhi2(), &sc->sc_hi2); diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c index d429544ba4b..794a1c3de2a 100644 --- a/arch/mips/kernel/smp_mt.c +++ b/arch/mips/kernel/smp_mt.c @@ -287,6 +287,7 @@ void prom_prepare_cpus(unsigned int max_cpus) */ void prom_boot_secondary(int cpu, struct task_struct *idle) { + struct thread_info *gp = task_thread_info(idle); dvpe(); set_c0_mvpcontrol(MVPCONTROL_VPC); @@ -307,11 +308,9 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) write_tc_gpr_sp( __KSTK_TOS(idle)); /* global pointer */ - write_tc_gpr_gp((unsigned long)idle->thread_info); + write_tc_gpr_gp((unsigned long)gp); - flush_icache_range((unsigned long)idle->thread_info, - (unsigned long)idle->thread_info + - sizeof(struct thread_info)); + flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1)); /* finally out of configuration and into chaos */ clear_c0_mvpcontrol(MVPCONTROL_VPC); diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index ee98eeb65e8..332358430ff 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -9,6 +9,7 @@ */ #include <linux/config.h> #include <linux/a.out.h> +#include <linux/capability.h> #include <linux/errno.h> #include <linux/linkage.h> #include <linux/mm.h> @@ -262,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) void sys_set_thread_area(unsigned long addr) { - struct thread_info *ti = current->thread_info; + struct thread_info *ti = task_thread_info(current); ti->tp_value = addr; diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 52924f8ce23..0fc3730a294 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/binfmts.h> +#include <linux/capability.h> #include <linux/highuid.h> #include <linux/pagemap.h> #include <linux/mm.h> diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 787ed541d44..7050b4ffffc 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } +int null_perf_irq(struct pt_regs *regs) +{ + return 0; +} + +int (*perf_irq)(struct pt_regs *regs) = null_perf_irq; + +EXPORT_SYMBOL(null_perf_irq); +EXPORT_SYMBOL(perf_irq); + asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) { + int r2 = cpu_has_mips_r2; + irq_enter(); kstat_this_cpu.irqs[irq]++; + /* + * Suckage alert: + * Before R2 of the architecture there was no way to see if a + * performance counter interrupt was pending, so we have to run the + * performance counter interrupt handler anyway. + */ + if (!r2 || (read_c0_cause() & (1 << 26))) + if (perf_irq(regs)) + goto out; + /* we keep interrupt disabled all the time */ - timer_interrupt(irq, NULL, regs); + if (!r2 || (read_c0_cause() & (1 << 30))) + timer_interrupt(irq, NULL, regs); +out: irq_exit(); } @@ -628,9 +652,9 @@ void __init time_init(void) mips_hpt_init = c0_hpt_init; } - if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) + if (cpu_has_mips32r1 || cpu_has_mips32r2 || + (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) /* * We need to calibrate the counter but we don't have * 64-bit division. diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 7058893d5ad..59a187956de 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -519,7 +519,7 @@ static inline int simulate_llsc(struct pt_regs *regs) */ static inline int simulate_rdhwr(struct pt_regs *regs) { - struct thread_info *ti = current->thread_info; + struct thread_info *ti = task_thread_info(current); unsigned int opcode; if (unlikely(get_insn_opcode(regs, &opcode))) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 9c89eebc356..ae83b755cf4 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -99,9 +99,9 @@ struct vpe { /* elfloader stuff */ void *load_addr; - u32 len; + unsigned long len; char *pbuffer; - u32 plen; + unsigned long plen; unsigned long __start; @@ -253,11 +253,11 @@ void dump_mtregs(void) } /* Find some VPE program space */ -static void *alloc_progmem(u32 len) +static void *alloc_progmem(unsigned long len) { #ifdef CONFIG_MIPS_VPE_LOADER_TOM /* this means you must tell linux to use less memory than you physically have */ - return (void *)((max_pfn * PAGE_SIZE) + KSEG0); + return pfn_to_kaddr(max_pfn); #else // simple grab some mem for now return kmalloc(len, GFP_KERNEL); diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c index b5d5fa83376..7e2ced715cf 100644 --- a/arch/mips/lib/iomap.c +++ b/arch/mips/lib/iomap.c @@ -3,7 +3,7 @@ * * This code is based on lib/iomap.c, by Linus Torvalds. * - * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 0065deaee24..a1962eb460f 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -33,8 +33,6 @@ ieee754dp ieee754dp_fint(int x) CLEARCX; - xc = ( 0 ? xc : xc ); - if (x == 0) return ieee754dp_zero(0); if (x == 1 || x == -1) diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index cb105b1dd86..eae90a866aa 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -33,8 +33,6 @@ ieee754dp ieee754dp_flong(s64 x) CLEARCX; - xc = ( 0 ? xc : xc ); - if (x == 0) return ieee754dp_zero(0); if (x == 1 || x == -1) diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 42d9ed4b9a9..7aac13afb09 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -33,8 +33,6 @@ ieee754sp ieee754sp_fint(int x) CLEARCX; - xc = ( 0 ? xc : xc ); - if (x == 0) return ieee754sp_zero(0); if (x == 1 || x == -1) diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index 1e26795ccec..3d6c1d11c17 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -33,8 +33,6 @@ ieee754sp ieee754sp_flong(s64 x) CLEARCX; - xc = ( 0 ? xc : xc ); - if (x == 0) return ieee754sp_zero(0); if (x == 1 || x == -1) diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 72a12d931cb..93f3bf2c2b2 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -75,20 +75,31 @@ static void mips_timer_dispatch (struct pt_regs *regs) do_IRQ (mips_cpu_timer_irq, regs); } +extern int null_perf_irq(struct pt_regs *regs); + +extern int (*perf_irq)(struct pt_regs *regs); + irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { -#ifdef CONFIG_SMP + int r2 = cpu_has_mips_r2; int cpu = smp_processor_id(); if (cpu == 0) { /* - * CPU 0 handles the global timer interrupt job and process accounting - * resets count/compare registers to trigger next timer int. + * CPU 0 handles the global timer interrupt job and process + * accounting resets count/compare registers to trigger next + * timer int. */ - (void) timer_interrupt(irq, dev_id, regs); + if (!r2 || (read_c0_cause() & (1 << 26))) + if (perf_irq(regs)) + goto out; + + /* we keep interrupt disabled all the time */ + if (!r2 || (read_c0_cause() & (1 << 30))) + timer_interrupt(irq, NULL, regs); + scroll_display_message(); - } - else { + } else { /* Everyone else needs to reset the timer int here as ll_local_timer_interrupt doesn't */ /* @@ -103,16 +114,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) local_timer_interrupt (irq, dev_id, regs); } +out: return IRQ_HANDLED; -#else - irqreturn_t r; - - r = timer_interrupt(irq, dev_id, regs); - - scroll_display_message(); - - return r; -#endif } /* diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 38223b44d96..422b55fab07 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1183,8 +1183,8 @@ static void __init setup_scache(void) if (!sc_present) return; - if ((c->isa_level == MIPS_CPU_ISA_M32 || - c->isa_level == MIPS_CPU_ISA_M64) && + if ((c->isa_level == MIPS_CPU_ISA_M32R1 || + c->isa_level == MIPS_CPU_ISA_M64R1) && !(c->scache.flags & MIPS_CACHE_NOT_PRESENT)) panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index dd2cc42f1b6..53f9889b30e 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -75,7 +75,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) int res; switch (current_cpu_data.cputype) { + case CPU_5KC: + case CPU_20KC: case CPU_24K: + case CPU_25KF: lmodel = &op_model_mipsxx; break; diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h index f0121557047..5cfce7d87a4 100644 --- a/arch/mips/oprofile/op_impl.h +++ b/arch/mips/oprofile/op_impl.h @@ -12,8 +12,8 @@ struct pt_regs; -extern void null_perf_irq(struct pt_regs *regs); -extern void (*perf_irq)(struct pt_regs *regs); +extern int null_perf_irq(struct pt_regs *regs); +extern int (*perf_irq)(struct pt_regs *regs); /* Per-counter configuration as set via oprofilefs. */ struct op_counter_config { diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index d36b64dfcb2..1d1eee407fa 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args) } } -static void mipsxx_perfcount_handler(struct pt_regs *regs) +static int mipsxx_perfcount_handler(struct pt_regs *regs) { unsigned int counters = op_model_mipsxx.num_counters; unsigned int control; unsigned int counter; + int handled = 0; switch (counters) { #define HANDLE_COUNTER(n) \ @@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs) (counter & M_COUNTER_OVERFLOW)) { \ oprofile_add_sample(regs, n); \ write_c0_perfcntr ## n(reg.counter[n]); \ + handled = 1; \ } HANDLE_COUNTER(3) HANDLE_COUNTER(2) HANDLE_COUNTER(1) HANDLE_COUNTER(0) } + + return handled; } #define M_CONFIG1_PC (1 << 4) @@ -176,17 +180,31 @@ static int __init mipsxx_init(void) int counters; counters = n_counters(); - if (counters == 0) + if (counters == 0) { + printk(KERN_ERR "Oprofile: CPU has no performance counters\n"); return -ENODEV; + } reset_counters(counters); op_model_mipsxx.num_counters = counters; switch (current_cpu_data.cputype) { + case CPU_20KC: + op_model_mipsxx.cpu_type = "mips/20K"; + break; + case CPU_24K: op_model_mipsxx.cpu_type = "mips/24K"; break; + case CPU_25KF: + op_model_mipsxx.cpu_type = "mips/25K"; + break; + + case CPU_5KC: + op_model_mipsxx.cpu_type = "mips/5K"; + break; + default: printk(KERN_ERR "Profiling unsupported for this CPU\n"); diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c index f2fc82c1c7c..1e530751936 100644 --- a/arch/mips/pci/fixup-capcella.c +++ b/arch/mips/pci/fixup-capcella.c @@ -1,7 +1,7 @@ /* * fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c index 4975846da75..b67ddaa4712 100644 --- a/arch/mips/pci/fixup-mpc30x.c +++ b/arch/mips/pci/fixup-mpc30x.c @@ -1,7 +1,7 @@ /* * fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index bc55b06e190..734f2b71e16 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> - * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c index b5d42b12de1..c9e7cb4361a 100644 --- a/arch/mips/pci/fixup-tb0226.c +++ b/arch/mips/pci/fixup-tb0226.c @@ -1,7 +1,7 @@ /* * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups. * - * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c index 8436d7f1fdb..fbe6bcb2819 100644 --- a/arch/mips/pci/fixup-tb0287.c +++ b/arch/mips/pci/fixup-tb0287.c @@ -1,7 +1,7 @@ /* * fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups. * - * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c index 430429b22ae..900c6b32576 100644 --- a/arch/mips/pci/ops-vr41xx.c +++ b/arch/mips/pci/ops-vr41xx.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2003 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index 91df4da7ddb..9885fa40360 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2003 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h index e087ec55641..8a35e32b837 100644 --- a/arch/mips/pci/pci-vr41xx.h +++ b/arch/mips/pci/pci-vr41xx.h @@ -3,7 +3,7 @@ * * Copyright (C) 2002 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 0527170d6ad..f17f575f58f 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -93,8 +93,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus) */ void prom_boot_secondary(int cpu, struct task_struct *idle) { - unsigned long gp = (unsigned long) idle->thread_info; - unsigned long sp = gp + THREAD_SIZE - 32; + unsigned long gp = (unsigned long) task_thread_info(idle); + unsigned long sp = __KSTK_TOP(idle); secondary_sp = sp; secondary_gp = gp; diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 3a8291b7d26..dbef3f6b565 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -168,8 +168,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus) */ void __init prom_boot_secondary(int cpu, struct task_struct *idle) { - unsigned long gp = (unsigned long) idle->thread_info; - unsigned long sp = gp + THREAD_SIZE - 32; + unsigned long gp = (unsigned long)task_thread_info(idle); + unsigned long sp = __KSTK_TOS(idle); LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu), (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c index e8485124b8f..4477af3d807 100644 --- a/arch/mips/sibyte/cfe/smp.c +++ b/arch/mips/sibyte/cfe/smp.c @@ -60,7 +60,7 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, __KSTK_TOS(idle), - (unsigned long)idle->thread_info, 0); + (unsigned long)task_thread_info(idle), 0); if (retval != 0) printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); } diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c index d29201acc4f..814900915c2 100644 --- a/arch/mips/vr41xx/casio-e55/setup.c +++ b/arch/mips/vr41xx/casio-e55/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65. * - * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c index cdfa4273a1c..de0c1b35f11 100644 --- a/arch/mips/vr41xx/common/bcu.c +++ b/arch/mips/vr41xx/common/bcu.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> - * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * - Added support for NEC VR4133. */ #include <linux/kernel.h> diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c index d758e432961..657c5133c93 100644 --- a/arch/mips/vr41xx/common/cmu.c +++ b/arch/mips/vr41xx/common/cmu.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2002 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copuright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * - Added support for NEC VR4133. */ #include <linux/init.h> diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 0b73c5ab3c0..07ae19cf0c2 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2002 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * - Coped with INTASSIGN of NEC VR4133. */ #include <linux/errno.h> diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index 578f6496ffd..707bd0933ee 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c @@ -1,7 +1,7 @@ /* * init.c, Common initialization routines for NEC VR4100 series. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S index 272c13aee4f..2b6043f16d0 100644 --- a/arch/mips/vr41xx/common/int-handler.S +++ b/arch/mips/vr41xx/common/int-handler.S @@ -35,7 +35,7 @@ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> * - New creation, NEC VR4100 series are supported. * - * Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * - Coped with INTASSIGN of NEC VR4133. */ #include <asm/asm.h> diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 43b214d3943..61aa264275f 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index 53166f3598b..02bf4f7d06b 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -1,7 +1,7 @@ /* * pmu.c, Power Management Unit routines for NEC VR4100 series. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c index bcb5f71b502..e0c1ac5e988 100644 --- a/arch/mips/vr41xx/common/type.c +++ b/arch/mips/vr41xx/common/type.c @@ -1,7 +1,7 @@ /* * type.c, System type for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c index cc52e75e14e..3e31f8193d2 100644 --- a/arch/mips/vr41xx/common/vrc4173.c +++ b/arch/mips/vr41xx/common/vrc4173.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2003 MontaVista Software Inc. * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> - * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c index e4b34ad6ea6..50fe8af4c52 100644 --- a/arch/mips/vr41xx/ibm-workpad/setup.c +++ b/arch/mips/vr41xx/ibm-workpad/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the IBM WorkPad z50. * - * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index a64fd48fbfb..29b4d61898f 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -22,6 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/capability.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/namei.h> diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 171f9c239f6..27827bc3717 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -6,7 +6,6 @@ extra-y := init_task.o head.o vmlinux.lds AFLAGS_entry.o := -traditional AFLAGS_pacache.o := -traditional -CFLAGS_ioctl32.o := -Ifs/ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ @@ -19,6 +18,6 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PA11) += pci-dma.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o +obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o # only supported for PCX-W/U in 64-bit mode at the moment obj-$(CONFIG_64BIT) += perf.o perf_asm.o diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index a065349aee3..d8a4ca021aa 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -29,9 +29,9 @@ #include <asm/processor.h> #include <asm/sections.h> -int split_tlb; -int dcache_stride; -int icache_stride; +int split_tlb __read_mostly; +int dcache_stride __read_mostly; +int icache_stride __read_mostly; EXPORT_SYMBOL(dcache_stride); @@ -45,29 +45,29 @@ DEFINE_SPINLOCK(pa_tlb_lock); EXPORT_SYMBOL(pa_tlb_lock); #endif -struct pdc_cache_info cache_info; +struct pdc_cache_info cache_info __read_mostly; #ifndef CONFIG_PA20 -static struct pdc_btlb_info btlb_info; +static struct pdc_btlb_info btlb_info __read_mostly; #endif #ifdef CONFIG_SMP void flush_data_cache(void) { - on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1); + on_each_cpu(flush_data_cache_local, NULL, 1, 1); } void flush_instruction_cache(void) { - on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1); + on_each_cpu(flush_instruction_cache_local, NULL, 1, 1); } #endif void flush_cache_all_local(void) { - flush_instruction_cache_local(); - flush_data_cache_local(); + flush_instruction_cache_local(NULL); + flush_data_cache_local(NULL); } EXPORT_SYMBOL(flush_cache_all_local); @@ -332,7 +332,7 @@ void clear_user_page_asm(void *page, unsigned long vaddr) } #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ -int parisc_cache_flush_threshold = FLUSH_THRESHOLD; +int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; void parisc_setup_cache_timing(void) { diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index d016d672ec2..1eaa0d37f67 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -39,7 +39,7 @@ #include <asm/parisc-device.h> /* See comments in include/asm-parisc/pci.h */ -struct hppa_dma_ops *hppa_dma_ops; +struct hppa_dma_ops *hppa_dma_ops __read_mostly; EXPORT_SYMBOL(hppa_dma_ops); static struct device root = { @@ -515,8 +515,13 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) (iodc_data[5] << 8) | iodc_data[6]; dev->hpa.name = parisc_pathname(dev); dev->hpa.start = hpa; - if (hpa == 0xf4000000 || hpa == 0xf6000000 || - hpa == 0xf8000000 || hpa == 0xfa000000) { + /* This is awkward. The STI spec says that gfx devices may occupy + * 32MB or 64MB. Unfortunately, we don't know how to tell whether + * it's the former or the latter. Assumptions either way can hurt us. + */ + if (hpa == 0xf4000000 || hpa == 0xf8000000) { + dev->hpa.end = hpa + 0x03ffffff; + } else if (hpa == 0xf6000000 || hpa == 0xfa000000) { dev->hpa.end = hpa + 0x01ffffff; } else { dev->hpa.end = hpa + 0xfff; @@ -834,7 +839,7 @@ static void print_parisc_device(struct parisc_device *dev) if (dev->num_addrs) { int k; - printk(", additional addresses: "); + printk(", additional addresses: "); for (k = 0; k < dev->num_addrs; k++) printk("0x%lx ", dev->addr[k]); } diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 553f8fe0322..2dc06b8e181 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -80,7 +80,7 @@ static unsigned long pdc_result2[32] __attribute__ ((aligned (8))); /* Firmware needs to be initially set to narrow to determine the * actual firmware width. */ -int parisc_narrow_firmware = 1; +int parisc_narrow_firmware __read_mostly = 1; #endif /* On most currently-supported platforms, IODC I/O calls are 32-bit calls diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index 2071b5bba15..3058bffd8a2 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -551,6 +551,7 @@ static struct hp_hardware hp_hardware_list[] __initdata = { {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"}, {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"}, {HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"}, + {HPHW_BRIDGE, 0x05D, 0x0000A, 0x00, "SummitHawk Dino PCI Bridge"}, {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"}, {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"}, {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"}, diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 8f563871e83..4e847ba5318 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -38,7 +38,7 @@ */ #undef DEBUG_PAT -int pdc_type = PDC_TYPE_ILLEGAL; +int pdc_type __read_mostly = PDC_TYPE_ILLEGAL; void __init setup_pdc(void) { @@ -120,8 +120,8 @@ set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start, * pdc info is bad in this case). */ - if ( ((start & (PAGE_SIZE - 1)) != 0) - || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) { + if (unlikely( ((start & (PAGE_SIZE - 1)) != 0) + || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) )) { panic("Memory range doesn't align with page size!\n"); } diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c deleted file mode 100644 index 4eada1bb27f..00000000000 --- a/arch/parisc/kernel/ioctl32.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $ - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * - * These routines maintain argument size conversion between 32bit and 64bit - * ioctls. - */ - -#include <linux/syscalls.h> - -#define INCLUDES -#include "compat_ioctl.c" - -#include <asm/perf.h> -#include <asm/ioctls.h> - -#define CODE -#include "compat_ioctl.c" - -#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL }, -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) - -#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END }; - -IOCTL_TABLE_START -#include <linux/compat_ioctl.h> - -#define DECLARES -#include "compat_ioctl.c" - -/* And these ioctls need translation */ -HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) -HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) -HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) - -#if defined(CONFIG_GEN_RTC) -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */ -HANDLE_IOCTL(RTC_IRQP_READ, w_long) -COMPATIBLE_IOCTL(RTC_IRQP_SET) -HANDLE_IOCTL(RTC_EPOCH_READ, w_long) -COMPATIBLE_IOCTL(RTC_EPOCH_SET) -#endif - -IOCTL_TABLE_END - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index f94a02ef3d9..a6caf107308 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -33,10 +33,10 @@ #include <asm/uaccess.h> #include <asm/tlbflush.h> /* for purge_tlb_*() macros */ -static struct proc_dir_entry * proc_gsc_root = NULL; +static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length); -static unsigned long pcxl_used_bytes = 0; -static unsigned long pcxl_used_pages = 0; +static unsigned long pcxl_used_bytes __read_mostly = 0; +static unsigned long pcxl_used_pages __read_mostly = 0; extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ static spinlock_t pcxl_res_lock; diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index 52004ae28d2..2a01fe1bdc9 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c @@ -30,6 +30,7 @@ #include <linux/kernel.h> #include <linux/reboot.h> #include <linux/notifier.h> +#include <linux/cache.h> #include <asm/pdc_chassis.h> #include <asm/processor.h> @@ -38,8 +39,8 @@ #ifdef CONFIG_PDC_CHASSIS -static int pdc_chassis_old = 0; -static unsigned int pdc_chassis_enabled = 1; +static int pdc_chassis_old __read_mostly = 0; +static unsigned int pdc_chassis_enabled __read_mostly = 1; /** @@ -132,7 +133,7 @@ void __init parisc_pdc_chassis_init(void) { #ifdef CONFIG_PDC_CHASSIS int handle = 0; - if (pdc_chassis_enabled) { + if (likely(pdc_chassis_enabled)) { DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__); /* Let see if we have something to handle... */ @@ -142,7 +143,7 @@ void __init parisc_pdc_chassis_init(void) printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n"); handle = 1; } - else if (pdc_chassis_old) { + else if (unlikely(pdc_chassis_old)) { printk(KERN_INFO "Enabling old style chassis LED panel support.\n"); handle = 1; } @@ -178,7 +179,7 @@ int pdc_chassis_send_status(int message) /* Maybe we should do that in an other way ? */ int retval = 0; #ifdef CONFIG_PDC_CHASSIS - if (pdc_chassis_enabled) { + if (likely(pdc_chassis_enabled)) { DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message); @@ -214,7 +215,7 @@ int pdc_chassis_send_status(int message) } } else retval = -1; #else - if (pdc_chassis_old) { + if (unlikely(pdc_chassis_old)) { switch (message) { case PDC_CHASSIS_DIRECT_BSTART: case PDC_CHASSIS_DIRECT_BCOMPLETE: diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index f6fec62b6a2..11d406cd0b3 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -42,6 +42,7 @@ * on every box. */ +#include <linux/capability.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/miscdevice.h> @@ -66,10 +67,10 @@ struct rdr_tbl_ent { uint8_t write_control; }; -static int perf_processor_interface = UNKNOWN_INTF; -static int perf_enabled = 0; +static int perf_processor_interface __read_mostly = UNKNOWN_INTF; +static int perf_enabled __read_mostly = 0; static spinlock_t perf_lock; -struct parisc_device *cpu_device = NULL; +struct parisc_device *cpu_device __read_mostly = NULL; /* RDRs to write for PCX-W */ static int perf_rdrs_W[] = diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index fee4f1f09ad..5da41677e70 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -54,7 +54,7 @@ #include <asm/uaccess.h> #include <asm/unwind.h> -static int hlt_counter; +static int hlt_counter __read_mostly; /* * Power off function, if any @@ -295,7 +295,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * pregs) { struct pt_regs * cregs = &(p->thread.regs); - struct thread_info *ti = p->thread_info; + void *stack = task_stack_page(p); /* We have to use void * instead of a function pointer, because * function pointers aren't a pointer to the function on 64-bit. @@ -322,7 +322,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, */ if (usp == 1) { /* kernel thread */ - cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN); + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ @@ -344,7 +344,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, */ /* Use same stack depth as parent */ - cregs->ksp = ((unsigned long)(ti)) + cregs->ksp = (unsigned long)stack + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; if (p->personality == PER_HPUX) { diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 4f5bbcf1f5a..6df9f62cecb 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -44,10 +44,10 @@ #include <asm/irq.h> /* for struct irq_region */ #include <asm/parisc-device.h> -struct system_cpuinfo_parisc boot_cpu_data; +struct system_cpuinfo_parisc boot_cpu_data __read_mostly; EXPORT_SYMBOL(boot_cpu_data); -struct cpuinfo_parisc cpu_data[NR_CPUS]; +struct cpuinfo_parisc cpu_data[NR_CPUS] __read_mostly; /* ** PARISC CPU driver - claim "device" and initialize CPU data structures. @@ -378,12 +378,12 @@ show_cpuinfo (struct seq_file *m, void *v) return 0; } -static struct parisc_device_id processor_tbl[] = { +static struct parisc_device_id processor_tbl[] __read_mostly = { { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, { 0, } }; -static struct parisc_driver cpu_driver = { +static struct parisc_driver cpu_driver __read_mostly = { .name = "CPU", .id_table = processor_tbl, .probe = processor_probe diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 73e9c34b094..4a36ec3f6ac 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -46,15 +46,15 @@ #include <asm/io.h> #include <asm/setup.h> -char command_line[COMMAND_LINE_SIZE]; +char command_line[COMMAND_LINE_SIZE] __read_mostly; /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ -struct proc_dir_entry * proc_runway_root = NULL; -struct proc_dir_entry * proc_gsc_root = NULL; -struct proc_dir_entry * proc_mckinley_root = NULL; +struct proc_dir_entry * proc_runway_root __read_mostly = NULL; +struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; +struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL; #if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)) -int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */ +int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */ EXPORT_SYMBOL(parisc_bus_is_phys); #endif diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index ce89da0f654..25564b7ca6b 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -39,7 +39,7 @@ #include <asm/atomic.h> #include <asm/current.h> #include <asm/delay.h> -#include <asm/pgalloc.h> /* for flush_tlb_all() proto/macro */ +#include <asm/tlbflush.h> #include <asm/io.h> #include <asm/irq.h> /* for CPU_IRQ_REGION and friends */ @@ -58,9 +58,9 @@ DEFINE_SPINLOCK(smp_lock); volatile struct task_struct *smp_init_current_idle_task; -static volatile int cpu_now_booting = 0; /* track which CPU is booting */ +static volatile int cpu_now_booting __read_mostly = 0; /* track which CPU is booting */ -static int parisc_max_cpus = 1; +static int parisc_max_cpus __read_mostly = 1; /* online cpus are ones that we've managed to bring up completely * possible cpus are all valid cpu @@ -71,8 +71,8 @@ static int parisc_max_cpus = 1; * empty in the beginning. */ -cpumask_t cpu_online_map = CPU_MASK_NONE; /* Bitmap of online CPUs */ -cpumask_t cpu_possible_map = CPU_MASK_ALL; /* Bitmap of Present CPUs */ +cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; /* Bitmap of online CPUs */ +cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; /* Bitmap of Present CPUs */ EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); @@ -406,12 +406,10 @@ EXPORT_SYMBOL(smp_call_function); * as we want to ensure all TLB's flushed before proceeding. */ -extern void flush_tlb_all_local(void); - void smp_flush_tlb_all(void) { - on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); + on_each_cpu(flush_tlb_all_local, NULL, 1, 1); } @@ -487,7 +485,7 @@ void __init smp_callin(void) #endif flush_cache_all_local(); /* start with known state */ - flush_tlb_all_local(); + flush_tlb_all_local(NULL); local_irq_enable(); /* Interrupts have been off until now */ @@ -519,7 +517,7 @@ int __init smp_boot_one_cpu(int cpuid) if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - idle->thread_info->cpu = cpuid; + task_thread_info(idle)->cpu = cpuid; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index cded2568078..594930bc4bc 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -36,8 +36,8 @@ /* xtime and wall_jiffies keep wall-clock time */ extern unsigned long wall_jiffies; -static long clocktick; /* timer cycles per tick */ -static long halftick; +static long clocktick __read_mostly; /* timer cycles per tick */ +static long halftick __read_mostly; #ifdef CONFIG_SMP extern void smp_do_timer(struct pt_regs *regs); diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c index ac2a4068141..3ba040050e4 100644 --- a/arch/parisc/kernel/topology.c +++ b/arch/parisc/kernel/topology.c @@ -20,8 +20,9 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/cpu.h> +#include <linux/cache.h> -static struct cpu cpu_devices[NR_CPUS]; +static struct cpu cpu_devices[NR_CPUS] __read_mostly; static int __init topology_init(void) { diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index eaae8a021f9..de0a1b21cb4 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -122,7 +122,7 @@ #define ERR_NOTHANDLED -1 #define ERR_PAGEFAULT -2 -int unaligned_enabled = 1; +int unaligned_enabled __read_mostly = 1; void die_if_kernel (char *str, struct pt_regs *regs, long err); diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index db141108412..cc1c1afc318 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -35,7 +35,7 @@ static spinlock_t unwind_lock; * we can call unwind_init as early in the bootup process as * possible (before the slab allocator is initialized) */ -static struct unwind_table kernel_unwind_table; +static struct unwind_table kernel_unwind_table __read_mostly; static LIST_HEAD(unwind_tables); static inline const struct unwind_table_entry * diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index e5fac3e08c7..6d6436a6b62 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -68,7 +68,7 @@ SECTIONS RODATA /* writeable */ - . = ALIGN(4096); /* Make sure this is paged aligned so + . = ALIGN(4096); /* Make sure this is page aligned so that we can properly leave these as writable */ data_start = .; @@ -105,6 +105,10 @@ SECTIONS . = ALIGN(16); .data.lock_aligned : { *(.data.lock_aligned) } + /* rarely changed data like cpu maps */ + . = ALIGN(16); + .data.read_mostly : { *(.data.read_mostly) } + _edata = .; /* End of data section */ . = ALIGN(16384); /* init_task */ @@ -194,14 +198,7 @@ SECTIONS #endif } - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } + STABS_DEBUG .note 0 : { *(.note) } } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 29b998e430e..720287d46e5 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -36,9 +36,9 @@ extern char _end; /* end of BSS, defined by linker */ extern char __init_begin, __init_end; #ifdef CONFIG_DISCONTIGMEM -struct node_map_data node_data[MAX_NUMNODES]; -bootmem_data_t bmem_data[MAX_NUMNODES]; -unsigned char pfnnid_map[PFNNID_MAP_MAX]; +struct node_map_data node_data[MAX_NUMNODES] __read_mostly; +bootmem_data_t bmem_data[MAX_NUMNODES] __read_mostly; +unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; #endif static struct resource data_resource = { @@ -58,14 +58,14 @@ static struct resource pdcdata_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; -static struct resource sysram_resources[MAX_PHYSMEM_RANGES]; +static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly; /* The following array is initialized from the firmware specific * information retrieved in kernel/inventory.c. */ -physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES]; -int npmem_ranges; +physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly; +int npmem_ranges __read_mostly; #ifdef __LP64__ #define MAX_MEM (~0UL) @@ -73,7 +73,7 @@ int npmem_ranges; #define MAX_MEM (3584U*1024U*1024U) #endif /* !__LP64__ */ -static unsigned long mem_limit = MAX_MEM; +static unsigned long mem_limit __read_mostly = MAX_MEM; static void __init mem_limit_func(void) { @@ -300,6 +300,13 @@ static void __init setup_bootmem(void) max_pfn = start_pfn + npages; } + /* IOMMU is always used to access "high mem" on those boxes + * that can support enough mem that a PCI device couldn't + * directly DMA to any physical addresses. + * ISA DMA support will need to revisit this. + */ + max_low_pfn = max_pfn; + if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) { printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n"); BUG(); @@ -431,11 +438,11 @@ void free_initmem(void) #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ & ~(VM_MAP_OFFSET-1))) -void *vmalloc_start; +void *vmalloc_start __read_mostly; EXPORT_SYMBOL(vmalloc_start); #ifdef CONFIG_PA11 -unsigned long pcxl_dma_start; +unsigned long pcxl_dma_start __read_mostly; #endif void __init mem_init(void) @@ -475,7 +482,7 @@ int do_check_pgt_cache(int low, int high) return 0; } -unsigned long *empty_zero_page; +unsigned long *empty_zero_page __read_mostly; void show_mem(void) { @@ -998,7 +1005,7 @@ void flush_tlb_all(void) void flush_tlb_all(void) { spin_lock(&sid_lock); - flush_tlb_all_local(); + flush_tlb_all_local(NULL); recycle_sids(); spin_unlock(&sid_lock); } diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c index 5c7a1b3b932..edd9a9559cb 100644 --- a/arch/parisc/mm/ioremap.c +++ b/arch/parisc/mm/ioremap.c @@ -1,12 +1,9 @@ /* * arch/parisc/mm/ioremap.c * - * Re-map IO memory to kernel address space so that we can access it. - * This is needed for high PCI addresses that aren't mapped in the - * 640k-1MB IO memory area on PC's - * * (C) Copyright 1995 1996 Linus Torvalds * (C) Copyright 2001 Helge Deller <deller@gmx.de> + * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org> */ #include <linux/vmalloc.h> @@ -14,81 +11,107 @@ #include <linux/module.h> #include <asm/io.h> #include <asm/pgalloc.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline void +remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) { - unsigned long end; + unsigned long end, pfn; + pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | + _PAGE_ACCESSED | flags); address &= ~PMD_MASK; + end = address + size; if (end > PMD_SIZE) end = PMD_SIZE; - if (address >= end) - BUG(); + + BUG_ON(address >= end); + + pfn = phys_addr >> PAGE_SHIFT; do { - if (!pte_none(*pte)) { - printk(KERN_ERR "remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | flags))); + BUG_ON(!pte_none(*pte)); + + set_pte(pte, pfn_pte(pfn, pgprot)); + address += PAGE_SIZE; - phys_addr += PAGE_SIZE; + pfn++; pte++; } while (address && (address < end)); } -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline int +remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) { unsigned long end; address &= ~PGDIR_MASK; + end = address + size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; + + BUG_ON(address >= end); + phys_addr -= address; - if (address >= end) - BUG(); do { - pte_t * pte = pte_alloc_kernel(pmd, address); + pte_t *pte = pte_alloc_kernel(pmd, address); if (!pte) return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); + + remap_area_pte(pte, address, end - address, + address + phys_addr, flags); + address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); + return 0; } -#if (USE_HPPA_IOREMAP) -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) +#if USE_HPPA_IOREMAP +static int +remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) { - int error; - pgd_t * dir; + pgd_t *dir; + int error = 0; unsigned long end = address + size; + BUG_ON(address >= end); + phys_addr -= address; - dir = pgd_offset(&init_mm, address); + dir = pgd_offset_k(address); + flush_cache_all(); - if (address >= end) - BUG(); + do { + pud_t *pud; pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + error = -ENOMEM; + pud = pud_alloc(&init_mm, dir, address); + if (!pud) + break; + + pmd = pmd_alloc(&init_mm, pud, address); if (!pmd) break; + if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) + phys_addr + address, flags)) break; + error = 0; address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (address && (address < end)); + flush_tlb_all(); + return error; } #endif /* USE_HPPA_IOREMAP */ @@ -123,8 +146,7 @@ EXPORT_SYMBOL(__raw_bad_addr); /* * Remap an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access high addresses - * directly. + * address space. * * NOTE! We need to allow non-page-aligned mappings too: we will obviously * have to convert them into an offset in a page-aligned mapping, but the @@ -148,8 +170,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l #endif #else - void * addr; - struct vm_struct * area; + void *addr; + struct vm_struct *area; unsigned long offset, last_addr; /* Don't allow wraparound or zero size */ @@ -167,9 +189,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l t_addr = __va(phys_addr); t_end = t_addr + (size - 1); - for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) + for (page = virt_to_page(t_addr); + page <= virt_to_page(t_end); page++) { if(!PageReserved(page)) return NULL; + } } /* @@ -185,11 +209,13 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l area = get_vm_area(size, VM_IOREMAP); if (!area) return NULL; + addr = area->addr; if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { vfree(addr); return NULL; } + return (void __iomem *) (offset + (char *)addr); #endif } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 28004f002ec..01feed0e2a1 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -71,15 +71,39 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config PPC_OF + def_bool y + +config PPC_UDBG_16550 + bool + default n + +config CRASH_DUMP + bool "kernel crash dumps (EXPERIMENTAL)" + depends on PPC_MULTIPLATFORM + depends on EXPERIMENTAL + help + Build a kernel suitable for use as a kdump capture kernel. + The kernel will be linked at a different address than normal, and + so can only be used for Kdump. + + Don't change this unless you know what you are doing. + +config GENERIC_TBSYNC + bool + default y if PPC32 && SMP + default n + menu "Processor support" choice prompt "Processor Type" depends on PPC32 default 6xx -config 6xx +config CLASSIC32 bool "6xx/7xx/74xx" select PPC_FPU + select 6xx help There are four families of PowerPC chips supported. The more common types (601, 603, 604, 740, 750, 7400), the Motorola embedded @@ -93,12 +117,20 @@ config 6xx config PPC_52xx bool "Freescale 52xx" + select 6xx + select PPC_FPU config PPC_82xx bool "Freescale 82xx" + select 6xx + select PPC_FPU config PPC_83xx bool "Freescale 83xx" + select 6xx + select FSL_SOC + select 83xx + select PPC_FPU config 40x bool "AMCC 40x" @@ -134,6 +166,13 @@ config POWER4 depends on PPC64 def_bool y +config 6xx + bool + +# this is temp to handle compat with arch=ppc +config 83xx + bool + config PPC_FPU bool default y if PPC64 @@ -166,7 +205,7 @@ config PHYS_64BIT config ALTIVEC bool "AltiVec Support" - depends on 6xx || POWER4 + depends on CLASSIC32 || POWER4 ---help--- This option enables kernel support for the Altivec extensions to the PowerPC processor. The kernel currently supports saving and restoring @@ -239,7 +278,7 @@ endmenu source "init/Kconfig" menu "Platform support" - depends on PPC64 || 6xx + depends on PPC64 || CLASSIC32 choice prompt "Machine type" @@ -275,6 +314,7 @@ config PPC_PSERIES select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING + select PPC_UDBG_16550 default y config PPC_CHRP @@ -284,6 +324,7 @@ config PPC_CHRP select PPC_INDIRECT_PCI select PPC_RTAS select PPC_MPC106 + select PPC_UDBG_16550 default y config PPC_PMAC @@ -306,6 +347,7 @@ config PPC_PREP depends on PPC_MULTIPLATFORM && PPC32 && BROKEN select PPC_I8259 select PPC_INDIRECT_PCI + select PPC_UDBG_16550 default y config PPC_MAPLE @@ -314,6 +356,7 @@ config PPC_MAPLE select U3_DART select MPIC_BROKEN_U3 select GENERIC_TBSYNC + select PPC_UDBG_16550 default n help This option enables support for the Maple 970FX Evaluation Board. @@ -324,9 +367,7 @@ config PPC_CELL depends on PPC_MULTIPLATFORM && PPC64 select PPC_RTAS select MMIO_NVRAM - -config PPC_OF - def_bool y + select PPC_UDBG_16550 config XICS depends on PPC_PSERIES @@ -375,17 +416,6 @@ config CELL_IIC bool default y -config CRASH_DUMP - bool "kernel crash dumps (EXPERIMENTAL)" - depends on PPC_MULTIPLATFORM - depends on EXPERIMENTAL - help - Build a kernel suitable for use as a kdump capture kernel. - The kernel will be linked at a different address than normal, and - so can only be used for Kdump. - - Don't change this unless you know what you are doing. - config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool @@ -401,11 +431,6 @@ config PPC_MPC106 bool default n -config GENERIC_TBSYNC - bool - default y if CONFIG_PPC32 && CONFIG_SMP - default n - source "drivers/cpufreq/Kconfig" config CPU_FREQ_PMAC @@ -486,6 +511,7 @@ endmenu source arch/powerpc/platforms/embedded6xx/Kconfig source arch/powerpc/platforms/4xx/Kconfig +source arch/powerpc/platforms/83xx/Kconfig source arch/powerpc/platforms/85xx/Kconfig source arch/powerpc/platforms/8xx/Kconfig source arch/powerpc/platforms/cell/Kconfig @@ -709,7 +735,7 @@ config PPC_I8259 config PPC_INDIRECT_PCI bool depends on PCI - default y if 40x || 44x || 85xx || 83xx + default y if 40x || 44x || 85xx default n config EISA @@ -718,13 +744,16 @@ config EISA config SBUS bool +config FSL_SOC + bool + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA bool config PCI - bool "PCI support" if 40x || CPM2 || 83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) - default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx + bool "PCI support" if 40x || CPM2 || PPC_83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) + default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !85xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS default PCI_QSPAN if !4xx && !CPM2 && 8xx help @@ -737,11 +766,6 @@ config PCI_DOMAINS bool default PCI -config MPC83xx_PCI2 - bool " Supprt for 2nd PCI host controller" - depends on PCI && MPC834x - default y if MPC834x_SYS - config PCI_QSPAN bool "QSpan PCI" depends on !4xx && !CPM2 && 8xx diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 30a30bf559e..9254806f703 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -115,4 +115,46 @@ config PPC_OCP depends on IBM_OCP || XILINX_OCP default y +choice + prompt "Early debugging (dangerous)" + bool + optional + help + Enable early debugging. Careful, if you enable debugging for the + wrong type of machine your kernel _will not boot_. + +config PPC_EARLY_DEBUG_LPAR + bool "LPAR HV Console" + depends on PPC_PSERIES + help + Select this to enable early debugging for a machine with a HVC + console on vterm 0. + +config PPC_EARLY_DEBUG_G5 + bool "Apple G5" + depends on PPC_PMAC64 + help + Select this to enable early debugging for Apple G5 machines. + +config PPC_EARLY_DEBUG_RTAS + bool "RTAS Panel" + depends on PPC_RTAS + help + Select this to enable early debugging via the RTAS panel. + +config PPC_EARLY_DEBUG_MAPLE + bool "Maple real mode" + depends on PPC_MAPLE + help + Select this to enable early debugging for Maple. + +config PPC_EARLY_DEBUG_ISERIES + bool "iSeries HV Console" + depends on PPC_ISERIES + help + Select this to enable early debugging for legacy iSeries. You need + to hit "Ctrl-x Ctrl-x" to see the messages on the console. + +endchoice + endmenu diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5f80e58e5cb..d3654a264ef 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -76,8 +76,7 @@ LINUXINCLUDE += $(LINUXINCLUDE-y) CHECKFLAGS += -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__ ifeq ($(CONFIG_PPC64),y) -GCC_VERSION := $(call cc-version) -GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi) +GCC_BROKEN_VEC := $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi) ifeq ($(CONFIG_POWER4_ONLY),y) ifeq ($(CONFIG_ALTIVEC),y) @@ -189,10 +188,9 @@ TOUT := .tmp_gas_check # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec # instructions. # gcc-3.4 and binutils-2.14 are a fatal combination. -GCC_VERSION := $(call cc-version) checkbin: - @if test "$(GCC_VERSION)" = "0304" ; then \ + @if test "$(call cc-version)" = "0304" ; then \ if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \ echo 'correctly with gcc-3.4 and your version of binutils.'; \ diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore new file mode 100644 index 00000000000..45c9ad23526 --- /dev/null +++ b/arch/powerpc/boot/.gitignore @@ -0,0 +1,20 @@ +addnote +infblock.c +infblock.h +infcodes.c +infcodes.h +inffast.c +inffast.h +inflate.c +inftrees.c +inftrees.h +infutil.c +infutil.h +kernel-vmlinux.strip.c +kernel-vmlinux.strip.gz +uImage +zImage +zImage.vmode +zconf.h +zlib.h +zutil.h diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 22726aefc8e..b53d677f674 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -176,4 +176,4 @@ $(obj)/uImage: $(obj)/vmlinux.gz install: $(CONFIGURE) $(BOOTIMAGE) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)" -clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip) +clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip) diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 509399eab6f..0b2b55a79c3 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -861,7 +861,7 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_PMACZILOG is not set CONFIG_SERIAL_ICOM=m -CONFIG_SERIAL_JSM=m +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -878,7 +878,7 @@ CONFIG_HVCS=m # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set +CONFIG_GEN_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 6e03b595b6c..a94699d8dc5 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -4,7 +4,6 @@ ifeq ($(CONFIG_PPC64),y) EXTRA_CFLAGS += -mno-minimal-toc -CFLAGS_ioctl32.o += -Ifs/ endif ifeq ($(CONFIG_PPC32),y) CFLAGS_prom_init.o += -fPIC @@ -12,11 +11,12 @@ CFLAGS_btext.o += -fPIC endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ - irq.o align.o signal_32.o pmc.o vdso.o + irq.o align.o signal_32.o pmc.o vdso.o \ + init_task.o process.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o systbl.o \ - paca.o ioctl32.o cpu_setup_power4.o \ + paca.o cpu_setup_power4.o \ firmware.o sysfs.o idle_64.o obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o @@ -45,8 +45,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-y += vmlinux.lds -obj-y += process.o init_task.o time.o \ - prom.o traps.o setup-common.o udbg.o +obj-y += time.o prom.o traps.o setup-common.o udbg.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o @@ -55,16 +54,16 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_6xx) += idle_6xx.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_SERIAL_8250) += legacy_serial.o udbg_16550.o +obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ pci_direct_iommu.o iomap.o obj-$(CONFIG_PCI) += $(pci64-y) -kexec-$(CONFIG_PPC64) := machine_kexec_64.o +kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o -obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) +obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) ifeq ($(CONFIG_PPC_ISERIES),y) $(obj)/head_64.o: $(obj)/lparmap.s diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 4681155121e..5f248e3fdf8 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -18,7 +18,6 @@ #include <linux/kexec.h> #include <linux/bootmem.h> #include <linux/crash_dump.h> -#include <linux/irq.h> #include <linux/delay.h> #include <linux/elf.h> #include <linux/elfcore.h> @@ -30,6 +29,7 @@ #include <asm/kdump.h> #include <asm/lmb.h> #include <asm/firmware.h> +#include <asm/smp.h> #ifdef DEBUG #include <asm/udbg.h> diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 87effa3f21a..211d72653ea 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -55,6 +55,7 @@ void __init kdump_setup(void) DBG(" <- kdump_setup()\n"); } +#ifdef CONFIG_PROC_VMCORE static int __init parse_elfcorehdr(char *p) { if (p) @@ -63,6 +64,7 @@ static int __init parse_elfcorehdr(char *p) return 0; } __setup("elfcorehdr=", parse_elfcorehdr); +#endif static int __init parse_savemaxmem(char *p) { diff --git a/arch/powerpc/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c deleted file mode 100644 index 0fa3d27fef0..00000000000 --- a/arch/powerpc/kernel/ioctl32.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * Based on sparc64 ioctl32.c by: - * - * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * - * ppc64 changes: - * - * Copyright (C) 2000 Ken Aaker (kdaaker@rchland.vnet.ibm.com) - * Copyright (C) 2001 Anton Blanchard (antonb@au.ibm.com) - * - * These routines maintain argument size conversion between 32bit and 64bit - * ioctls. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#define INCLUDES -#include "compat_ioctl.c" -#include <linux/syscalls.h> - -#define CODE -#include "compat_ioctl.c" - -#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, NULL }, -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) - -#define IOCTL_TABLE_START \ - struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END \ - }; - -IOCTL_TABLE_START -#include <linux/compat_ioctl.h> -#define DECLARES -#include "compat_ioctl.c" - -IOCTL_TABLE_END - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 5368f9c2e6b..cfab48566db 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -35,7 +35,6 @@ #include <asm/kdebug.h> #include <asm/sstep.h> -static DECLARE_MUTEX(kprobe_mutex); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); @@ -54,19 +53,17 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) /* insn must be on a special executable page on ppc64 */ if (!ret) { - down(&kprobe_mutex); p->ainsn.insn = get_insn_slot(); - up(&kprobe_mutex); if (!p->ainsn.insn) ret = -ENOMEM; } - return ret; -} -void __kprobes arch_copy_kprobe(struct kprobe *p) -{ - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); - p->opcode = *p->addr; + if (!ret) { + memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + p->opcode = *p->addr; + } + + return ret; } void __kprobes arch_arm_kprobe(struct kprobe *p) @@ -182,6 +179,18 @@ static inline int kprobe_handler(struct pt_regs *regs) kcb->kprobe_status = KPROBE_REENTER; return 1; } else { + if (*addr != BREAKPOINT_INSTRUCTION) { + /* If trap variant, then it belongs not to us */ + kprobe_opcode_t cur_insn = *addr; + if (is_trap(cur_insn)) + goto no_kprobe; + /* The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + ret = 1; + goto no_kprobe; + } p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index a91e40c9ae4..a81ca1b841e 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -14,12 +14,6 @@ #include <linux/threads.h> #include <asm/machdep.h> -/* - * Provide a dummy crash_notes definition until crash dump is implemented. - * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. - */ -note_buf_t crash_notes[NR_CPUS]; - void machine_crash_shutdown(struct pt_regs *regs) { if (ppc_md.machine_crash_shutdown) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index fc60a773af7..c367520bc1c 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -53,6 +53,7 @@ EXPORT_SYMBOL(io_page_mask); #ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); +static void phbs_remap_io(void); #endif /* pci_io_base -- the base address from which io bars are offsets. @@ -251,6 +252,7 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } +#ifndef CONFIG_PPC_ISERIES void __devinit pcibios_claim_one_bus(struct pci_bus *b) { struct pci_dev *dev; @@ -271,8 +273,10 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *b) list_for_each_entry(child_bus, &b->children, node) pcibios_claim_one_bus(child_bus); } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL_GPL(pcibios_claim_one_bus); +#endif -#ifndef CONFIG_PPC_ISERIES static void __init pcibios_claim_of_setup(void) { struct pci_bus *b; @@ -381,7 +385,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); dev->subsystem_device = get_int_prop(node, "subsystem-id", 0); - dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/ + dev->cfg_size = pci_cfg_space_size(dev); sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); @@ -1215,7 +1219,7 @@ int remap_bus_range(struct pci_bus *bus) } EXPORT_SYMBOL(remap_bus_range); -void phbs_remap_io(void) +static void phbs_remap_io(void) { struct pci_controller *hose, *tmp; diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index b2758148a0d..16d9a904f3c 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -244,7 +244,6 @@ EXPORT_SYMBOL(set_context); extern long mol_trampoline; EXPORT_SYMBOL(mol_trampoline); /* For MOL */ EXPORT_SYMBOL(flush_hash_pages); /* For MOL */ -EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */ #ifdef CONFIG_SMP extern int mmu_hash_lock; EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */ diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 105d5609ff5..57703994a06 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -201,13 +201,13 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) } #endif /* CONFIG_SPE */ +#ifndef CONFIG_SMP /* * If we are doing lazy switching of CPU state (FP, altivec or SPE), * and the current task has some state, discard it. */ -static inline void discard_lazy_cpu_state(void) +void discard_lazy_cpu_state(void) { -#ifndef CONFIG_SMP preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; @@ -220,9 +220,10 @@ static inline void discard_lazy_cpu_state(void) last_task_used_spe = NULL; #endif preempt_enable(); -#endif /* CONFIG_SMP */ } +#endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC_MERGE /* XXX for now */ int set_dabr(unsigned long dabr) { if (ppc_md.set_dabr) @@ -231,6 +232,7 @@ int set_dabr(unsigned long dabr) mtspr(SPRN_DABR, dabr); return 0; } +#endif #ifdef CONFIG_PPC64 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); @@ -424,7 +426,7 @@ void show_regs(struct pt_regs * regs) if (trap == 0x300 || trap == 0x600) printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); printk("TASK = %p[%d] '%s' THREAD: %p", - current, current->pid, current->comm, current->thread_info); + current, current->pid, current->comm, task_thread_info(current)); #ifdef CONFIG_SMP printk(" CPU: %d", smp_processor_id()); @@ -503,7 +505,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); - unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; + unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; CHECK_FULL_REGS(regs); /* Copy registers */ @@ -516,7 +518,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_PPC32 childregs->gpr[2] = (unsigned long) p; #else - clear_ti_thread_flag(p->thread_info, TIF_32BIT); + clear_tsk_thread_flag(p, TIF_32BIT); #endif p->thread.regs = NULL; /* no user register state */ } else { @@ -588,10 +590,8 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) * set. Do it now. */ if (!current->thread.regs) { - unsigned long childregs = (unsigned long)current->thread_info + - THREAD_SIZE; - childregs -= sizeof(struct pt_regs); - current->thread.regs = (struct pt_regs *)childregs; + struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE; + current->thread.regs = regs - 1; } memset(regs->gpr, 0, sizeof(regs->gpr)); @@ -767,7 +767,7 @@ out: static int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { - unsigned long stack_page = (unsigned long)p->thread_info; + unsigned long stack_page = (unsigned long)task_stack_page(p); if (sp >= stack_page + sizeof(struct thread_struct) && sp <= stack_page + THREAD_SIZE - nbytes) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 34ab0daec3a..02e2115323e 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1100,17 +1100,37 @@ static int __init early_init_dt_scan_memory(unsigned long node, static void __init early_reserve_mem(void) { - unsigned long base, size; - unsigned long *reserve_map; + u64 base, size; + u64 *reserve_map; - reserve_map = (unsigned long *)(((unsigned long)initial_boot_params) + + reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap); +#ifdef CONFIG_PPC32 + /* + * Handle the case where we might be booting from an old kexec + * image that setup the mem_rsvmap as pairs of 32-bit values + */ + if (*reserve_map > 0xffffffffull) { + u32 base_32, size_32; + u32 *reserve_map_32 = (u32 *)reserve_map; + + while (1) { + base_32 = *(reserve_map_32++); + size_32 = *(reserve_map_32++); + if (size_32 == 0) + break; + DBG("reserving: %lx -> %lx\n", base_32, size_32); + lmb_reserve(base_32, size_32); + } + return; + } +#endif while (1) { base = *(reserve_map++); size = *(reserve_map++); if (size == 0) break; - DBG("reserving: %lx -> %lx\n", base, size); + DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index e381f2fc121..d963a12ec64 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -137,8 +137,8 @@ struct prom_t { }; struct mem_map_entry { - unsigned long base; - unsigned long size; + u64 base; + u64 size; }; typedef u32 cell_t; @@ -897,9 +897,9 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp) * If problems seem to show up, it would be a good start to track * them down. */ -static void reserve_mem(unsigned long base, unsigned long size) +static void reserve_mem(u64 base, u64 size) { - unsigned long top = base + size; + u64 top = base + size; unsigned long cnt = RELOC(mem_reserve_cnt); if (size == 0) diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index b1babb72967..5ccbdbe0d5c 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -62,7 +62,7 @@ static inline void set_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr |= MSR_SE; - set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); + set_tsk_thread_flag(task, TIF_SINGLESTEP); } static inline void clear_single_step(struct task_struct *task) @@ -70,7 +70,7 @@ static inline void clear_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr &= ~MSR_SE; - clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); + clear_tsk_thread_flag(task, TIF_SINGLESTEP); } #ifdef CONFIG_ALTIVEC diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index ae2e2a31a70..4b9cfe4637b 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -17,6 +17,7 @@ #include <linux/spinlock.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/capability.h> #include <linux/delay.h> #include <asm/prom.h> @@ -29,6 +30,7 @@ #include <asm/delay.h> #include <asm/uaccess.h> #include <asm/lmb.h> +#include <asm/udbg.h> struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED @@ -52,7 +54,7 @@ EXPORT_SYMBOL(rtas_flash_term_hook); * are designed only for very early low-level debugging, which * is why the token is hard-coded to 10. */ -void call_rtas_display_status(unsigned char c) +static void call_rtas_display_status(char c) { struct rtas_args *args = &rtas.args; unsigned long s; @@ -65,14 +67,14 @@ void call_rtas_display_status(unsigned char c) args->nargs = 1; args->nret = 1; args->rets = (rtas_arg_t *)&(args->args[1]); - args->args[0] = (int)c; + args->args[0] = (unsigned char)c; enter_rtas(__pa(args)); spin_unlock_irqrestore(&rtas.lock, s); } -void call_rtas_display_status_delay(unsigned char c) +static void call_rtas_display_status_delay(char c) { static int pending_newline = 0; /* did last write end with unprinted newline? */ static int width = 16; @@ -96,6 +98,11 @@ void call_rtas_display_status_delay(unsigned char c) } } +void __init udbg_init_rtas(void) +{ + udbg_putc = call_rtas_display_status_delay; +} + void rtas_progress(char *s, unsigned short hex) { struct device_node *root; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 45b8109951f..5579f655991 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -72,7 +72,7 @@ static int of_device_available(struct device_node * dn) return 0; } -static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) +int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) { int returnval = -1; unsigned long buid, addr; diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index e5d285adb49..db72a92943b 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -299,9 +299,7 @@ void __init setup_arch(char **cmdline_p) if (ppc_md.init_early) ppc_md.init_early(); -#ifdef CONFIG_SERIAL_8250 find_legacy_serial_ports(); -#endif finish_device_tree(); smp_setup_cpu_maps(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 81567e93126..e29b275e09e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -33,6 +33,7 @@ #include <linux/unistd.h> #include <linux/serial.h> #include <linux/serial_8250.h> +#include <linux/bootmem.h> #include <asm/io.h> #include <asm/kdump.h> #include <asm/prom.h> @@ -70,33 +71,6 @@ #define DBG(fmt...) #endif -/* - * Here are some early debugging facilities. You can enable one - * but your kernel will not boot on anything else if you do so - */ - -/* This one is for use on LPAR machines that support an HVC console - * on vterm 0 - */ -extern void udbg_init_debug_lpar(void); -/* This one is for use on Apple G5 machines - */ -extern void udbg_init_pmac_realmode(void); -/* That's RTAS panel debug */ -extern void call_rtas_display_status_delay(unsigned char c); -/* Here's maple real mode debug */ -extern void udbg_init_maple_realmode(void); - -#define EARLY_DEBUG_INIT() do {} while(0) - -#if 0 -#define EARLY_DEBUG_INIT() udbg_init_debug_lpar() -#define EARLY_DEBUG_INIT() udbg_init_maple_realmode() -#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode() -#define EARLY_DEBUG_INIT() \ - do { udbg_putc = call_rtas_display_status_delay; } while(0) -#endif - int have_of = 1; int boot_cpuid = 0; int boot_cpuid_phys = 0; @@ -237,11 +211,8 @@ void __init early_setup(unsigned long dt_ptr) struct paca_struct *lpaca = get_paca(); static struct machdep_calls **mach; - /* - * Enable early debugging if any specified (see top of - * this file) - */ - EARLY_DEBUG_INIT(); + /* Enable early debugging if any specified (see udbg.h) */ + udbg_early_init(); DBG(" -> early_setup()\n"); @@ -472,9 +443,7 @@ void __init setup_system(void) * hash table management for us, thus ioremap works. We do that early * so that further code can be debugged */ -#ifdef CONFIG_SERIAL_8250 find_legacy_serial_ports(); -#endif /* * "Finish" the device-tree, that is do the actual parsing of @@ -686,3 +655,28 @@ void cpu_die(void) if (ppc_md.cpu_die) ppc_md.cpu_die(); } + +#ifdef CONFIG_SMP +void __init setup_per_cpu_areas(void) +{ + int i; + unsigned long size; + char *ptr; + + /* Copy section for each CPU (we discard the original) */ + size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES); +#ifdef CONFIG_MODULES + if (size < PERCPU_ENOUGH_ROOM) + size = PERCPU_ENOUGH_ROOM; +#endif + + for_each_cpu(i) { + ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size); + if (!ptr) + panic("Cannot allocate cpu data for CPU %d\n", i); + + paca[i].data_offset = ptr - __per_cpu_start; + memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); + } +} +#endif diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d3f0b6d452f..177bba78fb0 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -497,6 +497,15 @@ static long restore_user_regs(struct pt_regs *regs, if (err) return 1; + /* + * Do this before updating the thread state in + * current->thread.fpr/vr/evr. That way, if we get preempted + * and another task grabs the FPU/Altivec/SPE, it won't be + * tempted to save the current CPU state into the thread_struct + * and corrupt what we are writing there. + */ + discard_lazy_cpu_state(); + /* force the process to reload the FP registers from current->thread when it next does FP instructions */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); @@ -538,18 +547,6 @@ static long restore_user_regs(struct pt_regs *regs, return 1; #endif /* CONFIG_SPE */ -#ifndef CONFIG_SMP - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -#endif return 0; } diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 5462bef898f..7b9d999e211 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -207,10 +207,20 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, if (!sig) regs->gpr[13] = save_r13; - err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); if (set != NULL) err |= __get_user(set->sig[0], &sc->oldmask); + /* + * Do this before updating the thread state in + * current->thread.fpr/vr. That way, if we get preempted + * and another task grabs the FPU/Altivec, it won't be + * tempted to save the current CPU state into the thread_struct + * and corrupt what we are writing there. + */ + discard_lazy_cpu_state(); + + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); err |= __get_user(msr, &sc->gp_regs[PT_MSR]); @@ -229,14 +239,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, current->thread.vrsave = 0; #endif /* CONFIG_ALTIVEC */ -#ifndef CONFIG_SMP - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; - preempt_enable(); -#endif /* Force reload of FP/VEC */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d381ec90b75..c8458c531b2 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -338,8 +338,8 @@ static void __init smp_create_idle(unsigned int cpu) #ifdef CONFIG_PPC64 paca[cpu].__current = p; #endif - current_set[cpu] = p->thread_info; - p->thread_info->cpu = cpu; + current_set[cpu] = task_thread_info(p); + task_thread_info(p)->cpu = cpu; } void __init smp_prepare_cpus(unsigned int max_cpus) @@ -375,7 +375,7 @@ void __devinit smp_prepare_boot_cpu(void) #ifdef CONFIG_PPC64 paca[boot_cpuid].__current = current; #endif - current_set[boot_cpuid] = current->thread_info; + current_set[boot_cpuid] = task_thread_info(current); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 9c921d1c408..475249dc235 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -552,30 +552,6 @@ asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec return ret; } -asmlinkage int compat_sys_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) -{ - return sys_pciconfig_read((unsigned long) bus, - (unsigned long) dfn, - (unsigned long) off, - (unsigned long) len, - compat_ptr(ubuf)); -} - -asmlinkage int compat_sys_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) -{ - return sys_pciconfig_write((unsigned long) bus, - (unsigned long) dfn, - (unsigned long) off, - (unsigned long) len, - compat_ptr(ubuf)); -} - -asmlinkage int compat_sys_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) -{ - return sys_pciconfig_iobase(which, in_bus, in_devfn); -} - - /* Note: it is necessary to treat mode as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -956,38 +932,6 @@ long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low, advice); } -long ppc32_timer_create(clockid_t clock, - struct compat_sigevent __user *ev32, - timer_t __user *timer_id) -{ - sigevent_t event; - timer_t t; - long err; - mm_segment_t savefs; - - if (ev32 == NULL) - return sys_timer_create(clock, NULL, timer_id); - - if (get_compat_sigevent(&event, ev32)) - return -EFAULT; - - if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t))) - return -EFAULT; - - savefs = get_fs(); - set_fs(KERNEL_DS); - /* The __user pointer casts are valid due to the set_fs() */ - err = sys_timer_create(clock, - (sigevent_t __user *) &event, - (timer_t __user *) &t); - set_fs(savefs); - - if (err == 0) - err = __put_user(t, timer_id); - - return err; -} - asmlinkage long compat_sys_add_key(const char __user *_type, const char __user *_description, const void __user *_payload, diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 65463a1076e..68013179a50 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -239,9 +239,9 @@ SYS32ONLY(ftruncate64) SYSX(sys_ni_syscall,sys_stat64,sys_stat64) SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) -COMPAT_SYS(pciconfig_read) -COMPAT_SYS(pciconfig_write) -COMPAT_SYS(pciconfig_iobase) +SYSCALL(pciconfig_read) +SYSCALL(pciconfig_write) +SYSCALL(pciconfig_iobase) SYSCALL(ni_syscall) SYSCALL(getdents64) SYSCALL(pivot_root) @@ -281,7 +281,7 @@ SYSCALL(epoll_create) SYSCALL(epoll_ctl) SYSCALL(epoll_wait) SYSCALL(remap_file_pages) -SYSX(sys_timer_create,ppc32_timer_create,sys_timer_create) +SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create) COMPAT_SYS(timer_settime) COMPAT_SYS(timer_gettime) SYSCALL(timer_getoverrun) diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 558c1ceb2b9..3774e80094f 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -15,11 +15,36 @@ #include <linux/sched.h> #include <linux/console.h> #include <asm/processor.h> +#include <asm/udbg.h> void (*udbg_putc)(char c); int (*udbg_getc)(void); int (*udbg_getc_poll)(void); +/* + * Early debugging facilities. You can enable _one_ of these via .config, + * if you do so your kernel _will not boot_ on anything else. Be careful. + */ +void __init udbg_early_init(void) +{ +#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR) + /* For LPAR machines that have an HVC console on vterm 0 */ + udbg_init_debug_lpar(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_G5) + /* For use on Apple G5 machines */ + udbg_init_pmac_realmode(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS) + /* RTAS panel debug */ + udbg_init_rtas(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE) + /* Maple real mode debug */ + udbg_init_maple_realmode(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES) + /* For iSeries - hit Ctrl-x Ctrl-x to see the output */ + udbg_init_iseries(); +#endif +} + /* udbg library, used by xmon et al */ void udbg_puts(const char *s) { diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 7541bf44d2d..2da65a9c93f 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -155,7 +155,7 @@ void udbg_maple_real_putc(unsigned char c) } } -void udbg_init_maple_realmode(void) +void __init udbg_init_maple_realmode(void) { udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; diff --git a/arch/powerpc/kernel/vdso32/.gitignore b/arch/powerpc/kernel/vdso32/.gitignore new file mode 100644 index 00000000000..e45fba9d0ce --- /dev/null +++ b/arch/powerpc/kernel/vdso32/.gitignore @@ -0,0 +1 @@ +vdso32.lds diff --git a/arch/powerpc/kernel/vdso64/.gitignore b/arch/powerpc/kernel/vdso64/.gitignore new file mode 100644 index 00000000000..3fd18cf9fec --- /dev/null +++ b/arch/powerpc/kernel/vdso64/.gitignore @@ -0,0 +1 @@ +vdso64.lds diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 2ffca63602c..7b278d83739 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -174,7 +174,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size, pa = addr & PAGE_MASK; size = PAGE_ALIGN(addr + size) - pa; - if (size == 0) + if ((size == 0) || (pa == 0)) return NULL; if (mem_init_done) { diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig new file mode 100644 index 00000000000..b20812d460e --- /dev/null +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -0,0 +1,26 @@ +menu "Platform support" + depends on PPC_83xx + +choice + prompt "Machine Type" + default MPC834x_SYS + +config MPC834x_SYS + bool "Freescale MPC834x SYS" + help + This option enables support for the MPC 834x SYS evaluation board. + + Be aware that PCI buses can only function when SYS board is plugged + into the PIB (Platform IO Board) board from Freescale which provide + 3 PCI slots. The PIBs PCI initialization is the bootloader's + responsiblilty. + +endchoice + +config MPC834x + bool + select PPC_UDBG_16550 + select PPC_INDIRECT_PCI + default y if MPC834x_SYS + +endmenu diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile new file mode 100644 index 00000000000..9d8b28ef334 --- /dev/null +++ b/arch/powerpc/platforms/83xx/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the PowerPC 83xx linux kernel. +# +obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o pci.o diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 8836b3a0066..04073fd987e 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -7,6 +7,7 @@ endif endif obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ +obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_85xx) += 85xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 85152544c15..e0e051c675d 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -142,7 +142,7 @@ static void cbe_idle(void) } } -int cbe_system_reset_exception(struct pt_regs *regs) +static int cbe_system_reset_exception(struct pt_regs *regs) { switch (regs->msr & SRR1_WAKEMASK) { case SRR1_WAKEEE: diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 18e25e65c04..b33a4443f5a 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -57,7 +57,7 @@ #define DBG(fmt...) #endif -void cell_show_cpuinfo(struct seq_file *m) +static void cell_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index de96eadf419..bdf6c5fe58c 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -86,7 +86,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); /* Fixup atomic count: it exited inside IRQ handler. */ - paca[lcpu].__current->thread_info->preempt_count = 0; + task_thread_info(paca[lcpu].__current)->preempt_count = 0; /* * If the RTAS start-cpu token does not exist then presume the diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d2ba358c6e3..b3962c3a034 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -138,7 +138,7 @@ static void spufs_prune_dir(struct dentry *dir) { struct dentry *dentry, *tmp; mutex_lock(&dir->d_inode->i_mutex); - list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { + list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (!(d_unhashed(dentry)) && dentry->d_inode) { diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 1061c12b2ed..212db28531f 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -169,11 +169,33 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) struct spu_priv2 __iomem *priv2 = spu->priv2; /* Save, Step 8: - * Read and save MFC_CNTL[Ss]. - */ - if (csa) { - csa->priv2.mfc_control_RW = in_be64(&priv2->mfc_control_RW) & - MFC_CNTL_SUSPEND_DMA_STATUS_MASK; + * Suspend DMA and save MFC_CNTL. + */ + switch (in_be64(&priv2->mfc_control_RW) & + MFC_CNTL_SUSPEND_DMA_STATUS_MASK) { + case MFC_CNTL_SUSPEND_IN_PROGRESS: + POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & + MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == + MFC_CNTL_SUSPEND_COMPLETE); + /* fall through */ + case MFC_CNTL_SUSPEND_COMPLETE: + if (csa) { + csa->priv2.mfc_control_RW = + in_be64(&priv2->mfc_control_RW) | + MFC_CNTL_SUSPEND_DMA_QUEUE; + } + break; + case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION: + out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE); + POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & + MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == + MFC_CNTL_SUSPEND_COMPLETE); + if (csa) { + csa->priv2.mfc_control_RW = + in_be64(&priv2->mfc_control_RW) & + ~MFC_CNTL_SUSPEND_DMA_QUEUE; + } + break; } } @@ -237,6 +259,8 @@ static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu) eieio(); csa->spu_chnldata_RW[7] = in_be64(&priv2->spu_chnldata_RW); eieio(); + } else { + csa->priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING; } } diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index d549aa7ebea..e6565a949dd 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -29,7 +29,9 @@ * value of the spu_status register after the SPU has stopped. * */ -long do_spu_run(struct file *filp, __u32 __user *unpc, __u32 __user *ustatus) +static long do_spu_run(struct file *filp, + __u32 __user *unpc, + __u32 __user *ustatus) { long ret; struct spufs_inode_info *i; diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 81250090f98..4fdbc9ae876 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -144,16 +144,6 @@ config LITE5200 much but it's only been tested on this board version. I think this board is also known as IceCube. -config MPC834x_SYS - bool "Freescale MPC834x SYS" - help - This option enables support for the MPC 834x SYS evaluation board. - - Be aware that PCI buses can only function when SYS board is plugged - into the PIB (Platform IO Board) board from Freescale which provide - 3 PCI slots. The PIBs PCI initialization is the bootloader's - responsiblilty. - config EV64360 bool "Marvell-EV64360BP" help @@ -192,14 +182,6 @@ config 8272 The MPC8272 CPM has a different internal dpram setup than other CPM2 devices -config 83xx - bool - default y if MPC834x_SYS - -config MPC834x - bool - default y if MPC834x_SYS - config CPM2 bool depends on 8260 || MPC8560 || MPC8555 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 127b465308b..ce8c0b943fa 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,8 +1,8 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ - hvcall.o proc.o htab.o iommu.o misc.o -obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o + hvcall.o proc.o htab.o iommu.o misc.o irq.o +obj-$(CONFIG_PCI) += pci.o vpdinfo.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 2b54eeb2c89..bea0b703f40 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -34,6 +34,8 @@ #include <asm/pci-bridge.h> #include <asm/iseries/hv_call_xm.h> +#include "iommu.h" + extern struct list_head iSeries_Global_Device_List; diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h new file mode 100644 index 00000000000..cb5658fbe65 --- /dev/null +++ b/arch/powerpc/platforms/iseries/iommu.h @@ -0,0 +1,35 @@ +#ifndef _PLATFORMS_ISERIES_IOMMU_H +#define _PLATFORMS_ISERIES_IOMMU_H + +/* + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +struct device_node; +struct iommu_table; + +/* Creates table for an individual device node */ +extern void iommu_devnode_init_iSeries(struct device_node *dn); + +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, unsigned char virtbus, + struct iommu_table *tbl); + +#endif /* _PLATFORMS_ISERIES_IOMMU_H */ diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 42e978e4897..83442ea7747 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -48,6 +48,8 @@ extern void iSeries_smp_message_recv(struct pt_regs *); #endif +#ifdef CONFIG_PCI + enum pci_event_type { pe_bus_created = 0, /* PHB has been created */ pe_bus_error = 1, /* PHB has failed */ @@ -147,20 +149,11 @@ static void int_received(struct pci_event *event, struct pt_regs *regs) static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs) { if (event && (event->xType == HvLpEvent_Type_PciIo)) { - switch (event->xFlags.xFunction) { - case HvLpEvent_Function_Int: + if (hvlpevent_is_int(event)) int_received((struct pci_event *)event, regs); - break; - case HvLpEvent_Function_Ack: + else printk(KERN_ERR "pci_event_handler: unexpected ack received\n"); - break; - default: - printk(KERN_ERR - "pci_event_handler: unexpected event function %d\n", - (int)event->xFlags.xFunction); - break; - } } else if (event) printk(KERN_ERR "pci_event_handler: Unrecognized PCI event type 0x%x\n", @@ -334,6 +327,8 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, return virtirq; } +#endif /* CONFIG_PCI */ + /* * Get the next pending IRQ. */ @@ -353,6 +348,7 @@ int iSeries_get_irq(struct pt_regs *regs) if (hvlpevent_is_pending()) process_hvlpevents(regs); +#ifdef CONFIG_PCI if (num_pending_irqs) { spin_lock(&pending_irqs_lock); for (irq = 0; irq < NR_IRQS; irq++) { @@ -366,6 +362,7 @@ int iSeries_get_irq(struct pt_regs *regs) if (irq >= NR_IRQS) irq = -2; } +#endif return irq; } diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index ea72385aaf0..438e2dba63b 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -93,10 +93,7 @@ struct ItLpNaca itLpNaca = { .xPirEnvironMode = 0, /* Piranha stuff */ .xPirConsoleMode = 0, .xPirDasdMode = 0, - .xLparInstalled = 0, - .xSysPartitioned = 0, - .xHwSyncedTBs = 0, - .xIntProcUtilHmt = 0, + .flags = 0, .xSpVpdFormat = 0, .xIntProcRatio = 0, .xPlicVrmIndex = 0, /* VRM index of PLIC */ diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index e9fb98bf895..0b885300d1d 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -53,7 +53,7 @@ static struct HvLpEvent * get_next_hvlpevent(void) struct HvLpEvent * event; event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - if (event->xFlags.xValid) { + if (hvlpevent_is_valid(event)) { /* rmb() needed only for weakly consistent machines (regatta) */ rmb(); /* Set pointer to next potential event */ @@ -84,7 +84,7 @@ int hvlpevent_is_pending(void) next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - return next_event->xFlags.xValid | + return hvlpevent_is_valid(next_event) || hvlpevent_queue.xPlicOverflowIntPending; } @@ -101,18 +101,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event) switch (extra) { case 3: tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); case 2: tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); case 1: tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); - tmp->xFlags.xValid = 0; + hvlpevent_invalidate(tmp); } mb(); - event->xFlags.xValid = 0; + hvlpevent_invalidate(event); } void process_hvlpevents(struct pt_regs *regs) diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 49e7e4b8584..a41d8b78c0c 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -251,10 +251,7 @@ static struct pending_event *new_pending_event(void) } memset(ev, 0, sizeof(struct pending_event)); hev = &ev->event.hp_lp_event; - hev->xFlags.xValid = 1; - hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; - hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck; - hev->xFlags.xFunction = HvLpEvent_Function_Int; + hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | HV_LP_EVENT_INT; hev->xType = HvLpEvent_Type_MachineFac; hev->xSourceLp = HvLpConfig_getLpIndex(); hev->xTargetLp = primary_lp; @@ -518,17 +515,10 @@ static void handle_ack(struct io_mf_lp_event *event) static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs) { if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) { - switch(event->xFlags.xFunction) { - case HvLpEvent_Function_Ack: + if (hvlpevent_is_ack(event)) handle_ack((struct io_mf_lp_event *)event); - break; - case HvLpEvent_Function_Int: + else handle_int((struct io_mf_lp_event *)event); - break; - default: - printk(KERN_ERR "mf.c: non ack/int event received\n"); - break; - } } else printk(KERN_ERR "mf.c: alien event received\n"); } diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index dafc518fbb8..a19833b880e 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -43,6 +43,7 @@ #include "irq.h" #include "pci.h" #include "call_pci.h" +#include "iommu.h" extern unsigned long io_page_mask; diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index ad5ef80500c..c6bbe5c2510 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -52,6 +52,7 @@ #include <asm/iseries/mf.h> #include <asm/iseries/hv_lp_event.h> #include <asm/iseries/lpar_map.h> +#include <asm/udbg.h> #include "naca.h" #include "setup.h" @@ -62,10 +63,8 @@ #include "call_sm.h" #include "call_hpt.h" -extern void hvlog(char *fmt, ...); - #ifdef DEBUG -#define DBG(fmt...) hvlog(fmt) +#define DBG(fmt...) udbg_printf(fmt) #else #define DBG(fmt...) #endif @@ -474,14 +473,6 @@ static unsigned long __init build_iSeries_Memory_Map(void) printk("HPT absolute addr = %016lx, size = %dK\n", chunk_to_addr(hptFirstChunk), hptSizeChunks * 256); - ppc64_pft_size = __ilog2(hptSizePages * HW_PAGE_SIZE); - - /* - * The actual hashed page table is in the hypervisor, - * we have no direct access - */ - htab_address = NULL; - /* * Determine if absolute memory has any * holes so that we can interpret the @@ -861,6 +852,11 @@ void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) dt_prop(dt, name, (char *)data, sizeof(u64) * n); } +void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) +{ + dt_prop(dt, name, (char *)data, sizeof(u32) * n); +} + void dt_prop_empty(struct iseries_flat_dt *dt, char *name) { dt_prop(dt, name, NULL, 0); @@ -872,6 +868,7 @@ void dt_cpus(struct iseries_flat_dt *dt) unsigned char *p; unsigned int i, index; struct IoHriProcessorVpd *d; + u32 pft_size[2]; /* yuck */ snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); @@ -882,6 +879,9 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); + pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ + pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); + for (i = 0; i < NR_CPUS; i++) { if (paca[i].lppaca.dyn_proc_status >= 2) continue; @@ -908,6 +908,8 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_prop_u32(dt, "reg", i); + dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); + dt_end_node(dt); } @@ -984,3 +986,16 @@ static int __init early_parsemem(char *p) return 0; } early_param("mem", early_parsemem); + +static void hvputc(char c) +{ + if (c == '\n') + hvputc('\r'); + + HvCall_writeLogBuffer(&c, 1); +} + +void __init udbg_init_iseries(void) +{ + udbg_putc = hvputc; +} diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 384360ee06e..ad36ab0639f 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -22,6 +22,8 @@ #include <asm/iseries/hv_lp_config.h> #include <asm/iseries/hv_call_xm.h> +#include "iommu.h" + struct device *iSeries_vio_dev = &vio_bus_device.dev; EXPORT_SYMBOL(iSeries_vio_dev); diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 84267269559..622a30149b4 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -270,7 +270,7 @@ static void handleMonitorEvent(struct HvLpEvent *event) * First see if this is just a normal monitor message from the * other partition */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { remoteLp = event->xSourceLp; if (!viopathStatus[remoteLp].isActive) sendMonMsg(remoteLp); @@ -331,13 +331,12 @@ static void handleConfig(struct HvLpEvent *event) { if (!event) return; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { printk(VIOPATH_KERN_WARN "unexpected config request from partition %d", event->xSourceLp); - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -377,7 +376,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) >> VIOMAJOR_SUBTYPE_SHIFT; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { remoteLp = event->xSourceLp; /* * The isActive is checked because if the hosting partition @@ -436,8 +435,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) "unexpected virtual io event subtype %d from partition %d\n", event->xSubtype, remoteLp); /* No handler. Ack if necessary */ - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index dd73e38bfb7..a1cb4d23672 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -71,9 +71,6 @@ #define DBG(fmt...) #endif -extern void generic_find_legacy_serial_ports(u64 *physport, - unsigned int *default_speed); - static void maple_restart(char *cmd) { unsigned int maple_nvram_base; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 3b1a9d4fcbc..89c4c363616 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -278,7 +278,7 @@ static void __init l2cr_init(void) } #endif -void __init pmac_setup_arch(void) +static void __init pmac_setup_arch(void) { struct device_node *cpu, *ic; int *fp; diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index e87d53acfb6..c4352a8db64 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c @@ -153,7 +153,7 @@ static void udbg_real_scc_putc(char c) udbg_real_scc_putc('\r'); } -void udbg_init_pmac_realmode(void) +void __init udbg_init_pmac_realmode(void) { sccc = (volatile u8 __iomem *)0x80013020ul; sccd = (volatile u8 __iomem *)0x80013030ul; diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 6accdd15550..61616d14407 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o -obj-$(CONFIG_EEH) += eeh.o eeh_event.o +obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVCS) += hvcserver.o diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 7fbfd16d72b..83578313ee7 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -76,15 +76,14 @@ */ #define EEH_MAX_FAILS 100000 -/* Misc forward declaraions */ -static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn); - /* RTAS tokens */ static int ibm_set_eeh_option; static int ibm_set_slot_reset; static int ibm_read_slot_reset_state; static int ibm_read_slot_reset_state2; static int ibm_slot_error_detail; +static int ibm_get_config_addr_info; +static int ibm_configure_bridge; int eeh_subsystem_enabled; EXPORT_SYMBOL(eeh_subsystem_enabled); @@ -98,308 +97,23 @@ static DEFINE_SPINLOCK(slot_errbuf_lock); static int eeh_error_buf_size; /* System monitoring statistics */ -static DEFINE_PER_CPU(unsigned long, no_device); -static DEFINE_PER_CPU(unsigned long, no_dn); -static DEFINE_PER_CPU(unsigned long, no_cfg_addr); -static DEFINE_PER_CPU(unsigned long, ignored_check); -static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); -static DEFINE_PER_CPU(unsigned long, false_positives); -static DEFINE_PER_CPU(unsigned long, ignored_failures); -static DEFINE_PER_CPU(unsigned long, slot_resets); - -/** - * The pci address cache subsystem. This subsystem places - * PCI device address resources into a red-black tree, sorted - * according to the address range, so that given only an i/o - * address, the corresponding PCI device can be **quickly** - * found. It is safe to perform an address lookup in an interrupt - * context; this ability is an important feature. - * - * Currently, the only customer of this code is the EEH subsystem; - * thus, this code has been somewhat tailored to suit EEH better. - * In particular, the cache does *not* hold the addresses of devices - * for which EEH is not enabled. - * - * (Implementation Note: The RB tree seems to be better/faster - * than any hash algo I could think of for this problem, even - * with the penalty of slow pointer chases for d-cache misses). - */ -struct pci_io_addr_range -{ - struct rb_node rb_node; - unsigned long addr_lo; - unsigned long addr_hi; - struct pci_dev *pcidev; - unsigned int flags; -}; - -static struct pci_io_addr_cache -{ - struct rb_root rb_root; - spinlock_t piar_lock; -} pci_io_addr_cache_root; - -static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr) -{ - struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node; - - while (n) { - struct pci_io_addr_range *piar; - piar = rb_entry(n, struct pci_io_addr_range, rb_node); - - if (addr < piar->addr_lo) { - n = n->rb_left; - } else { - if (addr > piar->addr_hi) { - n = n->rb_right; - } else { - pci_dev_get(piar->pcidev); - return piar->pcidev; - } - } - } - - return NULL; -} - -/** - * pci_get_device_by_addr - Get device, given only address - * @addr: mmio (PIO) phys address or i/o port number - * - * Given an mmio phys address, or a port number, find a pci device - * that implements this address. Be sure to pci_dev_put the device - * when finished. I/O port numbers are assumed to be offset - * from zero (that is, they do *not* have pci_io_addr added in). - * It is safe to call this function within an interrupt. - */ -static struct pci_dev *pci_get_device_by_addr(unsigned long addr) -{ - struct pci_dev *dev; - unsigned long flags; - - spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); - dev = __pci_get_device_by_addr(addr); - spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); - return dev; -} - -#ifdef DEBUG -/* - * Handy-dandy debug print routine, does nothing more - * than print out the contents of our addr cache. - */ -static void pci_addr_cache_print(struct pci_io_addr_cache *cache) -{ - struct rb_node *n; - int cnt = 0; - - n = rb_first(&cache->rb_root); - while (n) { - struct pci_io_addr_range *piar; - piar = rb_entry(n, struct pci_io_addr_range, rb_node); - printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n", - (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt, - piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev)); - cnt++; - n = rb_next(n); - } -} -#endif - -/* Insert address range into the rb tree. */ -static struct pci_io_addr_range * -pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, - unsigned long ahi, unsigned int flags) -{ - struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node; - struct rb_node *parent = NULL; - struct pci_io_addr_range *piar; - - /* Walk tree, find a place to insert into tree */ - while (*p) { - parent = *p; - piar = rb_entry(parent, struct pci_io_addr_range, rb_node); - if (ahi < piar->addr_lo) { - p = &parent->rb_left; - } else if (alo > piar->addr_hi) { - p = &parent->rb_right; - } else { - if (dev != piar->pcidev || - alo != piar->addr_lo || ahi != piar->addr_hi) { - printk(KERN_WARNING "PIAR: overlapping address range\n"); - } - return piar; - } - } - piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC); - if (!piar) - return NULL; - - piar->addr_lo = alo; - piar->addr_hi = ahi; - piar->pcidev = dev; - piar->flags = flags; - -#ifdef DEBUG - printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", - alo, ahi, pci_name (dev)); -#endif - - rb_link_node(&piar->rb_node, parent, p); - rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); - - return piar; -} - -static void __pci_addr_cache_insert_device(struct pci_dev *dev) -{ - struct device_node *dn; - struct pci_dn *pdn; - int i; - int inserted = 0; - - dn = pci_device_to_OF_node(dev); - if (!dn) { - printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev)); - return; - } - - /* Skip any devices for which EEH is not enabled. */ - pdn = PCI_DN(dn); - if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || - pdn->eeh_mode & EEH_MODE_NOCHECK) { -#ifdef DEBUG - printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", - pci_name(dev), pdn->node->full_name); -#endif - return; - } - - /* The cache holds a reference to the device... */ - pci_dev_get(dev); - - /* Walk resources on this device, poke them into the tree */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - unsigned long start = pci_resource_start(dev,i); - unsigned long end = pci_resource_end(dev,i); - unsigned int flags = pci_resource_flags(dev,i); - - /* We are interested only bus addresses, not dma or other stuff */ - if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM))) - continue; - if (start == 0 || ~start == 0 || end == 0 || ~end == 0) - continue; - pci_addr_cache_insert(dev, start, end, flags); - inserted = 1; - } - - /* If there was nothing to add, the cache has no reference... */ - if (!inserted) - pci_dev_put(dev); -} - -/** - * pci_addr_cache_insert_device - Add a device to the address cache - * @dev: PCI device whose I/O addresses we are interested in. - * - * In order to support the fast lookup of devices based on addresses, - * we maintain a cache of devices that can be quickly searched. - * This routine adds a device to that cache. - */ -static void pci_addr_cache_insert_device(struct pci_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); - __pci_addr_cache_insert_device(dev); - spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); -} - -static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) -{ - struct rb_node *n; - int removed = 0; - -restart: - n = rb_first(&pci_io_addr_cache_root.rb_root); - while (n) { - struct pci_io_addr_range *piar; - piar = rb_entry(n, struct pci_io_addr_range, rb_node); - - if (piar->pcidev == dev) { - rb_erase(n, &pci_io_addr_cache_root.rb_root); - removed = 1; - kfree(piar); - goto restart; - } - n = rb_next(n); - } - - /* The cache no longer holds its reference to this device... */ - if (removed) - pci_dev_put(dev); -} - -/** - * pci_addr_cache_remove_device - remove pci device from addr cache - * @dev: device to remove - * - * Remove a device from the addr-cache tree. - * This is potentially expensive, since it will walk - * the tree multiple times (once per resource). - * But so what; device removal doesn't need to be that fast. - */ -static void pci_addr_cache_remove_device(struct pci_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); - __pci_addr_cache_remove_device(dev); - spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); -} - -/** - * pci_addr_cache_build - Build a cache of I/O addresses - * - * Build a cache of pci i/o addresses. This cache will be used to - * find the pci device that corresponds to a given address. - * This routine scans all pci busses to build the cache. - * Must be run late in boot process, after the pci controllers - * have been scaned for devices (after all device resources are known). - */ -void __init pci_addr_cache_build(void) -{ - struct device_node *dn; - struct pci_dev *dev = NULL; - - if (!eeh_subsystem_enabled) - return; - - spin_lock_init(&pci_io_addr_cache_root.piar_lock); - - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - /* Ignore PCI bridges ( XXX why ??) */ - if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) { - continue; - } - pci_addr_cache_insert_device(dev); - - /* Save the BAR's; firmware doesn't restore these after EEH reset */ - dn = pci_device_to_OF_node(dev); - eeh_save_bars(dev, PCI_DN(dn)); - } +static unsigned long no_device; +static unsigned long no_dn; +static unsigned long no_cfg_addr; +static unsigned long ignored_check; +static unsigned long total_mmio_ffs; +static unsigned long false_positives; +static unsigned long ignored_failures; +static unsigned long slot_resets; -#ifdef DEBUG - /* Verify tree built up above, echo back the list of addrs. */ - pci_addr_cache_print(&pci_io_addr_cache_root); -#endif -} +#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) /* --------------------------------------------------------------- */ -/* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ +/* Below lies the EEH event infrastructure */ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) { + int config_addr; unsigned long flags; int rc; @@ -407,8 +121,13 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) spin_lock_irqsave(&slot_errbuf_lock, flags); memset(slot_errbuf, 0, eeh_error_buf_size); + /* Use PE configuration address, if present */ + config_addr = pdn->eeh_config_addr; + if (pdn->eeh_pe_config_addr) + config_addr = pdn->eeh_pe_config_addr; + rc = rtas_call(ibm_slot_error_detail, - 8, 1, NULL, pdn->eeh_config_addr, + 8, 1, NULL, config_addr, BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid), NULL, 0, virt_to_phys(slot_errbuf), @@ -428,6 +147,7 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) { int token, outputs; + int config_addr; if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { token = ibm_read_slot_reset_state2; @@ -438,7 +158,12 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) outputs = 3; } - return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr, + /* Use PE configuration address, if present */ + config_addr = pdn->eeh_config_addr; + if (pdn->eeh_pe_config_addr) + config_addr = pdn->eeh_pe_config_addr; + + return rtas_call(token, 3, outputs, rets, config_addr, BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); } @@ -462,7 +187,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) /** * Return the "partitionable endpoint" (pe) under which this device lies */ -static struct device_node * find_device_pe(struct device_node *dn) +struct device_node * find_device_pe(struct device_node *dn) { while ((dn->parent) && PCI_DN(dn->parent) && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { @@ -483,8 +208,14 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag) { while (dn) { if (PCI_DN(dn)) { + /* Mark the pci device driver too */ + struct pci_dev *dev = PCI_DN(dn)->pcidev; + PCI_DN(dn)->eeh_mode |= mode_flag; + if (dev && dev->driver) + dev->error_state = pci_channel_io_frozen; + if (dn->child) __eeh_mark_slot (dn->child, mode_flag); } @@ -495,6 +226,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag) void eeh_mark_slot (struct device_node *dn, int mode_flag) { dn = find_device_pe (dn); + + /* Back up one, since config addrs might be shared */ + if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + dn = dn->parent; + PCI_DN(dn)->eeh_mode |= mode_flag; __eeh_mark_slot (dn->child, mode_flag); } @@ -516,7 +252,13 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) { unsigned long flags; spin_lock_irqsave(&confirm_error_lock, flags); + dn = find_device_pe (dn); + + /* Back up one, since config addrs might be shared */ + if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + dn = dn->parent; + PCI_DN(dn)->eeh_mode &= ~mode_flag; PCI_DN(dn)->eeh_check_count = 0; __eeh_clear_slot (dn->child, mode_flag); @@ -544,15 +286,16 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) int rets[3]; unsigned long flags; struct pci_dn *pdn; + enum pci_channel_state state; int rc = 0; - __get_cpu_var(total_mmio_ffs)++; + total_mmio_ffs++; if (!eeh_subsystem_enabled) return 0; if (!dn) { - __get_cpu_var(no_dn)++; + no_dn++; return 0; } pdn = PCI_DN(dn); @@ -560,7 +303,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) /* Access to IO BARs might get this far and still not want checking. */ if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || pdn->eeh_mode & EEH_MODE_NOCHECK) { - __get_cpu_var(ignored_check)++; + ignored_check++; #ifdef DEBUG printk ("EEH:ignored check (%x) for %s %s\n", pdn->eeh_mode, pci_name (dev), dn->full_name); @@ -568,8 +311,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) return 0; } - if (!pdn->eeh_config_addr) { - __get_cpu_var(no_cfg_addr)++; + if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) { + no_cfg_addr++; return 0; } @@ -611,7 +354,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) if (ret != 0) { printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", ret, dn->full_name); - __get_cpu_var(false_positives)++; + false_positives++; rc = 0; goto dn_unlock; } @@ -620,14 +363,14 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) if (rets[1] != 1) { printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", ret, dn->full_name); - __get_cpu_var(false_positives)++; + false_positives++; rc = 0; goto dn_unlock; } /* If not the kind of error we know about, punt. */ if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { - __get_cpu_var(false_positives)++; + false_positives++; rc = 0; goto dn_unlock; } @@ -635,12 +378,12 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) /* Note that config-io to empty slots may fail; * we recognize empty because they don't have children. */ if ((rets[0] == 5) && (dn->child == NULL)) { - __get_cpu_var(false_positives)++; + false_positives++; rc = 0; goto dn_unlock; } - __get_cpu_var(slot_resets)++; + slot_resets++; /* Avoid repeated reports of this failure, including problems * with other functions on this device, and functions under @@ -648,8 +391,13 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) eeh_mark_slot (dn, EEH_MODE_ISOLATED); spin_unlock_irqrestore(&confirm_error_lock, flags); - eeh_send_failure_event (dn, dev, rets[0], rets[2]); - + state = pci_channel_io_normal; + if ((rets[0] == 2) || (rets[0] == 4)) + state = pci_channel_io_frozen; + if (rets[0] == 5) + state = pci_channel_io_perm_failure; + eeh_send_failure_event (dn, dev, state, rets[2]); + /* Most EEH events are due to device driver bugs. Having * a stack trace will help the device-driver authors figure * out what happened. So print that out. */ @@ -685,7 +433,7 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon addr = eeh_token_to_phys((unsigned long __force) token); dev = pci_get_device_by_addr(addr); if (!dev) { - __get_cpu_var(no_device)++; + no_device++; return val; } @@ -716,11 +464,16 @@ eeh_slot_availability(struct pci_dn *pdn) if (rc) return rc; if (rets[1] == 0) return -1; /* EEH is not supported */ - if (rets[0] == 0) return 0; /* Oll Korrect */ + if (rets[0] == 0) return 0; /* Oll Korrect */ if (rets[0] == 5) { if (rets[2] == 0) return -1; /* permanently unavailable */ return rets[2]; /* number of millisecs to wait */ } + if (rets[0] == 1) + return 250; + + printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", + rc, rets[0], rets[1], rets[2]); return -1; } @@ -737,6 +490,7 @@ eeh_slot_availability(struct pci_dn *pdn) static void rtas_pci_slot_reset(struct pci_dn *pdn, int state) { + int config_addr; int rc; BUG_ON (pdn==NULL); @@ -747,8 +501,13 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state) return; } + /* Use PE configuration address, if present */ + config_addr = pdn->eeh_config_addr; + if (pdn->eeh_pe_config_addr) + config_addr = pdn->eeh_pe_config_addr; + rc = rtas_call(ibm_set_slot_reset,4,1, NULL, - pdn->eeh_config_addr, + config_addr, BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid), state); @@ -761,9 +520,11 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state) /** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second * dn -- device node to be reset. + * + * Return 0 if success, else a non-zero value. */ -void +int rtas_set_slot_reset(struct pci_dn *pdn) { int i, rc; @@ -793,10 +554,21 @@ rtas_set_slot_reset(struct pci_dn *pdn) * ready to be used; if not, wait for recovery. */ for (i=0; i<10; i++) { rc = eeh_slot_availability (pdn); - if (rc <= 0) break; + if (rc < 0) + printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name); + if (rc == 0) + return 0; + if (rc < 0) + return -1; msleep (rc+100); } + + rc = eeh_slot_availability (pdn); + if (rc) + printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name); + + return rc; } /* ------------------------------------------------------- */ @@ -851,7 +623,7 @@ void eeh_restore_bars(struct pci_dn *pdn) if (!pdn) return; - if (! pdn->eeh_is_bridge) + if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) __restore_bars (pdn); dn = pdn->node->child; @@ -869,30 +641,30 @@ void eeh_restore_bars(struct pci_dn *pdn) * PCI devices are added individuallly; but, for the restore, * an entire slot is reset at a time. */ -static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn) +static void eeh_save_bars(struct pci_dn *pdn) { int i; - if (!pdev || !pdn ) + if (!pdn ) return; for (i = 0; i < 16; i++) - pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]); - - if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - pdn->eeh_is_bridge = 1; + rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); } void rtas_configure_bridge(struct pci_dn *pdn) { - int token = rtas_token ("ibm,configure-bridge"); + int config_addr; int rc; - if (token == RTAS_UNKNOWN_SERVICE) - return; - rc = rtas_call(token,3,1, NULL, - pdn->eeh_config_addr, + /* Use PE configuration address, if present */ + config_addr = pdn->eeh_config_addr; + if (pdn->eeh_pe_config_addr) + config_addr = pdn->eeh_pe_config_addr; + + rc = rtas_call(ibm_configure_bridge,3,1, NULL, + config_addr, BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); if (rc) { @@ -927,6 +699,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) int enable; struct pci_dn *pdn = PCI_DN(dn); + pdn->class_code = 0; pdn->eeh_mode = 0; pdn->eeh_check_count = 0; pdn->eeh_freeze_count = 0; @@ -943,6 +716,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) pdn->eeh_mode |= EEH_MODE_NOCHECK; return NULL; } + pdn->class_code = *class_code; /* * Now decide if we are going to "Disable" EEH checking @@ -953,8 +727,10 @@ static void *early_enable_eeh(struct device_node *dn, void *data) * But there are a few cases like display devices that make sense. */ enable = 1; /* i.e. we will do checking */ +#if 0 if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY) enable = 0; +#endif if (!enable) pdn->eeh_mode |= EEH_MODE_NOCHECK; @@ -973,8 +749,22 @@ static void *early_enable_eeh(struct device_node *dn, void *data) eeh_subsystem_enabled = 1; pdn->eeh_mode |= EEH_MODE_SUPPORTED; pdn->eeh_config_addr = regs[0]; + + /* If the newer, better, ibm,get-config-addr-info is supported, + * then use that instead. */ + pdn->eeh_pe_config_addr = 0; + if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { + unsigned int rets[2]; + ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, + pdn->eeh_config_addr, + info->buid_hi, info->buid_lo, + 0); + if (ret == 0) + pdn->eeh_pe_config_addr = rets[0]; + } #ifdef DEBUG - printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); + printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n", + dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr); #endif } else { @@ -993,6 +783,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) dn->full_name); } + eeh_save_bars(pdn); return NULL; } @@ -1026,6 +817,8 @@ void __init eeh_init(void) ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2"); ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); + ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); + ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) return; @@ -1080,12 +873,10 @@ void eeh_add_device_early(struct device_node *dn) if (!dn || !PCI_DN(dn)) return; phb = PCI_DN(dn)->phb; - if (NULL == phb || 0 == phb->buid) { - printk(KERN_WARNING "EEH: Expected buid but found none for %s\n", - dn->full_name); - dump_stack(); + + /* USB Bus children of PCI devices will not have BUID's */ + if (NULL == phb || 0 == phb->buid) return; - } info.buid_hi = BUID_HI(phb->buid); info.buid_lo = BUID_LO(phb->buid); @@ -1127,7 +918,6 @@ void eeh_add_device_late(struct pci_dev *dev) pdn->pcidev = dev; pci_addr_cache_insert_device (dev); - eeh_save_bars(dev, pdn); } EXPORT_SYMBOL_GPL(eeh_add_device_late); @@ -1175,25 +965,9 @@ EXPORT_SYMBOL_GPL(eeh_remove_bus_device); static int proc_eeh_show(struct seq_file *m, void *v) { - unsigned int cpu; - unsigned long ffs = 0, positives = 0, failures = 0; - unsigned long resets = 0; - unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0; - - for_each_cpu(cpu) { - ffs += per_cpu(total_mmio_ffs, cpu); - positives += per_cpu(false_positives, cpu); - failures += per_cpu(ignored_failures, cpu); - resets += per_cpu(slot_resets, cpu); - no_dev += per_cpu(no_device, cpu); - no_dn += per_cpu(no_dn, cpu); - no_cfg += per_cpu(no_cfg_addr, cpu); - no_check += per_cpu(ignored_check, cpu); - } - if (0 == eeh_subsystem_enabled) { seq_printf(m, "EEH Subsystem is globally disabled\n"); - seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); + seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs); } else { seq_printf(m, "EEH Subsystem is enabled\n"); seq_printf(m, @@ -1205,8 +979,10 @@ static int proc_eeh_show(struct seq_file *m, void *v) "eeh_false_positives=%ld\n" "eeh_ignored_failures=%ld\n" "eeh_slot_resets=%ld\n", - no_dev, no_dn, no_cfg, no_check, - ffs, positives, failures, resets); + no_device, no_dn, no_cfg_addr, + ignored_check, total_mmio_ffs, + false_positives, ignored_failures, + slot_resets); } return 0; diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c new file mode 100644 index 00000000000..d4a402c5866 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_cache.c @@ -0,0 +1,316 @@ +/* + * eeh_cache.c + * PCI address cache; allows the lookup of PCI devices based on I/O address + * + * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/list.h> +#include <linux/pci.h> +#include <linux/rbtree.h> +#include <linux/spinlock.h> +#include <asm/atomic.h> +#include <asm/pci-bridge.h> +#include <asm/ppc-pci.h> + +#undef DEBUG + +/** + * The pci address cache subsystem. This subsystem places + * PCI device address resources into a red-black tree, sorted + * according to the address range, so that given only an i/o + * address, the corresponding PCI device can be **quickly** + * found. It is safe to perform an address lookup in an interrupt + * context; this ability is an important feature. + * + * Currently, the only customer of this code is the EEH subsystem; + * thus, this code has been somewhat tailored to suit EEH better. + * In particular, the cache does *not* hold the addresses of devices + * for which EEH is not enabled. + * + * (Implementation Note: The RB tree seems to be better/faster + * than any hash algo I could think of for this problem, even + * with the penalty of slow pointer chases for d-cache misses). + */ +struct pci_io_addr_range +{ + struct rb_node rb_node; + unsigned long addr_lo; + unsigned long addr_hi; + struct pci_dev *pcidev; + unsigned int flags; +}; + +static struct pci_io_addr_cache +{ + struct rb_root rb_root; + spinlock_t piar_lock; +} pci_io_addr_cache_root; + +static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr) +{ + struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node; + + while (n) { + struct pci_io_addr_range *piar; + piar = rb_entry(n, struct pci_io_addr_range, rb_node); + + if (addr < piar->addr_lo) { + n = n->rb_left; + } else { + if (addr > piar->addr_hi) { + n = n->rb_right; + } else { + pci_dev_get(piar->pcidev); + return piar->pcidev; + } + } + } + + return NULL; +} + +/** + * pci_get_device_by_addr - Get device, given only address + * @addr: mmio (PIO) phys address or i/o port number + * + * Given an mmio phys address, or a port number, find a pci device + * that implements this address. Be sure to pci_dev_put the device + * when finished. I/O port numbers are assumed to be offset + * from zero (that is, they do *not* have pci_io_addr added in). + * It is safe to call this function within an interrupt. + */ +struct pci_dev *pci_get_device_by_addr(unsigned long addr) +{ + struct pci_dev *dev; + unsigned long flags; + + spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); + dev = __pci_get_device_by_addr(addr); + spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); + return dev; +} + +#ifdef DEBUG +/* + * Handy-dandy debug print routine, does nothing more + * than print out the contents of our addr cache. + */ +static void pci_addr_cache_print(struct pci_io_addr_cache *cache) +{ + struct rb_node *n; + int cnt = 0; + + n = rb_first(&cache->rb_root); + while (n) { + struct pci_io_addr_range *piar; + piar = rb_entry(n, struct pci_io_addr_range, rb_node); + printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n", + (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt, + piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev)); + cnt++; + n = rb_next(n); + } +} +#endif + +/* Insert address range into the rb tree. */ +static struct pci_io_addr_range * +pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, + unsigned long ahi, unsigned int flags) +{ + struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node; + struct rb_node *parent = NULL; + struct pci_io_addr_range *piar; + + /* Walk tree, find a place to insert into tree */ + while (*p) { + parent = *p; + piar = rb_entry(parent, struct pci_io_addr_range, rb_node); + if (ahi < piar->addr_lo) { + p = &parent->rb_left; + } else if (alo > piar->addr_hi) { + p = &parent->rb_right; + } else { + if (dev != piar->pcidev || + alo != piar->addr_lo || ahi != piar->addr_hi) { + printk(KERN_WARNING "PIAR: overlapping address range\n"); + } + return piar; + } + } + piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC); + if (!piar) + return NULL; + + piar->addr_lo = alo; + piar->addr_hi = ahi; + piar->pcidev = dev; + piar->flags = flags; + +#ifdef DEBUG + printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", + alo, ahi, pci_name (dev)); +#endif + + rb_link_node(&piar->rb_node, parent, p); + rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); + + return piar; +} + +static void __pci_addr_cache_insert_device(struct pci_dev *dev) +{ + struct device_node *dn; + struct pci_dn *pdn; + int i; + int inserted = 0; + + dn = pci_device_to_OF_node(dev); + if (!dn) { + printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev)); + return; + } + + /* Skip any devices for which EEH is not enabled. */ + pdn = PCI_DN(dn); + if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || + pdn->eeh_mode & EEH_MODE_NOCHECK) { +#ifdef DEBUG + printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", + pci_name(dev), pdn->node->full_name); +#endif + return; + } + + /* The cache holds a reference to the device... */ + pci_dev_get(dev); + + /* Walk resources on this device, poke them into the tree */ + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + unsigned long start = pci_resource_start(dev,i); + unsigned long end = pci_resource_end(dev,i); + unsigned int flags = pci_resource_flags(dev,i); + + /* We are interested only bus addresses, not dma or other stuff */ + if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM))) + continue; + if (start == 0 || ~start == 0 || end == 0 || ~end == 0) + continue; + pci_addr_cache_insert(dev, start, end, flags); + inserted = 1; + } + + /* If there was nothing to add, the cache has no reference... */ + if (!inserted) + pci_dev_put(dev); +} + +/** + * pci_addr_cache_insert_device - Add a device to the address cache + * @dev: PCI device whose I/O addresses we are interested in. + * + * In order to support the fast lookup of devices based on addresses, + * we maintain a cache of devices that can be quickly searched. + * This routine adds a device to that cache. + */ +void pci_addr_cache_insert_device(struct pci_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); + __pci_addr_cache_insert_device(dev); + spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); +} + +static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) +{ + struct rb_node *n; + int removed = 0; + +restart: + n = rb_first(&pci_io_addr_cache_root.rb_root); + while (n) { + struct pci_io_addr_range *piar; + piar = rb_entry(n, struct pci_io_addr_range, rb_node); + + if (piar->pcidev == dev) { + rb_erase(n, &pci_io_addr_cache_root.rb_root); + removed = 1; + kfree(piar); + goto restart; + } + n = rb_next(n); + } + + /* The cache no longer holds its reference to this device... */ + if (removed) + pci_dev_put(dev); +} + +/** + * pci_addr_cache_remove_device - remove pci device from addr cache + * @dev: device to remove + * + * Remove a device from the addr-cache tree. + * This is potentially expensive, since it will walk + * the tree multiple times (once per resource). + * But so what; device removal doesn't need to be that fast. + */ +void pci_addr_cache_remove_device(struct pci_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); + __pci_addr_cache_remove_device(dev); + spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); +} + +/** + * pci_addr_cache_build - Build a cache of I/O addresses + * + * Build a cache of pci i/o addresses. This cache will be used to + * find the pci device that corresponds to a given address. + * This routine scans all pci busses to build the cache. + * Must be run late in boot process, after the pci controllers + * have been scaned for devices (after all device resources are known). + */ +void __init pci_addr_cache_build(void) +{ + struct device_node *dn; + struct pci_dev *dev = NULL; + + spin_lock_init(&pci_io_addr_cache_root.piar_lock); + + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + /* Ignore PCI bridges */ + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) + continue; + + pci_addr_cache_insert_device(dev); + + dn = pci_device_to_OF_node(dev); + pci_dev_get (dev); /* matching put is in eeh_remove_device() */ + PCI_DN(dn)->pcidev = dev; + } + +#ifdef DEBUG + /* Verify tree built up above, echo back the list of addrs. */ + pci_addr_cache_print(&pci_io_addr_cache_root); +#endif +} + diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c new file mode 100644 index 00000000000..6373372932b --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -0,0 +1,376 @@ +/* + * PCI Error Recovery Driver for RPA-compliant PPC64 platform. + * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to <linas@us.ibm.com> + * + */ +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/notifier.h> +#include <linux/pci.h> +#include <asm/eeh.h> +#include <asm/eeh_event.h> +#include <asm/ppc-pci.h> +#include <asm/pci-bridge.h> +#include <asm/prom.h> +#include <asm/rtas.h> + + +static inline const char * pcid_name (struct pci_dev *pdev) +{ + if (pdev->dev.driver) + return pdev->dev.driver->name; + return ""; +} + +#ifdef DEBUG +static void print_device_node_tree (struct pci_dn *pdn, int dent) +{ + int i; + if (!pdn) return; + for (i=0;i<dent; i++) + printk(" "); + printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n", + pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr, + pdn->eeh_pe_config_addr, pdn->node->full_name); + dent += 3; + struct device_node *pc = pdn->node->child; + while (pc) { + print_device_node_tree(PCI_DN(pc), dent); + pc = pc->sibling; + } +} +#endif + +/** + * irq_in_use - return true if this irq is being used + */ +static int irq_in_use(unsigned int irq) +{ + int rc = 0; + unsigned long flags; + struct irq_desc *desc = irq_desc + irq; + + spin_lock_irqsave(&desc->lock, flags); + if (desc->action) + rc = 1; + spin_unlock_irqrestore(&desc->lock, flags); + return rc; +} + +/* ------------------------------------------------------- */ +/** eeh_report_error - report an EEH error to each device, + * collect up and merge the device responses. + */ + +static void eeh_report_error(struct pci_dev *dev, void *userdata) +{ + enum pci_ers_result rc, *res = userdata; + struct pci_driver *driver = dev->driver; + + dev->error_state = pci_channel_io_frozen; + + if (!driver) + return; + + if (irq_in_use (dev->irq)) { + struct device_node *dn = pci_device_to_OF_node(dev); + PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; + disable_irq_nosync(dev->irq); + } + if (!driver->err_handler) + return; + if (!driver->err_handler->error_detected) + return; + + rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); + if (*res == PCI_ERS_RESULT_NONE) *res = rc; + if (*res == PCI_ERS_RESULT_NEED_RESET) return; + if (*res == PCI_ERS_RESULT_DISCONNECT && + rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; +} + +/** eeh_report_reset -- tell this device that the pci slot + * has been reset. + */ + +static void eeh_report_reset(struct pci_dev *dev, void *userdata) +{ + struct pci_driver *driver = dev->driver; + struct device_node *dn = pci_device_to_OF_node(dev); + + if (!driver) + return; + + if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) { + PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; + enable_irq(dev->irq); + } + if (!driver->err_handler) + return; + if (!driver->err_handler->slot_reset) + return; + + driver->err_handler->slot_reset(dev); +} + +static void eeh_report_resume(struct pci_dev *dev, void *userdata) +{ + struct pci_driver *driver = dev->driver; + + dev->error_state = pci_channel_io_normal; + + if (!driver) + return; + if (!driver->err_handler) + return; + if (!driver->err_handler->resume) + return; + + driver->err_handler->resume(dev); +} + +static void eeh_report_failure(struct pci_dev *dev, void *userdata) +{ + struct pci_driver *driver = dev->driver; + + dev->error_state = pci_channel_io_perm_failure; + + if (!driver) + return; + + if (irq_in_use (dev->irq)) { + struct device_node *dn = pci_device_to_OF_node(dev); + PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; + disable_irq_nosync(dev->irq); + } + if (!driver->err_handler) + return; + if (!driver->err_handler->error_detected) + return; + driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); +} + +/* ------------------------------------------------------- */ +/** + * handle_eeh_events -- reset a PCI device after hard lockup. + * + * pSeries systems will isolate a PCI slot if the PCI-Host + * bridge detects address or data parity errors, DMA's + * occuring to wild addresses (which usually happen due to + * bugs in device drivers or in PCI adapter firmware). + * Slot isolations also occur if #SERR, #PERR or other misc + * PCI-related errors are detected. + * + * Recovery process consists of unplugging the device driver + * (which generated hotplug events to userspace), then issuing + * a PCI #RST to the device, then reconfiguring the PCI config + * space for all bridges & devices under this slot, and then + * finally restarting the device drivers (which cause a second + * set of hotplug events to go out to userspace). + */ + +/** + * eeh_reset_device() -- perform actual reset of a pci slot + * Args: bus: pointer to the pci bus structure corresponding + * to the isolated slot. A non-null value will + * cause all devices under the bus to be removed + * and then re-added. + * pe_dn: pointer to a "Partionable Endpoint" device node. + * This is the top-level structure on which pci + * bus resets can be performed. + */ + +static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) +{ + int rc; + if (bus) + pcibios_remove_pci_devices(bus); + + /* Reset the pci controller. (Asserts RST#; resets config space). + * Reconfigure bridges and devices. Don't try to bring the system + * up if the reset failed for some reason. */ + rc = rtas_set_slot_reset(pe_dn); + if (rc) + return rc; + + /* New-style config addrs might be shared across multiple devices, + * Walk over all functions on this device */ + if (pe_dn->eeh_pe_config_addr) { + struct device_node *pe = pe_dn->node; + pe = pe->parent->child; + while (pe) { + struct pci_dn *ppe = PCI_DN(pe); + if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { + rtas_configure_bridge(ppe); + eeh_restore_bars(ppe); + } + pe = pe->sibling; + } + } else { + rtas_configure_bridge(pe_dn); + eeh_restore_bars(pe_dn); + } + + /* Give the system 5 seconds to finish running the user-space + * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, + * this is a hack, but if we don't do this, and try to bring + * the device up before the scripts have taken it down, + * potentially weird things happen. + */ + if (bus) { + ssleep (5); + pcibios_add_pci_devices(bus); + } + + return 0; +} + +/* The longest amount of time to wait for a pci device + * to come back on line, in seconds. + */ +#define MAX_WAIT_FOR_RECOVERY 15 + +void handle_eeh_events (struct eeh_event *event) +{ + struct device_node *frozen_dn; + struct pci_dn *frozen_pdn; + struct pci_bus *frozen_bus; + int rc = 0; + enum pci_ers_result result = PCI_ERS_RESULT_NONE; + + frozen_dn = find_device_pe(event->dn); + frozen_bus = pcibios_find_pci_bus(frozen_dn); + + if (!frozen_dn) { + printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", + pci_name(event->dev)); + return; + } + + /* There are two different styles for coming up with the PE. + * In the old style, it was the highest EEH-capable device + * which was always an EADS pci bridge. In the new style, + * there might not be any EADS bridges, and even when there are, + * the firmware marks them as "EEH incapable". So another + * two-step is needed to find the pci bus.. */ + if (!frozen_bus) + frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); + + if (!frozen_bus) { + printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", + frozen_dn->full_name); + return; + } + +#if 0 + /* We may get "permanent failure" messages on empty slots. + * These are false alarms. Empty slots have no child dn. */ + if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL)) + return; +#endif + + frozen_pdn = PCI_DN(frozen_dn); + frozen_pdn->eeh_freeze_count++; + + if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) + goto hard_fail; + + /* If the reset state is a '5' and the time to reset is 0 (infinity) + * or is more then 15 seconds, then mark this as a permanent failure. + */ + if ((event->state == pci_channel_io_perm_failure) && + ((event->time_unavail <= 0) || + (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000))) + goto hard_fail; + + eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); + printk(KERN_WARNING + "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", + frozen_pdn->eeh_freeze_count, + pci_name (frozen_pdn->pcidev), + pcid_name(frozen_pdn->pcidev)); + + /* Walk the various device drivers attached to this slot through + * a reset sequence, giving each an opportunity to do what it needs + * to accomplish the reset. Each child gets a report of the + * status ... if any child can't handle the reset, then the entire + * slot is dlpar removed and added. + */ + pci_walk_bus(frozen_bus, eeh_report_error, &result); + + /* If all device drivers were EEH-unaware, then shut + * down all of the device drivers, and hope they + * go down willingly, without panicing the system. + */ + if (result == PCI_ERS_RESULT_NONE) { + rc = eeh_reset_device(frozen_pdn, frozen_bus); + if (rc) + goto hard_fail; + } + + /* If any device called out for a reset, then reset the slot */ + if (result == PCI_ERS_RESULT_NEED_RESET) { + rc = eeh_reset_device(frozen_pdn, NULL); + if (rc) + goto hard_fail; + pci_walk_bus(frozen_bus, eeh_report_reset, 0); + } + + /* If all devices reported they can proceed, the re-enable PIO */ + if (result == PCI_ERS_RESULT_CAN_RECOVER) { + /* XXX Not supported; we brute-force reset the device */ + rc = eeh_reset_device(frozen_pdn, NULL); + if (rc) + goto hard_fail; + pci_walk_bus(frozen_bus, eeh_report_reset, 0); + } + + /* Tell all device drivers that they can resume operations */ + pci_walk_bus(frozen_bus, eeh_report_resume, 0); + + return; + +hard_fail: + /* + * About 90% of all real-life EEH failures in the field + * are due to poorly seated PCI cards. Only 10% or so are + * due to actual, failed cards. + */ + printk(KERN_ERR + "EEH: PCI device %s - %s has failed %d times \n" + "and has been permanently disabled. Please try reseating\n" + "this device or replacing it.\n", + pci_name (frozen_pdn->pcidev), + pcid_name(frozen_pdn->pcidev), + frozen_pdn->eeh_freeze_count); + + eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); + + /* Notify all devices that they're about to go down. */ + pci_walk_bus(frozen_bus, eeh_report_failure, 0); + + /* Shut down the device drivers for good. */ + pcibios_remove_pci_devices(frozen_bus); +} + +/* ---------- end of file ---------- */ diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 92497333c2b..9a9961f2748 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -21,6 +21,7 @@ #include <linux/list.h> #include <linux/pci.h> #include <asm/eeh_event.h> +#include <asm/ppc-pci.h> /** Overview: * EEH error states may be detected within exception handlers; @@ -37,31 +38,6 @@ static void eeh_thread_launcher(void *); DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); /** - * eeh_panic - call panic() for an eeh event that cannot be handled. - * The philosophy of this routine is that it is better to panic and - * halt the OS than it is to risk possible data corruption by - * oblivious device drivers that don't know better. - * - * @dev pci device that had an eeh event - * @reset_state current reset state of the device slot - */ -static void eeh_panic(struct pci_dev *dev, int reset_state) -{ - /* - * Since the panic_on_oops sysctl is used to halt the system - * in light of potential corruption, we can use it here. - */ - if (panic_on_oops) { - panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, - pci_name(dev)); - } - else { - printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", - reset_state, pci_name(dev)); - } -} - -/** * eeh_event_handler - dispatch EEH events. The detection of a frozen * slot can occur inside an interrupt, where it can be hard to do * anything about it. The goal of this routine is to pull these @@ -82,10 +58,16 @@ static int eeh_event_handler(void * dummy) spin_lock_irqsave(&eeh_eventlist_lock, flags); event = NULL; + + /* Unqueue the event, get ready to process. */ if (!list_empty(&eeh_eventlist)) { event = list_entry(eeh_eventlist.next, struct eeh_event, list); list_del(&event->list); } + + if (event) + eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); if (event == NULL) break; @@ -93,8 +75,11 @@ static int eeh_event_handler(void * dummy) printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", pci_name(event->dev)); - eeh_panic (event->dev, event->state); + handle_eeh_events(event); + + eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); + pci_dev_put(event->dev); kfree(event); } @@ -122,7 +107,7 @@ static void eeh_thread_launcher(void *dummy) */ int eeh_send_failure_event (struct device_node *dn, struct pci_dev *dev, - int state, + enum pci_channel_state state, int time_unavail) { unsigned long flags; diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4d584172055..22bfb5c89db 100644 --- a/arch/powerpc/platforms/pseries/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c @@ -40,7 +40,7 @@ MODULE_VERSION(HVCS_ARCH_VERSION); * functions aren't performance sensitive, so this conversion isn't an * issue. */ -int hvcs_convert(long to_convert) +static int hvcs_convert(long to_convert) { switch (to_convert) { case H_Success: @@ -91,7 +91,7 @@ int hvcs_free_partner_info(struct list_head *head) EXPORT_SYMBOL(hvcs_free_partner_info); /* Helper function for hvcs_get_partner_info */ -int hvcs_next_partner(uint32_t unit_address, +static int hvcs_next_partner(uint32_t unit_address, unsigned long last_p_partition_ID, unsigned long last_p_unit_address, unsigned long *pi_buff) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 169f9148789..48cfbfc43f9 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -51,8 +51,6 @@ #define DBG(fmt...) -extern int is_python(struct device_node *); - static void tce_build_pSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 2edc947f7c4..50643496eb6 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -192,7 +192,7 @@ struct file_operations scanlog_fops = { .release = scanlog_release, }; -int __init scanlog_init(void) +static int __init scanlog_init(void) { struct proc_dir_entry *ent; @@ -222,7 +222,7 @@ int __init scanlog_init(void) return 0; } -void __exit scanlog_cleanup(void) +static void __exit scanlog_cleanup(void) { if (proc_ppc64_scan_log_dump) { kfree(proc_ppc64_scan_log_dump->data); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 8903cf63236..68b7f086d63 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -86,7 +86,7 @@ static void pseries_dedicated_idle(void); struct mpic *pSeries_mpic; -void pSeries_show_cpuinfo(struct seq_file *m) +static void pSeries_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 25181c594d7..8e6b1ed1396 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -93,7 +93,7 @@ static int query_cpu_stopped(unsigned int pcpu) return cpu_status; } -int pSeries_cpu_disable(void) +static int pSeries_cpu_disable(void) { int cpu = smp_processor_id(); @@ -109,7 +109,7 @@ int pSeries_cpu_disable(void) return 0; } -void pSeries_cpu_die(unsigned int cpu) +static void pSeries_cpu_die(unsigned int cpu) { int tries; int cpu_status; @@ -282,7 +282,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); /* Fixup atomic count: it exited inside IRQ handler. */ - paca[lcpu].__current->thread_info->preempt_count = 0; + task_thread_info(paca[lcpu].__current)->preempt_count = 0; /* * If the RTAS start-cpu token does not exist then presume the diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0c0cfa32eb5..fd823c7c9ac 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -381,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs) #ifdef CONFIG_SMP -irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 14b9abde2d2..0ae841347a0 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -6,4 +6,4 @@ obj-$(CONFIG_BOOKE) += dcr.o obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o -obj-$(CONFIG_83xx) += ipic.o +obj-$(CONFIG_PPC_83xx) += ipic.o diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index e00b46b9514..977de9db875 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -139,7 +139,6 @@ static void dart_build(struct iommu_table *tbl, long index, *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); - rpn++; uaddr += DART_PAGE_SIZE; } diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 22612ed5379..7d02fa2a899 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -311,7 +311,7 @@ static void release_output_lock(void) } #endif -int xmon_core(struct pt_regs *regs, int fromipi) +static int xmon_core(struct pt_regs *regs, int fromipi) { int cmd = 0; unsigned long msr; @@ -528,7 +528,7 @@ xmon_irq(int irq, void *d, struct pt_regs *regs) return IRQ_HANDLED; } -int xmon_bpt(struct pt_regs *regs) +static int xmon_bpt(struct pt_regs *regs) { struct bpt *bp; unsigned long offset; @@ -554,7 +554,7 @@ int xmon_bpt(struct pt_regs *regs) return 1; } -int xmon_sstep(struct pt_regs *regs) +static int xmon_sstep(struct pt_regs *regs) { if (user_mode(regs)) return 0; @@ -562,7 +562,7 @@ int xmon_sstep(struct pt_regs *regs) return 1; } -int xmon_dabr_match(struct pt_regs *regs) +static int xmon_dabr_match(struct pt_regs *regs) { if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) return 0; @@ -572,7 +572,7 @@ int xmon_dabr_match(struct pt_regs *regs) return 1; } -int xmon_iabr_match(struct pt_regs *regs) +static int xmon_iabr_match(struct pt_regs *regs) { if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) return 0; @@ -582,7 +582,7 @@ int xmon_iabr_match(struct pt_regs *regs) return 1; } -int xmon_ipi(struct pt_regs *regs) +static int xmon_ipi(struct pt_regs *regs) { #ifdef CONFIG_SMP if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon)) @@ -591,7 +591,7 @@ int xmon_ipi(struct pt_regs *regs) return 0; } -int xmon_fault_handler(struct pt_regs *regs) +static int xmon_fault_handler(struct pt_regs *regs) { struct bpt *bp; unsigned long offset; diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index 84d96b857e4..ebc4db8fcc6 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -47,6 +47,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/capability.h> #include <linux/circ_buf.h> #include <linux/serial.h> #include <linux/console.h> diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index e396f4591d5..d65810108bc 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -743,6 +743,10 @@ config MPC834x bool default y if MPC834x_SYS +config PPC_83xx + bool + default y if 83xx + config CPM1 bool depends on 8xx diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index e719a4933af..98e940beeb3 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -128,10 +128,9 @@ TOUT := .tmp_gas_check # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec # instructions. # gcc-3.4 and binutils-2.14 are a fatal combination. -GCC_VERSION := $(call cc-version) checkbin: - @if test "$(GCC_VERSION)" = "0304" ; then \ + @if test "$(call cc-version)" = "0304" ; then \ if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \ echo 'correctly with gcc-3.4 and your version of binutils.'; \ diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c index 91195e2ce38..5f35cf3986f 100644 --- a/arch/ppc/amiga/amiints.c +++ b/arch/ppc/amiga/amiints.c @@ -96,8 +96,8 @@ void amiga_init_IRQ(void) gayle.inten = GAYLE_IRQ_IDE; /* turn off all interrupts... */ - custom.intena = 0x7fff; - custom.intreq = 0x7fff; + amiga_custom.intena = 0x7fff; + amiga_custom.intreq = 0x7fff; #ifdef CONFIG_APUS /* Clear any inter-CPU interrupt requests. Circumvents bug in @@ -110,7 +110,7 @@ void amiga_init_IRQ(void) APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK); #endif /* ... and enable the master interrupt bit */ - custom.intena = IF_SETCLR | IF_INTEN; + amiga_custom.intena = IF_SETCLR | IF_INTEN; cia_init_IRQ(&ciaa_base); cia_init_IRQ(&ciab_base); @@ -151,7 +151,7 @@ void amiga_enable_irq(unsigned int irq) } /* enable the interrupt */ - custom.intena = IF_SETCLR | ami_intena_vals[irq]; + amiga_custom.intena = IF_SETCLR | ami_intena_vals[irq]; } void amiga_disable_irq(unsigned int irq) @@ -177,7 +177,7 @@ void amiga_disable_irq(unsigned int irq) } /* disable the interrupt */ - custom.intena = ami_intena_vals[irq]; + amiga_custom.intena = ami_intena_vals[irq]; } inline void amiga_do_irq(int irq, struct pt_regs *fp) @@ -196,7 +196,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) kstat_cpu(0).irqs[irq]++; - custom.intreq = ami_intena_vals[irq]; + amiga_custom.intreq = ami_intena_vals[irq]; for (action = desc->action; action; action = action->next) action->handler(irq, action->dev_id, fp); @@ -208,40 +208,40 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp) static void ami_int1(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { - custom.intreq = IF_TBE; + amiga_custom.intreq = IF_TBE; amiga_do_irq(IRQ_AMIGA_TBE, fp); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { - custom.intreq = IF_DSKBLK; + amiga_custom.intreq = IF_DSKBLK; amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { - custom.intreq = IF_SOFT; + amiga_custom.intreq = IF_SOFT; amiga_do_irq(IRQ_AMIGA_SOFT, fp); } } static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if a blitter interrupt */ if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; + amiga_custom.intreq = IF_BLIT; amiga_do_irq(IRQ_AMIGA_BLIT, fp); } /* if a copper interrupt */ if (ints & IF_COPER) { - custom.intreq = IF_COPER; + amiga_custom.intreq = IF_COPER; amiga_do_irq(IRQ_AMIGA_COPPER, fp); } @@ -252,36 +252,36 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) static void ami_int4(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if audio 0 interrupt */ if (ints & IF_AUD0) { - custom.intreq = IF_AUD0; + amiga_custom.intreq = IF_AUD0; amiga_do_irq(IRQ_AMIGA_AUD0, fp); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { - custom.intreq = IF_AUD1; + amiga_custom.intreq = IF_AUD1; amiga_do_irq(IRQ_AMIGA_AUD1, fp); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { - custom.intreq = IF_AUD2; + amiga_custom.intreq = IF_AUD2; amiga_do_irq(IRQ_AMIGA_AUD2, fp); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { - custom.intreq = IF_AUD3; + amiga_custom.intreq = IF_AUD3; amiga_do_irq(IRQ_AMIGA_AUD3, fp); } } static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { @@ -291,7 +291,7 @@ static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { - custom.intreq = IF_DSKSYN; + amiga_custom.intreq = IF_DSKSYN; amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); } } diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c index ad961465b6c..4431c58f611 100644 --- a/arch/ppc/amiga/cia.c +++ b/arch/ppc/amiga/cia.c @@ -66,7 +66,7 @@ static unsigned char cia_set_irq_private(struct ciabase *base, else base->icr_data &= ~mask; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old & base->icr_mask; } @@ -114,7 +114,7 @@ static unsigned char cia_able_irq_private(struct ciabase *base, base->icr_mask &= CIA_ICR_ALL; if (base->icr_data & base->icr_mask) - custom.intreq = IF_SETCLR | base->int_mask; + amiga_custom.intreq = IF_SETCLR | base->int_mask; return old; } @@ -145,7 +145,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) irq = base->cia_irq; desc = irq_desc + irq; ints = cia_set_irq_private(base, CIA_ICR_ALL); - custom.intreq = base->int_mask; + amiga_custom.intreq = base->int_mask; for (i = 0; i < CIA_IRQS; i++, irq++) { if (ints & 1) { kstat_cpu(0).irqs[irq]++; @@ -174,5 +174,5 @@ void __init cia_init_IRQ(struct ciabase *base) action->name = base->name; setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]); - custom.intena = IF_SETCLR | base->int_mask; + amiga_custom.intena = IF_SETCLR | base->int_mask; } diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index af881d7454d..60e2da1c92c 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -90,9 +90,6 @@ static void a3000_gettod (int *, int *, int *, int *, int *, int *); static void a2000_gettod (int *, int *, int *, int *, int *, int *); static int amiga_hwclk (int, struct hwclk_time *); static int amiga_set_clock_mmss (unsigned long); -#ifdef CONFIG_AMIGA_FLOPPY -extern void amiga_floppy_setup(char *, int *); -#endif static void amiga_reset (void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); @@ -281,7 +278,7 @@ static void __init amiga_identify(void) case CS_OCS: case CS_ECS: case CS_AGA: - switch (custom.deniseid & 0xf) { + switch (amiga_custom.deniseid & 0xf) { case 0x0c: AMIGAHW_SET(DENISE_HR); break; @@ -294,7 +291,7 @@ static void __init amiga_identify(void) AMIGAHW_SET(DENISE); break; } - switch ((custom.vposr>>8) & 0x7f) { + switch ((amiga_custom.vposr>>8) & 0x7f) { case 0x00: AMIGAHW_SET(AGNUS_PAL); break; @@ -419,9 +416,6 @@ void __init config_amiga(void) mach_hwclk = amiga_hwclk; mach_set_clock_mmss = amiga_set_clock_mmss; -#ifdef CONFIG_AMIGA_FLOPPY - mach_floppy_setup = amiga_floppy_setup; -#endif mach_reset = amiga_reset; #ifdef CONFIG_HEARTBEAT mach_heartbeat = amiga_heartbeat; @@ -432,9 +426,9 @@ void __init config_amiga(void) amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ /* clear all DMA bits */ - custom.dmacon = DMAF_ALL; + amiga_custom.dmacon = DMAF_ALL; /* ensure that the DMA master bit is set */ - custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER; /* request all RAM */ for (i = 0; i < m68k_num_memory; i++) { @@ -753,9 +747,9 @@ static void amiga_savekmsg_init(void) static void amiga_serial_putc(char c) { - custom.serdat = (unsigned char)c | 0x100; + amiga_custom.serdat = (unsigned char)c | 0x100; mb(); - while (!(custom.serdatr & 0x2000)) + while (!(amiga_custom.serdatr & 0x2000)) ; } @@ -785,11 +779,11 @@ int amiga_serial_console_wait_key(struct console *co) { int ch; - while (!(custom.intreqr & IF_RBF)) + while (!(amiga_custom.intreqr & IF_RBF)) barrier(); - ch = custom.serdatr & 0xff; + ch = amiga_custom.serdatr & 0xff; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return ch; } diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index e6c1d615bb8..ca020130086 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -13,7 +13,6 @@ extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds obj-y := entry.o traps.o idle.o time.o misc.o \ - process.o \ setup.o \ ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c index a882b0dbe8d..84d65a87191 100644 --- a/arch/ppc/kernel/machine_kexec.c +++ b/arch/ppc/kernel/machine_kexec.c @@ -28,12 +28,6 @@ typedef NORET_TYPE void (*relocate_new_kernel_t)( const extern unsigned char relocate_new_kernel[]; const extern unsigned int relocate_new_kernel_size; -/* - * Provide a dummy crash_notes definition while crash dump arrives to ppc. - * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. - */ -note_buf_t crash_notes[NR_CPUS]; - void machine_shutdown(void) { if (ppc_md.machine_shutdown) diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index ca810025993..2f5c7650274 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -16,6 +16,7 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/sysctl.h> +#include <linux/capability.h> #include <linux/ctype.h> #include <linux/threads.h> #include <linux/smp_lock.h> diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c deleted file mode 100644 index 25cbdc8d294..00000000000 --- a/arch/ppc/kernel/process.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * arch/ppc/kernel/process.c - * - * Derived from "arch/i386/kernel/process.c" - * Copyright (C) 1995 Linus Torvalds - * - * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and - * Paul Mackerras (paulus@cs.anu.edu.au) - * - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/user.h> -#include <linux/elf.h> -#include <linux/init.h> -#include <linux/prctl.h> -#include <linux/init_task.h> -#include <linux/module.h> -#include <linux/kallsyms.h> -#include <linux/mqueue.h> -#include <linux/hardirq.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/mmu.h> -#include <asm/prom.h> - -extern unsigned long _get_SP(void); - -struct task_struct *last_task_used_math = NULL; -struct task_struct *last_task_used_altivec = NULL; -struct task_struct *last_task_used_spe = NULL; - -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - -/* this is 8kB-aligned so we can get to the thread_info struct - at the base of it from the stack pointer with 1 integer instruction. */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = -{ INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); -EXPORT_SYMBOL(init_task); - -/* only used to get secondary processor up */ -struct task_struct *current_set[NR_CPUS] = {&init_task, }; - -#undef SHOW_TASK_SWITCHES -#undef CHECK_STACK - -#if defined(CHECK_STACK) -unsigned long -kernel_stack_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(union task_union); -} - -unsigned long -task_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(struct thread_info); -} - -/* check to make sure the kernel stack is healthy */ -int check_stack(struct task_struct *tsk) -{ - unsigned long stack_top = kernel_stack_top(tsk); - unsigned long tsk_top = task_top(tsk); - int ret = 0; - -#if 0 - /* check thread magic */ - if ( tsk->thread.magic != THREAD_MAGIC ) - { - ret |= 1; - printk("thread.magic bad: %08x\n", tsk->thread.magic); - } -#endif - - if ( !tsk ) - printk("check_stack(): tsk bad tsk %p\n",tsk); - - /* check if stored ksp is bad */ - if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) ) - { - printk("stack out of bounds: %s/%d\n" - " tsk_top %08lx ksp %08lx stack_top %08lx\n", - tsk->comm,tsk->pid, - tsk_top, tsk->thread.ksp, stack_top); - ret |= 2; - } - - /* check if stack ptr RIGHT NOW is bad */ - if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) ) - { - printk("current stack ptr out of bounds: %s/%d\n" - " tsk_top %08lx sp %08lx stack_top %08lx\n", - current->comm,current->pid, - tsk_top, _get_SP(), stack_top); - ret |= 4; - } - -#if 0 - /* check amount of free stack */ - for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ ) - { - if ( !i ) - printk("check_stack(): i = %p\n", i); - if ( *i != 0 ) - { - /* only notify if it's less than 900 bytes */ - if ( (i - (unsigned long *)task_top(tsk)) < 900 ) - printk("%d bytes free on stack\n", - i - task_top(tsk)); - break; - } - } -#endif - - if (ret) - { - panic("bad kernel stack"); - } - return(ret); -} -#endif /* defined(CHECK_STACK) */ - -/* - * Make sure the floating-point register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_fp_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - /* - * We need to disable preemption here because if we didn't, - * another process could get scheduled after the regs->msr - * test but before we have finished saving the FP registers - * to the thread_struct. That process could take over the - * FPU, and then when we get scheduled again we would store - * bogus values for the remaining FP registers. - */ - preempt_disable(); - if (tsk->thread.regs->msr & MSR_FP) { -#ifdef CONFIG_SMP - /* - * This should only ever be called for current or - * for a stopped child process. Since we save away - * the FP register state on context switch on SMP, - * there is something wrong if a stopped child appears - * to still have its FP state in the CPU registers. - */ - BUG_ON(tsk != current); -#endif - giveup_fpu(current); - } - preempt_enable(); - } -} - -void enable_kernel_fp(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) - giveup_fpu(current); - else - giveup_fpu(NULL); /* just enables FP for kernel */ -#else - giveup_fpu(last_task_used_math); -#endif /* CONFIG_SMP */ -} -EXPORT_SYMBOL(enable_kernel_fp); - -int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) -{ - preempt_disable(); - if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP)) - giveup_fpu(tsk); - preempt_enable(); - memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); - return 1; -} - -#ifdef CONFIG_ALTIVEC -void enable_kernel_altivec(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) - giveup_altivec(current); - else - giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ -#else - giveup_altivec(last_task_used_altivec); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_altivec); - -/* - * Make sure the VMX/Altivec register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_altivec_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_VEC) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_altivec(current); - } - preempt_enable(); - } -} - -int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) -{ - if (regs->msr & MSR_VEC) - giveup_altivec(current); - memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); - return 1; -} -#endif /* CONFIG_ALTIVEC */ - -#ifdef CONFIG_SPE -void -enable_kernel_spe(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) - giveup_spe(current); - else - giveup_spe(NULL); /* just enable SPE for kernel - force */ -#else - giveup_spe(last_task_used_spe); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_spe); - -void flush_spe_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_SPE) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_spe(current); - } - preempt_enable(); - } -} - -int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) -{ - if (regs->msr & MSR_SPE) - giveup_spe(current); - /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ - memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); - return 1; -} -#endif /* CONFIG_SPE */ - -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *new) -{ - struct thread_struct *new_thread, *old_thread; - unsigned long s; - struct task_struct *last; - - local_irq_save(s); -#ifdef CHECK_STACK - check_stack(prev); - check_stack(new); -#endif - -#ifdef CONFIG_SMP - /* avoid complexity of lazy save/restore of fpu - * by just saving it every time we switch out if - * this task used the fpu during the last quantum. - * - * If it tries to use the fpu again, it'll trap and - * reload its fp regs. So we don't have to do a restore - * every switch, just a save. - * -- Cort - */ - if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) - giveup_fpu(prev); -#ifdef CONFIG_ALTIVEC - /* - * If the previous thread used altivec in the last quantum - * (thus changing altivec regs) then save them. - * We used to check the VRSAVE register but not all apps - * set it, so we don't rely on it now (and in fact we need - * to save & restore VSCR even if VRSAVE == 0). -- paulus - * - * On SMP we always save/restore altivec regs just to avoid the - * complexity of changing processors. - * -- Cort - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))) - giveup_altivec(prev); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - /* - * If the previous thread used spe in the last quantum - * (thus changing spe regs) then save them. - * - * On SMP we always save/restore spe regs just to avoid the - * complexity of changing processors. - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) - giveup_spe(prev); -#endif /* CONFIG_SPE */ -#endif /* CONFIG_SMP */ - -#ifdef CONFIG_ALTIVEC - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_altivec -- Cort - */ - if (new->thread.regs && last_task_used_altivec == new) - new->thread.regs->msr |= MSR_VEC; -#endif -#ifdef CONFIG_SPE - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_spe - */ - if (new->thread.regs && last_task_used_spe == new) - new->thread.regs->msr |= MSR_SPE; -#endif /* CONFIG_SPE */ - new_thread = &new->thread; - old_thread = ¤t->thread; - last = _switch(old_thread, new_thread); - local_irq_restore(s); - return last; -} - -void show_regs(struct pt_regs * regs) -{ - int i, trap; - - printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n", - regs->nip, regs->link, regs->gpr[1], regs, regs->trap, - print_tainted()); - printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", - regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, - regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, - regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); - trap = TRAP(regs); - if (trap == 0x300 || trap == 0x600) - printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p\n", - current, current->pid, current->comm, current->thread_info); - printk("Last syscall: %ld ", current->thread.last_syscall); - -#ifdef CONFIG_SMP - printk(" CPU: %d", smp_processor_id()); -#endif /* CONFIG_SMP */ - - for (i = 0; i < 32; i++) { - long r; - if ((i % 8) == 0) - printk("\n" KERN_INFO "GPR%02d: ", i); - if (__get_user(r, ®s->gpr[i])) - break; - printk("%08lX ", r); - if (i == 12 && !FULL_REGS(regs)) - break; - } - printk("\n"); -#ifdef CONFIG_KALLSYMS - /* - * Lookup NIP late so we have the best change of getting the - * above info out without failing - */ - printk("NIP [%08lx] ", regs->nip); - print_symbol("%s\n", regs->nip); - printk("LR [%08lx] ", regs->link); - print_symbol("%s\n", regs->link); -#endif - show_stack(current, (unsigned long *) regs->gpr[1]); -} - -void exit_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void flush_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void -release_thread(struct task_struct *t) -{ -} - -/* - * This gets called before we allocate a new thread and copy - * the current task into it. - */ -void prepare_to_copy(struct task_struct *tsk) -{ - struct pt_regs *regs = tsk->thread.regs; - - if (regs == NULL) - return; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); -} - -/* - * Copy a thread.. - */ -int -copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct pt_regs *childregs, *kregs; - extern void ret_from_fork(void); - unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; - unsigned long childframe; - - CHECK_FULL_REGS(regs); - /* Copy registers */ - sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *) sp; - *childregs = *regs; - if ((childregs->msr & MSR_PR) == 0) { - /* for kernel thread, set `current' and stackptr in new task */ - childregs->gpr[1] = sp + sizeof(struct pt_regs); - childregs->gpr[2] = (unsigned long) p; - p->thread.regs = NULL; /* no user register state */ - } else { - childregs->gpr[1] = usp; - p->thread.regs = childregs; - if (clone_flags & CLONE_SETTLS) - childregs->gpr[2] = childregs->gpr[6]; - } - childregs->gpr[3] = 0; /* Result from fork() */ - sp -= STACK_FRAME_OVERHEAD; - childframe = sp; - - /* - * The way this works is that at some point in the future - * some task will call _switch to switch to the new task. - * That will pop off the stack frame created below and start - * the new task running at ret_from_fork. The new task will - * do some house keeping and then return from the fork or clone - * system call, using the stack frame created above. - */ - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *) sp; - sp -= STACK_FRAME_OVERHEAD; - p->thread.ksp = sp; - kregs->nip = (unsigned long)ret_from_fork; - - p->thread.last_syscall = -1; - - return 0; -} - -/* - * Set up a thread for executing a new program - */ -void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) -{ - set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); - regs->ctr = 0; - regs->link = 0; - regs->xer = 0; - regs->ccr = 0; - regs->mq = 0; - regs->nip = nip; - regs->gpr[1] = sp; - regs->msr = MSR_USER; - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); - memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); - current->thread.fpscr.val = 0; -#ifdef CONFIG_ALTIVEC - memset(current->thread.vr, 0, sizeof(current->thread.vr)); - memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); - current->thread.vrsave = 0; - current->thread.used_vr = 0; -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - memset(current->thread.evr, 0, sizeof(current->thread.evr)); - current->thread.acc = 0; - current->thread.spefscr = 0; - current->thread.used_spe = 0; -#endif /* CONFIG_SPE */ -} - -#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ - | PR_FP_EXC_RES | PR_FP_EXC_INV) - -int set_fpexc_mode(struct task_struct *tsk, unsigned int val) -{ - struct pt_regs *regs = tsk->thread.regs; - - /* This is a bit hairy. If we are an SPE enabled processor - * (have embedded fp) we store the IEEE exception enable flags in - * fpexc_mode. fpexc_mode is also used for setting FP exception - * mode (asyn, precise, disabled) for 'Classic' FP. */ - if (val & PR_FP_EXC_SW_ENABLE) { -#ifdef CONFIG_SPE - tsk->thread.fpexc_mode = val & - (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); -#else - return -EINVAL; -#endif - } else { - /* on a CONFIG_SPE this does not hurt us. The bits that - * __pack_fe01 use do not overlap with bits used for - * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits - * on CONFIG_SPE implementations are reserved so writing to - * them does not change anything */ - if (val > PR_FP_EXC_PRECISE) - return -EINVAL; - tsk->thread.fpexc_mode = __pack_fe01(val); - if (regs != NULL && (regs->msr & MSR_FP) != 0) - regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) - | tsk->thread.fpexc_mode; - } - return 0; -} - -int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) -{ - unsigned int val; - - if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) -#ifdef CONFIG_SPE - val = tsk->thread.fpexc_mode; -#else - return -EINVAL; -#endif - else - val = __unpack_fe01(tsk->thread.fpexc_mode); - return put_user(val, (unsigned int __user *) adr); -} - -int sys_clone(unsigned long clone_flags, unsigned long usp, - int __user *parent_tidp, void __user *child_threadptr, - int __user *child_tidp, int p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - if (usp == 0) - usp = regs->gpr[1]; /* stack pointer for child */ - return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); -} - -int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); -} - -int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], - regs, 0, NULL, NULL); -} - -int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs *regs) -{ - int error; - char * filename; - - filename = getname((char __user *) a0); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); - error = do_execve(filename, (char __user *__user *) a1, - (char __user *__user *) a2, regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - return error; -} - -void dump_stack(void) -{ - show_stack(current, NULL); -} - -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *tsk, unsigned long *stack) -{ - unsigned long sp, stack_top, prev_sp, ret; - int count = 0; - unsigned long next_exc = 0; - struct pt_regs *regs; - extern char ret_from_except, ret_from_except_full, ret_from_syscall; - - sp = (unsigned long) stack; - if (tsk == NULL) - tsk = current; - if (sp == 0) { - if (tsk == current) - asm("mr %0,1" : "=r" (sp)); - else - sp = tsk->thread.ksp; - } - - prev_sp = (unsigned long) (tsk->thread_info + 1); - stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE; - while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) { - if (count == 0) { - printk("Call trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - } else { - if (next_exc) { - ret = next_exc; - next_exc = 0; - } else - ret = *(unsigned long *)(sp + 4); - printk(" [%08lx] ", ret); -#ifdef CONFIG_KALLSYMS - print_symbol("%s", ret); - printk("\n"); -#endif - if (ret == (unsigned long) &ret_from_except - || ret == (unsigned long) &ret_from_except_full - || ret == (unsigned long) &ret_from_syscall) { - /* sp + 16 points to an exception frame */ - regs = (struct pt_regs *) (sp + 16); - if (sp + 16 + sizeof(*regs) <= stack_top) - next_exc = regs->nip; - } - } - ++count; - sp = *(unsigned long *)sp; - } -#ifndef CONFIG_KALLSYMS - if (count > 0) - printk("\n"); -#endif -} - -#if 0 -/* - * Low level print for debugging - Cort - */ -int __init ll_printk(const char *fmt, ...) -{ - va_list args; - char buf[256]; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - ll_puts(buf); - va_end(args); - return i; -} - -int lines = 24, cols = 80; -int orig_x = 0, orig_y = 0; - -void puthex(unsigned long val) -{ - unsigned char buf[10]; - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789ABCDEF"[val & 0x0F]; - val >>= 4; - } - buf[8] = '\0'; - prom_print(buf); -} - -void __init ll_puts(const char *s) -{ - int x,y; - char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000; - char c; - extern int mem_init_done; - - if ( mem_init_done ) /* assume this means we can printk */ - { - printk(s); - return; - } - -#if 0 - if ( have_of ) - { - prom_print(s); - return; - } -#endif - - /* - * can't ll_puts on chrp without openfirmware yet. - * vidmem just needs to be setup for it. - * -- Cort - */ - if ( _machine != _MACH_prep ) - return; - x = orig_x; - y = orig_y; - - while ( ( c = *s++ ) != '\0' ) { - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } - } - } - - orig_x = x; - orig_y = y; -} -#endif - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long ip, sp; - unsigned long stack_page = (unsigned long) p->thread_info; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - sp = p->thread.ksp; - do { - sp = *(unsigned long *)sp; - if (sp < stack_page || sp >= stack_page + 8188) - return 0; - if (count > 0) { - ip = *(unsigned long *)(sp + 4); - if (!in_sched_functions(ip)) - return ip; - } - } while (count++ < 16); - return 0; -} diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index becbfa39755..e55cdda6149 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -318,7 +318,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - p->thread_info->cpu = cpu; + task_thread_info(p)->cpu = cpu; idle_tasks[cpu] = p; } } @@ -369,7 +369,7 @@ int __cpu_up(unsigned int cpu) char buf[32]; int c; - secondary_ti = idle_tasks[cpu]->thread_info; + secondary_ti = task_thread_info(idle_tasks[cpu]); mb(); /* diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c index 2f74fde98eb..c42c50073da 100644 --- a/arch/ppc/platforms/apus_setup.c +++ b/arch/ppc/platforms/apus_setup.c @@ -55,9 +55,6 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL; void (*mach_reset)( void ); long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -#if defined(CONFIG_AMIGA_FLOPPY) -void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -#endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) = NULL; extern void apus_heartbeat (void); @@ -76,7 +73,6 @@ struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ struct mem_info ramdisk; -extern void amiga_floppy_setup(char *, int *); extern void config_amiga(void); static int __60nsram = 0; @@ -305,16 +301,6 @@ void kbd_reset_setup(char *str, int *ints) { } -/*********************************************************** FLOPPY */ -#if defined(CONFIG_AMIGA_FLOPPY) -__init -void floppy_setup(char *str, int *ints) -{ - if (mach_floppy_setup) - mach_floppy_setup (str, ints); -} -#endif - /*********************************************************** MEMORY */ #define KMAP_MAX 32 unsigned long kmap_chunks[KMAP_MAX*3]; @@ -574,9 +560,9 @@ static __inline__ void ser_RTSon(void) int __debug_ser_out( unsigned char c ) { - custom.serdat = c | 0x100; + amiga_custom.serdat = c | 0x100; mb(); - while (!(custom.serdatr & 0x2000)) + while (!(amiga_custom.serdatr & 0x2000)) barrier(); return 1; } @@ -586,11 +572,11 @@ unsigned char __debug_ser_in( void ) unsigned char c; /* XXX: is that ok?? derived from amiga_ser.c... */ - while( !(custom.intreqr & IF_RBF) ) + while( !(amiga_custom.intreqr & IF_RBF) ) barrier(); - c = custom.serdatr; + c = amiga_custom.serdatr; /* clear the interrupt, so that another character can be read */ - custom.intreq = IF_RBF; + amiga_custom.intreq = IF_RBF; return c; } @@ -601,10 +587,10 @@ int __debug_serinit( void ) local_irq_save(flags); /* turn off Rx and Tx interrupts */ - custom.intena = IF_RBF | IF_TBE; + amiga_custom.intena = IF_RBF | IF_TBE; /* clear any pending interrupt */ - custom.intreq = IF_RBF | IF_TBE; + amiga_custom.intreq = IF_RBF | IF_TBE; local_irq_restore(flags); @@ -617,7 +603,7 @@ int __debug_serinit( void ) #ifdef CONFIG_KGDB /* turn Rx interrupts on for GDB */ - custom.intena = IF_SETCLR | IF_RBF; + amiga_custom.intena = IF_SETCLR | IF_RBF; ser_RTSon(); #endif diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 2b483b4f160..9075a7538e2 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -99,7 +99,7 @@ static void remove_bpts(void); static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned pc); static void bpt_cmds(void); -static void cacheflush(void); +void cacheflush(void); #ifdef CONFIG_SMP static void cpu_cmd(void); #endif /* CONFIG_SMP */ diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 6fe532d8241..b66602ad7b3 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -27,11 +27,6 @@ config S390 bool default y -config UID16 - bool - default y - depends on !64BIT - source "init/Kconfig" menu "Base setup" diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 4865e4b4946..9269b5788fa 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -17,8 +17,7 @@ obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ - compat_ioctl.o compat_wrapper.o \ - compat_exec_domain.o + compat_wrapper.o compat_exec_domain.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o obj-$(CONFIG_VIRT_TIMER) += vtime.o diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 03ba5893f17..1f451c2cb07 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -112,7 +112,7 @@ static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs) static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs *ptregs = __KSTK_PTREGS(tsk); + struct pt_regs *ptregs = task_pt_regs(tsk); int i; memcpy(®s->psw.mask, &ptregs->psw.mask, 4); diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c deleted file mode 100644 index 6504c4e6998..00000000000 --- a/arch/s390/kernel/compat_ioctl.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * S390 version - * Copyright (C) 2000-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Gerhard Tonn (ton@de.ibm.com) - * Arnd Bergmann (arndb@de.ibm.com) - * - * Original implementation from 32-bit Sparc compat code which is - * Copyright (C) 2000 Silicon Graphics, Inc. - * Written by Ulf Carlsson (ulfc@engr.sgi.com) - */ - -#include "compat_linux.h" -#define INCLUDES -#define CODE -#include "../../../fs/compat_ioctl.c" -#include <asm/dasd.h> -#include <asm/cmb.h> -#include <asm/tape390.h> -#include <asm/ccwdev.h> -#include "../../../drivers/s390/char/raw3270.h" - -static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); -} - -static int do_ioctl32_ulong(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - return sys_ioctl(fd, cmd, arg); -} - -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_pointer) -#define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_ulong) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, - -struct ioctl_trans ioctl_start[] = { -/* architecture independent ioctls */ -#include <linux/compat_ioctl.h> -#define DECLARES -#include "../../../fs/compat_ioctl.c" - -/* s390 only ioctls */ -COMPATIBLE_IOCTL(DASDAPIVER) -COMPATIBLE_IOCTL(BIODASDDISABLE) -COMPATIBLE_IOCTL(BIODASDENABLE) -COMPATIBLE_IOCTL(BIODASDRSRV) -COMPATIBLE_IOCTL(BIODASDRLSE) -COMPATIBLE_IOCTL(BIODASDSLCK) -COMPATIBLE_IOCTL(BIODASDINFO) -COMPATIBLE_IOCTL(BIODASDINFO2) -COMPATIBLE_IOCTL(BIODASDFMT) -COMPATIBLE_IOCTL(BIODASDPRRST) -COMPATIBLE_IOCTL(BIODASDQUIESCE) -COMPATIBLE_IOCTL(BIODASDRESUME) -COMPATIBLE_IOCTL(BIODASDPRRD) -COMPATIBLE_IOCTL(BIODASDPSRD) -COMPATIBLE_IOCTL(BIODASDGATTR) -COMPATIBLE_IOCTL(BIODASDSATTR) -COMPATIBLE_IOCTL(BIODASDCMFENABLE) -COMPATIBLE_IOCTL(BIODASDCMFDISABLE) -COMPATIBLE_IOCTL(BIODASDREADALLCMB) - -COMPATIBLE_IOCTL(TUBICMD) -COMPATIBLE_IOCTL(TUBOCMD) -COMPATIBLE_IOCTL(TUBGETI) -COMPATIBLE_IOCTL(TUBGETO) -COMPATIBLE_IOCTL(TUBSETMOD) -COMPATIBLE_IOCTL(TUBGETMOD) - -COMPATIBLE_IOCTL(TAPE390_DISPLAY) - -/* s390 doesn't need handlers here */ -COMPATIBLE_IOCTL(TIOCGSERIAL) -COMPATIBLE_IOCTL(TIOCSSERIAL) -}; - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 41b197a3f3a..bf9a7a361b3 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -55,6 +55,7 @@ #include <linux/syscalls.h> #include <linux/sysctl.h> #include <linux/binfmts.h> +#include <linux/capability.h> #include <linux/compat.h> #include <linux/vfs.h> #include <linux/ptrace.h> @@ -1014,38 +1015,6 @@ asmlinkage long sys32_clone(struct pt_regs regs) } /* - * Wrapper function for sys_timer_create. - */ -extern asmlinkage long -sys_timer_create(clockid_t, struct sigevent *, timer_t *); - -asmlinkage long -sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32, - timer_t *timer_id) -{ - struct sigevent se; - timer_t ktimer_id; - mm_segment_t old_fs; - long ret; - - if (se32 == NULL) - return sys_timer_create(which_clock, NULL, timer_id); - - if (get_compat_sigevent(&se, se32)) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_timer_create(which_clock, &se, &ktimer_id); - set_fs(old_fs); - - if (!ret) - ret = put_user (ktimer_id, timer_id); - - return ret; -} - -/* * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} * because the 31 bit values differ from the 64 bit values. diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 23fe94e5868..cfde1905d07 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1289,7 +1289,7 @@ sys32_timer_create_wrapper: lgfr %r2,%r2 # timer_t (int) llgtr %r3,%r3 # struct compat_sigevent * llgtr %r4,%r4 # timer_t * - jg sys32_timer_create + jg compat_sys_timer_create .globl sys32_timer_settime_wrapper sys32_timer_settime_wrapper: diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c index 7bd169c58b0..926cceeae0f 100644 --- a/arch/s390/kernel/crash.c +++ b/arch/s390/kernel/crash.c @@ -10,8 +10,6 @@ #include <linux/threads.h> #include <linux/kexec.h> -note_buf_t crash_notes[NR_CPUS]; - void machine_crash_shutdown(struct pt_regs *regs) { } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index a942bf2d58e..2ff90a1a105 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -153,7 +153,7 @@ void show_regs(struct pt_regs *regs) { struct task_struct *tsk = current; - printk("CPU: %d %s\n", tsk->thread_info->cpu, print_tainted()); + printk("CPU: %d %s\n", task_thread_info(tsk)->cpu, print_tainted()); printk("Process %s (pid: %d, task: %p, ksp: %p)\n", current->comm, current->pid, (void *) tsk, (void *) tsk->thread.ksp); @@ -217,8 +217,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, struct pt_regs childregs; } *frame; - frame = ((struct fake_frame *) - (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + frame = container_of(task_pt_regs(p), struct fake_frame, childregs); p->thread.ksp = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ frame->childregs = *regs; @@ -352,38 +351,16 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) return 1; } -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - -/* changed the size calculations - should hopefully work better. lbt */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = regs->gprs[15] & ~(PAGE_SIZE - 1); - dump->u_tsize = current->mm->end_code >> PAGE_SHIFT; - dump->u_dsize = (current->mm->brk + PAGE_SIZE - 1) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = (TASK_SIZE - dump->start_stack) >> PAGE_SHIFT; - memcpy(&dump->regs, regs, sizeof(s390_regs)); - dump_fpu (regs, &dump->regs.fp_regs); - dump->regs.per_info = current->thread.per_info; -} - unsigned long get_wchan(struct task_struct *p) { struct stack_frame *sf, *low, *high; unsigned long return_address; int count; - if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info) + if (!p || p == current || p->state == TASK_RUNNING || !task_stack_page(p)) return 0; - low = (struct stack_frame *) p->thread_info; - high = (struct stack_frame *) - ((unsigned long) p->thread_info + THREAD_SIZE) - 1; + low = task_stack_page(p); + high = (struct stack_frame *) task_pt_regs(p); sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN); if (sf <= low || sf > high) return 0; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index cc02232aa96..37dfe33dab7 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -52,7 +52,7 @@ FixPerRegisters(struct task_struct *task) struct pt_regs *regs; per_struct *per_info; - regs = __KSTK_PTREGS(task); + regs = task_pt_regs(task); per_info = (per_struct *) &task->thread.per_info; per_info->control_regs.bits.em_instruction_fetch = per_info->single_step | per_info->instruction_fetch; @@ -150,7 +150,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) /* * psw and gprs are stored on the stack */ - tmp = *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr); + tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr); if (addr == (addr_t) &dummy->regs.psw.mask) /* Remove per bit from user psw. */ tmp &= ~PSW_MASK_PER; @@ -176,7 +176,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - tmp = (addr_t) __KSTK_PTREGS(child)->orig_gpr2; + tmp = (addr_t) task_pt_regs(child)->orig_gpr2; } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* @@ -243,7 +243,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) high order bit but older gdb's rely on it */ data |= PSW_ADDR_AMODE; #endif - *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr) = data; + *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { /* @@ -267,7 +267,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - __KSTK_PTREGS(child)->orig_gpr2 = data; + task_pt_regs(child)->orig_gpr2 = data; } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* @@ -393,15 +393,15 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) */ if (addr == (addr_t) &dummy32->regs.psw.mask) { /* Fake a 31 bit psw mask. */ - tmp = (__u32)(__KSTK_PTREGS(child)->psw.mask >> 32); + tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32); tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Fake a 31 bit psw address. */ - tmp = (__u32) __KSTK_PTREGS(child)->psw.addr | + tmp = (__u32) task_pt_regs(child)->psw.addr | PSW32_ADDR_AMODE31; } else { /* gpr 0-15 */ - tmp = *(__u32 *)((addr_t) &__KSTK_PTREGS(child)->psw + + tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw + addr*2 + 4); } } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { @@ -415,7 +415,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - tmp = *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4); + tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4); } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* @@ -472,15 +472,15 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp)) /* Invalid psw mask. */ return -EINVAL; - __KSTK_PTREGS(child)->psw.mask = + task_pt_regs(child)->psw.mask = PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Build a 64 bit psw address from 31 bit address. */ - __KSTK_PTREGS(child)->psw.addr = + task_pt_regs(child)->psw.addr = (__u64) tmp & PSW32_ADDR_INSN; } else { /* gpr 0-15 */ - *(__u32*)((addr_t) &__KSTK_PTREGS(child)->psw + *(__u32*)((addr_t) &task_pt_regs(child)->psw + addr*2 + 4) = tmp; } } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { @@ -494,7 +494,7 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* * orig_gpr2 is stored on the kernel stack */ - *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4) = tmp; + *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp; } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index bee654abb6d..4176c77670c 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -10,7 +10,6 @@ #include <linux/smp.h> #include <linux/syscalls.h> #include <linux/interrupt.h> -#include <linux/ioctl32.h> #include <asm/checksum.h> #include <asm/cpcmd.h> #include <asm/delay.h> diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e10f4ca0049..cbfcfd02a43 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -657,7 +657,7 @@ __cpu_up(unsigned int cpu) idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; cpu_lowcore->kernel_stack = (unsigned long) - idle->thread_info + (THREAD_SIZE); + task_stack_page(idle) + (THREAD_SIZE); sf = (struct stack_frame *) (cpu_lowcore->kernel_stack - sizeof(struct pt_regs) - sizeof(struct stack_frame)); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c36353e8c14..b0d8ca8e5ee 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -282,7 +282,7 @@ static inline void start_hz_timer(void) { if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) return; - account_ticks(__KSTK_PTREGS(current)); + account_ticks(task_pt_regs(current)); cpu_clear(smp_processor_id(), nohz_cpu_mask); } diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 95d10996861..5d21e9e6e7b 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -136,8 +136,8 @@ void show_trace(struct task_struct *task, unsigned long * stack) sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE, S390_lowcore.async_stack); if (task) - __show_trace(sp, (unsigned long) task->thread_info, - (unsigned long) task->thread_info + THREAD_SIZE); + __show_trace(sp, (unsigned long) task_stack_page(task), + (unsigned long) task_stack_page(task) + THREAD_SIZE); else __show_trace(sp, S390_lowcore.thread_info, S390_lowcore.thread_info + THREAD_SIZE); @@ -240,7 +240,7 @@ char *task_show_regs(struct task_struct *task, char *buffer) { struct pt_regs *regs; - regs = __KSTK_PTREGS(task); + regs = task_pt_regs(task); buffer += sprintf(buffer, "task: %p, ksp: %p\n", task, (void *)task->thread.ksp); buffer += sprintf(buffer, "User PSW : %p %p\n", diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index fd4f240b833..aac15e42d03 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -191,13 +191,8 @@ void flush_thread(void) { #if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)tsk->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - /* Forget lazy FPU state */ - clear_fpu(tsk, regs); + clear_fpu(tsk, task_pt_regs(tsk)); clear_used_math(); #endif } @@ -232,13 +227,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { struct pt_regs ptregs; - ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info + THREAD_SIZE - - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)); + ptregs = *task_pt_regs(tsk); elf_core_copy_regs(regs, &ptregs); return 1; @@ -252,11 +241,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) #if defined(CONFIG_SH_FPU) fpvalid = !!tsk_used_math(tsk); if (fpvalid) { - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)tsk->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - unlazy_fpu(tsk, regs); + unlazy_fpu(tsk, task_pt_regs(tsk)); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } #endif @@ -279,18 +264,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, copy_to_stopped_child_used_math(p); #endif - childregs = ((struct pt_regs *) - (THREAD_SIZE + (unsigned long) p->thread_info) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)) - 1; + childregs = task_pt_regs(p); *childregs = *regs; if (user_mode(regs)) { childregs->regs[15] = usp; } else { - childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE; + childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; } if (clone_flags & CLONE_SETTLS) { childregs->gbr = childregs->regs[0]; @@ -305,26 +285,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, return 0; } -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - dump->magic = CMAGIC; - dump->start_code = current->mm->start_code; - dump->start_data = current->mm->start_data; - dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1); - dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; - dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT; - dump->u_ssize = (current->mm->start_stack - dump->start_stack + - PAGE_SIZE - 1) >> PAGE_SHIFT; - /* Debug registers will come here. */ - - dump->regs = *regs; - - dump->u_fpvalid = dump_fpu(regs, &dump->fpu); -} - /* Tracing by user break controller. */ static void ubc_set_tracing(int asid, unsigned long pc) @@ -353,11 +313,7 @@ ubc_set_tracing(int asid, unsigned long pc) struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(CONFIG_SH_FPU) - struct pt_regs *regs = (struct pt_regs *) - ((unsigned long)prev->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) - - sizeof(unsigned long)); - unlazy_fpu(prev, regs); + unlazy_fpu(prev, task_pt_regs(prev)); #endif #ifdef CONFIG_PREEMPT @@ -366,13 +322,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne struct pt_regs *regs; local_irq_save(flags); - regs = (struct pt_regs *) - ((unsigned long)prev->thread_info - + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long)); + regs = task_pt_regs(prev); if (user_mode(regs) && regs->regs[15] >= 0xc0000000) { int offset = (int)regs->regs[15]; @@ -392,7 +342,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne */ asm volatile("ldc %0, r7_bank" : /* no output */ - : "r" (next->thread_info)); + : "r" (task_thread_info(next))); #ifdef CONFIG_MMU /* If no tasks are using the UBC, we're done */ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1a8be06519e..3887b4f6feb 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -41,12 +41,7 @@ static inline int get_stack_long(struct task_struct *task, int offset) { unsigned char *stack; - stack = (unsigned char *) - task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long); + stack = (unsigned char *)task_pt_regs(task); stack += offset; return (*((int *)stack)); } @@ -59,12 +54,7 @@ static inline int put_stack_long(struct task_struct *task, int offset, { unsigned char *stack; - stack = (unsigned char *) - task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) -#ifdef CONFIG_SH_DSP - - sizeof(struct pt_dspregs) -#endif - - sizeof(unsigned long); + stack = (unsigned char *)task_pt_regs(task); stack += offset; *(unsigned long *) stack = data; return 0; diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 6954fd62470..1cf94a618be 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -21,14 +21,12 @@ #include <asm/cacheflush.h> #include <asm/checksum.h> -extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; EXPORT_SYMBOL(sh_mv); /* platform dependent support */ -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(enable_irq); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 59e49b18252..62c7d1c0ad7 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -103,7 +103,7 @@ int __cpu_up(unsigned int cpu) if (IS_ERR(tsk)) panic("Failed forking idle task for cpu %d\n", cpu); - tsk->thread_info->cpu = cpu; + task_thread_info(tsk)->cpu = cpu; cpu_set(cpu, cpu_online_map); diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig index fb35b45dc13..07b172deb87 100644 --- a/arch/sh64/Kconfig +++ b/arch/sh64/Kconfig @@ -17,10 +17,6 @@ config MMU bool default y -config UID16 - bool - default y - config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index b95d0414185..1da9c61d682 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -744,7 +744,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, } #endif /* Copy from sh version */ - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info )) - 1; + childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; *childregs = *regs; @@ -752,7 +752,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->regs[15] = usp; p->thread.uregs = childregs; } else { - childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE; + childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; } childregs->regs[9] = 0; /* Set return value for child */ @@ -775,26 +775,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, return 0; } -/* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs * regs, struct user * dump) -{ - dump->magic = CMAGIC; - dump->start_code = current->mm->start_code; - dump->start_data = current->mm->start_data; - dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1); - dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; - dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT; - dump->u_ssize = (current->mm->start_stack - dump->start_stack + - PAGE_SIZE - 1) >> PAGE_SHIFT; - /* Debug registers will come here. */ - - dump->regs = *regs; - - dump->u_fpvalid = dump_fpu(regs, &dump->fpu); -} - asmlinkage int sys_fork(unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c index 0b5497d70bd..472b450e61b 100644 --- a/arch/sh64/kernel/sh_ksyms.c +++ b/arch/sh64/kernel/sh_ksyms.c @@ -29,7 +29,6 @@ #include <asm/delay.h> #include <asm/irq.h> -extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); #if 0 @@ -41,7 +40,6 @@ EXPORT_SYMBOL(drive_info); #endif /* platform dependent support */ -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(enable_irq); diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c index 526fedae6db..58087331b8a 100644 --- a/arch/sh64/lib/dbg.c +++ b/arch/sh64/lib/dbg.c @@ -174,7 +174,7 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) struct ring_node *rr; pid = current->pid; - stack_bottom = (unsigned long) current->thread_info; + stack_bottom = (unsigned long) task_stack_page(current); asm volatile("ori r15, 0, %0" : "=r" (sp)); rr = event_ring + event_ptr; rr->evt = evt; diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index ea864741146..fbb05a452e5 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -302,7 +302,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) int count = 0; if (tsk != NULL) - task_base = (unsigned long) tsk->thread_info; + task_base = (unsigned long) task_stack_page(tsk); else task_base = (unsigned long) current_thread_info(); @@ -337,7 +337,7 @@ EXPORT_SYMBOL(dump_stack); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - return tsk->thread_info->kpc; + return task_thread_info(tsk)->kpc; } /* @@ -392,7 +392,7 @@ void flush_thread(void) /* We must fixup kregs as well. */ /* XXX This was not fixed for ti for a while, worked. Unused? */ current->thread.kregs = (struct pt_regs *) - ((char *)current->thread_info + (THREAD_SIZE - TRACEREG_SZ)); + (task_stack_page(current) + (THREAD_SIZE - TRACEREG_SZ)); } } @@ -459,7 +459,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *ti = p->thread_info; + struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; char *new_stack; @@ -482,7 +482,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, * V V (stk.fr.) V (pt_regs) { (stk.fr.) } * +----- - - - - - ------+===========+============={+==========}+ */ - new_stack = (char*)ti + THREAD_SIZE; + new_stack = task_stack_page(p) + THREAD_SIZE; if (regs->psr & PSR_PS) new_stack -= STACKFRAME_SZ; new_stack -= STACKFRAME_SZ + TRACEREG_SZ; @@ -724,7 +724,7 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; - fp = task->thread_info->ksp + bias; + fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ if (fp < (task_base + sizeof(struct thread_info)) || diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index fc470c0e9dc..1baf13ed5c3 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -75,7 +75,7 @@ static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset, struct task_struct *tsk, long __user *addr) { struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = tsk->thread_info; + struct thread_info *t = task_thread_info(tsk); int v; if(offset >= 1024) @@ -170,7 +170,7 @@ static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset, struct task_struct *tsk) { struct pt_regs *cregs = tsk->thread.kregs; - struct thread_info *t = tsk->thread_info; + struct thread_info *t = task_thread_info(tsk); unsigned long value = regs->u_regs[UREG_I3]; if(offset >= 1024) diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 1c8fd0fd930..0b0d492c953 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -82,8 +82,6 @@ extern int __lshrdi3(int, int); extern int __muldi3(int, int); extern int __divdi3(int, int); -extern void dump_thread(struct pt_regs *, struct user *); - /* Private functions with odd calling conventions. */ extern void ___atomic24_add(void); extern void ___atomic24_sub(void); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index cc1fc898495..40d426cce82 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -200,7 +200,7 @@ void __init smp4d_boot_cpus(void) /* Cook up an idler for this guy. */ p = fork_idle(i); cpucount++; - current_set[i] = p->thread_info; + current_set[i] = task_thread_info(p); for (no = 0; !cpu_find_by_instance(no, NULL, &mid) && mid != i; no++) ; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index f113422a372..a21f27d10e5 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -173,7 +173,7 @@ void __init smp4m_boot_cpus(void) /* Cook up an idler for this guy. */ p = fork_idle(i); cpucount++; - current_set[i] = p->thread_info; + current_set[i] = task_thread_info(p); /* See trampoline.S for details... */ entry += ((i-1) * 3); diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index d07ae02101a..288de276d9f 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -30,6 +30,7 @@ #include <linux/stat.h> #include <linux/slab.h> #include <linux/pagemap.h> +#include <linux/capability.h> #include <linux/errno.h> #include <linux/smp.h> #include <linux/smp_lock.h> diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 3f451ae6648..41d45c298fb 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -291,7 +291,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, #ifndef CONFIG_SMP if(!fpt) { #else - if(!(fpt->thread_info->flags & _TIF_USEDFPU)) { + if(!(task_thread_info(fpt)->flags & _TIF_USEDFPU)) { #endif fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth); regs->psr &= ~PSR_EF; @@ -334,7 +334,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, /* nope, better SIGFPE the offending process... */ #ifdef CONFIG_SMP - fpt->thread_info->flags &= ~_TIF_USEDFPU; + task_thread_info(fpt)->flags &= ~_TIF_USEDFPU; #endif if(psr & PSR_PS) { /* The first fsr store/load we tried trapped, diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index b775ceb4cf9..ab733be9af0 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -179,7 +179,7 @@ config HUGETLB_PAGE_SIZE_512K bool "512K" config HUGETLB_PAGE_SIZE_64K - depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512K + depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB bool "64K" endchoice diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 6f00ab8b9d2..83d67eb1889 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -16,7 +16,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o pci_schizo.o obj-$(CONFIG_SMP) += smp.o trampoline.o -obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o +obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_MODULES) += module.o @@ -40,5 +40,3 @@ endif head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \ etrap.S rtrap.S winfixup.S entry.S - -CFLAGS_ioctl32.o += -Ifs/ diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index edf52d06b28..202a80c24b6 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -36,8 +36,6 @@ static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout32_library(struct file*); static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file); -extern void dump_thread(struct pt_regs *, struct user *); - static struct linux_binfmt aout32_format = { NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump, PAGE_SIZE diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c deleted file mode 100644 index 196b208665a..00000000000 --- a/arch/sparc64/kernel/ioctl32.c +++ /dev/null @@ -1,39 +0,0 @@ -/* $Id: ioctl32.c,v 1.136 2002/01/14 09:49:52 davem Exp $ - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) - * - * These routines maintain argument size conversion between 32bit and 64bit - * ioctls. - */ - -#define INCLUDES -#include "compat_ioctl.c" -#include <linux/syscalls.h> - -#define CODE -#include "compat_ioctl.c" - -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, -#define IOCTL_TABLE_START \ - struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END \ - }; - -IOCTL_TABLE_START -#include <linux/compat_ioctl.h> -#define DECLARES -#include "compat_ioctl.c" -#if 0 -HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl) -HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl) -HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl) -HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl) -#endif -/* take care of sizeof(sizeof()) breakage */ -IOCTL_TABLE_END - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index a97b0f0727a..b9a9ce70e55 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -43,14 +43,10 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); int __kprobes arch_prepare_kprobe(struct kprobe *p) { - return 0; -} - -void __kprobes arch_copy_kprobe(struct kprobe *p) -{ p->ainsn.insn[0] = *p->addr; p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; p->opcode = *p->addr; + return 0; } void __kprobes arch_arm_kprobe(struct kprobe *p) @@ -65,10 +61,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) flushi(p->addr); } -void __kprobes arch_remove_kprobe(struct kprobe *p) -{ -} - static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { kcb->prev_kprobe.kp = kprobe_running(); @@ -143,6 +135,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) prepare_singlestep(p, regs, kcb); return 1; } else { + if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { + /* The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + ret = 1; + goto no_kprobe; + } p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 02f9dec1d45..1dc3650c5ca 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -390,7 +390,7 @@ void show_regs32(struct pt_regs32 *regs) unsigned long thread_saved_pc(struct task_struct *tsk) { - struct thread_info *ti = tsk->thread_info; + struct thread_info *ti = task_thread_info(tsk); unsigned long ret = 0xdeadbeefUL; if (ti && ti->ksp) { @@ -616,11 +616,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *t = p->thread_info; + struct thread_info *t = task_thread_info(p); char *child_trap_frame; /* Calculate offset to stack_frame & pt_regs */ - child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); + child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | @@ -845,9 +845,9 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; - thread_info_base = (unsigned long) task->thread_info; + thread_info_base = (unsigned long) task_stack_page(task); bias = STACK_BIAS; - fp = task->thread_info->ksp + bias; + fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 84d3df2264c..3f9746f856d 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -296,7 +296,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_GETREGS: { struct pt_regs32 __user *pregs = (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); int rval; if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || @@ -320,11 +320,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_GETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned long tpc = cregs->tpc; int rval; - if ((child->thread_info->flags & _TIF_32BIT) != 0) + if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) tpc &= 0xffffffff; if (__put_user(cregs->tstate, (&pregs->tstate)) || __put_user(tpc, (&pregs->tpc)) || @@ -348,7 +348,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_SETREGS: { struct pt_regs32 __user *pregs = (struct pt_regs32 __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned int psr, pc, npc, y; int i; @@ -381,7 +381,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) case PTRACE_SETREGS64: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread_info->kregs; + struct pt_regs *cregs = task_pt_regs(child); unsigned long tstate, tpc, tnpc, y; int i; @@ -395,7 +395,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_error_return(regs, EFAULT); goto out_tsk; } - if ((child->thread_info->flags & _TIF_32BIT) != 0) { + if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } @@ -430,11 +430,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_to_user(&fps->regs[0], fpregs, (32 * sizeof(unsigned int))) || - __put_user(child->thread_info->xfsr[0], (&fps->fsr)) || + __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || __put_user(0, (&fps->fpqd)) || __put_user(0, (&fps->flags)) || __put_user(0, (&fps->extra)) || @@ -452,11 +452,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) unsigned long fsr; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_to_user(&fps->regs[0], fpregs, (64 * sizeof(unsigned int))) || - __put_user(child->thread_info->xfsr[0], (&fps->fsr))) { + __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out_tsk; } @@ -477,7 +477,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } fpq[16]; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; unsigned fsr; if (copy_from_user(fpregs, &fps->regs[0], @@ -486,11 +486,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_error_return(regs, EFAULT); goto out_tsk; } - child->thread_info->xfsr[0] &= 0xffffffff00000000UL; - child->thread_info->xfsr[0] |= fsr; - if (!(child->thread_info->fpsaved[0] & FPRS_FEF)) - child->thread_info->gsr[0] = 0; - child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL); + task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; + task_thread_info(child)->xfsr[0] |= fsr; + if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) + task_thread_info(child)->gsr[0] = 0; + task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); pt_succ_return(regs, 0); goto out_tsk; } @@ -501,17 +501,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs) unsigned long fsr; }; struct fps __user *fps = (struct fps __user *) addr; - unsigned long *fpregs = child->thread_info->fpregs; + unsigned long *fpregs = task_thread_info(child)->fpregs; if (copy_from_user(fpregs, &fps->regs[0], (64 * sizeof(unsigned int))) || - __get_user(child->thread_info->xfsr[0], (&fps->fsr))) { + __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out_tsk; } - if (!(child->thread_info->fpsaved[0] & FPRS_FEF)) - child->thread_info->gsr[0] = 0; - child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); + if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) + task_thread_info(child)->gsr[0] = 0; + task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); pt_succ_return(regs, 0); goto out_tsk; } @@ -562,8 +562,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs) #ifdef DEBUG_PTRACE printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm, child->pid, child->exit_code, - child->thread_info->kregs->tpc, - child->thread_info->kregs->tnpc); + task_pt_regs(child)->tpc, + task_pt_regs(child)->tnpc); #endif wake_up_process(child); diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 48180531562..250745896ae 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -520,7 +520,7 @@ void __init setup_arch(char **cmdline_p) rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif - init_task.thread_info->kregs = &fake_swapper_regs; + task_thread_info(&init_task)->kregs = &fake_swapper_regs; #ifdef CONFIG_IP_PNP if (!ic_set_manually) { diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 6efc03df51c..1fb6323e65a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -335,7 +335,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) p = fork_idle(cpu); callin_flag = 0; - cpu_new_thread = p->thread_info; + cpu_new_thread = task_thread_info(p); cpu_set(cpu, cpu_callout_map); cpu_find_by_mid(cpu, &cpu_node); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index fb7a5370dbf..d177d7e5c9d 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -94,7 +94,6 @@ extern void (*prom_palette)(int); extern int __ashrdi3(int, int); -extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); extern unsigned long phys_base; @@ -241,7 +240,6 @@ EXPORT_SYMBOL(io_remap_pfn_range); EXPORT_SYMBOL(_sigpause_common); EXPORT_SYMBOL(verify_compat_iovec); -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(pte_alloc_one_kernel); #ifndef CONFIG_SMP diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 7f6239ed252..d4b7a100cb8 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -11,6 +11,7 @@ #include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/capability.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/file.h> @@ -1120,39 +1121,3 @@ long sys32_lookup_dcookie(unsigned long cookie_high, return sys_lookup_dcookie((cookie_high << 32) | cookie_low, buf, len); } - -extern asmlinkage long -sys_timer_create(clockid_t which_clock, - struct sigevent __user *timer_event_spec, - timer_t __user *created_timer_id); - -long -sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, - timer_t __user *timer_id) -{ - struct sigevent se; - mm_segment_t oldfs; - timer_t t; - long err; - - if (se32 == NULL) - return sys_timer_create(clock, NULL, timer_id); - - if (get_compat_sigevent(&se, se32)) - return -EFAULT; - - if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) - return -EFAULT; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_timer_create(clock, - (struct sigevent __user *) &se, - (timer_t __user *) &t); - set_fs(oldfs); - - if (!err) - err = __put_user (t, timer_id); - - return err; -} diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index bfa4aa68312..ae5b32f817f 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/types.h> +#include <linux/capability.h> #include <linux/compat.h> #include <linux/mman.h> #include <linux/mm.h> diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 53eaf2345fe..98d24bc0004 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -73,7 +73,7 @@ sys_call_table32: /*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun - .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy + .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid /*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl @@ -98,7 +98,7 @@ sys_call_table: .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_stat64, sys_getpagesize +/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 5570e7bb22b..8d44ae5a15e 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1808,7 +1808,7 @@ static void user_instruction_dump (unsigned int __user *pc) void show_stack(struct task_struct *tsk, unsigned long *_ksp) { unsigned long pc, fp, thread_base, ksp; - struct thread_info *tp = tsk->thread_info; + void *tp = task_stack_page(tsk); struct reg_window *rw; int count = 0; @@ -1862,7 +1862,7 @@ static inline int is_kernel_stack(struct task_struct *task, return 0; } - thread_base = (unsigned long) task->thread_info; + thread_base = (unsigned long) task_stack_page(task); thread_end = thread_base + sizeof(union thread_union); if (rw_addr >= thread_base && rw_addr < thread_end && diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index d7c99fa8966..4885ca6cbc7 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -10,6 +10,7 @@ #include <linux/types.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/capability.h> #include <linux/fs.h> #include <linux/namei.h> #include <linux/mm.h> diff --git a/arch/um/Kconfig b/arch/um/Kconfig index b4ff2e57602..8ff3bcbce5f 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -35,12 +35,12 @@ menu "UML-specific options" config MODE_TT bool "Tracing thread support" - default y + default n help This option controls whether tracing thread support is compiled - into UML. Normally, this should be set to Y. If you intend to - use only skas mode (and the host has the skas patch applied to it), - then it is OK to say N here. + into UML. This option is largely obsolete, given that skas0 provides + skas security and performance without needing to patch the host. + It is safe to say 'N' here. config STATIC_LINK bool "Force a static link" diff --git a/arch/um/Makefile b/arch/um/Makefile index 1b12feeba36..322972fd064 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -189,6 +189,12 @@ define filechk_umlconfig sed 's/ CONFIG/ UML_CONFIG/' endef +$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h + $(call filechk,umlconfig) + +$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c + $(CC) $(USER_CFLAGS) -S -o $@ $< + define filechk_gen-asm-offsets (set -e; \ echo "/*"; \ @@ -202,24 +208,13 @@ define filechk_gen-asm-offsets echo ""; ) endef -$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h - $(call filechk,umlconfig) - -$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c - $(CC) $(USER_CFLAGS) -S -o $@ $< - $(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s $(call filechk,gen-asm-offsets) CLEAN_FILES += $(ARCH_DIR)/user-offsets.s -$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \ - archprepare - $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $< - -$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/kernel-offsets.s - $(call filechk,gen-asm-offsets) - -CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s +$(ARCH_DIR)/include/kern_constants.h: + @echo ' SYMLINK $@' + $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@ export SUBARCH USER_CFLAGS OS diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index cd13b91b9ff..ab0d0b17081 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -186,9 +186,6 @@ static void tty_receive_char(struct tty_struct *tty, char ch) } } - if((tty->flip.flag_buf_ptr == NULL) || - (tty->flip.char_buf_ptr == NULL)) - return; tty_insert_flip_char(tty, ch, TTY_NORMAL); } @@ -653,8 +650,7 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, chan = list_entry(ele, struct chan, list); if(!chan->input || (chan->ops->read == NULL)) continue; do { - if((tty != NULL) && - (tty->flip.count >= TTY_FLIPBUF_SIZE)){ + if (tty && !tty_buffer_request_room(tty, 1)) { schedule_delayed_work(task, 1); goto out; } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index be610125429..e3d57656717 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -500,7 +500,7 @@ static void console_write(struct console *console, const char *string, static struct console mc_console = { .name = "mc", .write = console_write, - .flags = CON_PRINTBUFFER | CON_ENABLED, + .flags = CON_ENABLED, .index = -1 }; static int mc_add_console(void) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 3a93c6f772f..7696f8d2d89 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1073,7 +1073,6 @@ static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; struct ubd *dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/include/sysdep-i386/kernel-offsets.h index 35db8505750..82f96c57414 100644 --- a/arch/um/sys-i386/kernel-offsets.c +++ b/arch/um/include/sysdep-i386/kernel-offsets.h @@ -1,12 +1,9 @@ -#include <linux/config.h> #include <linux/stddef.h> #include <linux/sched.h> -#include <linux/time.h> #include <linux/elf.h> -#include <asm/page.h> #define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) #define STR(x) #x #define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/include/sysdep-x86_64/kernel-offsets.h index bfcb104b846..5ce93abd0b5 100644 --- a/arch/um/sys-x86_64/kernel-offsets.c +++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h @@ -6,7 +6,7 @@ #include <asm/page.h> #define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) #define DEFINE_STR1(x) #x #define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : ) diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c index c13a64a288f..91ea538e161 100644 --- a/arch/um/kernel/asm-offsets.c +++ b/arch/um/kernel/asm-offsets.c @@ -1 +1 @@ -/* Dummy file to make kbuild happy - unused! */ +#include "sysdep/kernel-offsets.h" diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index d2d3f256778..7f13b85d265 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -107,7 +107,7 @@ void set_current(void *t) { struct task_struct *task = t; - cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) + cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { external_pid(task), task }); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 9264d4021df..3b3955d8440 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -68,7 +68,7 @@ void wait_stub_done(int pid, int sig, char * fname) if((n < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ - unsigned long regs[FRAME_SIZE]; + unsigned long regs[HOST_FRAME_SIZE]; if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) printk("Failed to get registers from stub, " "errno = %d\n", errno); @@ -76,7 +76,7 @@ void wait_stub_done(int pid, int sig, char * fname) int i; printk("Stub registers -\n"); - for(i = 0; i < FRAME_SIZE; i++) + for(i = 0; i < HOST_FRAME_SIZE; i++) printk("\t%d - %lx\n", i, regs[i]); } panic("%s : failed to wait for SIGUSR1/SIGTRAP, " diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 09790ccb161..dc41c6dc2f3 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -118,7 +118,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, handler = new_thread_handler; } - new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, + new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, &p->thread.mode.skas.fork_buf, handler); return(0); } @@ -185,7 +185,7 @@ int start_uml_skas(void) init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread(init_task.thread_info, + return(start_idle_thread(task_stack_page(&init_task), &init_task.thread.mode.skas.switch_buf, &init_task.thread.mode.skas.fork_buf)); } diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 11f518a7e15..8fa2ae7f302 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -99,7 +99,8 @@ void uml_idle_timer(void) set_interval(ITIMER_REAL); } -extern int do_posix_clock_monotonic_gettime(struct timespec *tp); +extern void ktime_get_ts(struct timespec *ts); +#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) void time_init(void) { @@ -114,8 +115,8 @@ void time_init(void) wall_to_monotonic.tv_nsec = -now.tv_nsec; } -/* Declared in linux/time.h, which can't be included here */ -extern void clock_was_set(void); +/* Defined in linux/ktimer.h, which can't be included here */ +#define clock_was_set() do { } while (0) void do_gettimeofday(struct timeval *tv) { diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 136e54c47d3..8f40e483873 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -39,7 +39,7 @@ void flush_thread_tt(void) do_exit(SIGKILL); } - new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); + new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); if(new_pid < 0){ printk(KERN_ERR "flush_thread : new thread failed, errno = %d\n", diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 14d4622a5fb..62535303aa2 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -36,7 +36,7 @@ void switch_to_tt(void *prev, void *next) from = prev; to = next; - cpu = from->thread_info->cpu; + cpu = task_thread_info(from)->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP @@ -253,7 +253,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, clone_flags &= CLONE_VM; p->thread.temp_stack = stack; - new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); + new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); if(new_pid < 0){ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -new_pid); @@ -343,7 +343,7 @@ int do_proc_op(void *t, int proc_id) pid = thread->request.u.exec.pid; do_exec(thread->mode.tt.extern_pid, pid); thread->mode.tt.extern_pid = pid; - cpu_tasks[task->thread_info->cpu].pid = pid; + cpu_tasks[task_thread_info(task)->cpu].pid = pid; break; case OP_FORK: attach_process(thread->request.u.fork.pid); @@ -425,7 +425,7 @@ int start_uml_tt(void) int pages; pages = (1 << CONFIG_KERNEL_STACK_ORDER); - sp = (void *) ((unsigned long) init_task.thread_info) + + sp = task_stack_page(&init_task) + pages * PAGE_SIZE - sizeof(unsigned long); return(tracer(start_kernel_proc, sp)); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 73747ac1977..e2d3ca445ef 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add) return(0); } -#else - -#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled - #endif #endif #endif diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c index 39cf247cdae..eb909937958 100644 --- a/arch/v850/kernel/process.c +++ b/arch/v850/kernel/process.c @@ -114,7 +114,7 @@ int copy_thread (int nr, unsigned long clone_flags, struct task_struct *p, struct pt_regs *regs) { /* Start pushing stuff from the top of the child's kernel stack. */ - unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE; + unsigned long orig_ksp = task_tos(p); unsigned long ksp = orig_ksp; /* We push two `state save' stack fames (see entry.S) on the new kernel stack: @@ -164,30 +164,6 @@ int copy_thread (int nr, unsigned long clone_flags, } /* - * fill in the user structure for a core dump.. - */ -void dump_thread (struct pt_regs *regs, struct user *dump) -{ -#if 0 /* Later. XXX */ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = regs->gpr[GPR_SP]; - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + - (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; - - dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); - dump->regs = *regs; - dump->u_fpvalid = 0; -#endif -} - -/* * sys_execve() executes a new program. */ int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs) diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index 18492d02aaf..67e05750966 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -58,7 +58,7 @@ static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t) regs = thread_saved_regs (t); else /* Register saved during kernel entry (or not available). */ - regs = task_regs (t); + regs = task_pt_regs (t); return (v850_reg_t *)((char *)regs + reg_offs); } diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c index 0ca64900dd9..8ffc29c1c89 100644 --- a/arch/v850/kernel/v850_ksyms.c +++ b/arch/v850/kernel/v850_ksyms.c @@ -21,8 +21,6 @@ extern void *trap_table; EXPORT_SYMBOL (trap_table); /* platform dependent support */ -extern void dump_thread (struct pt_regs *, struct user *); -EXPORT_SYMBOL (dump_thread); EXPORT_SYMBOL (kernel_thread); EXPORT_SYMBOL (enable_irq); EXPORT_SYMBOL (disable_irq); diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4f3e925962c..2efc4be2270 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -69,12 +69,34 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config DMI + bool + default y + source "init/Kconfig" menu "Processor type and features" choice + prompt "Subarchitecture Type" + default X86_PC + +config X86_PC + bool "PC-compatible" + help + Choose this option if your computer is a standard PC or compatible. + +config X86_VSMP + bool "Support for ScaleMP vSMP" + help + Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is + supposed to run on these EM64T-based machines. Only choose this option + if you have one of these machines. + +endchoice + +choice prompt "Processor family" default MK8 @@ -347,32 +369,24 @@ config HPET_EMULATE_RTC depends on HPET_TIMER && RTC=y config GART_IOMMU - bool "IOMMU support" + bool "K8 GART IOMMU support" default y + select SWIOTLB depends on PCI help Support the IOMMU. Needed to run systems with more than 3GB of memory properly with 32-bit PCI devices that do not support DAC (Double Address Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter. Normally the kernel will take the right choice by itself. - This option includes a driver for the AMD Opteron/Athlon64 IOMMU - and a software emulation used on some other systems. + This option includes a driver for the AMD Opteron/Athlon64 northbridge IOMMU + and a software emulation used on other systems. If unsure, say Y. # need this always enabled with GART_IOMMU for the VIA workaround config SWIOTLB - bool - depends on GART_IOMMU - default y - -config DUMMY_IOMMU bool - depends on !GART_IOMMU && !SWIOTLB default y - help - Don't use IOMMU code. This will cause problems when you have more than 4GB - of memory and any 32-bit devices. Don't turn on unless you know what you - are doing. + depends on GART_IOMMU config X86_MCE bool "Machine check support" if EMBEDDED @@ -399,17 +413,6 @@ config X86_MCE_AMD Additional support for AMD specific MCE features such as the DRAM Error Threshold. -config PHYSICAL_START - hex "Physical address where the kernel is loaded" if EMBEDDED - default "0x100000" - help - This gives the physical address where the kernel is loaded. - Primarily used in the case of kexec on panic where the - fail safe kernel needs to run at a different address than - the panic-ed kernel. - - Don't change this unless you know what you are doing. - config KEXEC bool "kexec system call (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -427,6 +430,31 @@ config KEXEC support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +config CRASH_DUMP + bool "kernel crash dumps (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Generate crash dump after being started by kexec. + +config PHYSICAL_START + hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) + default "0x1000000" if CRASH_DUMP + default "0x100000" + help + This gives the physical address where the kernel is loaded. Normally + for regular kernels this value is 0x100000 (1MB). But in the case + of kexec on panic the fail safe kernel needs to run at a different + address than the panic-ed kernel. This option is used to set the load + address for kernels used to capture crash dump on being kexec'ed + after panic. The default value for crash dump kernels is + 0x1000000 (16MB). This can also be set based on the "X" value as + specified in the "crashkernel=YM@XM" command line boot parameter + passed to the panic-ed kernel. Typically this parameter is set as + crashkernel=64M@16M. Please take a look at + Documentation/kdump/kdump.txt for more details about crash dumps. + + Don't change this unless you know what you are doing. + config SECCOMP bool "Enable seccomp to safely compute untrusted bytecode" depends on PROC_FS diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index a9cd42e6182..d7fd46479c5 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -31,6 +31,7 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) CFLAGS += $(cflags-y) +CFLAGS += -m64 CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel CFLAGS += -pipe @@ -38,8 +39,10 @@ CFLAGS += -pipe # actually it makes the kernel smaller too. CFLAGS += -fno-reorder-blocks CFLAGS += -Wno-sign-compare -ifneq ($(CONFIG_DEBUG_INFO),y) +ifneq ($(CONFIG_UNWIND_INFO),y) CFLAGS += -fno-asynchronous-unwind-tables +endif +ifneq ($(CONFIG_DEBUG_INFO),y) # -fweb shrinks the kernel a bit, but the difference is very small # it also messes up debugging, so don't use it for now. #CFLAGS += $(call cc-option,-fweb) @@ -50,6 +53,8 @@ CFLAGS += $(call cc-option,-funit-at-a-time) # prevent gcc from generating any FP code by mistake CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) +AFLAGS += -m64 + head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o libs-y += arch/x86_64/lib/ @@ -80,9 +85,12 @@ bzlilo: vmlinux bzdisk: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk -install fdimage fdimage144 fdimage288: vmlinux +fdimage fdimage144 fdimage288: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ +install: + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ + archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile index 18c6e915d69..29f8396ed15 100644 --- a/arch/x86_64/boot/Makefile +++ b/arch/x86_64/boot/Makefile @@ -98,5 +98,5 @@ zlilo: $(BOOTIMAGE) cp System.map $(INSTALL_PATH)/ if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi -install: $(BOOTIMAGE) +install: sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh index 198af15a775..baaa2369bdb 100644 --- a/arch/x86_64/boot/install.sh +++ b/arch/x86_64/boot/install.sh @@ -1,40 +1,2 @@ #!/bin/sh -# -# arch/x86_64/boot/install.sh -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 1995 by Linus Torvalds -# -# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin -# -# "make install" script for i386 architecture -# -# Arguments: -# $1 - kernel version -# $2 - kernel image file -# $3 - kernel map file -# $4 - default install path (blank if root directory) -# - -# User may have a custom install script - -if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi -if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi - -# Default install - same as make zlilo - -if [ -f $4/vmlinuz ]; then - mv $4/vmlinuz $4/vmlinuz.old -fi - -if [ -f $4/System.map ]; then - mv $4/System.map $4/System.old -fi - -cat $2 > $4/vmlinuz -cp $3 $4/System.map - -if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi +. $srctree/arch/i386/boot/install.sh diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 5d56542fb68..054dcd8a5e9 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-git7 -# Sat Nov 5 15:55:50 2005 +# Linux kernel version: 2.6.15-git7 +# Wed Jan 11 11:57:36 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -15,6 +15,7 @@ CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y # # Code maturity level options @@ -35,18 +36,21 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_VM86=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -55,8 +59,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -71,8 +77,28 @@ CONFIG_OBSOLETE_MODPARM=y CONFIG_STOP_MACHINE=y # +# Block layer +# +CONFIG_LBD=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# # Processor type and features # +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set CONFIG_GENERIC_CPU=y @@ -89,14 +115,14 @@ CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y CONFIG_SMP=y CONFIG_SCHED_SMT=y -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_PREEMPT_BKL=y CONFIG_NUMA=y CONFIG_K8_NUMA=y CONFIG_X86_64_ACPI_NUMA=y -# CONFIG_NUMA_EMU is not set +CONFIG_NUMA_EMU=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -109,6 +135,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y @@ -120,8 +147,9 @@ CONFIG_SWIOTLB=y CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y CONFIG_X86_MCE_AMD=y -CONFIG_PHYSICAL_START=0x100000 # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y @@ -136,6 +164,7 @@ CONFIG_GENERIC_PENDING_IRQ=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set CONFIG_SOFTWARE_SUSPEND=y CONFIG_PM_STD_PARTITION="" @@ -152,7 +181,7 @@ CONFIG_ACPI_AC=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y # CONFIG_ACPI_VIDEO is not set -CONFIG_ACPI_HOTKEY=m +# CONFIG_ACPI_HOTKEY is not set CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y @@ -205,7 +234,7 @@ CONFIG_PCI=y CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y CONFIG_UNORDERED_IO=y -# CONFIG_PCIEPORTBUS is not set +CONFIG_PCIEPORTBUS=y CONFIG_PCI_MSI=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_DEBUG is not set @@ -229,7 +258,6 @@ CONFIG_IA32_EMULATION=y CONFIG_IA32_AOUT=y CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y -CONFIG_UID16=y # # Networking @@ -294,8 +322,11 @@ CONFIG_IPV6=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -315,7 +346,7 @@ CONFIG_IPV6=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # @@ -356,21 +387,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_LBD=y # CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -CONFIG_DEFAULT_DEADLINE=y -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_ATA_OVER_ETH is not set # @@ -410,7 +427,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_BLK_DEV_ATIIXP is not set +CONFIG_BLK_DEV_ATIIXP=y # CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_TRIFLEX is not set # CONFIG_BLK_DEV_CY82C693 is not set @@ -458,20 +475,21 @@ CONFIG_BLK_DEV_SD=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # # SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers # +# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -485,11 +503,13 @@ CONFIG_AIC79XX_RESET_DELAY_MS=4000 # CONFIG_AIC79XX_DEBUG_ENABLE is not set CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -# CONFIG_MEGARAID_NEWGEN is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=y +CONFIG_MEGARAID_MAILBOX=y # CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set +CONFIG_MEGARAID_SAS=y CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set +CONFIG_SCSI_SATA_AHCI=y # CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set @@ -498,7 +518,7 @@ CONFIG_SCSI_SATA_NV=y # CONFIG_SCSI_SATA_QSTOR is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_SX4 is not set -# CONFIG_SCSI_SATA_SIL is not set +CONFIG_SCSI_SATA_SIL=y # CONFIG_SCSI_SATA_SIL24 is not set # CONFIG_SCSI_SATA_SIS is not set # CONFIG_SCSI_SATA_ULI is not set @@ -518,12 +538,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -633,6 +648,7 @@ CONFIG_E1000=y # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y @@ -645,7 +661,6 @@ CONFIG_TIGON3=y # CONFIG_IXGB is not set CONFIG_S2IO=m # CONFIG_S2IO_NAPI is not set -# CONFIG_2BUFF_MODE is not set # # Token Ring devices @@ -744,6 +759,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_SERIAL_8250_ACPI is not set CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -751,7 +767,6 @@ CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -817,10 +832,10 @@ CONFIG_AGP_INTEL=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 CONFIG_HPET=y # CONFIG_HPET_RTC_IRQ is not set CONFIG_HPET_MMAP=y -CONFIG_MAX_RAW_DEVS=256 # CONFIG_HANGCHECK_TIMER is not set # @@ -892,6 +907,7 @@ CONFIG_SOUND=y # Open Sound System # CONFIG_SOUND_PRIME=y +CONFIG_OBSOLETE_OSS_DRIVER=y # CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set @@ -968,7 +984,8 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices @@ -988,6 +1005,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set @@ -1097,6 +1115,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1135,6 +1154,7 @@ CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y CONFIG_RELAYFS_FS=y +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -1232,21 +1252,23 @@ CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y # -# Profiling support +# Instrumentation Support # CONFIG_PROFILING=y CONFIG_OPROFILE=y +CONFIG_KPROBES=y # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1256,8 +1278,8 @@ CONFIG_DEBUG_FS=y # CONFIG_FRAME_POINTER is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_INIT_DEBUG=y +# CONFIG_DEBUG_RODATA is not set # CONFIG_IOMMU_DEBUG is not set -CONFIG_KPROBES=y # # Security options diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index f76217d8f57..051608d5592 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -2,8 +2,7 @@ # Makefile for the ia32 kernel emulation subsystem. # -obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ - ia32_signal.o tls32.o \ +obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o sysv-$(CONFIG_SYSVIPC) := ipc32.o @@ -29,4 +28,3 @@ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE AFLAGS_vsyscall-sysenter.o = -m32 AFLAGS_vsyscall-syscall.o = -m32 -CFLAGS_ia32_ioctl.o += -Ifs/ diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 2b760d0d9ce..029bddab045 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -197,8 +197,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *re static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { - struct pt_regs *pp = (struct pt_regs *)(t->thread.rsp0); - --pp; + struct pt_regs *pp = task_pt_regs(t); ELF_CORE_COPY_REGS((*elfregs), pp); /* fix wrong segments */ (*elfregs)[7] = t->thread.ds; @@ -217,7 +216,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr if (!tsk_used_math(tsk)) return 0; if (!regs) - regs = ((struct pt_regs *)tsk->thread.rsp0) - 1; + regs = task_pt_regs(tsk); if (tsk == current) unlazy_fpu(tsk); set_fs(KERNEL_DS); @@ -233,7 +232,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) { - struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1; + struct pt_regs *regs = task_pt_regs(t); if (!tsk_used_math(t)) return 0; if (t == current) diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c deleted file mode 100644 index e335bd0b637..00000000000 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ /dev/null @@ -1,79 +0,0 @@ -/* $Id: ia32_ioctl.c,v 1.25 2002/10/11 07:17:06 ak Exp $ - * ioctl32.c: Conversion between 32bit and 64bit native ioctls. - * - * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs - * - * These routines maintain argument size conversion between 32bit and 64bit - * ioctls. - */ - -#define INCLUDES -#include <linux/syscalls.h> -#include "compat_ioctl.c" -#include <asm/ia32.h> - -#define CODE -#include "compat_ioctl.c" - -#define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ -#define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ -#define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ -#define RTC_EPOCH_SET32 _IOW('p', 0x0e, unsigned) /* Set epoch */ - -static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) -{ - unsigned long val; - mm_segment_t oldfs = get_fs(); - int ret; - - switch (cmd) { - case RTC_IRQP_READ32: - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, RTC_IRQP_READ, (unsigned long)&val); - set_fs(oldfs); - if (!ret) - ret = put_user(val, (unsigned int __user *) arg); - return ret; - - case RTC_IRQP_SET32: - cmd = RTC_IRQP_SET; - break; - - case RTC_EPOCH_READ32: - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, RTC_EPOCH_READ, (unsigned long) &val); - set_fs(oldfs); - if (!ret) - ret = put_user(val, (unsigned int __user *) arg); - return ret; - - case RTC_EPOCH_SET32: - cmd = RTC_EPOCH_SET; - break; - } - return sys_ioctl(fd,cmd,arg); -} - - -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) }, -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) - -struct ioctl_trans ioctl_start[] = { -#include <linux/compat_ioctl.h> -#define DECLARES -#include "compat_ioctl.c" - -/* And these ioctls need translation */ -/* realtime device */ -HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) -HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) -HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) -/* take care of sizeof(sizeof()) breakage */ -}; - -int ioctl_table_size = ARRAY_SIZE(ioctl_start); - diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 0903cc1faef..e0a92439f63 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -353,7 +353,6 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ struct pt_regs *regs, unsigned int mask) { int tmp, err = 0; - u32 eflags; tmp = 0; __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); @@ -378,10 +377,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ err |= __put_user(current->thread.trap_no, &sc->trapno); err |= __put_user(current->thread.error_code, &sc->err); err |= __put_user((u32)regs->rip, &sc->eip); - eflags = regs->eflags; - if (current->ptrace & PT_PTRACED) - eflags &= ~TF_MASK; - err |= __put_user((u32)eflags, &sc->eflags); + err |= __put_user((u32)regs->eflags, &sc->eflags); err |= __put_user((u32)regs->rsp, &sc->esp_at_signal); tmp = save_i387_ia32(current, fpstate, regs, 0); @@ -505,13 +501,9 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, regs->ss = __USER32_DS; set_fs(USER_DS); - if (regs->eflags & TF_MASK) { - if (current->ptrace & PT_PTRACED) { - ptrace_notify(SIGTRAP); - } else { - regs->eflags &= ~TF_MASK; - } - } + regs->eflags &= ~TF_MASK; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -605,13 +597,9 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->ss = __USER32_DS; set_fs(USER_DS); - if (regs->eflags & TF_MASK) { - if (current->ptrace & PT_PTRACED) { - ptrace_notify(SIGTRAP); - } else { - regs->eflags &= ~TF_MASK; - } - } + regs->eflags &= ~TF_MASK; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 1f0ff5adc80..58f5bfb52c6 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -35,6 +35,18 @@ movq %rax,R8(%rsp) .endm + .macro CFI_STARTPROC32 simple + CFI_STARTPROC \simple + CFI_UNDEFINED r8 + CFI_UNDEFINED r9 + CFI_UNDEFINED r10 + CFI_UNDEFINED r11 + CFI_UNDEFINED r12 + CFI_UNDEFINED r13 + CFI_UNDEFINED r14 + CFI_UNDEFINED r15 + .endm + /* * 32bit SYSENTER instruction entry. * @@ -55,7 +67,7 @@ * with the int 0x80 path. */ ENTRY(ia32_sysenter_target) - CFI_STARTPROC simple + CFI_STARTPROC32 simple CFI_DEF_CFA rsp,0 CFI_REGISTER rsp,rbp swapgs @@ -92,6 +104,7 @@ ENTRY(ia32_sysenter_target) .quad 1b,ia32_badarg .previous GET_THREAD_INFO(%r10) + orl $TS_COMPAT,threadinfo_status(%r10) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10) CFI_REMEMBER_STATE jnz sysenter_tracesys @@ -105,6 +118,7 @@ sysenter_do_call: cli testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call + andl $~TS_COMPAT,threadinfo_status(%r10) /* clear IF, that popfq doesn't enable interrupts early */ andl $~0x200,EFLAGS-R11(%rsp) RESTORE_ARGS 1,24,1,1,1,1 @@ -161,7 +175,7 @@ sysenter_tracesys: * with the int 0x80 path. */ ENTRY(ia32_cstar_target) - CFI_STARTPROC simple + CFI_STARTPROC32 simple CFI_DEF_CFA rsp,0 CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ @@ -191,6 +205,7 @@ ENTRY(ia32_cstar_target) .quad 1b,ia32_badarg .previous GET_THREAD_INFO(%r10) + orl $TS_COMPAT,threadinfo_status(%r10) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10) CFI_REMEMBER_STATE jnz cstar_tracesys @@ -204,6 +219,7 @@ cstar_do_call: cli testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call + andl $~TS_COMPAT,threadinfo_status(%r10) RESTORE_ARGS 1,-ARG_SKIP,1,1,1 movl RIP-ARGOFFSET(%rsp),%ecx CFI_REGISTER rip,rcx @@ -276,6 +292,7 @@ ENTRY(ia32_syscall) this could be a problem. */ SAVE_ARGS 0,0,1 GET_THREAD_INFO(%r10) + orl $TS_COMPAT,threadinfo_status(%r10) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10) jnz ia32_tracesys ia32_do_syscall: @@ -318,7 +335,7 @@ quiet_ni_syscall: jmp ia32_ptregs_common .endm - CFI_STARTPROC + CFI_STARTPROC32 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi @@ -333,8 +350,19 @@ quiet_ni_syscall: ENTRY(ia32_ptregs_common) popq %r11 - CFI_ADJUST_CFA_OFFSET -8 - CFI_REGISTER rip, r11 + CFI_ENDPROC + CFI_STARTPROC32 simple + CFI_DEF_CFA rsp,SS+8-ARGOFFSET + CFI_REL_OFFSET rax,RAX-ARGOFFSET + CFI_REL_OFFSET rcx,RCX-ARGOFFSET + CFI_REL_OFFSET rdx,RDX-ARGOFFSET + CFI_REL_OFFSET rsi,RSI-ARGOFFSET + CFI_REL_OFFSET rdi,RDI-ARGOFFSET + CFI_REL_OFFSET rip,RIP-ARGOFFSET +/* CFI_REL_OFFSET cs,CS-ARGOFFSET*/ +/* CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/ + CFI_REL_OFFSET rsp,RSP-ARGOFFSET +/* CFI_REL_OFFSET ss,SS-ARGOFFSET*/ SAVE_REST call *%rax RESTORE_REST @@ -608,7 +636,7 @@ ia32_sys_call_table: .quad sys_epoll_wait .quad sys_remap_file_pages .quad sys_set_tid_address - .quad sys32_timer_create + .quad compat_sys_timer_create .quad compat_sys_timer_settime /* 260 */ .quad compat_sys_timer_gettime .quad sys_timer_getoverrun diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 5f4cdfa5690..23a4515a73b 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -28,9 +28,12 @@ #include <asm/i387.h> #include <asm/fpu32.h> -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x44dd5UL +/* + * Determines which flags the user has access to [1 = access, 0 = no access]. + * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). + * Also masks reserved bits (31-22, 15, 5, 3, 1). + */ +#define FLAG_MASK 0x54dd5UL #define R32(l,q) \ case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break @@ -38,7 +41,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) { int i; - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): @@ -134,7 +137,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) static int getreg32(struct task_struct *child, unsigned regno, u32 *val) { - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): @@ -235,7 +238,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) if (ret < 0) goto out; - childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); + childregs = task_pt_regs(child); switch (request) { case PTRACE_PEEKDATA: diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 5389df610e7..54481af5344 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -969,25 +969,6 @@ long sys32_kill(int pid, int sig) return sys_kill(pid, sig); } -extern asmlinkage long -sys_timer_create(clockid_t which_clock, - struct sigevent __user *timer_event_spec, - timer_t __user * created_timer_id); - -long -sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) -{ - struct sigevent __user *p = NULL; - if (se32) { - struct sigevent se; - p = compat_alloc_user_space(sizeof(struct sigevent)); - if (get_compat_sigevent(&se, se32) || - copy_to_user(p, &se, sizeof(se))) - return -EFAULT; - } - return sys_timer_create(clock, p, timer_id); -} - long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, __u32 len_low, __u32 len_high, int advice) { diff --git a/arch/x86_64/ia32/vsyscall-sigreturn.S b/arch/x86_64/ia32/vsyscall-sigreturn.S index 8b5a4b060bb..d90321fe9bb 100644 --- a/arch/x86_64/ia32/vsyscall-sigreturn.S +++ b/arch/x86_64/ia32/vsyscall-sigreturn.S @@ -7,6 +7,7 @@ * by doing ".balign 32" must match in both versions of the page. */ + .code32 .section .text.sigreturn,"ax" .balign 32 .globl __kernel_sigreturn diff --git a/arch/x86_64/ia32/vsyscall-syscall.S b/arch/x86_64/ia32/vsyscall-syscall.S index b024965bb68..cf9ef678de3 100644 --- a/arch/x86_64/ia32/vsyscall-syscall.S +++ b/arch/x86_64/ia32/vsyscall-syscall.S @@ -6,6 +6,7 @@ #include <asm/asm-offsets.h> #include <asm/segment.h> + .code32 .text .section .text.vsyscall,"ax" .globl __kernel_vsyscall diff --git a/arch/x86_64/ia32/vsyscall-sysenter.S b/arch/x86_64/ia32/vsyscall-sysenter.S index 71f3de586b5..ae056e553d1 100644 --- a/arch/x86_64/ia32/vsyscall-sysenter.S +++ b/arch/x86_64/ia32/vsyscall-sysenter.S @@ -5,6 +5,7 @@ #include <asm/ia32_unistd.h> #include <asm/asm-offsets.h> + .code32 .text .section .text.vsyscall,"ax" .globl __kernel_vsyscall diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index fe4cbd1c4b2..72fe60c20d3 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -7,7 +7,8 @@ EXTRA_AFLAGS := -traditional obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o + setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ + dmi_scan.o pci-dma.o pci-nommu.o obj-$(CONFIG_X86_MCE) += mce.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o @@ -22,14 +23,16 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ genapic.o genapic_cluster.o genapic_flat.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o -obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o +obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o +obj-$(CONFIG_X86_VSMP) += vsmp.o obj-$(CONFIG_MODULES) += module.o @@ -46,3 +49,5 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o quirks-y += ../../i386/kernel/quirks.o i8237-y += ../../i386/kernel/i8237.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o +dmi_scan-y += ../../i386/kernel/dmi_scan.o + diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index c7f4fdd20f0..e4e2b7d01f8 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -23,6 +23,7 @@ #include <asm/io.h> #include <asm/proto.h> #include <asm/pci-direct.h> +#include <asm/dma.h> int iommu_aperture; int iommu_aperture_disabled __initdata = 0; @@ -247,7 +248,7 @@ void __init iommu_hole_init(void) /* Got the aperture from the AGP bridge */ } else if (swiotlb && !valid_agp) { /* Do nothing */ - } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) || + } else if ((!no_iommu && end_pfn >= MAX_DMA32_PFN) || force_iommu || valid_agp || fallback_aper_force) { diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 18691ce4c75..8fdd089fd17 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -25,6 +25,7 @@ #include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> #include <linux/sysdev.h> +#include <linux/module.h> #include <asm/atomic.h> #include <asm/smp.h> @@ -33,36 +34,36 @@ #include <asm/pgalloc.h> #include <asm/mach_apic.h> #include <asm/nmi.h> +#include <asm/idle.h> int apic_verbosity; int disable_apic_timer __initdata; +/* + * cpu_mask that denotes the CPUs that needs timer interrupt coming in as + * IPIs in place of local APIC timers + */ +static cpumask_t timer_interrupt_broadcast_ipi_mask; + /* Using APIC to generate smp_local_timer_interrupt? */ int using_apic_timer = 0; -static DEFINE_PER_CPU(int, prof_multiplier) = 1; -static DEFINE_PER_CPU(int, prof_old_multiplier) = 1; -static DEFINE_PER_CPU(int, prof_counter) = 1; - static void apic_pm_activate(void); void enable_NMI_through_LVT0 (void * dummy) { - unsigned int v, ver; + unsigned int v; - ver = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(ver); v = APIC_DM_NMI; /* unmask and set to NMI */ - apic_write_around(APIC_LVT0, v); + apic_write(APIC_LVT0, v); } int get_maxlvt(void) { - unsigned int v, ver, maxlvt; + unsigned int v, maxlvt; v = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(v); maxlvt = GET_APIC_MAXLVT(v); return maxlvt; } @@ -80,33 +81,33 @@ void clear_local_APIC(void) */ if (maxlvt >= 3) { v = ERROR_APIC_VECTOR; /* any non-zero vector will do */ - apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED); + apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); } /* * Careful: we have to set masks only first to deassert * any level-triggered sources. */ v = apic_read(APIC_LVTT); - apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); + apic_write(APIC_LVTT, v | APIC_LVT_MASKED); v = apic_read(APIC_LVT0); - apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); + apic_write(APIC_LVT0, v | APIC_LVT_MASKED); v = apic_read(APIC_LVT1); - apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED); + apic_write(APIC_LVT1, v | APIC_LVT_MASKED); if (maxlvt >= 4) { v = apic_read(APIC_LVTPC); - apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); + apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); } /* * Clean APIC state for other OSs: */ - apic_write_around(APIC_LVTT, APIC_LVT_MASKED); - apic_write_around(APIC_LVT0, APIC_LVT_MASKED); - apic_write_around(APIC_LVT1, APIC_LVT_MASKED); + apic_write(APIC_LVTT, APIC_LVT_MASKED); + apic_write(APIC_LVT0, APIC_LVT_MASKED); + apic_write(APIC_LVT1, APIC_LVT_MASKED); if (maxlvt >= 3) - apic_write_around(APIC_LVTERR, APIC_LVT_MASKED); + apic_write(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) - apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); + apic_write(APIC_LVTPC, APIC_LVT_MASKED); v = GET_APIC_VERSION(apic_read(APIC_LVR)); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); @@ -151,7 +152,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) value &= ~APIC_VECTOR_MASK; value |= APIC_SPIV_APIC_ENABLED; value |= 0xf; - apic_write_around(APIC_SPIV, value); + apic_write(APIC_SPIV, value); if (!virt_wire_setup) { /* For LVT0 make it edge triggered, active high, external and enabled */ @@ -161,11 +162,11 @@ void disconnect_bsp_APIC(int virt_wire_setup) APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); - apic_write_around(APIC_LVT0, value); + apic_write(APIC_LVT0, value); } else { /* Disable LVT0 */ - apic_write_around(APIC_LVT0, APIC_LVT_MASKED); + apic_write(APIC_LVT0, APIC_LVT_MASKED); } /* For LVT1 make it edge triggered, active high, nmi and enabled */ @@ -176,7 +177,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); - apic_write_around(APIC_LVT1, value); + apic_write(APIC_LVT1, value); } } @@ -192,7 +193,7 @@ void disable_local_APIC(void) */ value = apic_read(APIC_SPIV); value &= ~APIC_SPIV_APIC_ENABLED; - apic_write_around(APIC_SPIV, value); + apic_write(APIC_SPIV, value); } /* @@ -269,7 +270,7 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } @@ -280,7 +281,7 @@ extern void __error_in_apic_c (void); */ void __init init_bsp_APIC(void) { - unsigned int value, ver; + unsigned int value; /* * Don't do the setup now if we have a SMP BIOS as the @@ -290,7 +291,6 @@ void __init init_bsp_APIC(void) return; value = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(value); /* * Do not trust the local APIC being empty at bootup. @@ -305,22 +305,21 @@ void __init init_bsp_APIC(void) value |= APIC_SPIV_APIC_ENABLED; value |= APIC_SPIV_FOCUS_DISABLED; value |= SPURIOUS_APIC_VECTOR; - apic_write_around(APIC_SPIV, value); + apic_write(APIC_SPIV, value); /* * Set up the virtual wire mode. */ - apic_write_around(APIC_LVT0, APIC_DM_EXTINT); + apic_write(APIC_LVT0, APIC_DM_EXTINT); value = APIC_DM_NMI; - apic_write_around(APIC_LVT1, value); + apic_write(APIC_LVT1, value); } void __cpuinit setup_local_APIC (void) { - unsigned int value, ver, maxlvt; + unsigned int value, maxlvt; value = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(value); if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f) __error_in_apic_c(); @@ -345,7 +344,7 @@ void __cpuinit setup_local_APIC (void) */ value = apic_read(APIC_TASKPRI); value &= ~APIC_TPRI_MASK; - apic_write_around(APIC_TASKPRI, value); + apic_write(APIC_TASKPRI, value); /* * Now that we are all set up, enable the APIC @@ -387,7 +386,7 @@ void __cpuinit setup_local_APIC (void) * Set spurious IRQ vector */ value |= SPURIOUS_APIC_VECTOR; - apic_write_around(APIC_SPIV, value); + apic_write(APIC_SPIV, value); /* * Set up LVT0, LVT1: @@ -407,7 +406,7 @@ void __cpuinit setup_local_APIC (void) value = APIC_DM_EXTINT | APIC_LVT_MASKED; apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id()); } - apic_write_around(APIC_LVT0, value); + apic_write(APIC_LVT0, value); /* * only the BP should see the LINT1 NMI signal, obviously. @@ -416,14 +415,14 @@ void __cpuinit setup_local_APIC (void) value = APIC_DM_NMI; else value = APIC_DM_NMI | APIC_LVT_MASKED; - apic_write_around(APIC_LVT1, value); + apic_write(APIC_LVT1, value); { unsigned oldvalue; maxlvt = get_maxlvt(); oldvalue = apic_read(APIC_ESR); value = ERROR_APIC_VECTOR; // enables sending errors - apic_write_around(APIC_LVTERR, value); + apic_write(APIC_LVTERR, value); /* * spec says clear errors after enabling vector. */ @@ -660,20 +659,25 @@ void __init init_apic_mappings(void) static void __setup_APIC_LVTT(unsigned int clocks) { unsigned int lvtt_value, tmp_value, ver; + int cpu = smp_processor_id(); ver = GET_APIC_VERSION(apic_read(APIC_LVR)); lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; - apic_write_around(APIC_LVTT, lvtt_value); + + if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) + lvtt_value |= APIC_LVT_MASKED; + + apic_write(APIC_LVTT, lvtt_value); /* * Divide PICLK by 16 */ tmp_value = apic_read(APIC_TDCR); - apic_write_around(APIC_TDCR, (tmp_value + apic_write(APIC_TDCR, (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | APIC_TDR_DIV_16); - apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); + apic_write(APIC_TMICT, clocks/APIC_DIVISOR); } static void setup_APIC_timer(unsigned int clocks) @@ -682,12 +686,6 @@ static void setup_APIC_timer(unsigned int clocks) local_irq_save(flags); - /* For some reasons this doesn't work on Simics, so fake it for now */ - if (!strstr(boot_cpu_data.x86_model_id, "Screwdriver")) { - __setup_APIC_LVTT(clocks); - return; - } - /* wait for irq slice */ if (vxtime.hpet_address) { int trigger = hpet_readl(HPET_T0_CMP); @@ -700,7 +698,7 @@ static void setup_APIC_timer(unsigned int clocks) outb_p(0x00, 0x43); c2 = inb_p(0x40); c2 |= inb_p(0x40) << 8; - do { + do { c1 = c2; outb_p(0x00, 0x43); c2 = inb_p(0x40); @@ -785,52 +783,68 @@ void __cpuinit setup_secondary_APIC_clock(void) local_irq_enable(); } -void __cpuinit disable_APIC_timer(void) +void disable_APIC_timer(void) { if (using_apic_timer) { unsigned long v; v = apic_read(APIC_LVTT); - apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); + apic_write(APIC_LVTT, v | APIC_LVT_MASKED); } } void enable_APIC_timer(void) { - if (using_apic_timer) { + int cpu = smp_processor_id(); + + if (using_apic_timer && + !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { unsigned long v; v = apic_read(APIC_LVTT); - apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED); + apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED); } } -/* - * the frequency of the profiling timer can be changed - * by writing a multiplier value into /proc/profile. - */ -int setup_profiling_timer(unsigned int multiplier) +void switch_APIC_timer_to_ipi(void *cpumask) { - int i; + cpumask_t mask = *(cpumask_t *)cpumask; + int cpu = smp_processor_id(); - /* - * Sanity check. [at least 500 APIC cycles should be - * between APIC interrupts as a rule of thumb, to avoid - * irqs flooding us] - */ - if ( (!multiplier) || (calibration_result/multiplier < 500)) - return -EINVAL; - - /* - * Set the new multiplier for each CPU. CPUs don't start using the - * new values until the next timer interrupt in which they do process - * accounting. At that time they also adjust their APIC timers - * accordingly. - */ - for (i = 0; i < NR_CPUS; ++i) - per_cpu(prof_multiplier, i) = multiplier; + if (cpu_isset(cpu, mask) && + !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { + disable_APIC_timer(); + cpu_set(cpu, timer_interrupt_broadcast_ipi_mask); + } +} +EXPORT_SYMBOL(switch_APIC_timer_to_ipi); - return 0; +void smp_send_timer_broadcast_ipi(void) +{ + cpumask_t mask; + + cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); + if (!cpus_empty(mask)) { + send_IPI_mask(mask, LOCAL_TIMER_VECTOR); + } +} + +void switch_ipi_to_APIC_timer(void *cpumask) +{ + cpumask_t mask = *(cpumask_t *)cpumask; + int cpu = smp_processor_id(); + + if (cpu_isset(cpu, mask) && + cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { + cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask); + enable_APIC_timer(); + } +} +EXPORT_SYMBOL(switch_ipi_to_APIC_timer); + +int setup_profiling_timer(unsigned int multiplier) +{ + return -EINVAL; } #ifdef CONFIG_X86_MCE_AMD @@ -857,32 +871,10 @@ void setup_threshold_lvt(unsigned long lvt_off) void smp_local_timer_interrupt(struct pt_regs *regs) { - int cpu = smp_processor_id(); - profile_tick(CPU_PROFILING, regs); - if (--per_cpu(prof_counter, cpu) <= 0) { - /* - * 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. - */ - per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu); - if (per_cpu(prof_counter, cpu) != - per_cpu(prof_old_multiplier, cpu)) { - __setup_APIC_LVTT(calibration_result/ - per_cpu(prof_counter, cpu)); - per_cpu(prof_old_multiplier, cpu) = - per_cpu(prof_counter, cpu); - } - #ifdef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode(regs)); #endif - } - /* * We take the 'long' return path, and there every subsystem * grabs the appropriate locks (kernel lock/ irq lock). @@ -920,6 +912,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) * Besides, if we don't timer interrupts ignore the global * interrupt lock, which is the WrongThing (tm) to do. */ + exit_idle(); irq_enter(); smp_local_timer_interrupt(regs); irq_exit(); @@ -979,6 +972,7 @@ __init int oem_force_hpet_timer(void) asmlinkage void smp_spurious_interrupt(void) { unsigned int v; + exit_idle(); irq_enter(); /* * Check if this really is a spurious interrupt and ACK it @@ -1014,6 +1008,7 @@ asmlinkage void smp_error_interrupt(void) { unsigned int v, v1; + exit_idle(); irq_enter(); /* First tickle the hardware, only then report what went on. -- REW */ v = apic_read(APIC_ESR); @@ -1060,7 +1055,7 @@ int __init APIC_init_uniprocessor (void) connect_bsp_APIC(); phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); - apic_write_around(APIC_ID, boot_cpu_id); + apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id)); setup_local_APIC(); diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index aaa6d383351..cfb4f9cebea 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -33,6 +33,7 @@ int main(void) ENTRY(flags); ENTRY(addr_limit); ENTRY(preempt_count); + ENTRY(status); BLANK(); #undef ENTRY #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) @@ -64,5 +65,9 @@ int main(void) DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); DEFINE(pbe_next, offsetof(struct pbe, next)); + BLANK(); +#if DEBUG_STKSZ > EXCEPTION_STKSZ + DEFINE(DEBUG_IST, DEBUG_STACK); +#endif return 0; } diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c index 535e0446607..4e6c3b729e3 100644 --- a/arch/x86_64/kernel/crash.c +++ b/arch/x86_64/kernel/crash.c @@ -11,19 +11,156 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> +#include <linux/irq.h> #include <linux/reboot.h> #include <linux/kexec.h> +#include <linux/delay.h> +#include <linux/elf.h> +#include <linux/elfcore.h> #include <asm/processor.h> #include <asm/hardirq.h> #include <asm/nmi.h> #include <asm/hw_irq.h> +#include <asm/mach_apic.h> -note_buf_t crash_notes[NR_CPUS]; +/* This keeps a track of which one is crashing cpu. */ +static int crashing_cpu; + +static u32 *append_elf_note(u32 *buf, char *name, unsigned type, + void *data, size_t data_len) +{ + struct elf_note note; + + note.n_namesz = strlen(name) + 1; + note.n_descsz = data_len; + note.n_type = type; + memcpy(buf, ¬e, sizeof(note)); + buf += (sizeof(note) +3)/4; + memcpy(buf, name, note.n_namesz); + buf += (note.n_namesz + 3)/4; + memcpy(buf, data, note.n_descsz); + buf += (note.n_descsz + 3)/4; + + return buf; +} + +static void final_note(u32 *buf) +{ + struct elf_note note; + + note.n_namesz = 0; + note.n_descsz = 0; + note.n_type = 0; + memcpy(buf, ¬e, sizeof(note)); +} + +static void crash_save_this_cpu(struct pt_regs *regs, int cpu) +{ + struct elf_prstatus prstatus; + u32 *buf; + + if ((cpu < 0) || (cpu >= NR_CPUS)) + return; + + /* Using ELF notes here is opportunistic. + * I need a well defined structure format + * for the data I pass, and I need tags + * on the data to indicate what information I have + * squirrelled away. ELF notes happen to provide + * all of that that no need to invent something new. + */ + + buf = (u32*)per_cpu_ptr(crash_notes, cpu); + + if (!buf) + return; + + memset(&prstatus, 0, sizeof(prstatus)); + prstatus.pr_pid = current->pid; + elf_core_copy_regs(&prstatus.pr_reg, regs); + buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, + sizeof(prstatus)); + final_note(buf); +} + +static void crash_save_self(struct pt_regs *regs) +{ + int cpu; + + cpu = smp_processor_id(); + crash_save_this_cpu(regs, cpu); +} + +#ifdef CONFIG_SMP +static atomic_t waiting_for_crash_ipi; + +static int crash_nmi_callback(struct pt_regs *regs, int cpu) +{ + /* + * Don't do anything if this handler is invoked on crashing cpu. + * Otherwise, system will completely hang. Crashing cpu can get + * an NMI if system was initially booted with nmi_watchdog parameter. + */ + if (cpu == crashing_cpu) + return 1; + local_irq_disable(); + + crash_save_this_cpu(regs, cpu); + disable_local_APIC(); + atomic_dec(&waiting_for_crash_ipi); + /* Assume hlt works */ + for(;;) + asm("hlt"); + + return 1; +} + +static void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} + +/* + * This code is a best effort heuristic to get the + * other cpus to stop executing. So races with + * cpu hotplug shouldn't matter. + */ + +static void nmi_shootdown_cpus(void) +{ + unsigned long msecs; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); + set_nmi_callback(crash_nmi_callback); + + /* + * Ensure the new callback function is set before sending + * out the NMI + */ + wmb(); + + smp_send_nmi_allbutself(); + + msecs = 1000; /* Wait at most a second for the other cpus to stop */ + while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { + mdelay(1); + msecs--; + } + /* Leave the nmi callback set */ + disable_local_APIC(); +} +#else +static void nmi_shootdown_cpus(void) +{ + /* There are no cpus to shootdown */ +} +#endif void machine_crash_shutdown(struct pt_regs *regs) { - /* This function is only called after the system + /* + * This function is only called after the system * has paniced or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. @@ -31,4 +168,19 @@ void machine_crash_shutdown(struct pt_regs *regs) * In practice this means shooting down the other cpus in * an SMP system. */ + /* The kernel is broken so disable interrupts */ + local_irq_disable(); + + /* Make a note of crashing cpu. Will be used in NMI callback.*/ + crashing_cpu = smp_processor_id(); + nmi_shootdown_cpus(); + + if(cpu_has_apic) + disable_local_APIC(); + +#if defined(CONFIG_X86_IO_APIC) + disable_IO_APIC(); +#endif + + crash_save_self(regs); } diff --git a/arch/x86_64/kernel/crash_dump.c b/arch/x86_64/kernel/crash_dump.c new file mode 100644 index 00000000000..942deac4d43 --- /dev/null +++ b/arch/x86_64/kernel/crash_dump.c @@ -0,0 +1,47 @@ +/* + * kernel/crash_dump.c - Memory preserving reboot related code. + * + * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) + * Copyright (C) IBM Corporation, 2004. All rights reserved + */ + +#include <linux/errno.h> +#include <linux/crash_dump.h> + +#include <asm/uaccess.h> +#include <asm/io.h> + +/** + * copy_oldmem_page - copy one page from "oldmem" + * @pfn: page frame number to be copied + * @buf: target memory address for the copy; this can be in kernel address + * space or user address space (see @userbuf) + * @csize: number of bytes to copy + * @offset: offset in bytes into the page (based on pfn) to begin the copy + * @userbuf: if set, @buf is in user address space, use copy_to_user(), + * otherwise @buf is in kernel address space, use memcpy(). + * + * Copy a page from "oldmem". For this page, there is no pte mapped + * in the current kernel. We stitch up a pte, similar to kmap_atomic. + */ +ssize_t copy_oldmem_page(unsigned long pfn, char *buf, + size_t csize, unsigned long offset, int userbuf) +{ + void *vaddr; + + if (!csize) + return 0; + + vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); + + if (userbuf) { + if (copy_to_user(buf, (vaddr + offset), csize)) { + iounmap(vaddr); + return -EFAULT; + } + } else + memcpy(buf, (vaddr + offset), csize); + + iounmap(vaddr); + return csize; +} diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 17579a1a174..293cd71a266 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -559,6 +559,27 @@ void __init parse_memopt(char *p, char **from) end_user_pfn >>= PAGE_SHIFT; } +void __init parse_memmapopt(char *p, char **from) +{ + unsigned long long start_at, mem_size; + + mem_size = memparse(p, from); + p = *from; + if (*p == '@') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_RAM); + } else if (*p == '#') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_ACPI); + } else if (*p == '$') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_RESERVED); + } else { + end_user_pfn = (mem_size >> PAGE_SHIFT); + } + p = *from; +} + unsigned long pci_mem_start = 0xaeedbabe; /* diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index 9cd968dd0f5..6dffb498ccd 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c @@ -216,7 +216,7 @@ void early_printk(const char *fmt, ...) va_end(ap); } -static int keep_early; +static int __initdata keep_early; int __init setup_early_printk(char *opt) { @@ -226,8 +226,6 @@ int __init setup_early_printk(char *opt) if (early_console_initialized) return -1; - opt = strchr(opt, '=') + 1; - strlcpy(buf,opt,sizeof(buf)); space = strchr(buf, ' '); if (space) diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 9ff42041bb6..632fc0f59fc 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -313,6 +313,7 @@ int_with_check: movl threadinfo_flags(%rcx),%edx andl %edi,%edx jnz int_careful + andl $~TS_COMPAT,threadinfo_status(%rcx) jmp retint_swapgs /* Either reschedule or signal or syscall exit tracking needed. */ @@ -673,7 +674,10 @@ ENTRY(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ - .macro paranoidentry sym +#ifndef DEBUG_IST +# define DEBUG_IST 0 +#endif + .macro paranoidentry sym, ist=0 SAVE_ALL cld movl $1,%ebx @@ -683,10 +687,20 @@ ENTRY(spurious_interrupt) js 1f swapgs xorl %ebx,%ebx -1: movq %rsp,%rdi +1: + .if \ist + movq %gs:pda_data_offset, %rbp + .endif + movq %rsp,%rdi movq ORIG_RAX(%rsp),%rsi movq $-1,ORIG_RAX(%rsp) + .if \ist + subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + .endif call \sym + .if \ist + addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + .endif cli .endm @@ -754,7 +768,7 @@ error_exit: jnz retint_careful swapgs RESTORE_ARGS 0,8,0 - iretq + jmp iret_label CFI_ENDPROC error_kernelspace: @@ -904,7 +918,7 @@ KPROBE_ENTRY(debug) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_debug + paranoidentry do_debug, DEBUG_IST jmp paranoid_exit CFI_ENDPROC .previous .text @@ -959,7 +973,12 @@ paranoid_schedule: CFI_ENDPROC KPROBE_ENTRY(int3) - zeroentry do_int3 + INTR_FRAME + pushq $0 + CFI_ADJUST_CFA_OFFSET 8 + paranoidentry do_int3, DEBUG_IST + jmp paranoid_exit + CFI_ENDPROC .previous .text ENTRY(overflow) @@ -1021,23 +1040,18 @@ ENTRY(machine_check) CFI_ENDPROC #endif -ENTRY(call_debug) - zeroentry do_call_debug - ENTRY(call_softirq) CFI_STARTPROC movq %gs:pda_irqstackptr,%rax - pushq %r15 - CFI_ADJUST_CFA_OFFSET 8 - movq %rsp,%r15 - CFI_DEF_CFA_REGISTER r15 + movq %rsp,%rdx + CFI_DEF_CFA_REGISTER rdx incl %gs:pda_irqcount cmove %rax,%rsp + pushq %rdx + /*todo CFI_DEF_CFA_EXPRESSION ...*/ call __do_softirq - movq %r15,%rsp + popq %rsp CFI_DEF_CFA_REGISTER rsp decl %gs:pda_irqcount - popq %r15 - CFI_ADJUST_CFA_OFFSET -8 ret CFI_ENDPROC diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c index a472d62f899..43fcf62fef0 100644 --- a/arch/x86_64/kernel/genapic_cluster.c +++ b/arch/x86_64/kernel/genapic_cluster.c @@ -72,14 +72,11 @@ static void cluster_send_IPI_mask(cpumask_t mask, int vector) static void cluster_send_IPI_allbutself(int vector) { cpumask_t mask = cpu_online_map; - int me = get_cpu(); /* Ensure we are not preempted when we clear */ - cpu_clear(me, mask); + cpu_clear(smp_processor_id(), mask); if (!cpus_empty(mask)) cluster_send_IPI_mask(mask, vector); - - put_cpu(); } static void cluster_send_IPI_all(int vector) diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c index 9da3edb799e..1a2ab825be9 100644 --- a/arch/x86_64/kernel/genapic_flat.c +++ b/arch/x86_64/kernel/genapic_flat.c @@ -83,12 +83,11 @@ static void flat_send_IPI_allbutself(int vector) __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL); #else cpumask_t allbutme = cpu_online_map; - int me = get_cpu(); /* Ensure we are not preempted when we clear */ - cpu_clear(me, allbutme); + + cpu_clear(smp_processor_id(), allbutme); if (!cpus_empty(allbutme)) flat_send_IPI_mask(allbutme, vector); - put_cpu(); #endif } @@ -149,10 +148,9 @@ static void physflat_send_IPI_mask(cpumask_t cpumask, int vector) static void physflat_send_IPI_allbutself(int vector) { cpumask_t allbutme = cpu_online_map; - int me = get_cpu(); - cpu_clear(me, allbutme); + + cpu_clear(smp_processor_id(), allbutme); physflat_send_IPI_mask(allbutme, vector); - put_cpu(); } static void physflat_send_IPI_all(int vector) diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 15290968e49..38fc3d5112e 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -379,14 +379,14 @@ gdt: * Also sysret mandates a special GDT layout */ -.align L1_CACHE_BYTES +.align PAGE_SIZE /* The TLS descriptors are currently at a different place compared to i386. Hopefully nobody expects them at a fixed place (Wine?) */ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x008f9a000000ffff /* __KERNEL_COMPAT32_CS */ + .quad 0x0 /* unused */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ .quad 0x00cffa000000ffff /* __USER32_CS */ @@ -396,15 +396,15 @@ ENTRY(cpu_gdt_table) .quad 0,0 /* TSS */ .quad 0,0 /* LDT */ .quad 0,0,0 /* three TLS descriptors */ - .quad 0x00009a000000ffff /* __KERNEL16_CS - 16bit PM for S3 wakeup. */ - /* base must be patched for real base address. */ + .quad 0 /* unused */ gdt_end: /* asm/segment.h:GDT_ENTRIES must match this */ /* This should be a multiple of the cache line size */ - /* GDTs of other CPUs: */ - .fill (GDT_SIZE * NR_CPUS) - (gdt_end - cpu_gdt_table) + /* GDTs of other CPUs are now dynamically allocated */ + + /* zero the remaining page */ + .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0 - .align L1_CACHE_BYTES ENTRY(idt_table) .rept 256 .quad 0 diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index b675c5add01..cea20a66c15 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -92,6 +92,9 @@ void __init x86_64_start_kernel(char * real_mode_data) memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t)); asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); + for (i = 0; i < NR_CPUS; i++) + cpu_pda(i) = &boot_cpu_pda[i]; + pda_init(0); copy_bootdata(real_mode_data); #ifdef CONFIG_SMP @@ -99,7 +102,7 @@ void __init x86_64_start_kernel(char * real_mode_data) #endif s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) - setup_early_printk(s); + setup_early_printk(strchr(s, '=') + 1); #ifdef CONFIG_NUMA s = strstr(saved_command_line, "numa="); if (s != NULL) diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c index d9b22b633e3..a5d7e16b928 100644 --- a/arch/x86_64/kernel/i387.c +++ b/arch/x86_64/kernel/i387.c @@ -95,7 +95,7 @@ int save_i387(struct _fpstate __user *buf) if (!used_math()) return 0; clear_used_math(); /* trigger finit */ - if (tsk->thread_info->status & TS_USEDFPU) { + if (task_thread_info(tsk)->status & TS_USEDFPU) { err = save_i387_checking((struct i387_fxsave_struct __user *)buf); if (err) return err; stts(); diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index 6e5101ad3d1..5ecd34ab8c2 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -133,7 +133,7 @@ static void end_8259A_irq (unsigned int irq) { if (irq > 256) { char var; - printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, current->thread_info); + printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, task_thread_info(current)); BUG(); } @@ -549,10 +549,9 @@ void __init init_IRQ(void) int vector = FIRST_EXTERNAL_VECTOR + i; if (i >= NR_IRQS) break; - if (vector != IA32_SYSCALL_VECTOR && vector != KDB_VECTOR) { + if (vector != IA32_SYSCALL_VECTOR) set_intr_gate(vector, interrupt[i]); } - } #ifdef CONFIG_SMP /* diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 97154ab058b..e8cf44ef877 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -37,6 +37,7 @@ #include <asm/proto.h> #include <asm/mach_apic.h> #include <asm/acpi.h> +#include <asm/dma.h> #define __apicdebuginit __init @@ -46,6 +47,9 @@ static int no_timer_check; int disable_timer_pin_1 __initdata; +/* Where if anywhere is the i8259 connect in external int mode */ +static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; + static DEFINE_SPINLOCK(ioapic_lock); /* @@ -260,9 +264,6 @@ __setup("apic", enable_ioapic_setup); void __init check_ioapic(void) { int num,slot,func; - if (ioapic_force) - return; - /* Poor man's PCI discovery */ for (num = 0; num < 32; num++) { for (slot = 0; slot < 32; slot++) { @@ -284,7 +285,7 @@ void __init check_ioapic(void) switch (vendor) { case PCI_VENDOR_ID_VIA: #ifdef CONFIG_GART_IOMMU - if ((end_pfn >= (0xffffffff>>PAGE_SHIFT) || + if ((end_pfn > MAX_DMA32_PFN || force_iommu) && !iommu_aperture_allowed) { printk(KERN_INFO @@ -363,7 +364,7 @@ static int find_irq_entry(int apic, int pin, int type) /* * Find the pin to which IRQ[irq] (ISA) is connected */ -static int find_isa_irq_pin(int irq, int type) +static int __init find_isa_irq_pin(int irq, int type) { int i; @@ -381,6 +382,31 @@ static int find_isa_irq_pin(int irq, int type) return -1; } +static int __init find_isa_irq_apic(int irq, int type) +{ + int i; + + for (i = 0; i < mp_irq_entries; i++) { + int lbus = mp_irqs[i].mpc_srcbus; + + if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || + mp_bus_id_to_type[lbus] == MP_BUS_EISA || + mp_bus_id_to_type[lbus] == MP_BUS_MCA) && + (mp_irqs[i].mpc_irqtype == type) && + (mp_irqs[i].mpc_srcbusirq == irq)) + break; + } + if (i < mp_irq_entries) { + int apic; + for(apic = 0; apic < nr_ioapics; apic++) { + if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic) + return apic; + } + } + + return -1; +} + /* * Find a specific PCI IRQ entry. * Not an __init, possibly needed by modules @@ -874,7 +900,7 @@ static void __init setup_IO_APIC_irqs(void) * Set up the 8259A-master output pin as broadcast to all * CPUs. */ -static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) +static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -884,7 +910,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) disable_8259A_irq(0); /* mask LVT0 */ - apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); + apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); /* * We use logical delivery to get the timer IRQ @@ -908,8 +934,8 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) * Add it to the IO-APIC irq-routing table: */ spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); - io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); spin_unlock_irqrestore(&ioapic_lock, flags); enable_8259A_irq(0); @@ -1188,7 +1214,8 @@ void __apicdebuginit print_PIC(void) static void __init enable_IO_APIC(void) { union IO_APIC_reg_01 reg_01; - int i; + int i8259_apic, i8259_pin; + int i, apic; unsigned long flags; for (i = 0; i < PIN_MAP_SIZE; i++) { @@ -1202,11 +1229,48 @@ static void __init enable_IO_APIC(void) /* * The number of IO-APIC IRQ registers (== #pins): */ - for (i = 0; i < nr_ioapics; i++) { + for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); - reg_01.raw = io_apic_read(i, 1); + reg_01.raw = io_apic_read(apic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[i] = reg_01.bits.entries+1; + nr_ioapic_registers[apic] = reg_01.bits.entries+1; + } + for(apic = 0; apic < nr_ioapics; apic++) { + int pin; + /* See if any of the pins is in ExtINT mode */ + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { + struct IO_APIC_route_entry entry; + spin_lock_irqsave(&ioapic_lock, flags); + *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); + *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); + + + /* If the interrupt line is enabled and in ExtInt mode + * I have found the pin where the i8259 is connected. + */ + if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) { + ioapic_i8259.apic = apic; + ioapic_i8259.pin = pin; + goto found_i8259; + } + } + } + found_i8259: + /* Look to see what if the MP table has reported the ExtINT */ + i8259_pin = find_isa_irq_pin(0, mp_ExtINT); + i8259_apic = find_isa_irq_apic(0, mp_ExtINT); + /* Trust the MP table if nothing is setup in the hardware */ + if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) { + printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n"); + ioapic_i8259.pin = i8259_pin; + ioapic_i8259.apic = i8259_apic; + } + /* Complain if the MP table and the hardware disagree */ + if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) && + (i8259_pin >= 0) && (ioapic_i8259.pin >= 0)) + { + printk(KERN_WARNING "ExtINT in hardware and MP table differ\n"); } /* @@ -1220,7 +1284,6 @@ static void __init enable_IO_APIC(void) */ void disable_IO_APIC(void) { - int pin; /* * Clear the IO-APIC before rebooting: */ @@ -1231,8 +1294,7 @@ void disable_IO_APIC(void) * Put that IOAPIC in virtual wire mode * so legacy interrupts can be delivered. */ - pin = find_isa_irq_pin(0, mp_ExtINT); - if (pin != -1) { + if (ioapic_i8259.pin != -1) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -1243,21 +1305,23 @@ void disable_IO_APIC(void) entry.polarity = 0; /* High */ entry.delivery_status = 0; entry.dest_mode = 0; /* Physical */ - entry.delivery_mode = 7; /* ExtInt */ + entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = 0; - + entry.dest.physical.physical_dest = + GET_APIC_ID(apic_read(APIC_ID)); /* * Add it to the IO-APIC irq-routing table: */ spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); - io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin, + *(((int *)&entry)+1)); + io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin, + *(((int *)&entry)+0)); spin_unlock_irqrestore(&ioapic_lock, flags); } - disconnect_bsp_APIC(pin != -1); + disconnect_bsp_APIC(ioapic_i8259.pin != -1); } /* @@ -1571,7 +1635,7 @@ static void enable_lapic_irq (unsigned int irq) unsigned long v; v = apic_read(APIC_LVT0); - apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); + apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); } static void disable_lapic_irq (unsigned int irq) @@ -1579,7 +1643,7 @@ static void disable_lapic_irq (unsigned int irq) unsigned long v; v = apic_read(APIC_LVT0); - apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); + apic_write(APIC_LVT0, v | APIC_LVT_MASKED); } static void ack_lapic_irq (unsigned int irq) @@ -1626,20 +1690,21 @@ static void setup_nmi (void) */ static inline void unlock_ExtINT_logic(void) { - int pin, i; + int apic, pin, i; struct IO_APIC_route_entry entry0, entry1; unsigned char save_control, save_freq_select; unsigned long flags; - pin = find_isa_irq_pin(8, mp_INT); + pin = find_isa_irq_pin(8, mp_INT); + apic = find_isa_irq_apic(8, mp_INT); if (pin == -1) return; spin_lock_irqsave(&ioapic_lock, flags); - *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin); - *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin); + *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin); spin_unlock_irqrestore(&ioapic_lock, flags); - clear_IO_APIC_pin(0, pin); + clear_IO_APIC_pin(apic, pin); memset(&entry1, 0, sizeof(entry1)); @@ -1652,8 +1717,8 @@ static inline void unlock_ExtINT_logic(void) entry1.vector = 0; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); - io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); spin_unlock_irqrestore(&ioapic_lock, flags); save_control = CMOS_READ(RTC_CONTROL); @@ -1671,11 +1736,11 @@ static inline void unlock_ExtINT_logic(void) CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - clear_IO_APIC_pin(0, pin); + clear_IO_APIC_pin(apic, pin); spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); - io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -1687,7 +1752,7 @@ static inline void unlock_ExtINT_logic(void) */ static inline void check_timer(void) { - int pin1, pin2; + int apic1, pin1, apic2, pin2; int vector; /* @@ -1704,14 +1769,17 @@ static inline void check_timer(void) * the 8259A which implies the virtual wire has to be * disabled in the local APIC. */ - apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); + apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); enable_8259A_irq(0); - pin1 = find_isa_irq_pin(0, mp_INT); - pin2 = find_isa_irq_pin(0, mp_ExtINT); + pin1 = find_isa_irq_pin(0, mp_INT); + apic1 = find_isa_irq_apic(0, mp_INT); + pin2 = ioapic_i8259.pin; + apic2 = ioapic_i8259.apic; - apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); + apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", + vector, apic1, pin1, apic2, pin2); if (pin1 != -1) { /* @@ -1729,17 +1797,20 @@ static inline void check_timer(void) clear_IO_APIC_pin(0, pin1); return; } - clear_IO_APIC_pin(0, pin1); - apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); + clear_IO_APIC_pin(apic1, pin1); + apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not " + "connected to IO-APIC\n"); } - apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); + apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) " + "through the 8259A ... "); if (pin2 != -1) { - apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2); + apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", + apic2, pin2); /* * legacy devices should be connected to IO APIC #0 */ - setup_ExtINT_IRQ0_pin(pin2, vector); + setup_ExtINT_IRQ0_pin(apic2, pin2, vector); if (timer_irq_works()) { printk("works.\n"); nmi_watchdog_default(); @@ -1751,7 +1822,7 @@ static inline void check_timer(void) /* * Cleanup, just in case ... */ - clear_IO_APIC_pin(0, pin2); + clear_IO_APIC_pin(apic2, pin2); } printk(" failed.\n"); @@ -1764,21 +1835,21 @@ static inline void check_timer(void) disable_8259A_irq(0); irq_desc[0].handler = &lapic_irq_type; - apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ + apic_write(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ enable_8259A_irq(0); if (timer_irq_works()) { apic_printk(APIC_QUIET, " works.\n"); return; } - apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); + apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); apic_printk(APIC_VERBOSE," failed.\n"); apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ..."); init_8259A(0); make_8259A_irq(0); - apic_write_around(APIC_LVT0, APIC_DM_EXTINT); + apic_write(APIC_LVT0, APIC_DM_EXTINT); unlock_ExtINT_logic(); diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c index cde0e868efe..b81614970ec 100644 --- a/arch/x86_64/kernel/ioport.c +++ b/arch/x86_64/kernel/ioport.c @@ -7,6 +7,7 @@ #include <linux/sched.h> #include <linux/kernel.h> +#include <linux/capability.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index d6a04a8320a..30d2a1e545f 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -17,6 +17,7 @@ #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/io_apic.h> +#include <asm/idle.h> atomic_t irq_err_count; #ifdef CONFIG_X86_IO_APIC @@ -69,13 +70,13 @@ skip: seq_printf(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); + seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda[j].apic_timer_irqs); + seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); @@ -98,6 +99,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) /* high bits used in ret_from_ code */ unsigned irq = regs->orig_rax & 0xff; + exit_idle(); irq_enter(); __do_IRQ(irq, regs); diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index afe11f4fbd1..8b866a8572c 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -42,8 +42,8 @@ #include <asm/pgtable.h> #include <asm/kdebug.h> -static DECLARE_MUTEX(kprobe_mutex); void jprobe_return_end(void); +static void __kprobes arch_copy_kprobe(struct kprobe *p); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); @@ -69,12 +69,11 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn) int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* insn: must be on special executable page on x86_64. */ - down(&kprobe_mutex); p->ainsn.insn = get_insn_slot(); - up(&kprobe_mutex); if (!p->ainsn.insn) { return -ENOMEM; } + arch_copy_kprobe(p); return 0; } @@ -181,7 +180,7 @@ static inline s32 *is_riprel(u8 *insn) return NULL; } -void __kprobes arch_copy_kprobe(struct kprobe *p) +static void __kprobes arch_copy_kprobe(struct kprobe *p) { s32 *ripdisp; memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE); @@ -335,6 +334,15 @@ int __kprobes kprobe_handler(struct pt_regs *regs) return 1; } } else { + if (*addr != BREAKPOINT_INSTRUCTION) { + /* The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + regs->rip = (unsigned long)addr; + ret = 1; + goto no_kprobe; + } p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 183dc610542..13a2eada6c9 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -15,6 +15,7 @@ #include <linux/sysdev.h> #include <linux/miscdevice.h> #include <linux/fs.h> +#include <linux/capability.h> #include <linux/cpu.h> #include <linux/percpu.h> #include <linux/ctype.h> @@ -23,9 +24,10 @@ #include <asm/mce.h> #include <asm/kdebug.h> #include <asm/uaccess.h> +#include <asm/smp.h> #define MISC_MCELOG_MINOR 227 -#define NR_BANKS 5 +#define NR_BANKS 6 static int mce_dont_init; @@ -91,6 +93,7 @@ void mce_log(struct mce *mce) static void print_mce(struct mce *m) { printk(KERN_EMERG "\n" + KERN_EMERG "HARDWARE ERROR\n" KERN_EMERG "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", m->cpu, m->mcgstatus, m->bank, m->status); @@ -109,6 +112,9 @@ static void print_mce(struct mce *m) if (m->misc) printk("MISC %Lx ", m->misc); printk("\n"); + printk(KERN_EMERG "This is not a software problem!\n"); + printk(KERN_EMERG + "Run through mcelog --ascii to decode and contact your hardware vendor\n"); } static void mce_panic(char *msg, struct mce *backup, unsigned long start) @@ -168,12 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code) int panicm_found = 0; if (regs) - notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL); + notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL); if (!banks) return; memset(&m, 0, sizeof(struct mce)); - m.cpu = hard_smp_processor_id(); + m.cpu = safe_smp_processor_id(); rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); if (!(m.mcgstatus & MCG_STATUS_RIPV)) kill_it = 1; @@ -573,6 +579,10 @@ ACCESSOR(bank1ctl,bank[1],mce_restart()) ACCESSOR(bank2ctl,bank[2],mce_restart()) ACCESSOR(bank3ctl,bank[3],mce_restart()) ACCESSOR(bank4ctl,bank[4],mce_restart()) +ACCESSOR(bank5ctl,bank[5],mce_restart()) +static struct sysdev_attribute * bank_attributes[NR_BANKS] = { + &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl, + &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl}; ACCESSOR(tolerant,tolerant,) ACCESSOR(check_interval,check_interval,mce_restart()) @@ -580,6 +590,7 @@ ACCESSOR(check_interval,check_interval,mce_restart()) static __cpuinit int mce_create_device(unsigned int cpu) { int err; + int i; if (!mce_available(&cpu_data[cpu])) return -EIO; @@ -589,11 +600,9 @@ static __cpuinit int mce_create_device(unsigned int cpu) err = sysdev_register(&per_cpu(device_mce,cpu)); if (!err) { - sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank0ctl); - sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank1ctl); - sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank2ctl); - sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank3ctl); - sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank4ctl); + for (i = 0; i < banks; i++) + sysdev_create_file(&per_cpu(device_mce,cpu), + bank_attributes[i]); sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant); sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval); } @@ -603,11 +612,11 @@ static __cpuinit int mce_create_device(unsigned int cpu) #ifdef CONFIG_HOTPLUG_CPU static __cpuinit void mce_remove_device(unsigned int cpu) { - sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank0ctl); - sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank1ctl); - sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank2ctl); - sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank3ctl); - sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank4ctl); + int i; + + for (i = 0; i < banks; i++) + sysdev_remove_file(&per_cpu(device_mce,cpu), + bank_attributes[i]); sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant); sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval); sysdev_unregister(&per_cpu(device_mce,cpu)); diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c index 1f76175ace0..d3ad7d81266 100644 --- a/arch/x86_64/kernel/mce_amd.c +++ b/arch/x86_64/kernel/mce_amd.c @@ -27,6 +27,7 @@ #include <asm/mce.h> #include <asm/msr.h> #include <asm/percpu.h> +#include <asm/idle.h> #define PFX "mce_threshold: " #define VERSION "version 1.00.9" @@ -140,6 +141,7 @@ asmlinkage void mce_threshold_interrupt(void) struct mce m; ack_APIC_irq(); + exit_idle(); irq_enter(); memset(&m, 0, sizeof(m)); @@ -318,7 +320,7 @@ static struct kobj_type threshold_ktype = { static __cpuinit int threshold_create_bank(unsigned int cpu, int bank) { int err = 0; - struct threshold_bank *b = 0; + struct threshold_bank *b = NULL; #ifdef CONFIG_SMP if (cpu_core_id[cpu] && shared_bank[bank]) { /* symlink */ @@ -407,7 +409,7 @@ static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank) if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) { sprintf(name, "bank%i", bank); sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name); - per_cpu(threshold_banks, cpu)[bank] = 0; + per_cpu(threshold_banks, cpu)[bank] = NULL; } else { kobject_unregister(&b->kobj); kfree(per_cpu(threshold_banks, cpu)[bank]); diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c index 0be0a795981..8f533d2c40c 100644 --- a/arch/x86_64/kernel/mce_intel.c +++ b/arch/x86_64/kernel/mce_intel.c @@ -10,6 +10,7 @@ #include <asm/msr.h> #include <asm/mce.h> #include <asm/hw_irq.h> +#include <asm/idle.h> static DEFINE_PER_CPU(unsigned long, next_check); @@ -19,6 +20,7 @@ asmlinkage void smp_thermal_interrupt(void) ack_APIC_irq(); + exit_idle(); irq_enter(); if (time_before(jiffies, __get_cpu_var(next_check))) goto done; @@ -78,7 +80,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c) h = THERMAL_APIC_VECTOR; h |= (APIC_DM_FIXED | APIC_LVT_MASKED); - apic_write_around(APIC_LVTTHMR, h); + apic_write(APIC_LVTTHMR, h); rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h); @@ -87,7 +89,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c) wrmsr(MSR_IA32_MISC_ENABLE, l | (1 << 3), h); l = apic_read(APIC_LVTTHMR); - apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); + apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", cpu, tm2 ? "TM2" : "TM1"); return; diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 39d445e16f2..5fae6f0cd99 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -151,23 +151,25 @@ int __init check_nmi_watchdog (void) printk(KERN_INFO "testing NMI watchdog ... "); +#ifdef CONFIG_SMP if (nmi_watchdog == NMI_LOCAL_APIC) smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); +#endif for (cpu = 0; cpu < NR_CPUS; cpu++) - counts[cpu] = cpu_pda[cpu].__nmi_count; + counts[cpu] = cpu_pda(cpu)->__nmi_count; local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks for (cpu = 0; cpu < NR_CPUS; cpu++) { if (!cpu_online(cpu)) continue; - if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) { + if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) { endflag = 1; printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", cpu, counts[cpu], - cpu_pda[cpu].__nmi_count); + cpu_pda(cpu)->__nmi_count); nmi_active = 0; lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG; nmi_perfctr_msr = 0; diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index cab471cf3ed..2f5d8328e2b 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c @@ -8,53 +8,259 @@ #include <linux/pci.h> #include <linux/module.h> #include <asm/io.h> +#include <asm/proto.h> -/* Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scatter-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. +int iommu_merge __read_mostly = 0; +EXPORT_SYMBOL(iommu_merge); + +dma_addr_t bad_dma_address __read_mostly; +EXPORT_SYMBOL(bad_dma_address); + +/* This tells the BIO block layer to assume merging. Default to off + because we cannot guarantee merging later. */ +int iommu_bio_merge __read_mostly = 0; +EXPORT_SYMBOL(iommu_bio_merge); + +int iommu_sac_force __read_mostly = 0; +EXPORT_SYMBOL(iommu_sac_force); + +int no_iommu __read_mostly; +#ifdef CONFIG_IOMMU_DEBUG +int panic_on_overflow __read_mostly = 1; +int force_iommu __read_mostly = 1; +#else +int panic_on_overflow __read_mostly = 0; +int force_iommu __read_mostly= 0; +#endif + +/* Dummy device used for NULL arguments (normally ISA). Better would + be probably a smaller DMA mask, but this is bug-to-bug compatible + to i386. */ +struct device fallback_dev = { + .bus_id = "fallback device", + .coherent_dma_mask = 0xffffffff, + .dma_mask = &fallback_dev.coherent_dma_mask, +}; + +/* Allocate DMA memory on node near device */ +noinline static void * +dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order) +{ + struct page *page; + int node; + if (dev->bus == &pci_bus_type) + node = pcibus_to_node(to_pci_dev(dev)->bus); + else + node = numa_node_id(); + page = alloc_pages_node(node, gfp, order); + return page ? page_address(page) : NULL; +} + +/* + * Allocate memory for a coherent mapping. */ -int dma_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, int direction) +void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp) { - int i; - - BUG_ON(direction == DMA_NONE); - for (i = 0; i < nents; i++ ) { - struct scatterlist *s = &sg[i]; - BUG_ON(!s->page); - s->dma_address = virt_to_bus(page_address(s->page) +s->offset); - s->dma_length = s->length; + void *memory; + unsigned long dma_mask = 0; + u64 bus; + + if (!dev) + dev = &fallback_dev; + dma_mask = dev->coherent_dma_mask; + if (dma_mask == 0) + dma_mask = 0xffffffff; + + /* Kludge to make it bug-to-bug compatible with i386. i386 + uses the normal dma_mask for alloc_coherent. */ + dma_mask &= *dev->dma_mask; + + /* Why <=? Even when the mask is smaller than 4GB it is often + larger than 16MB and in this case we have a chance of + finding fitting memory in the next higher zone first. If + not retry with true GFP_DMA. -AK */ + if (dma_mask <= 0xffffffff) + gfp |= GFP_DMA32; + + again: + memory = dma_alloc_pages(dev, gfp, get_order(size)); + if (memory == NULL) + return NULL; + + { + int high, mmu; + bus = virt_to_bus(memory); + high = (bus + size) >= dma_mask; + mmu = high; + if (force_iommu && !(gfp & GFP_DMA)) + mmu = 1; + else if (high) { + free_pages((unsigned long)memory, + get_order(size)); + + /* Don't use the 16MB ZONE_DMA unless absolutely + needed. It's better to use remapping first. */ + if (dma_mask < 0xffffffff && !(gfp & GFP_DMA)) { + gfp = (gfp & ~GFP_DMA32) | GFP_DMA; + goto again; + } + + if (dma_ops->alloc_coherent) + return dma_ops->alloc_coherent(dev, size, + dma_handle, gfp); + return NULL; + } + + memset(memory, 0, size); + if (!mmu) { + *dma_handle = virt_to_bus(memory); + return memory; + } + } + + if (dma_ops->alloc_coherent) { + free_pages((unsigned long)memory, get_order(size)); + gfp &= ~(GFP_DMA|GFP_DMA32); + return dma_ops->alloc_coherent(dev, size, dma_handle, gfp); + } + + if (dma_ops->map_simple) { + *dma_handle = dma_ops->map_simple(dev, memory, + size, + PCI_DMA_BIDIRECTIONAL); + if (*dma_handle != bad_dma_address) + return memory; } - return nents; -} -EXPORT_SYMBOL(dma_map_sg); + if (panic_on_overflow) + panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",size); + free_pages((unsigned long)memory, get_order(size)); + return NULL; +} +EXPORT_SYMBOL(dma_alloc_coherent); -/* Unmap a set of streaming mode DMA translations. - * Again, cpu read rules concerning calls here are the same as for - * pci_unmap_single() above. +/* + * Unmap coherent memory. + * The caller must ensure that the device has finished accessing the mapping. */ -void dma_unmap_sg(struct device *dev, struct scatterlist *sg, - int nents, int dir) +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t bus) +{ + if (dma_ops->unmap_single) + dma_ops->unmap_single(dev, bus, size, 0); + free_pages((unsigned long)vaddr, get_order(size)); +} +EXPORT_SYMBOL(dma_free_coherent); + +int dma_supported(struct device *dev, u64 mask) +{ + if (dma_ops->dma_supported) + return dma_ops->dma_supported(dev, mask); + + /* Copied from i386. Doesn't make much sense, because it will + only work for pci_alloc_coherent. + The caller just has to use GFP_DMA in this case. */ + if (mask < 0x00ffffff) + return 0; + + /* Tell the device to use SAC when IOMMU force is on. This + allows the driver to use cheaper accesses in some cases. + + Problem with this is that if we overflow the IOMMU area and + return DAC as fallback address the device may not handle it + correctly. + + As a special case some controllers have a 39bit address + mode that is as efficient as 32bit (aic79xx). Don't force + SAC for these. Assume all masks <= 40 bits are of this + type. Normally this doesn't make any difference, but gives + more gentle handling of IOMMU overflow. */ + if (iommu_sac_force && (mask >= 0xffffffffffULL)) { + printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask); + return 0; + } + + return 1; +} +EXPORT_SYMBOL(dma_supported); + +int dma_set_mask(struct device *dev, u64 mask) { - int i; - for (i = 0; i < nents; i++) { - struct scatterlist *s = &sg[i]; - BUG_ON(s->page == NULL); - BUG_ON(s->dma_address == 0); - dma_unmap_single(dev, s->dma_address, s->dma_length, dir); - } + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + *dev->dma_mask = mask; + return 0; } +EXPORT_SYMBOL(dma_set_mask); + +/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] + [,forcesac][,fullflush][,nomerge][,biomerge] + size set size of iommu (in bytes) + noagp don't initialize the AGP driver and use full aperture. + off don't use the IOMMU + leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) + memaper[=order] allocate an own aperture over RAM with size 32MB^order. + noforce don't force IOMMU usage. Default. + force Force IOMMU. + merge Do lazy merging. This may improve performance on some block devices. + Implies force (experimental) + biomerge Do merging at the BIO layer. This is more efficient than merge, + but should be only done with very big IOMMUs. Implies merge,force. + nomerge Don't do SG merging. + forcesac For SAC mode for masks <40bits (experimental) + fullflush Flush IOMMU on each allocation (default) + nofullflush Don't use IOMMU fullflush + allowed overwrite iommu off workarounds for specific chipsets. + soft Use software bounce buffering (default for Intel machines) + noaperture Don't touch the aperture for AGP. +*/ +__init int iommu_setup(char *p) +{ + iommu_merge = 1; -EXPORT_SYMBOL(dma_unmap_sg); + while (*p) { + if (!strncmp(p,"off",3)) + no_iommu = 1; + /* gart_parse_options has more force support */ + if (!strncmp(p,"force",5)) + force_iommu = 1; + if (!strncmp(p,"noforce",7)) { + iommu_merge = 0; + force_iommu = 0; + } + + if (!strncmp(p, "biomerge",8)) { + iommu_bio_merge = 4096; + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "panic",5)) + panic_on_overflow = 1; + if (!strncmp(p, "nopanic",7)) + panic_on_overflow = 0; + if (!strncmp(p, "merge",5)) { + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "nomerge",7)) + iommu_merge = 0; + if (!strncmp(p, "forcesac",8)) + iommu_sac_force = 1; + +#ifdef CONFIG_SWIOTLB + if (!strncmp(p, "soft",4)) + swiotlb = 1; +#endif + +#ifdef CONFIG_GART_IOMMU + gart_parse_options(p); +#endif + + p += strcspn(p, ","); + if (*p == ',') + ++p; + } + return 1; +} diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 2e28e855ec3..c37fc7726ba 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -30,8 +30,8 @@ #include <asm/proto.h> #include <asm/cacheflush.h> #include <asm/kdebug.h> - -dma_addr_t bad_dma_address; +#include <asm/swiotlb.h> +#include <asm/dma.h> unsigned long iommu_bus_base; /* GART remapping area (physical) */ static unsigned long iommu_size; /* size of remapping area bytes */ @@ -39,18 +39,6 @@ static unsigned long iommu_pages; /* .. and in pages */ u32 *iommu_gatt_base; /* Remapping table */ -int no_iommu; -static int no_agp; -#ifdef CONFIG_IOMMU_DEBUG -int panic_on_overflow = 1; -int force_iommu = 1; -#else -int panic_on_overflow = 0; -int force_iommu = 0; -#endif -int iommu_merge = 1; -int iommu_sac_force = 0; - /* If this is disabled the IOMMU will use an optimized flushing strategy of only flushing when an mapping is reused. With it true the GART is flushed for every mapping. Problem is that doing the lazy flush seems to trigger @@ -58,10 +46,6 @@ int iommu_sac_force = 0; also seen with Qlogic at least). */ int iommu_fullflush = 1; -/* This tells the BIO block layer to assume merging. Default to off - because we cannot guarantee merging later. */ -int iommu_bio_merge = 0; - #define MAX_NB 8 /* Allocation bitmap for the remapping area */ @@ -102,16 +86,6 @@ AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, - size_t size, int dir, int do_panic); - -/* Dummy device used for NULL arguments (normally ISA). Better would - be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */ -static struct device fallback_dev = { - .bus_id = "fallback device", - .coherent_dma_mask = 0xffffffff, - .dma_mask = &fallback_dev.coherent_dma_mask, -}; static unsigned long alloc_iommu(int size) { @@ -185,114 +159,7 @@ static void flush_gart(struct device *dev) spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } -/* Allocate DMA memory on node near device */ -noinline -static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order) -{ - struct page *page; - int node; - if (dev->bus == &pci_bus_type) - node = pcibus_to_node(to_pci_dev(dev)->bus); - else - node = numa_node_id(); - page = alloc_pages_node(node, gfp, order); - return page ? page_address(page) : NULL; -} - -/* - * Allocate memory for a coherent mapping. - */ -void * -dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t gfp) -{ - void *memory; - unsigned long dma_mask = 0; - u64 bus; - if (!dev) - dev = &fallback_dev; - dma_mask = dev->coherent_dma_mask; - if (dma_mask == 0) - dma_mask = 0xffffffff; - - /* Kludge to make it bug-to-bug compatible with i386. i386 - uses the normal dma_mask for alloc_coherent. */ - dma_mask &= *dev->dma_mask; - - /* Why <=? Even when the mask is smaller than 4GB it is often larger - than 16MB and in this case we have a chance of finding fitting memory - in the next higher zone first. If not retry with true GFP_DMA. -AK */ - if (dma_mask <= 0xffffffff) - gfp |= GFP_DMA32; - - again: - memory = dma_alloc_pages(dev, gfp, get_order(size)); - if (memory == NULL) - return NULL; - - { - int high, mmu; - bus = virt_to_bus(memory); - high = (bus + size) >= dma_mask; - mmu = high; - if (force_iommu && !(gfp & GFP_DMA)) - mmu = 1; - if (no_iommu || dma_mask < 0xffffffffUL) { - if (high) { - free_pages((unsigned long)memory, - get_order(size)); - - if (swiotlb) { - return - swiotlb_alloc_coherent(dev, size, - dma_handle, - gfp); - } - - if (!(gfp & GFP_DMA)) { - gfp = (gfp & ~GFP_DMA32) | GFP_DMA; - goto again; - } - return NULL; - } - mmu = 0; - } - memset(memory, 0, size); - if (!mmu) { - *dma_handle = virt_to_bus(memory); - return memory; - } - } - - *dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0); - if (*dma_handle == bad_dma_address) - goto error; - flush_gart(dev); - return memory; - -error: - if (panic_on_overflow) - panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size); - free_pages((unsigned long)memory, get_order(size)); - return NULL; -} - -/* - * Unmap coherent memory. - * The caller must ensure that the device has finished accessing the mapping. - */ -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t bus) -{ - if (swiotlb) { - swiotlb_free_coherent(dev, size, vaddr, bus); - return; - } - - dma_unmap_single(dev, bus, size, 0); - free_pages((unsigned long)vaddr, get_order(size)); -} #ifdef CONFIG_IOMMU_LEAK @@ -326,7 +193,7 @@ void dump_leak(void) #define CLEAR_LEAK(x) #endif -static void iommu_full(struct device *dev, size_t size, int dir, int do_panic) +static void iommu_full(struct device *dev, size_t size, int dir) { /* * Ran out of IOMMU space for this operation. This is very bad. @@ -342,11 +209,11 @@ static void iommu_full(struct device *dev, size_t size, int dir, int do_panic) "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", size, dev->bus_id); - if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) { + if (size > PAGE_SIZE*EMERGENCY_PAGES) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) panic("PCI-DMA: Memory would be corrupted\n"); if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic("PCI-DMA: Random memory would be DMAed\n"); + panic(KERN_ERR "PCI-DMA: Random memory would be DMAed\n"); } #ifdef CONFIG_IOMMU_LEAK @@ -385,8 +252,8 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t /* Map a single continuous physical area into the IOMMU. * Caller needs to check if the iommu is needed and flush. */ -static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, - size_t size, int dir, int do_panic) +static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, + size_t size, int dir) { unsigned long npages = to_pages(phys_mem, size); unsigned long iommu_page = alloc_iommu(npages); @@ -396,7 +263,7 @@ static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, return phys_mem; if (panic_on_overflow) panic("dma_map_area overflow %lu bytes\n", size); - iommu_full(dev, size, dir, do_panic); + iommu_full(dev, size, dir); return bad_dma_address; } @@ -408,15 +275,21 @@ static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); } +static dma_addr_t gart_map_simple(struct device *dev, char *buf, + size_t size, int dir) +{ + dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir); + flush_gart(dev); + return map; +} + /* Map a single area into the IOMMU */ -dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir) +dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, int dir) { unsigned long phys_mem, bus; BUG_ON(dir == DMA_NONE); - if (swiotlb) - return swiotlb_map_single(dev,addr,size,dir); if (!dev) dev = &fallback_dev; @@ -424,10 +297,24 @@ dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir) if (!need_iommu(dev, phys_mem, size)) return phys_mem; - bus = dma_map_area(dev, phys_mem, size, dir, 1); - flush_gart(dev); + bus = gart_map_simple(dev, addr, size, dir); return bus; -} +} + +/* + * Wrapper for pci_unmap_single working with scatterlists. + */ +void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) +{ + int i; + + for (i = 0; i < nents; i++) { + struct scatterlist *s = &sg[i]; + if (!s->dma_length || !s->length) + break; + dma_unmap_single(dev, s->dma_address, s->dma_length, dir); + } +} /* Fallback for dma_map_sg in case of overflow */ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, @@ -443,10 +330,10 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, struct scatterlist *s = &sg[i]; unsigned long addr = page_to_phys(s->page) + s->offset; if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir, 0); + addr = dma_map_area(dev, addr, s->length, dir); if (addr == bad_dma_address) { if (i > 0) - dma_unmap_sg(dev, sg, i, dir); + gart_unmap_sg(dev, sg, i, dir); nents = 0; sg[0].dma_length = 0; break; @@ -515,7 +402,7 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, * DMA map all entries in a scatterlist. * Merge chunks that have page aligned sizes into a continuous mapping. */ -int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) +int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; int out; @@ -527,8 +414,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) if (nents == 0) return 0; - if (swiotlb) - return swiotlb_map_sg(dev,sg,nents,dir); if (!dev) dev = &fallback_dev; @@ -571,13 +456,13 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) error: flush_gart(NULL); - dma_unmap_sg(dev, sg, nents, dir); + gart_unmap_sg(dev, sg, nents, dir); /* When it was forced try again unforced */ if (force_iommu) return dma_map_sg_nonforce(dev, sg, nents, dir); if (panic_on_overflow) panic("dma_map_sg: overflow on %lu pages\n", pages); - iommu_full(dev, pages << PAGE_SHIFT, dir, 0); + iommu_full(dev, pages << PAGE_SHIFT, dir); for (i = 0; i < nents; i++) sg[i].dma_address = bad_dma_address; return 0; @@ -586,18 +471,13 @@ error: /* * Free a DMA mapping. */ -void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, +void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, int direction) { unsigned long iommu_page; int npages; int i; - if (swiotlb) { - swiotlb_unmap_single(dev,dma_addr,size,direction); - return; - } - if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) return; @@ -610,68 +490,7 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, free_iommu(iommu_page, npages); } -/* - * Wrapper for pci_unmap_single working with scatterlists. - */ -void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) -{ - int i; - if (swiotlb) { - swiotlb_unmap_sg(dev,sg,nents,dir); - return; - } - for (i = 0; i < nents; i++) { - struct scatterlist *s = &sg[i]; - if (!s->dma_length || !s->length) - break; - dma_unmap_single(dev, s->dma_address, s->dma_length, dir); - } -} - -int dma_supported(struct device *dev, u64 mask) -{ - /* Copied from i386. Doesn't make much sense, because it will - only work for pci_alloc_coherent. - The caller just has to use GFP_DMA in this case. */ - if (mask < 0x00ffffff) - return 0; - - /* Tell the device to use SAC when IOMMU force is on. - This allows the driver to use cheaper accesses in some cases. - - Problem with this is that if we overflow the IOMMU area - and return DAC as fallback address the device may not handle it correctly. - - As a special case some controllers have a 39bit address mode - that is as efficient as 32bit (aic79xx). Don't force SAC for these. - Assume all masks <= 40 bits are of this type. Normally this doesn't - make any difference, but gives more gentle handling of IOMMU overflow. */ - if (iommu_sac_force && (mask >= 0xffffffffffULL)) { - printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask); - return 0; - } - - return 1; -} - -int dma_get_cache_alignment(void) -{ - return boot_cpu_data.x86_clflush_size; -} - -EXPORT_SYMBOL(dma_unmap_sg); -EXPORT_SYMBOL(dma_map_sg); -EXPORT_SYMBOL(dma_map_single); -EXPORT_SYMBOL(dma_unmap_single); -EXPORT_SYMBOL(dma_supported); -EXPORT_SYMBOL(no_iommu); -EXPORT_SYMBOL(force_iommu); -EXPORT_SYMBOL(bad_dma_address); -EXPORT_SYMBOL(iommu_bio_merge); -EXPORT_SYMBOL(iommu_sac_force); -EXPORT_SYMBOL(dma_get_cache_alignment); -EXPORT_SYMBOL(dma_alloc_coherent); -EXPORT_SYMBOL(dma_free_coherent); +static int no_agp; static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) { @@ -772,12 +591,27 @@ static __init int init_k8_gatt(struct agp_kern_info *info) nommu: /* Should not happen anymore */ printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" - KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction."); + KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction.\n"); return -1; } extern int agp_amd64_init(void); +static struct dma_mapping_ops gart_dma_ops = { + .mapping_error = NULL, + .map_single = gart_map_single, + .map_simple = gart_map_simple, + .unmap_single = gart_unmap_single, + .sync_single_for_cpu = NULL, + .sync_single_for_device = NULL, + .sync_single_range_for_cpu = NULL, + .sync_single_range_for_device = NULL, + .sync_sg_for_cpu = NULL, + .sync_sg_for_device = NULL, + .map_sg = gart_map_sg, + .unmap_sg = gart_unmap_sg, +}; + static int __init pci_iommu_init(void) { struct agp_kern_info info; @@ -799,16 +633,15 @@ static int __init pci_iommu_init(void) if (swiotlb) { no_iommu = 1; - printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); return -1; } if (no_iommu || - (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) || + (!force_iommu && end_pfn <= MAX_DMA32_PFN) || !iommu_aperture || (no_agp && init_k8_gatt(&info) < 0)) { - printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; + no_iommu_init(); return -1; } @@ -885,100 +718,50 @@ static int __init pci_iommu_init(void) flush_gart(NULL); + printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); + dma_ops = &gart_dma_ops; + return 0; } /* Must execute after PCI subsystem */ fs_initcall(pci_iommu_init); -/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] - [,forcesac][,fullflush][,nomerge][,biomerge] - size set size of iommu (in bytes) - noagp don't initialize the AGP driver and use full aperture. - off don't use the IOMMU - leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) - memaper[=order] allocate an own aperture over RAM with size 32MB^order. - noforce don't force IOMMU usage. Default. - force Force IOMMU. - merge Do lazy merging. This may improve performance on some block devices. - Implies force (experimental) - biomerge Do merging at the BIO layer. This is more efficient than merge, - but should be only done with very big IOMMUs. Implies merge,force. - nomerge Don't do SG merging. - forcesac For SAC mode for masks <40bits (experimental) - fullflush Flush IOMMU on each allocation (default) - nofullflush Don't use IOMMU fullflush - allowed overwrite iommu off workarounds for specific chipsets. - soft Use software bounce buffering (default for Intel machines) - noaperture Don't touch the aperture for AGP. -*/ -__init int iommu_setup(char *p) -{ - int arg; - - while (*p) { - if (!strncmp(p,"noagp",5)) - no_agp = 1; - if (!strncmp(p,"off",3)) - no_iommu = 1; - if (!strncmp(p,"force",5)) { - force_iommu = 1; - iommu_aperture_allowed = 1; - } - if (!strncmp(p,"allowed",7)) - iommu_aperture_allowed = 1; - if (!strncmp(p,"noforce",7)) { - iommu_merge = 0; - force_iommu = 0; - } - if (!strncmp(p, "memaper", 7)) { - fallback_aper_force = 1; - p += 7; - if (*p == '=') { - ++p; - if (get_option(&p, &arg)) - fallback_aper_order = arg; - } - } - if (!strncmp(p, "biomerge",8)) { - iommu_bio_merge = 4096; - iommu_merge = 1; - force_iommu = 1; - } - if (!strncmp(p, "panic",5)) - panic_on_overflow = 1; - if (!strncmp(p, "nopanic",7)) - panic_on_overflow = 0; - if (!strncmp(p, "merge",5)) { - iommu_merge = 1; - force_iommu = 1; - } - if (!strncmp(p, "nomerge",7)) - iommu_merge = 0; - if (!strncmp(p, "forcesac",8)) - iommu_sac_force = 1; - if (!strncmp(p, "fullflush",8)) - iommu_fullflush = 1; - if (!strncmp(p, "nofullflush",11)) - iommu_fullflush = 0; - if (!strncmp(p, "soft",4)) - swiotlb = 1; - if (!strncmp(p, "noaperture",10)) - fix_aperture = 0; +void gart_parse_options(char *p) +{ + int arg; + #ifdef CONFIG_IOMMU_LEAK - if (!strncmp(p,"leak",4)) { - leak_trace = 1; - p += 4; - if (*p == '=') ++p; - if (isdigit(*p) && get_option(&p, &arg)) - iommu_leak_pages = arg; - } else + if (!strncmp(p,"leak",4)) { + leak_trace = 1; + p += 4; + if (*p == '=') ++p; + if (isdigit(*p) && get_option(&p, &arg)) + iommu_leak_pages = arg; + } #endif - if (isdigit(*p) && get_option(&p, &arg)) - iommu_size = arg; - p += strcspn(p, ","); - if (*p == ',') - ++p; - } - return 1; -} + if (isdigit(*p) && get_option(&p, &arg)) + iommu_size = arg; + if (!strncmp(p, "fullflush",8)) + iommu_fullflush = 1; + if (!strncmp(p, "nofullflush",11)) + iommu_fullflush = 0; + if (!strncmp(p,"noagp",5)) + no_agp = 1; + if (!strncmp(p, "noaperture",10)) + fix_aperture = 0; + /* duplicated from pci-dma.c */ + if (!strncmp(p,"force",5)) + iommu_aperture_allowed = 1; + if (!strncmp(p,"allowed",7)) + iommu_aperture_allowed = 1; + if (!strncmp(p, "memaper", 7)) { + fallback_aper_force = 1; + p += 7; + if (*p == '=') { + ++p; + if (get_option(&p, &arg)) + fallback_aper_order = arg; + } + } +} diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index 5a981dca87f..e4156497519 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -6,89 +6,94 @@ #include <linux/string.h> #include <asm/proto.h> #include <asm/processor.h> +#include <asm/dma.h> -int iommu_merge = 0; -EXPORT_SYMBOL(iommu_merge); - -dma_addr_t bad_dma_address; -EXPORT_SYMBOL(bad_dma_address); - -int iommu_bio_merge = 0; -EXPORT_SYMBOL(iommu_bio_merge); - -int iommu_sac_force = 0; -EXPORT_SYMBOL(iommu_sac_force); - -/* - * Dummy IO MMU functions - */ - -void *dma_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +static int +check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size) { - void *ret; - u64 mask; - int order = get_order(size); - - if (hwdev) - mask = hwdev->coherent_dma_mask & *hwdev->dma_mask; - else - mask = 0xffffffff; - for (;;) { - ret = (void *)__get_free_pages(gfp, order); - if (ret == NULL) - return NULL; - *dma_handle = virt_to_bus(ret); - if ((*dma_handle & ~mask) == 0) - break; - free_pages((unsigned long)ret, order); - if (gfp & GFP_DMA) - return NULL; - gfp |= GFP_DMA; + if (hwdev && bus + size > *hwdev->dma_mask) { + printk(KERN_ERR + "nommu_%s: overflow %Lx+%lu of device mask %Lx\n", + name, (long long)bus, size, (long long)*hwdev->dma_mask); + return 0; } + return 1; +} - memset(ret, 0, size); - return ret; +static dma_addr_t +nommu_map_single(struct device *hwdev, void *ptr, size_t size, + int direction) +{ + dma_addr_t bus = virt_to_bus(ptr); + if (!check_addr("map_single", hwdev, bus, size)) + return bad_dma_address; + return bus; } -EXPORT_SYMBOL(dma_alloc_coherent); -void dma_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) +void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size, + int direction) { - free_pages((unsigned long)vaddr, get_order(size)); } -EXPORT_SYMBOL(dma_free_coherent); -int dma_supported(struct device *hwdev, u64 mask) +/* Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scatter-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction) { - /* - * we fall back to GFP_DMA when the mask isn't all 1s, - * so we can't guarantee allocations that must be - * within a tighter range than GFP_DMA.. - * RED-PEN this won't work for pci_map_single. Caller has to - * use GFP_DMA in the first place. - */ - if (mask < 0x00ffffff) - return 0; + int i; - return 1; -} -EXPORT_SYMBOL(dma_supported); + BUG_ON(direction == DMA_NONE); + for (i = 0; i < nents; i++ ) { + struct scatterlist *s = &sg[i]; + BUG_ON(!s->page); + s->dma_address = virt_to_bus(page_address(s->page) +s->offset); + if (!check_addr("map_sg", hwdev, s->dma_address, s->length)) + return 0; + s->dma_length = s->length; + } + return nents; +} -int dma_get_cache_alignment(void) +/* Unmap a set of streaming mode DMA translations. + * Again, cpu read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +void nommu_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, int dir) { - return boot_cpu_data.x86_clflush_size; } -EXPORT_SYMBOL(dma_get_cache_alignment); -static int __init check_ram(void) -{ - if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { - printk( - KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n" - KERN_ERR "WARNING 32bit PCI may malfunction.\n"); - } - return 0; -} -__initcall(check_ram); +struct dma_mapping_ops nommu_dma_ops = { + .map_single = nommu_map_single, + .unmap_single = nommu_unmap_single, + .map_sg = nommu_map_sg, + .unmap_sg = nommu_unmap_sg, + .is_phys = 1, +}; +void __init no_iommu_init(void) +{ + if (dma_ops) + return; + printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); + dma_ops = &nommu_dma_ops; + if (end_pfn > MAX_DMA32_PFN) { + printk(KERN_ERR + "WARNING more than 4GB of memory but IOMMU not compiled in.\n" + KERN_ERR "WARNING 32bit PCI may malfunction.\n" + KERN_ERR "You might want to enable CONFIG_GART_IOMMU\n"); + } +} diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c new file mode 100644 index 00000000000..3569a25ad7f --- /dev/null +++ b/arch/x86_64/kernel/pci-swiotlb.c @@ -0,0 +1,42 @@ +/* Glue code to lib/swiotlb.c */ + +#include <linux/pci.h> +#include <linux/cache.h> +#include <linux/module.h> +#include <asm/dma-mapping.h> +#include <asm/proto.h> +#include <asm/swiotlb.h> +#include <asm/dma.h> + +int swiotlb __read_mostly; +EXPORT_SYMBOL(swiotlb); + +struct dma_mapping_ops swiotlb_dma_ops = { + .mapping_error = swiotlb_dma_mapping_error, + .alloc_coherent = swiotlb_alloc_coherent, + .free_coherent = swiotlb_free_coherent, + .map_single = swiotlb_map_single, + .unmap_single = swiotlb_unmap_single, + .sync_single_for_cpu = swiotlb_sync_single_for_cpu, + .sync_single_for_device = swiotlb_sync_single_for_device, + .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, + .sync_single_range_for_device = swiotlb_sync_single_range_for_device, + .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, + .sync_sg_for_device = swiotlb_sync_sg_for_device, + .map_sg = swiotlb_map_sg, + .unmap_sg = swiotlb_unmap_sg, + .dma_supported = NULL, +}; + +void pci_swiotlb_init(void) +{ + /* don't initialize swiotlb if iommu=off (no_iommu=1) */ + if (!iommu_aperture && !no_iommu && + (end_pfn > MAX_DMA32_PFN || force_iommu)) + swiotlb = 1; + if (swiotlb) { + swiotlb_init(); + printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); + dma_ops = &swiotlb_dma_ops; + } +} diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 3060ed97b75..8ded407e4a9 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -36,6 +36,7 @@ #include <linux/utsname.h> #include <linux/random.h> #include <linux/kprobes.h> +#include <linux/notifier.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -50,13 +51,12 @@ #include <asm/desc.h> #include <asm/proto.h> #include <asm/ia32.h> +#include <asm/idle.h> asmlinkage extern void ret_from_fork(void); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; -static atomic_t hlt_counter = ATOMIC_INIT(0); - unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); @@ -66,19 +66,49 @@ EXPORT_SYMBOL(boot_option_idle_override); void (*pm_idle)(void); static DEFINE_PER_CPU(unsigned int, cpu_idle_state); -void disable_hlt(void) +static struct notifier_block *idle_notifier; +static DEFINE_SPINLOCK(idle_notifier_lock); + +void idle_notifier_register(struct notifier_block *n) +{ + unsigned long flags; + spin_lock_irqsave(&idle_notifier_lock, flags); + notifier_chain_register(&idle_notifier, n); + spin_unlock_irqrestore(&idle_notifier_lock, flags); +} +EXPORT_SYMBOL_GPL(idle_notifier_register); + +void idle_notifier_unregister(struct notifier_block *n) { - atomic_inc(&hlt_counter); + unsigned long flags; + spin_lock_irqsave(&idle_notifier_lock, flags); + notifier_chain_unregister(&idle_notifier, n); + spin_unlock_irqrestore(&idle_notifier_lock, flags); } +EXPORT_SYMBOL(idle_notifier_unregister); -EXPORT_SYMBOL(disable_hlt); +enum idle_state { CPU_IDLE, CPU_NOT_IDLE }; +static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE; -void enable_hlt(void) +void enter_idle(void) { - atomic_dec(&hlt_counter); + __get_cpu_var(idle_state) = CPU_IDLE; + notifier_call_chain(&idle_notifier, IDLE_START, NULL); } -EXPORT_SYMBOL(enable_hlt); +static void __exit_idle(void) +{ + __get_cpu_var(idle_state) = CPU_NOT_IDLE; + notifier_call_chain(&idle_notifier, IDLE_END, NULL); +} + +/* Called from interrupts to signify idle end */ +void exit_idle(void) +{ + if (current->pid | read_pda(irqcount)) + return; + __exit_idle(); +} /* * We use this if we don't have any better @@ -88,21 +118,16 @@ void default_idle(void) { local_irq_enable(); - if (!atomic_read(&hlt_counter)) { - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb__after_clear_bit(); - while (!need_resched()) { - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); - } - set_thread_flag(TIF_POLLING_NRFLAG); - } else { - while (!need_resched()) - cpu_relax(); + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + while (!need_resched()) { + local_irq_disable(); + if (!need_resched()) + safe_halt(); + else + local_irq_enable(); } + set_thread_flag(TIF_POLLING_NRFLAG); } /* @@ -201,7 +226,9 @@ void cpu_idle (void) idle = default_idle; if (cpu_is_offline(smp_processor_id())) play_dead(); + enter_idle(); idle(); + __exit_idle(); } preempt_enable_no_resched(); @@ -424,7 +451,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, struct task_struct *me = current; childregs = ((struct pt_regs *) - (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + (THREAD_SIZE + task_stack_page(p))) - 1; *childregs = *regs; childregs->rax = 0; @@ -436,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, p->thread.rsp0 = (unsigned long) (childregs+1); p->thread.userrsp = me->thread.userrsp; - set_ti_thread_flag(p->thread_info, TIF_FORK); + set_tsk_thread_flag(p, TIF_FORK); p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; @@ -563,7 +590,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) write_pda(oldrsp, next->userrsp); write_pda(pcurrent, next_p); write_pda(kernelstack, - (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); + task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); /* * Now maybe reload the debug registers @@ -677,7 +704,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state==TASK_RUNNING) return 0; - stack = (unsigned long)p->thread_info; + stack = (unsigned long)task_stack_page(p); if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.rsp); @@ -795,8 +822,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { struct pt_regs *pp, ptregs; - pp = (struct pt_regs *)(tsk->thread.rsp0); - --pp; + pp = task_pt_regs(tsk); ptregs = *pp; ptregs.cs &= 0xffff; diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index a87b6cebe80..53205622351 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -36,9 +36,12 @@ * in exit.c or in signal.c. */ -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x44dd5UL +/* + * Determines which flags the user has access to [1 = access, 0 = no access]. + * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). + * Also masks reserved bits (63-22, 15, 5, 3, 1). + */ +#define FLAG_MASK 0x54dd5UL /* set's the trap flag. */ #define TRAP_FLAG 0x100UL @@ -64,12 +67,6 @@ static inline unsigned long get_stack_long(struct task_struct *task, int offset) return (*((unsigned long *)stack)); } -static inline struct pt_regs *get_child_regs(struct task_struct *task) -{ - struct pt_regs *regs = (void *)task->thread.rsp0; - return regs - 1; -} - /* * this routine will put a word on the processes privileged stack. * the offset is how far from the base addr as stored in the TSS. @@ -167,7 +164,7 @@ static int is_at_popf(struct task_struct *child, struct pt_regs *regs) static void set_singlestep(struct task_struct *child) { - struct pt_regs *regs = get_child_regs(child); + struct pt_regs *regs = task_pt_regs(child); /* * Always set TIF_SINGLESTEP - this guarantees that @@ -205,7 +202,7 @@ static void clear_singlestep(struct task_struct *child) /* But touch TF only if it was set by us.. */ if (child->ptrace & PT_DTRACE) { - struct pt_regs *regs = get_child_regs(child); + struct pt_regs *regs = task_pt_regs(child); regs->eflags &= ~TRAP_FLAG; child->ptrace &= ~PT_DTRACE; } diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index 75235ed2b31..57117b8beb2 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -6,6 +6,7 @@ #include <linux/kernel.h> #include <linux/ctype.h> #include <linux/string.h> +#include <linux/pm.h> #include <asm/io.h> #include <asm/kdebug.h> #include <asm/delay.h> @@ -154,10 +155,11 @@ void machine_halt(void) void machine_power_off(void) { - if (!reboot_force) { - machine_shutdown(); - } - if (pm_power_off) + if (pm_power_off) { + if (!reboot_force) { + machine_shutdown(); + } pm_power_off(); + } } diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 64c4534b930..28895c03cb1 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -35,6 +35,7 @@ #include <asm/processor.h> #include <linux/console.h> #include <linux/seq_file.h> +#include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/pci.h> #include <linux/acpi.h> @@ -43,6 +44,8 @@ #include <linux/mmzone.h> #include <linux/kexec.h> #include <linux/cpufreq.h> +#include <linux/dmi.h> +#include <linux/dma-mapping.h> #include <asm/mtrr.h> #include <asm/uaccess.h> @@ -61,7 +64,9 @@ #include <asm/setup.h> #include <asm/mach_apic.h> #include <asm/numa.h> +#include <asm/swiotlb.h> #include <asm/sections.h> +#include <asm/gart-mapping.h> /* * Machine setup.. @@ -86,11 +91,6 @@ int bootloader_type; unsigned long saved_video_mode; -#ifdef CONFIG_SWIOTLB -int swiotlb; -EXPORT_SYMBOL(swiotlb); -#endif - /* * Setup options */ @@ -275,10 +275,7 @@ static __init void parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; - - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); - saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; + int userdef = 0; for (;;) { if (c != ' ') @@ -346,10 +343,14 @@ static __init void parse_cmdline_early (char ** cmdline_p) !memcmp(from, "disableapic", 11)) disable_apic = 1; - if (!memcmp(from, "noapic", 6)) + /* Don't confuse with noapictimer */ + if (!memcmp(from, "noapic", 6) && + (from[6] == ' ' || from[6] == 0)) skip_ioapic_setup = 1; - if (!memcmp(from, "apic", 4)) { + /* Make sure to not confuse with apic= */ + if (!memcmp(from, "apic", 4) && + (from[4] == ' ' || from[4] == 0)) { skip_ioapic_setup = 0; ioapic_force = 1; } @@ -357,16 +358,36 @@ static __init void parse_cmdline_early (char ** cmdline_p) if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); + if (!memcmp(from, "memmap=", 7)) { + /* exactmap option is for used defined memory */ + if (!memcmp(from+7, "exactmap", 8)) { +#ifdef CONFIG_CRASH_DUMP + /* If we are doing a crash dump, we + * still need to know the real mem + * size before original memory map is + * reset. + */ + saved_max_pfn = e820_end_of_ram(); +#endif + from += 8+7; + end_pfn_map = 0; + e820.nr_map = 0; + userdef = 1; + } + else { + parse_memmapopt(from+7, &from); + userdef = 1; + } + } + #ifdef CONFIG_NUMA if (!memcmp(from, "numa=", 5)) numa_setup(from+5); #endif -#ifdef CONFIG_GART_IOMMU if (!memcmp(from,"iommu=",6)) { iommu_setup(from+6); } -#endif if (!memcmp(from,"oops=panic", 10)) panic_on_oops = 1; @@ -395,6 +416,14 @@ static __init void parse_cmdline_early (char ** cmdline_p) } #endif +#ifdef CONFIG_PROC_VMCORE + /* elfcorehdr= specifies the location of elf core header + * stored by the crashed kernel. This option will be passed + * by kexec loader to the capture kernel. + */ + else if(!memcmp(from, "elfcorehdr=", 11)) + elfcorehdr_addr = memparse(from+11, &from); +#endif next_char: c = *(from++); if (!c) @@ -403,6 +432,10 @@ static __init void parse_cmdline_early (char ** cmdline_p) break; *(to++) = c; } + if (userdef) { + printk(KERN_INFO "user-defined physical RAM map:\n"); + e820_print_map("user"); + } *to = '\0'; *cmdline_p = command_line; } @@ -443,6 +476,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = { k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, }; +extern char __vsyscall_0; + /* Replace instructions with better alternatives for this CPU type. This runs before SMP is initialized to avoid SMP problems with @@ -454,11 +489,17 @@ void apply_alternatives(void *start, void *end) struct alt_instr *a; int diff, i, k; for (a = start; (void *)a < end; a++) { + u8 *instr; + if (!boot_cpu_has(a->cpuid)) continue; BUG_ON(a->replacementlen > a->instrlen); - __inline_memcpy(a->instr, a->replacement, a->replacementlen); + instr = a->instr; + /* vsyscall code is not mapped yet. resolve it manually. */ + if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) + instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0)); + __inline_memcpy(instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; /* Pad the rest with nops */ @@ -466,7 +507,7 @@ void apply_alternatives(void *start, void *end) k = diff; if (k > ASM_NOP_MAX) k = ASM_NOP_MAX; - __inline_memcpy(a->instr + i, k8_nops[k], k); + __inline_memcpy(instr + i, k8_nops[k], k); } } } @@ -670,6 +711,8 @@ void __init setup_arch(char **cmdline_p) acpi_boot_init(); #endif + init_cpu_to_node(); + #ifdef CONFIG_X86_LOCAL_APIC /* * get boot-time SMP configuration: @@ -834,7 +877,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) static int __init init_amd(struct cpuinfo_x86 *c) { int r; - int level; #ifdef CONFIG_SMP unsigned long value; @@ -857,11 +899,6 @@ static int __init init_amd(struct cpuinfo_x86 *c) 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); - /* C-stepping K8? */ - level = cpuid_eax(1); - if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) - set_bit(X86_FEATURE_K8_C, &c->x86_capability); - r = get_model_name(c); if (!r) { switch (c->x86) { @@ -874,6 +911,10 @@ static int __init init_amd(struct cpuinfo_x86 *c) } display_cacheinfo(c); + /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */ + if (c->x86_power & (1<<8)) + set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); + if (c->extended_cpuid_level >= 0x80000008) { c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; if (c->x86_max_cores & (c->x86_max_cores - 1)) @@ -992,8 +1033,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (c->x86 == 15) c->x86_cache_alignment = c->x86_clflush_size * 2; - if (c->x86 >= 15) + if ((c->x86 == 0xf && c->x86_model >= 0x03) || + (c->x86 == 0x6 && c->x86_model >= 0x0e)) set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); + set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); c->x86_max_cores = intel_num_cpu_cores(c); srat_detect_node(); @@ -1192,7 +1235,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -1220,7 +1263,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, + "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1231,7 +1274,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) "vid", /* voltage id control */ "ttp", /* thermal trip */ "tm", - "stc" + "stc", + NULL, + /* nothing */ /* constant_tsc - moved to flags */ }; @@ -1311,8 +1356,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) unsigned i; for (i = 0; i < 32; i++) if (c->x86_power & (1 << i)) { - if (i < ARRAY_SIZE(x86_power_flags)) - seq_printf(m, " %s", x86_power_flags[i]); + if (i < ARRAY_SIZE(x86_power_flags) && + x86_power_flags[i]) + seq_printf(m, "%s%s", + x86_power_flags[i][0]?" ":"", + x86_power_flags[i]); else seq_printf(m, " [%d]", i); } @@ -1344,3 +1392,11 @@ struct seq_operations cpuinfo_op = { .stop = c_stop, .show = show_cpuinfo, }; + +static int __init run_dmi_scan(void) +{ + dmi_scan_machine(); + return 0; +} +core_initcall(run_dmi_scan); + diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 06dc354375c..6eff51e9400 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -30,7 +30,8 @@ char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,}; cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; -struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; +struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly; +struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned; struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table }; @@ -110,18 +111,18 @@ void __init setup_per_cpu_areas(void) } if (!ptr) panic("Cannot allocate cpu data for CPU %d\n", i); - cpu_pda[i].data_offset = ptr - __per_cpu_start; + cpu_pda(i)->data_offset = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); } } void pda_init(int cpu) { - struct x8664_pda *pda = &cpu_pda[cpu]; + struct x8664_pda *pda = cpu_pda(cpu); /* Setup up data that may be needed in __get_free_pages early */ asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); - wrmsrl(MSR_GS_BASE, cpu_pda + cpu); + wrmsrl(MSR_GS_BASE, pda); pda->cpunumber = cpu; pda->irqcount = -1; @@ -145,7 +146,7 @@ void pda_init(int cpu) pda->irqstackptr += IRQSTACKSIZE-64; } -char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ] +char boot_exception_stacks[(N_EXCEPTION_STACKS - 2) * EXCEPTION_STKSZ + DEBUG_STKSZ] __attribute__((section(".bss.page_aligned"))); /* May not be marked __init: used by software suspend */ @@ -213,23 +214,14 @@ void __cpuinit cpu_init (void) * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ - if (cpu) { - memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE); - } + if (cpu) + memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE); cpu_gdt_descr[cpu].size = GDT_SIZE; - cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu]; asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu])); asm volatile("lidt %0" :: "m" (idt_descr)); - memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8); - - /* - * Delete NT - */ - - asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax"); - + memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); syscall_init(); wrmsrl(MSR_FS_BASE, 0); @@ -243,13 +235,27 @@ void __cpuinit cpu_init (void) */ for (v = 0; v < N_EXCEPTION_STACKS; v++) { if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, - EXCEPTION_STACK_ORDER); + static const unsigned int order[N_EXCEPTION_STACKS] = { + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, + [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + }; + + estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); if (!estacks) panic("Cannot allocate exception stack %ld %d\n", v, cpu); } - estacks += EXCEPTION_STKSZ; + switch (v + 1) { +#if DEBUG_STKSZ > EXCEPTION_STKSZ + case DEBUG_STACK: + cpu_pda[cpu].debugstack = (unsigned long)estacks; + estacks += DEBUG_STKSZ; + break; +#endif + default: + estacks += EXCEPTION_STKSZ; + break; + } t->ist[v] = (unsigned long)estacks; } diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index cfc3d9dccbd..19ef012b1f1 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -27,6 +27,7 @@ #include <asm/mmu_context.h> #include <asm/proto.h> #include <asm/apicdef.h> +#include <asm/idle.h> /* * Smarter SMP flushing macros. @@ -280,11 +281,6 @@ void flush_tlb_all(void) on_each_cpu(do_flush_tlb_all, NULL, 1, 1); } -void smp_kdb_stop(void) -{ - send_IPI_allbutself(KDB_VECTOR); -} - /* * this function sends a 'reschedule' IPI to another CPU. * it goes straight through and wastes no time serializing @@ -512,6 +508,7 @@ asmlinkage void smp_call_function_interrupt(void) /* * At this point the info structure may be out of scope unless wait==1 */ + exit_idle(); irq_enter(); (*func)(info); irq_exit(); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index ecbd7b83acc..a28756ef7ce 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -335,7 +335,13 @@ static __cpuinit void sync_tsc(unsigned int master) static void __cpuinit tsc_sync_wait(void) { - if (notscsync || !cpu_has_tsc) + /* + * When the CPU has synchronized TSCs assume the BIOS + * or the hardware already synced. Otherwise we could + * mess up a possible perfect synchronization with a + * not-quite-perfect algorithm. + */ + if (notscsync || !cpu_has_tsc || !unsynchronized_tsc()) return; sync_tsc(0); } @@ -646,6 +652,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; } while (send_status && (timeout++ < 1000)); + mb(); atomic_set(&init_deasserted, 1); num_starts = 2; @@ -659,7 +666,6 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta for (j = 1; j <= num_starts; j++) { Dprintk("Sending STARTUP #%d.\n",j); - apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); Dprintk("After apic_write.\n"); @@ -698,7 +704,6 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta * Due to the Pentium erratum 3AP. */ if (maxlvt > 3) { - apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); } accept_status = (apic_read(APIC_ESR) & 0xEF); @@ -743,11 +748,35 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) }; DECLARE_WORK(work, do_fork_idle, &c_idle); + /* allocate memory for gdts of secondary cpus. Hotplug is considered */ + if (!cpu_gdt_descr[cpu].address && + !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { + printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu); + return -1; + } + + /* Allocate node local memory for AP pdas */ + if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) { + struct x8664_pda *newpda, *pda; + int node = cpu_to_node(cpu); + pda = cpu_pda(cpu); + newpda = kmalloc_node(sizeof (struct x8664_pda), GFP_ATOMIC, + node); + if (newpda) { + memcpy(newpda, pda, sizeof (struct x8664_pda)); + cpu_pda(cpu) = newpda; + } else + printk(KERN_ERR + "Could not allocate node local PDA for CPU %d on node %d\n", + cpu, node); + } + + c_idle.idle = get_idle_for_cpu(cpu); if (c_idle.idle) { c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *) - (THREAD_SIZE + (unsigned long) c_idle.idle->thread_info)) - 1); + (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1); init_idle(c_idle.idle, cpu); goto do_rest; } @@ -778,14 +807,14 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) do_rest: - cpu_pda[cpu].pcurrent = c_idle.idle; + cpu_pda(cpu)->pcurrent = c_idle.idle; start_rip = setup_trampoline(); init_rsp = c_idle.idle->thread.rsp; per_cpu(init_tss,cpu).rsp0 = init_rsp; initial_code = start_secondary; - clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK); + clear_tsk_thread_flag(c_idle.idle, TIF_FORK); printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu, cpus_weight(cpu_present_map), @@ -811,11 +840,8 @@ do_rest: /* * Be paranoid about clearing APIC errors. */ - if (APIC_INTEGRATED(apic_version[apicid])) { - apic_read_around(APIC_SPIV); - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); - } + apic_write(APIC_ESR, 0); + apic_read(APIC_ESR); /* * Status is now clean @@ -927,8 +953,8 @@ int additional_cpus __initdata = -1; * * Three ways to find out the number of additional hotplug CPUs: * - If the BIOS specified disabled CPUs in ACPI/mptables use that. - * - otherwise use half of the available CPUs or 2, whatever is more. * - The user can overwrite it with additional_cpus=NUM + * - Otherwise don't reserve additional CPUs. * We do this because additional CPUs waste a lot of memory. * -AK */ @@ -938,13 +964,10 @@ __init void prefill_possible_map(void) int possible; if (additional_cpus == -1) { - if (disabled_cpus > 0) { + if (disabled_cpus > 0) additional_cpus = disabled_cpus; - } else { - additional_cpus = num_processors / 2; - if (additional_cpus == 0) - additional_cpus = 2; - } + else + additional_cpus = 0; } possible = num_processors + additional_cpus; if (possible > NR_CPUS) @@ -996,7 +1019,7 @@ static int __init smp_sanity_check(unsigned max_cpus) /* * If we couldn't find a local APIC, then get out of here now! */ - if (APIC_INTEGRATED(apic_version[boot_cpu_id]) && !cpu_has_apic) { + if (!cpu_has_apic) { printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", boot_cpu_id); printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index fd2bef78088..ecbd34c1093 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c @@ -120,7 +120,7 @@ void fix_processor_context(void) set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ - cpu_gdt_table[cpu][GDT_ENTRY_TSS].type = 9; + cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9; syscall_init(); /* This sets MSR_*STAR and related */ load_TR_desc(); /* This does ltr */ diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 43c9fa0f8d5..f8c47c68844 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -71,14 +71,6 @@ unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES; struct timespec __xtime __section_xtime; struct timezone __sys_tz __section_sys_tz; -static inline void rdtscll_sync(unsigned long *tsc) -{ -#ifdef CONFIG_SMP - sync_core(); -#endif - rdtscll(*tsc); -} - /* * do_gettimeoffset() returns microseconds since last timer interrupt was * triggered by hardware. A memory read of HPET is slower than a register read @@ -93,7 +85,7 @@ static inline unsigned int do_gettimeoffset_tsc(void) { unsigned long t; unsigned long x; - rdtscll_sync(&t); + t = get_cycles_sync(); if (t < vxtime.last_tsc) t = vxtime.last_tsc; /* hack */ x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32; return x; @@ -259,8 +251,8 @@ static void set_rtc_mmss(unsigned long nowtime) #endif { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); } @@ -297,25 +289,21 @@ unsigned long long monotonic_clock(void) last_offset = vxtime.last; base = monotonic_base; this_offset = hpet_readl(HPET_COUNTER); - } while (read_seqretry(&xtime_lock, seq)); offset = (this_offset - last_offset); offset *=(NSEC_PER_SEC/HZ)/hpet_tick; return base + offset; - }else{ + } else { do { seq = read_seqbegin(&xtime_lock); last_offset = vxtime.last_tsc; base = monotonic_base; } while (read_seqretry(&xtime_lock, seq)); - sync_core(); - rdtscll(this_offset); + this_offset = get_cycles_sync(); offset = (this_offset - last_offset)*1000/cpu_khz; return base + offset; } - - } EXPORT_SYMBOL(monotonic_clock); @@ -391,7 +379,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) delay = LATCH - 1 - delay; } - rdtscll_sync(&tsc); + tsc = get_cycles_sync(); if (vxtime.mode == VXTIME_HPET) { if (offset - vxtime.last > hpet_tick) { @@ -471,6 +459,11 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_sequnlock(&xtime_lock); +#ifdef CONFIG_X86_LOCAL_APIC + if (using_apic_timer) + smp_send_timer_broadcast_ipi(); +#endif + return IRQ_HANDLED; } @@ -509,10 +502,10 @@ unsigned long long sched_clock(void) return cycles_2_ns(a); } -unsigned long get_cmos_time(void) +static unsigned long get_cmos_time(void) { - unsigned int timeout, year, mon, day, hour, min, sec; - unsigned char last, this; + unsigned int timeout = 1000000, year, mon, day, hour, min, sec; + unsigned char uip = 0, this = 0; unsigned long flags; /* @@ -525,45 +518,41 @@ unsigned long get_cmos_time(void) spin_lock_irqsave(&rtc_lock, flags); - timeout = 1000000; - last = this = 0; - - while (timeout && last && !this) { - last = this; + while (timeout && (!uip || this)) { + uip |= this; this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP; timeout--; } -/* - * Here we are safe to assume the registers won't change for a whole second, so - * we just go ahead and read them. - */ - - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); + /* + * Here we are safe to assume the registers won't change for a whole + * second, so we just go ahead and read them. + */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); spin_unlock_irqrestore(&rtc_lock, flags); -/* - * We know that x86-64 always uses BCD format, no need to check the config - * register. - */ + /* + * We know that x86-64 always uses BCD format, no need to check the + * config register. + */ - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); -/* - * x86-64 systems only exists since 2002. - * This will work up to Dec 31, 2100 - */ + /* + * x86-64 systems only exists since 2002. + * This will work up to Dec 31, 2100 + */ year += 2000; return mktime(year, mon, day, hour, min, sec); @@ -695,8 +684,7 @@ static unsigned int __init hpet_calibrate_tsc(void) do { local_irq_disable(); hpet_now = hpet_readl(HPET_COUNTER); - sync_core(); - rdtscl(tsc_now); + tsc_now = get_cycles_sync(); local_irq_restore(flags); } while ((tsc_now - tsc_start) < TICK_COUNT && (hpet_now - hpet_start) < TICK_COUNT); @@ -726,11 +714,9 @@ static unsigned int __init pit_calibrate_tsc(void) outb(0xb0, 0x43); outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); - rdtscll(start); - sync_core(); + start = get_cycles_sync(); while ((inb(0x61) & 0x20) == 0); - sync_core(); - rdtscll(end); + end = get_cycles_sync(); spin_unlock_irqrestore(&i8253_lock, flags); @@ -744,7 +730,7 @@ static __init int late_hpet_init(void) unsigned int ntimer; if (!vxtime.hpet_address) - return -1; + return -1; memset(&hd, 0, sizeof (hd)); @@ -878,8 +864,6 @@ static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL }; -extern void __init config_acpi_tables(void); - void __init time_init(void) { char *timename; @@ -934,7 +918,7 @@ void __init time_init(void) vxtime.mode = VXTIME_TSC; vxtime.quot = (1000000L << 32) / vxtime_hz; vxtime.tsc_quot = (1000L << 32) / cpu_khz; - rdtscll_sync(&vxtime.last_tsc); + vxtime.last_tsc = get_cycles_sync(); setup_irq(0, &irq0); set_cyc2ns_scale(cpu_khz); @@ -948,7 +932,7 @@ void __init time_init(void) * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs. */ -static __init int unsynchronized_tsc(void) +__init int unsynchronized_tsc(void) { #ifdef CONFIG_SMP if (oem_force_hpet_timer()) @@ -959,7 +943,7 @@ static __init int unsynchronized_tsc(void) return 0; #endif /* Assume multi socket systems are not synchronized */ - return num_online_cpus() > 1; + return num_present_cpus() > 1; } /* @@ -999,6 +983,10 @@ __setup("report_lost_ticks", time_setup); static long clock_cmos_diff; static unsigned long sleep_start; +/* + * sysfs support for the timer. + */ + static int timer_suspend(struct sys_device *dev, pm_message_t state) { /* @@ -1041,7 +1029,6 @@ static struct sysdev_class timer_sysclass = { set_kset_name("timer"), }; - /* XXX this driverfs stuff should probably go elsewhere later -john */ static struct sys_device device_timer = { .id = 0, @@ -1283,8 +1270,6 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) } #endif - - static int __init nohpet_setup(char *s) { nohpet = 1; @@ -1301,5 +1286,3 @@ static int __init notsc_setup(char *s) } __setup("notsc", notsc_setup); - - diff --git a/arch/x86_64/kernel/trampoline.S b/arch/x86_64/kernel/trampoline.S index 6d9c9a8e7d0..23a03eb91fc 100644 --- a/arch/x86_64/kernel/trampoline.S +++ b/arch/x86_64/kernel/trampoline.S @@ -42,8 +42,15 @@ r_base = . movl $0xA5A5A5A5, trampoline_data - r_base # write marker for master knows we're running - lidt idt_48 - r_base # load idt with 0, 0 - lgdt gdt_48 - r_base # load gdt with whatever is appropriate + /* + * GDT tables in non default location kernel can be beyond 16MB and + * lgdt will not be able to load the address as in real mode default + * operand size is 16bit. Use lgdtl instead to force operand size + * to 32 bit. + */ + + lidtl idt_48 - r_base # load idt with 0, 0 + lgdtl gdt_48 - r_base # load gdt with whatever is appropriate xor %ax, %ax inc %ax # protected mode (PE) bit diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index bf337f49318..8bb0aeda78b 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -70,7 +70,6 @@ asmlinkage void reserved(void); asmlinkage void alignment_check(void); asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); -asmlinkage void call_debug(void); struct notifier_block *die_chain; static DEFINE_SPINLOCK(die_notifier_lock); @@ -121,19 +120,31 @@ int printk_address(unsigned long address) static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, unsigned *usedp, const char **idp) { - static const char ids[N_EXCEPTION_STACKS][8] = { + static char ids[][8] = { [DEBUG_STACK - 1] = "#DB", [NMI_STACK - 1] = "NMI", [DOUBLEFAULT_STACK - 1] = "#DF", [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", +#if DEBUG_STKSZ > EXCEPTION_STKSZ + [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" +#endif }; unsigned k; for (k = 0; k < N_EXCEPTION_STACKS; k++) { unsigned long end; - end = per_cpu(init_tss, cpu).ist[k]; + switch (k + 1) { +#if DEBUG_STKSZ > EXCEPTION_STKSZ + case DEBUG_STACK: + end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ; + break; +#endif + default: + end = per_cpu(init_tss, cpu).ist[k]; + break; + } if (stack >= end) continue; if (stack >= end - EXCEPTION_STKSZ) { @@ -143,6 +154,22 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, *idp = ids[k]; return (unsigned long *)end; } +#if DEBUG_STKSZ > EXCEPTION_STKSZ + if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) { + unsigned j = N_EXCEPTION_STACKS - 1; + + do { + ++j; + end -= EXCEPTION_STKSZ; + ids[j][4] = '1' + (j - N_EXCEPTION_STACKS); + } while (stack < end - EXCEPTION_STKSZ); + if (*usedp & (1U << j)) + break; + *usedp |= 1U << j; + *idp = ids[j]; + return (unsigned long *)end; + } +#endif } return NULL; } @@ -156,9 +183,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, void show_trace(unsigned long *stack) { - unsigned long addr; const unsigned cpu = safe_smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *)cpu_pda[cpu].irqstackptr; + unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; int i; unsigned used = 0; @@ -166,8 +192,14 @@ void show_trace(unsigned long *stack) #define HANDLE_STACK(cond) \ do while (cond) { \ - addr = *stack++; \ + unsigned long addr = *stack++; \ if (kernel_text_address(addr)) { \ + if (i > 50) { \ + printk("\n "); \ + i = 0; \ + } \ + else \ + i += printk(" "); \ /* \ * If the address is either in the text segment of the \ * kernel, or in the region which contains vmalloc'ed \ @@ -177,25 +209,19 @@ void show_trace(unsigned long *stack) * out the call path that was taken. \ */ \ i += printk_address(addr); \ - if (i > 50) { \ - printk("\n "); \ - i = 0; \ - } \ - else \ - i += printk(" "); \ } \ } while (0) - for(i = 0; ; ) { + for(i = 11; ; ) { const char *id; unsigned long *estack_end; estack_end = in_exception_stack(cpu, (unsigned long)stack, &used, &id); if (estack_end) { - i += printk(" <%s> ", id); + i += printk(" <%s>", id); HANDLE_STACK (stack < estack_end); - i += printk(" <EOE> "); + i += printk(" <EOE>"); stack = (unsigned long *) estack_end[-2]; continue; } @@ -205,11 +231,11 @@ void show_trace(unsigned long *stack) (IRQSTACKSIZE - 64) / sizeof(*irqstack); if (stack >= irqstack && stack < irqstack_end) { - i += printk(" <IRQ> "); + i += printk(" <IRQ>"); HANDLE_STACK (stack < irqstack_end); stack = (unsigned long *) (irqstack_end[-1]); irqstack_end = NULL; - i += printk(" <EOI> "); + i += printk(" <EOI>"); continue; } } @@ -226,8 +252,8 @@ void show_stack(struct task_struct *tsk, unsigned long * rsp) unsigned long *stack; int i; const int cpu = safe_smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr); - unsigned long *irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE); + unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr); + unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); // debugging aid: "show_stack(NULL, NULL);" prints the // back trace for this cpu. @@ -275,14 +301,14 @@ void show_registers(struct pt_regs *regs) int in_kernel = !user_mode(regs); unsigned long rsp; const int cpu = safe_smp_processor_id(); - struct task_struct *cur = cpu_pda[cpu].pcurrent; + struct task_struct *cur = cpu_pda(cpu)->pcurrent; rsp = regs->rsp; printk("CPU %d ", cpu); __show_regs(regs); printk("Process %s (pid: %d, threadinfo %p, task %p)\n", - cur->comm, cur->pid, cur->thread_info, cur); + cur->comm, cur->pid, task_thread_info(cur), cur); /* * When in-kernel, we also print out the stack and code at the @@ -314,20 +340,26 @@ bad: void handle_BUG(struct pt_regs *regs) { struct bug_frame f; - char tmp; + long len; + const char *prefix = ""; if (user_mode(regs)) return; - if (__copy_from_user(&f, (struct bug_frame *) regs->rip, + if (__copy_from_user(&f, (const void __user *) regs->rip, sizeof(struct bug_frame))) return; if (f.filename >= 0 || f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) return; - if (__get_user(tmp, (char *)(long)f.filename)) + len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1; + if (len < 0 || len >= PATH_MAX) f.filename = (int)(long)"unmapped filename"; + else if (len > 50) { + f.filename += len - 50; + prefix = "..."; + } printk("----------- [cut here ] --------- [please bite here ] ---------\n"); - printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line); + printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line); } #ifdef CONFIG_BUG @@ -382,7 +414,7 @@ void __die(const char * str, struct pt_regs * regs, long err) printk("DEBUG_PAGEALLOC"); #endif printk("\n"); - notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); + notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); show_registers(regs); /* Executive summary in case the oops scrolled away */ printk(KERN_ALERT "RIP "); @@ -399,11 +431,6 @@ void die(const char * str, struct pt_regs * regs, long err) oops_end(flags); do_exit(SIGSEGV); } -static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) -{ - if (!(regs->eflags & VM_MASK) && (regs->cs == __KERNEL_CS)) - die(str, regs, err); -} void die_nmi(char *str, struct pt_regs *regs) { @@ -426,19 +453,20 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, struct pt_regs * regs, long error_code, siginfo_t *info) { + struct task_struct *tsk = current; + conditional_sti(regs); - if (user_mode(regs)) { - struct task_struct *tsk = current; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = trapnr; + if (user_mode(regs)) { if (exception_trace && unhandled_signal(tsk, signr)) printk(KERN_INFO "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", tsk->comm, tsk->pid, str, regs->rip,regs->rsp,error_code); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = trapnr; if (info) force_sig_info(signr, info, tsk); else @@ -485,7 +513,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip) DO_ERROR( 4, SIGSEGV, "overflow", overflow) DO_ERROR( 5, SIGSEGV, "bounds", bounds) -DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip) +DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->rip) DO_ERROR( 7, SIGSEGV, "device not available", device_not_available) DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) @@ -493,24 +521,41 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR(18, SIGSEGV, "reserved", reserved) DO_ERROR(12, SIGBUS, "stack segment", stack_segment) -DO_ERROR( 8, SIGSEGV, "double fault", double_fault) + +asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) +{ + static const char str[] = "double fault"; + struct task_struct *tsk = current; + + /* Return not checked because double check cannot be ignored */ + notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV); + + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 8; + + /* This is always a kernel trap and never fixable (and thus must + never return). */ + for (;;) + die(str, regs, error_code); +} asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, long error_code) { + struct task_struct *tsk = current; + conditional_sti(regs); - if (user_mode(regs)) { - struct task_struct *tsk = current; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 13; + if (user_mode(regs)) { if (exception_trace && unhandled_signal(tsk, SIGSEGV)) printk(KERN_INFO "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", tsk->comm, tsk->pid, regs->rip,regs->rsp,error_code); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = 13; force_sig(SIGSEGV, tsk); return; } @@ -573,7 +618,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs) reason = get_nmi_reason(); if (!(reason & 0xc0)) { - if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) + if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT) == NOTIFY_STOP) return; #ifdef CONFIG_X86_LOCAL_APIC @@ -589,7 +634,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs) unknown_nmi_error(reason, regs); return; } - if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) + if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) return; /* AK: following checks seem to be broken on modern chipsets. FIXME */ @@ -600,6 +645,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs) io_check_error(reason, regs); } +/* runs on IST stack. */ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { @@ -620,7 +666,7 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs) ; /* Exception from user space */ else if (user_mode(eregs)) - regs = ((struct pt_regs *)current->thread.rsp0) - 1; + regs = task_pt_regs(current); /* Exception from kernel and interrupts are enabled. Move to kernel process stack. */ else if (eregs->eflags & X86_EFLAGS_IF) @@ -684,11 +730,9 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; - if (!user_mode(regs)) - goto clear_dr7; + info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL; + force_sig_info(SIGTRAP, &info, tsk); - info.si_addr = (void __user *)regs->rip; - force_sig_info(SIGTRAP, &info, tsk); clear_dr7: set_debugreg(0UL, 7); return; @@ -698,7 +742,7 @@ clear_TF_reenable: regs->eflags &= ~TF_MASK; } -static int kernel_math_error(struct pt_regs *regs, char *str) +static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->rip); @@ -706,8 +750,9 @@ static int kernel_math_error(struct pt_regs *regs, char *str) regs->rip = fixup->fixup; return 1; } - notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE); + notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE); /* Illegal floating point operation in the kernel */ + current->thread.trap_no = trapnr; die(str, regs, 0); return 0; } @@ -726,7 +771,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs) conditional_sti(regs); if (!user_mode(regs) && - kernel_math_error(regs, "kernel x87 math error")) + kernel_math_error(regs, "kernel x87 math error", 16)) return; /* @@ -795,7 +840,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) conditional_sti(regs); if (!user_mode(regs) && - kernel_math_error(regs, "kernel simd math error")) + kernel_math_error(regs, "kernel simd math error", 19)) return; /* @@ -867,12 +912,7 @@ asmlinkage void math_state_restore(void) if (!used_math()) init_fpu(me); restore_fpu_checking(&me->thread.i387.fxsave); - me->thread_info->status |= TS_USEDFPU; -} - -void do_call_debug(struct pt_regs *regs) -{ - notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); + task_thread_info(me)->status |= TS_USEDFPU; } void __init trap_init(void) @@ -880,9 +920,9 @@ void __init trap_init(void) set_intr_gate(0,÷_error); set_intr_gate_ist(1,&debug,DEBUG_STACK); set_intr_gate_ist(2,&nmi,NMI_STACK); - set_system_gate(3,&int3); - set_system_gate(4,&overflow); /* int4-5 can be called from all */ - set_system_gate(5,&bounds); + set_system_gate_ist(3,&int3,DEBUG_STACK); /* int3 can be called from all */ + set_system_gate(4,&overflow); /* int4 can be called from all */ + set_intr_gate(5,&bounds); set_intr_gate(6,&invalid_op); set_intr_gate(7,&device_not_available); set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK); @@ -904,8 +944,6 @@ void __init trap_init(void) set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall); #endif - set_intr_gate(KDB_VECTOR, call_debug); - /* * Should be a barrier for any external CPU state. */ diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 58b19215b4b..b0eed1faf74 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -8,6 +8,8 @@ #include <asm/page.h> #include <linux/config.h> +#undef i386 /* in case the preprocessor is a 32bit one */ + OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(phys_startup_64) @@ -189,7 +191,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { *(.exitcall.exit) -#ifndef CONFIG_DEBUG_INFO +#ifndef CONFIG_UNWIND_INFO *(.eh_frame) #endif } diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c new file mode 100644 index 00000000000..92f70c74965 --- /dev/null +++ b/arch/x86_64/kernel/vsmp.c @@ -0,0 +1,45 @@ +/* + * vSMPowered(tm) systems specific initialization + * Copyright (C) 2005 ScaleMP Inc. + * + * Use of this code is subject to the terms and conditions of the + * GNU general public license version 2. See "COPYING" or + * http://www.gnu.org/licenses/gpl.html + * + * Ravikiran Thirumalai <kiran@scalemp.com>, + * Shai Fultheim <shai@scalemp.com> + */ + +#include <linux/init.h> +#include <linux/pci_ids.h> +#include <linux/pci_regs.h> +#include <asm/pci-direct.h> + +static int __init vsmp_init(void) +{ + void *address; + unsigned int cap, ctl; + + /* Check if we are running on a ScaleMP vSMP box */ + if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) || + (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL)) + return 0; + + /* set vSMP magic bits to indicate vSMP capable kernel */ + address = ioremap(read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0), 8); + cap = readl(address); + ctl = readl(address + 4); + printk("vSMP CTL: capabilities:0x%08x control:0x%08x\n", cap, ctl); + if (cap & ctl & (1 << 4)) { + /* Turn on vSMP IRQ fastpath handling (see system.h) */ + ctl &= ~(1 << 4); + writel(ctl, address + 4); + ctl = readl(address + 4); + printk("vSMP CTL: control set to:0x%08x\n", ctl); + } + + iounmap(address); + return 0; +} + +core_initcall(vsmp_init); diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index 70a0bd16085..9468fb20b0b 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -35,14 +35,13 @@ #include <asm/io.h> #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) -#define force_inline __attribute__((always_inline)) inline int __sysctl_vsyscall __section_sysctl_vsyscall = 1; seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED; #include <asm/unistd.h> -static force_inline void timeval_normalize(struct timeval * tv) +static __always_inline void timeval_normalize(struct timeval * tv) { time_t __sec; @@ -53,7 +52,7 @@ static force_inline void timeval_normalize(struct timeval * tv) } } -static force_inline void do_vgettimeofday(struct timeval * tv) +static __always_inline void do_vgettimeofday(struct timeval * tv) { long sequence, t; unsigned long sec, usec; @@ -66,8 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv) (__jiffies - __wall_jiffies) * (1000000 / HZ); if (__vxtime.mode != VXTIME_HPET) { - sync_core(); - rdtscll(t); + t = get_cycles_sync(); if (t < __vxtime.last_tsc) t = __vxtime.last_tsc; usec += ((t - __vxtime.last_tsc) * @@ -84,12 +82,12 @@ static force_inline void do_vgettimeofday(struct timeval * tv) } /* RED-PEN may want to readd seq locking, but then the variable should be write-once. */ -static force_inline void do_get_tz(struct timezone * tz) +static __always_inline void do_get_tz(struct timezone * tz) { *tz = __sys_tz; } -static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz) +static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz) { int ret; asm volatile("vsysc2: syscall" @@ -98,7 +96,7 @@ static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz) return ret; } -static force_inline long time_syscall(long *t) +static __always_inline long time_syscall(long *t) { long secs; asm volatile("vsysc1: syscall" diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 4a54221e10b..b614d54d2ae 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -13,7 +13,6 @@ #include <linux/string.h> #include <linux/syscalls.h> #include <linux/tty.h> -#include <linux/ioctl32.h> #include <asm/semaphore.h> #include <asm/processor.h> @@ -45,22 +44,15 @@ extern struct drive_info_struct drive_info; EXPORT_SYMBOL(drive_info); #endif -extern unsigned long get_cmos_time(void); - /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); //EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(ioremap_nocache); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); -EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); @@ -84,9 +76,6 @@ EXPORT_SYMBOL(__put_user_2); EXPORT_SYMBOL(__put_user_4); EXPORT_SYMBOL(__put_user_8); -EXPORT_SYMBOL(strpbrk); -EXPORT_SYMBOL(strstr); - EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(clear_user); @@ -98,25 +87,18 @@ EXPORT_SYMBOL(copy_in_user); EXPORT_SYMBOL(strnlen_user); #ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); -#endif - -#ifdef CONFIG_PCI EXPORT_SYMBOL(pci_mem_start); #endif EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(cpu_pda); +EXPORT_SYMBOL(_cpu_pda); #ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_data); -EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(__write_lock_failed); EXPORT_SYMBOL(__read_lock_failed); -EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(cpu_callout_map); #endif @@ -137,30 +119,17 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback); #undef memcpy #undef memset #undef memmove -#undef memchr #undef strlen -#undef strncmp -#undef strncpy -#undef strchr extern void * memset(void *,int,__kernel_size_t); extern size_t strlen(const char *); extern void * memmove(void * dest,const void *src,size_t count); -extern void *memchr(const void *s, int c, size_t n); extern void * memcpy(void *,const void *,__kernel_size_t); extern void * __memcpy(void *,const void *,__kernel_size_t); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(memchr); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__memcpy); diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S index dfa358b05c8..79422b6559c 100644 --- a/arch/x86_64/lib/copy_user.S +++ b/arch/x86_64/lib/copy_user.S @@ -4,12 +4,9 @@ * Functions to copy from and to user space. */ -#define FIX_ALIGNMENT 1 - #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> - #include <asm/cpufeature.h> /* Standard copy_to_user with segment limit checking */ .globl copy_to_user @@ -21,23 +18,7 @@ copy_to_user: jc bad_to_user cmpq threadinfo_addr_limit(%rax),%rcx jae bad_to_user -2: - .byte 0xe9 /* 32bit jump */ - .long .Lcug-1f -1: - - .section .altinstr_replacement,"ax" -3: .byte 0xe9 /* replacement jmp with 8 bit immediate */ - .long copy_user_generic_c-1b /* offset */ - .previous - .section .altinstructions,"a" - .align 8 - .quad 2b - .quad 3b - .byte X86_FEATURE_K8_C - .byte 5 - .byte 5 - .previous + jmp copy_user_generic /* Standard copy_from_user with segment limit checking */ .globl copy_from_user @@ -72,223 +53,44 @@ bad_to_user: * rsi source * rdx count * + * Only 4GB of copy is supported. This shouldn't be a problem + * because the kernel normally only writes from/to page sized chunks + * even if user space passed a longer buffer. + * And more would be dangerous because both Intel and AMD have + * errata with rep movsq > 4GB. If someone feels the need to fix + * this please consider this. + * * Output: * eax uncopied bytes or 0 if successful. */ - .globl copy_user_generic - .p2align 4 -copy_user_generic: - .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */ - .byte 0x66,0x90 -1: - .section .altinstr_replacement,"ax" -2: .byte 0xe9 /* near jump with 32bit immediate */ - .long copy_user_generic_c-1b /* offset */ - .previous - .section .altinstructions,"a" - .align 8 - .quad copy_user_generic - .quad 2b - .byte X86_FEATURE_K8_C - .byte 5 - .byte 5 - .previous -.Lcug: - pushq %rbx - xorl %eax,%eax /*zero for the exception handler */ - -#ifdef FIX_ALIGNMENT - /* check for bad alignment of destination */ - movl %edi,%ecx - andl $7,%ecx - jnz .Lbad_alignment -.Lafter_bad_alignment: -#endif - movq %rdx,%rcx - - movl $64,%ebx - shrq $6,%rdx - decq %rdx - js .Lhandle_tail - - .p2align 4 -.Lloop: -.Ls1: movq (%rsi),%r11 -.Ls2: movq 1*8(%rsi),%r8 -.Ls3: movq 2*8(%rsi),%r9 -.Ls4: movq 3*8(%rsi),%r10 -.Ld1: movq %r11,(%rdi) -.Ld2: movq %r8,1*8(%rdi) -.Ld3: movq %r9,2*8(%rdi) -.Ld4: movq %r10,3*8(%rdi) - -.Ls5: movq 4*8(%rsi),%r11 -.Ls6: movq 5*8(%rsi),%r8 -.Ls7: movq 6*8(%rsi),%r9 -.Ls8: movq 7*8(%rsi),%r10 -.Ld5: movq %r11,4*8(%rdi) -.Ld6: movq %r8,5*8(%rdi) -.Ld7: movq %r9,6*8(%rdi) -.Ld8: movq %r10,7*8(%rdi) - - decq %rdx - - leaq 64(%rsi),%rsi - leaq 64(%rdi),%rdi - - jns .Lloop - - .p2align 4 -.Lhandle_tail: - movl %ecx,%edx - andl $63,%ecx - shrl $3,%ecx - jz .Lhandle_7 - movl $8,%ebx - .p2align 4 -.Lloop_8: -.Ls9: movq (%rsi),%r8 -.Ld9: movq %r8,(%rdi) - decl %ecx - leaq 8(%rdi),%rdi - leaq 8(%rsi),%rsi - jnz .Lloop_8 - -.Lhandle_7: - movl %edx,%ecx - andl $7,%ecx - jz .Lende - .p2align 4 -.Lloop_1: -.Ls10: movb (%rsi),%bl -.Ld10: movb %bl,(%rdi) - incq %rdi - incq %rsi - decl %ecx - jnz .Lloop_1 - -.Lende: - popq %rbx - ret - -#ifdef FIX_ALIGNMENT - /* align destination */ - .p2align 4 -.Lbad_alignment: - movl $8,%r9d - subl %ecx,%r9d - movl %r9d,%ecx - cmpq %r9,%rdx - jz .Lhandle_7 - js .Lhandle_7 -.Lalign_1: -.Ls11: movb (%rsi),%bl -.Ld11: movb %bl,(%rdi) - incq %rsi - incq %rdi - decl %ecx - jnz .Lalign_1 - subq %r9,%rdx - jmp .Lafter_bad_alignment -#endif - - /* table sorted by exception address */ - .section __ex_table,"a" - .align 8 - .quad .Ls1,.Ls1e - .quad .Ls2,.Ls2e - .quad .Ls3,.Ls3e - .quad .Ls4,.Ls4e - .quad .Ld1,.Ls1e - .quad .Ld2,.Ls2e - .quad .Ld3,.Ls3e - .quad .Ld4,.Ls4e - .quad .Ls5,.Ls5e - .quad .Ls6,.Ls6e - .quad .Ls7,.Ls7e - .quad .Ls8,.Ls8e - .quad .Ld5,.Ls5e - .quad .Ld6,.Ls6e - .quad .Ld7,.Ls7e - .quad .Ld8,.Ls8e - .quad .Ls9,.Le_quad - .quad .Ld9,.Le_quad - .quad .Ls10,.Le_byte - .quad .Ld10,.Le_byte -#ifdef FIX_ALIGNMENT - .quad .Ls11,.Lzero_rest - .quad .Ld11,.Lzero_rest -#endif - .quad .Le5,.Le_zero - .previous - - /* compute 64-offset for main loop. 8 bytes accuracy with error on the - pessimistic side. this is gross. it would be better to fix the - interface. */ - /* eax: zero, ebx: 64 */ -.Ls1e: addl $8,%eax -.Ls2e: addl $8,%eax -.Ls3e: addl $8,%eax -.Ls4e: addl $8,%eax -.Ls5e: addl $8,%eax -.Ls6e: addl $8,%eax -.Ls7e: addl $8,%eax -.Ls8e: addl $8,%eax - addq %rbx,%rdi /* +64 */ - subq %rax,%rdi /* correct destination with computed offset */ - - shlq $6,%rdx /* loop counter * 64 (stride length) */ - addq %rax,%rdx /* add offset to loopcnt */ - andl $63,%ecx /* remaining bytes */ - addq %rcx,%rdx /* add them */ - jmp .Lzero_rest - - /* exception on quad word loop in tail handling */ - /* ecx: loopcnt/8, %edx: length, rdi: correct */ -.Le_quad: - shll $3,%ecx - andl $7,%edx - addl %ecx,%edx - /* edx: bytes to zero, rdi: dest, eax:zero */ -.Lzero_rest: - movq %rdx,%rcx -.Le_byte: - xorl %eax,%eax -.Le5: rep - stosb - /* when there is another exception while zeroing the rest just return */ -.Le_zero: - movq %rdx,%rax - jmp .Lende - - /* C stepping K8 run faster using the string copy instructions. - This is also a lot simpler. Use them when possible. - Patch in jmps to this code instead of copying it fully - to avoid unwanted aliasing in the exception tables. */ - - /* rdi destination - * rsi source - * rdx count - * - * Output: - * eax uncopied bytes or 0 if successfull. - */ -copy_user_generic_c: + .globl copy_user_generic +copy_user_generic: movl %edx,%ecx shrl $3,%ecx andl $7,%edx + jz 5f 1: rep movsq movl %edx,%ecx + xor %eax,%eax 2: rep movsb -4: movl %ecx,%eax ret + /* align here? */ +5: xorl %eax,%eax +6: rep movsq + ret + + .section .fixup,"ax" 3: lea (%rdx,%rcx,8),%rax ret - +4: movl %ecx,%eax + ret + .previous + .section __ex_table,"a" .quad 1b,3b .quad 2b,4b + .quad 6b,4b .previous diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c index 841bd738a18..03c460cbdd1 100644 --- a/arch/x86_64/lib/delay.c +++ b/arch/x86_64/lib/delay.c @@ -39,7 +39,7 @@ void __delay(unsigned long loops) inline void __const_udelay(unsigned long xloops) { - __delay(((xloops * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) * HZ); + __delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32); } void __udelay(unsigned long usecs) diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c index db8abba1ad8..9bc2c295818 100644 --- a/arch/x86_64/lib/usercopy.c +++ b/arch/x86_64/lib/usercopy.c @@ -109,14 +109,11 @@ unsigned long clear_user(void __user *to, unsigned long n) * Return 0 on exception, a value greater than N if too long */ -long strnlen_user(const char __user *s, long n) +long __strnlen_user(const char __user *s, long n) { long res = 0; char c; - if (!access_ok(VERIFY_READ, s, n)) - return 0; - while (1) { if (res>n) return n+1; @@ -129,6 +126,13 @@ long strnlen_user(const char __user *s, long n) } } +long strnlen_user(const char __user *s, long n) +{ + if (!access_ok(VERIFY_READ, s, n)) + return 0; + return __strnlen_user(s, n); +} + long strlen_user(const char __user *s) { long res = 0; diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 3a63707a698..26eac194064 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -35,6 +35,13 @@ #include <asm-generic/sections.h> #include <asm/kdebug.h> +/* Page fault error code bits */ +#define PF_PROT (1<<0) /* or no page found */ +#define PF_WRITE (1<<1) +#define PF_USER (1<<2) +#define PF_RSVD (1<<3) +#define PF_INSTR (1<<4) + void bust_spinlocks(int yes) { int loglevel_save = console_loglevel; @@ -68,7 +75,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, unsigned char *max_instr; /* If it was a exec fault ignore */ - if (error_code & (1<<4)) + if (error_code & PF_INSTR) return 0; instr = (unsigned char *)convert_rip_to_linear(current, regs); @@ -222,17 +229,22 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, unsigned long error_code) { unsigned long flags = oops_begin(); + struct task_struct *tsk; printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", current->comm, address); dump_pagetable(address); + tsk = current; + tsk->thread.cr2 = address; + tsk->thread.trap_no = 14; + tsk->thread.error_code = error_code; __die("Bad pagetable", regs, error_code); oops_end(flags); do_exit(SIGKILL); } /* - * Handle a fault on the vmalloc or module mapping area + * Handle a fault on the vmalloc area * * This assumes no large pages in there. */ @@ -278,7 +290,6 @@ static int vmalloc_fault(unsigned long address) that. */ if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref)) BUG(); - __flush_tlb_all(); return 0; } @@ -289,12 +300,6 @@ int exception_trace = 1; * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. - * - * error_code: - * bit 0 == 0 means no page found, 1 means protection fault - * bit 1 == 0 means read, 1 means write - * bit 2 == 0 means kernel, 1 means user-mode - * bit 3 == 1 means fault was an instruction fetch */ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) @@ -337,12 +342,16 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, * * This verifies that the fault happens in kernel space * (error_code & 4) == 0, and that the fault was not a - * protection error (error_code & 1) == 0. + * protection error (error_code & 9) == 0. */ if (unlikely(address >= TASK_SIZE64)) { - if (!(error_code & 5) && - ((address >= VMALLOC_START && address < VMALLOC_END) || - (address >= MODULES_VADDR && address < MODULES_END))) { + /* + * Don't check for the module range here: its PML4 + * is always initialized because it's shared with the main + * kernel text. Only vmalloc may need PML4 syncups. + */ + if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) && + ((address >= VMALLOC_START && address < VMALLOC_END))) { if (vmalloc_fault(address) < 0) goto bad_area_nosemaphore; return; @@ -354,7 +363,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area_nosemaphore; } - if (unlikely(error_code & (1 << 3))) + if (unlikely(error_code & PF_RSVD)) pgtable_bad(address, regs, error_code); /* @@ -381,7 +390,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, * thus avoiding the deadlock. */ if (!down_read_trylock(&mm->mmap_sem)) { - if ((error_code & 4) == 0 && + if ((error_code & PF_USER) == 0 && !search_exception_tables(regs->rip)) goto bad_area_nosemaphore; down_read(&mm->mmap_sem); @@ -408,17 +417,17 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, good_area: info.si_code = SEGV_ACCERR; write = 0; - switch (error_code & 3) { + switch (error_code & (PF_PROT|PF_WRITE)) { default: /* 3: write, present */ /* fall through */ - case 2: /* write, not present */ + case PF_WRITE: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; write++; break; - case 1: /* read, present */ + case PF_PROT: /* read, present */ goto bad_area; - case 0: /* read, not present */ + case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } @@ -453,7 +462,7 @@ bad_area: bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ - if (error_code & 4) { + if (error_code & PF_USER) { if (is_prefetch(regs, address, error_code)) return; @@ -521,6 +530,9 @@ no_context: printk_address(regs->rip); printk("\n"); dump_pagetable(address); + tsk->thread.cr2 = address; + tsk->thread.trap_no = 14; + tsk->thread.error_code = error_code; __die("Oops", regs, error_code); /* Executive summary in case the body of the oops scrolled away */ printk(KERN_EMERG "CR2: %016lx\n", address); @@ -546,7 +558,7 @@ do_sigbus: up_read(&mm->mmap_sem); /* Kernel mode? Handle exceptions or die */ - if (!(error_code & 4)) + if (!(error_code & PF_USER)) goto no_context; tsk->thread.cr2 = address; diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 1faae5fc1c0..eca60125efc 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -23,6 +23,7 @@ #include <linux/bootmem.h> #include <linux/proc_fs.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <asm/processor.h> #include <asm/system.h> @@ -38,11 +39,16 @@ #include <asm/proto.h> #include <asm/smp.h> #include <asm/sections.h> +#include <asm/dma-mapping.h> +#include <asm/swiotlb.h> #ifndef Dprintk #define Dprintk(x...) #endif +struct dma_mapping_ops* dma_ops; +EXPORT_SYMBOL(dma_ops); + static unsigned long dma_reserve __initdata; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -249,14 +255,26 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon static void __init find_early_table_space(unsigned long end) { - unsigned long puds, pmds, tables; + unsigned long puds, pmds, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + round_up(pmds * sizeof(pmd_t), PAGE_SIZE); - table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables); + /* Put page tables beyond the DMA zones if possible. + RED-PEN might be better to spread them out more over + memory to avoid hotspots */ + if (end > MAX_DMA32_PFN<<PAGE_SHIFT) + start = MAX_DMA32_PFN << PAGE_SHIFT; + else if (end > MAX_DMA_PFN << PAGE_SHIFT) + start = MAX_DMA_PFN << PAGE_SHIFT; + else + start = 0x8000; + + table_start = find_e820_area(start, end, tables); + if (table_start == -1) + table_start = find_e820_area(0x8000, end, tables); if (table_start == -1UL) panic("Cannot find space for the kernel page tables"); @@ -423,12 +441,9 @@ void __init mem_init(void) long codesize, reservedpages, datasize, initsize; #ifdef CONFIG_SWIOTLB - if (!iommu_aperture && - (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu)) - swiotlb = 1; - if (swiotlb) - swiotlb_init(); + pci_swiotlb_init(); #endif + no_iommu_init(); /* How many end-of-memory variables you have, grandma! */ max_low_pfn = end_pfn; diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 15b67d2760c..6ef9f9a7623 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -46,8 +46,8 @@ int numa_off __initdata; * 0 if memnodmap[] too small (of shift too small) * -1 if node overlap or lost ram (shift too big) */ -static int __init populate_memnodemap( - const struct node *nodes, int numnodes, int shift) +static int __init +populate_memnodemap(const struct node *nodes, int numnodes, int shift) { int i; int res = -1; @@ -81,7 +81,7 @@ int __init compute_hash_shift(struct node *nodes, int numnodes) while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0) shift++; - printk(KERN_DEBUG "Using %d for the hash shift.\n", + printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n", shift); if (populate_memnodemap(nodes, numnodes, shift) != 1) { @@ -110,7 +110,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en start = round_up(start, ZONE_ALIGN); - printk("Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end); + printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end); start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; @@ -156,7 +156,7 @@ void __init setup_node_zones(int nodeid) start_pfn = node_start_pfn(nodeid); end_pfn = node_end_pfn(nodeid); - Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", + Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); size_zones(zones, holes, start_pfn, end_pfn); @@ -200,7 +200,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) while ((x << 1) < sz) x <<= 1; if (x < sz/2) - printk("Numa emulation unbalanced. Complain to maintainer\n"); + printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n"); sz = x; } @@ -272,7 +272,7 @@ __cpuinit void numa_add_cpu(int cpu) void __cpuinit numa_set_node(int cpu, int node) { - cpu_pda[cpu].nodenumber = node; + cpu_pda(cpu)->nodenumber = node; cpu_to_node[cpu] = node; } @@ -330,8 +330,69 @@ __init int numa_setup(char *opt) return 1; } +/* + * Setup early cpu_to_node. + * + * Populate cpu_to_node[] only if x86_cpu_to_apicid[], + * and apicid_to_node[] tables have valid entries for a CPU. + * This means we skip cpu_to_node[] initialisation for NUMA + * emulation and faking node case (when running a kernel compiled + * for NUMA on a non NUMA box), which is OK as cpu_to_node[] + * is already initialized in a round robin manner at numa_init_array, + * prior to this call, and this initialization is good enough + * for the fake NUMA cases. + */ +void __init init_cpu_to_node(void) +{ + int i; + for (i = 0; i < NR_CPUS; i++) { + u8 apicid = x86_cpu_to_apicid[i]; + if (apicid == BAD_APICID) + continue; + if (apicid_to_node[apicid] == NUMA_NO_NODE) + continue; + cpu_to_node[i] = apicid_to_node[apicid]; + } +} + EXPORT_SYMBOL(cpu_to_node); EXPORT_SYMBOL(node_to_cpumask); EXPORT_SYMBOL(memnode_shift); EXPORT_SYMBOL(memnodemap); EXPORT_SYMBOL(node_data); + +#ifdef CONFIG_DISCONTIGMEM +/* + * Functions to convert PFNs from/to per node page addresses. + * These are out of line because they are quite big. + * They could be all tuned by pre caching more state. + * Should do that. + */ + +/* Requires pfn_valid(pfn) to be true */ +struct page *pfn_to_page(unsigned long pfn) +{ + int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); + return (pfn - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; +} +EXPORT_SYMBOL(pfn_to_page); + +unsigned long page_to_pfn(struct page *page) +{ + return (long)(((page) - page_zone(page)->zone_mem_map) + + page_zone(page)->zone_start_pfn); +} +EXPORT_SYMBOL(page_to_pfn); + +int pfn_valid(unsigned long pfn) +{ + unsigned nid; + if (pfn >= num_physpages) + return 0; + nid = pfn_to_nid(pfn); + if (nid == 0xff) + return 0; + return pfn >= node_start_pfn(nid) && (pfn) < node_end_pfn(nid); +} +EXPORT_SYMBOL(pfn_valid); +#endif diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 33340bd1e32..8b7f85608fa 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -17,21 +17,23 @@ #include <linux/topology.h> #include <asm/proto.h> #include <asm/numa.h> +#include <asm/e820.h> static struct acpi_table_slit *acpi_slit; static nodemask_t nodes_parsed __initdata; static nodemask_t nodes_found __initdata; static struct node nodes[MAX_NUMNODES] __initdata; -static __u8 pxm2node[256] = { [0 ... 255] = 0xff }; +static u8 pxm2node[256] = { [0 ... 255] = 0xff }; static int node_to_pxm(int n); int pxm_to_node(int pxm) { if ((unsigned)pxm >= 256) - return 0; - return pxm2node[pxm]; + return -1; + /* Extend 0xff to (int)-1 */ + return (signed char)pxm2node[pxm]; } static __init int setup_node(int pxm) @@ -91,9 +93,36 @@ static __init inline int srat_disabled(void) return numa_off || acpi_numa < 0; } +/* + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes + * up the NUMA heuristics which wants the local node to have a smaller + * distance than the others. + * Do some quick checks here and only use the SLIT if it passes. + */ +static __init int slit_valid(struct acpi_table_slit *slit) +{ + int i, j; + int d = slit->localities; + for (i = 0; i < d; i++) { + for (j = 0; j < d; j++) { + u8 val = slit->entry[d*i + j]; + if (i == j) { + if (val != 10) + return 0; + } else if (val <= 10) + return 0; + } + } + return 1; +} + /* Callback for SLIT parsing */ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) { + if (!slit_valid(slit)) { + printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); + return; + } acpi_slit = slit; } @@ -168,12 +197,39 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) nd->start, nd->end); } +/* Sanity check to catch more bad SRATs (they are amazingly common). + Make sure the PXMs cover all memory. */ +static int nodes_cover_memory(void) +{ + int i; + unsigned long pxmram, e820ram; + + pxmram = 0; + for_each_node_mask(i, nodes_parsed) { + unsigned long s = nodes[i].start >> PAGE_SHIFT; + unsigned long e = nodes[i].end >> PAGE_SHIFT; + pxmram += e - s; + pxmram -= e820_hole_size(s, e); + } + + e820ram = end_pfn - e820_hole_size(0, end_pfn); + if (pxmram < e820ram) { + printk(KERN_ERR + "SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n", + (pxmram << PAGE_SHIFT) >> 20, + (e820ram << PAGE_SHIFT) >> 20); + return 0; + } + return 1; +} + void __init acpi_numa_arch_fixup(void) {} /* Use the information discovered above to actually set up the nodes. */ int __init acpi_scan_nodes(unsigned long start, unsigned long end) { int i; + if (acpi_numa <= 0) return -1; @@ -184,6 +240,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) node_clear(i, nodes_parsed); } + if (!nodes_cover_memory()) { + bad_srat(); + return -1; + } + memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed)); if (memnode_shift < 0) { printk(KERN_ERR diff --git a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS deleted file mode 100644 index 4f0c05abd40..00000000000 --- a/arch/x86_64/pci/Makefile-BUS +++ /dev/null @@ -1,22 +0,0 @@ -# -# Makefile for X86_64 specific PCI routines -# -# Reuse the i386 PCI subsystem -# -CFLAGS += -I arch/i386/pci - -obj-y := i386.o -obj-$(CONFIG_PCI_DIRECT)+= direct.o -obj-y += fixup.o -obj-$(CONFIG_ACPI) += acpi.o -obj-y += legacy.o irq.o common.o -# mmconfig has a 64bit special -obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o - -direct-y += ../../i386/pci/direct.o -acpi-y += ../../i386/pci/acpi.o -legacy-y += ../../i386/pci/legacy.o -irq-y += ../../i386/pci/irq.o -common-y += ../../i386/pci/common.o -fixup-y += ../../i386/pci/fixup.o -i386-y += ../../i386/pci/i386.o diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 7e841aa2a4a..7ee4a14ec3b 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -18,10 +18,6 @@ config XTENSA with reasonable minimum requirements. The Xtensa Linux project has a home page at <http://xtensa.sourceforge.net/>. -config UID16 - bool - default n - config RWSEM_XCHGADD_ALGORITHM bool default y diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a44b54ae81..f1f596644bf 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -145,7 +145,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, int user_mode = user_mode(regs); /* Set up new TSS. */ - tos = (unsigned long)p->thread_info + THREAD_SIZE; + tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; if (user_mode) childregs = (struct pt_regs*)(tos - PT_USER_SIZE); else @@ -217,7 +217,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) unsigned long get_wchan(struct task_struct *p) { unsigned long sp, pc; - unsigned long stack_page = (unsigned long) p->thread_info; + unsigned long stack_page = (unsigned long) task_stack_page(p); int count = 0; if (!p || p == current || p->state == TASK_RUNNING) diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index ab5c4c65b5c..4cc85285a70 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -72,7 +72,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct pt_regs *regs; unsigned long tmp; - regs = xtensa_pt_regs(child); + regs = task_pt_regs(child); tmp = 0; /* Default return value. */ switch(addr) { @@ -149,7 +149,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEUSR: { struct pt_regs *regs; - regs = xtensa_pt_regs(child); + regs = task_pt_regs(child); switch (addr) { case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: @@ -240,7 +240,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * elf_gregset_t format. */ xtensa_gregset_t format; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); do_copy_regs (&format, regs, child); @@ -257,7 +257,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * values in the elf_gregset_t format. */ xtensa_gregset_t format; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){ ret = -EFAULT; @@ -281,7 +281,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * elf_fpregset_t format. */ elf_fpregset_t fpregs; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); do_save_fpregs (&fpregs, regs, child); @@ -299,7 +299,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * values in the elf_fpregset_t format. */ elf_fpregset_t fpregs; - struct pt_regs *regs = xtensa_pt_regs(child); + struct pt_regs *regs = task_pt_regs(child); ret = 0; if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) { |