diff options
Diffstat (limited to 'arch/sparc')
44 files changed, 251 insertions, 174 deletions
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index e0cabe7..77f906d 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -330,9 +330,9 @@ BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *) #define FAULT_CODE_WRITE 0x2 #define FAULT_CODE_USER 0x4 -BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t) +BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t *) -#define update_mmu_cache(vma,addr,pte) BTFIXUP_CALL(update_mmu_cache)(vma,addr,pte) +#define update_mmu_cache(vma,addr,ptep) BTFIXUP_CALL(update_mmu_cache)(vma,addr,ptep) BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long, unsigned long, unsigned int) diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index f3cb790..f5b5fa7 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -706,7 +706,7 @@ extern unsigned long find_ecache_flush_span(unsigned long size); #define mmu_unlockarea(vaddr, len) do { } while(0) struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) diff --git a/arch/sparc/include/asm/scatterlist.h b/arch/sparc/include/asm/scatterlist.h index e580f55..d112025 100644 --- a/arch/sparc/include/asm/scatterlist.h +++ b/arch/sparc/include/asm/scatterlist.h @@ -1,27 +1,8 @@ #ifndef _SPARC_SCATTERLIST_H #define _SPARC_SCATTERLIST_H -#include <asm/page.h> -#include <asm/types.h> - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - unsigned int offset; - - unsigned int length; - - dma_addr_t dma_address; - __u32 dma_length; -}; - -#define sg_dma_address(sg) ((sg)->dma_address) #define sg_dma_len(sg) ((sg)->dma_length) -#define ISA_DMA_THRESHOLD (~0UL) - -#define ARCH_HAS_SG_CHAIN +#include <asm-generic/scatterlist.h> #endif /* !(_SPARC_SCATTERLIST_H) */ diff --git a/arch/sparc/include/asm/stat.h b/arch/sparc/include/asm/stat.h index 55db5ec..39327d6 100644 --- a/arch/sparc/include/asm/stat.h +++ b/arch/sparc/include/asm/stat.h @@ -53,8 +53,8 @@ struct stat { ino_t st_ino; mode_t st_mode; short st_nlink; - uid_t st_uid; - gid_t st_gid; + uid16_t st_uid; + gid16_t st_gid; unsigned short st_rdev; off_t st_size; time_t st_atime; diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h index 7486c60..025a02a 100644 --- a/arch/sparc/include/asm/syscall.h +++ b/arch/sparc/include/asm/syscall.h @@ -5,6 +5,13 @@ #include <linux/sched.h> #include <asm/ptrace.h> +/* + * The syscall table always contains 32 bit pointers since we know that the + * address of the function to be called is (way) below 4GB. So the "int" + * type here is what we want [need] for both 32 bit and 64 bit systems. + */ +extern const unsigned int sys_call_table[]; + /* The system call number is given by the user in %g1 */ static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b171ae8..62dc7a0 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -59,7 +59,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, cur_inst = 0; for_each_node_by_type(dp, "cpu") { - int err = check_cpu_node(dp->node, &cur_inst, + int err = check_cpu_node(dp->phandle, &cur_inst, compare, compare_arg, prom_node, mid); if (!err) { @@ -143,6 +143,4 @@ void __init device_scan(void) if (ARCH_SUN4C) sun4c_probe_memerr_reg(); - - return; } diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index 29973da..9103a56 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c @@ -91,14 +91,3 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } #endif - -#ifdef CONFIG_FTRACE_SYSCALLS - -extern unsigned int sys_call_table[]; - -unsigned long __init arch_syscall_addr(int nr) -{ - return (unsigned long)sys_call_table[nr]; -} - -#endif diff --git a/arch/sparc/kernel/kstack.h b/arch/sparc/kernel/kstack.h index 4248d96..5247283 100644 --- a/arch/sparc/kernel/kstack.h +++ b/arch/sparc/kernel/kstack.h @@ -11,6 +11,10 @@ static inline bool kstack_valid(struct thread_info *tp, unsigned long sp) { unsigned long base = (unsigned long) tp; + /* Stack pointer must be 16-byte aligned. */ + if (sp & (16UL - 1)) + return false; + if (sp >= (base + sizeof(struct thread_info)) && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 87f1760..0409d62 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -124,7 +124,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & (1<<LEON3_GPTIMER_SEPIRQ))) { - prom_printf("irq timer not configured with seperate irqs \n"); + prom_printf("irq timer not configured with separate irqs\n"); BUG(); } diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 05c0dad..8578757 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -177,7 +177,7 @@ void __init leon_boot_cpus(void) int nrcpu = leon_smp_nrcpus(); int me = smp_processor_id(); - printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x \n", (unsigned int)me, + printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsigned int)me, (unsigned int)nrcpu, (unsigned int)NR_CPUS, (unsigned int)&(leon3_irqctrl_regs->mpstatus)); @@ -226,7 +226,7 @@ int __cpuinit leon_boot_one_cpu(int i) break; udelay(200); } - printk(KERN_INFO "Started CPU %d \n", (unsigned int)i); + printk(KERN_INFO "Started CPU %d\n", (unsigned int)i); if (!(cpu_callin_map[i])) { printk(KERN_ERR "Processor %d is stuck.\n", i); diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index 4c26eb5..da527b3 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c @@ -105,7 +105,7 @@ static unsigned long of_bus_sbus_get_flags(const u32 *addr, unsigned long flags) static int of_bus_ambapp_match(struct device_node *np) { - return !strcmp(np->name, "ambapp"); + return !strcmp(np->type, "ambapp"); } static void of_bus_ambapp_count_cells(struct device_node *child, @@ -433,7 +433,7 @@ build_resources: if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->node); + dev_set_name(&op->dev, "%08x", dp->phandle); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 0a6f2d1..b3d4cb5 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -676,7 +676,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->node); + dev_set_name(&op->dev, "%08x", dp->phandle); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 539e83f..5ac539a 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -247,6 +247,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct pci_bus *bus, int devfn) { struct dev_archdata *sd; + struct pci_slot *slot; struct of_device *op; struct pci_dev *dev; const char *type; @@ -286,6 +287,11 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->dev.bus = &pci_bus_type; dev->devfn = devfn; dev->multifunction = 0; /* maybe a lie? */ + set_pcie_port_type(dev); + + list_for_each_entry(slot, &dev->bus->slots, list) + if (PCI_SLOT(dev->devfn) == slot->number) + dev->slot = slot; dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); dev->device = of_getintprop_default(node, "device-id", 0xffff); @@ -322,6 +328,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->current_state = 4; /* unknown power state */ dev->error_state = pci_channel_io_normal; + dev->dma_mask = 0xffffffff; if (!strcmp(node->name, "pci")) { /* a PCI-PCI bridge */ @@ -715,9 +722,10 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) { } -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) +resource_size_t pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) { + return res->start; } int pcibios_enable_device(struct pci_dev *dev, int mask) @@ -1087,3 +1095,78 @@ static int __init pcibios_init(void) return 0; } subsys_initcall(pcibios_init); + +#ifdef CONFIG_SYSFS +static void __devinit pci_bus_slot_names(struct device_node *node, + struct pci_bus *bus) +{ + const struct pci_slot_names { + u32 slot_mask; + char names[0]; + } *prop; + const char *sp; + int len, i; + u32 mask; + + prop = of_get_property(node, "slot-names", &len); + if (!prop) + return; + + mask = prop->slot_mask; + sp = prop->names; + + if (ofpci_verbose) + printk("PCI: Making slots for [%s] mask[0x%02x]\n", + node->full_name, mask); + + i = 0; + while (mask) { + struct pci_slot *pci_slot; + u32 this_bit = 1 << i; + + if (!(mask & this_bit)) { + i++; + continue; + } + + if (ofpci_verbose) + printk("PCI: Making slot [%s]\n", sp); + + pci_slot = pci_create_slot(bus, i, sp, NULL); + if (IS_ERR(pci_slot)) + printk(KERN_ERR "PCI: pci_create_slot returned %ld\n", + PTR_ERR(pci_slot)); + + sp += strlen(sp) + 1; + mask &= ~this_bit; + i++; + } +} + +static int __init of_pci_slot_init(void) +{ + struct pci_bus *pbus = NULL; + + while ((pbus = pci_find_next_bus(pbus)) != NULL) { + struct device_node *node; + + if (pbus->self) { + struct dev_archdata *sd = pbus->self->sysdata; + + /* PCI->PCI bridge */ + node = sd->prom_node; + } else { + struct pci_pbm_info *pbm = pbus->sysdata; + + /* Host PCI controller */ + node = pbm->op->node; + } + + pci_bus_slot_names(node, pbus); + } + + return 0; +} + +module_init(of_pci_slot_init); +#endif diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 4e2724e..d36a8d3 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -585,8 +585,6 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); } } - - return; } /* @@ -768,9 +766,10 @@ char * __devinit pcibios_setup(char *str) return str; } -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) +resource_size_t pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) { + return res->start; } int pcibios_enable_device(struct pci_dev *pdev, int mask) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index e856456..9f2b2ba 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -980,10 +980,10 @@ static int collect_events(struct perf_event *group, int max_count, return n; } -static void event_sched_in(struct perf_event *event, int cpu) +static void event_sched_in(struct perf_event *event) { event->state = PERF_EVENT_STATE_ACTIVE; - event->oncpu = cpu; + event->oncpu = smp_processor_id(); event->tstamp_running += event->ctx->time - event->tstamp_stopped; if (is_software_event(event)) event->pmu->enable(event); @@ -991,7 +991,7 @@ static void event_sched_in(struct perf_event *event, int cpu) int hw_perf_group_sched_in(struct perf_event *group_leader, struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx, int cpu) + struct perf_event_context *ctx) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct perf_event *sub; @@ -1015,10 +1015,10 @@ int hw_perf_group_sched_in(struct perf_event *group_leader, cpuctx->active_oncpu += n; n = 1; - event_sched_in(group_leader, cpu); + event_sched_in(group_leader); list_for_each_entry(sub, &group_leader->sibling_list, group_entry) { if (sub->state != PERF_EVENT_STATE_OFF) { - event_sched_in(sub, cpu); + event_sched_in(sub); n++; } } diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 2830b41..c49865b 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -526,7 +526,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, * Set some valid stack frames to give to the child. */ childstack = (struct sparc_stackf __user *) - (sp & ~0x7UL); + (sp & ~0xfUL); parentstack = (struct sparc_stackf __user *) regs->u_regs[UREG_FP]; diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index c3f1cce..cb70476 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -398,11 +398,11 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) } else __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); - /* Now 8-byte align the stack as this is mandatory in the - * Sparc ABI due to how register windows work. This hides - * the restriction from thread libraries etc. -DaveM + /* Now align the stack as this is mandatory in the Sparc ABI + * due to how register windows work. This hides the + * restriction from thread libraries etc. */ - csp &= ~7UL; + csp &= ~15UL; distance = fp - psp; rval = (csp - distance); diff --git a/arch/sparc/kernel/prom.h b/arch/sparc/kernel/prom.h index 453397f..a8591ef 100644 --- a/arch/sparc/kernel/prom.h +++ b/arch/sparc/kernel/prom.h @@ -4,9 +4,6 @@ #include <linux/spinlock.h> #include <asm/prom.h> -extern struct device_node *allnodes; /* temporary while merging */ -extern rwlock_t devtree_lock; /* temporary while merging */ - extern void * prom_early_alloc(unsigned long size); extern void irq_trans_init(struct device_node *dp); diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index d80a65d..57ac9e2 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -37,18 +37,6 @@ EXPORT_SYMBOL(of_console_path); char *of_console_options; EXPORT_SYMBOL(of_console_options); -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - for (np = allnodes; np; np = np->allnext) - if (np->node == handle) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -89,7 +77,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; - ret = prom_setprop(dp->node, name, val, len); + ret = prom_setprop(dp->phandle, name, val, len); err = -EINVAL; if (ret >= 0) { @@ -236,7 +224,7 @@ static struct device_node * __init prom_create_node(phandle node, dp->name = get_one_property(node, "name"); dp->type = get_one_property(node, "device_type"); - dp->node = node; + dp->phandle = node; dp->properties = build_prop_list(node); @@ -313,7 +301,7 @@ void __init prom_build_devicetree(void) nextp = &allnodes->allnext; allnodes->child = prom_build_tree(allnodes, - prom_getchild(allnodes->node), + prom_getchild(allnodes->phandle), &nextp); of_console_init(); diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 9be2af5..b22ce61 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -95,8 +95,6 @@ static void prom_sync_me(void) "nop\n\t" "nop\n\t" : : "r" (prom_tbr)); local_irq_restore(flags); - - return; } static unsigned int boot_flags __initdata = 0; diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ba5b09a..ea22cd3 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -120,8 +120,8 @@ struct rt_signal_frame32 { }; /* Align macros */ -#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7))) -#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) +#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 15) & (~15))) +#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 15) & (~15))) int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { @@ -420,15 +420,17 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns sp = current->sas_ss_sp + current->sas_ss_size; } + sp -= framesize; + /* Always align the stack frame. This handles two cases. First, * sigaltstack need not be mindful of platform specific stack * alignment. Second, if we took this signal because the stack * is not aligned properly, we'd like to take the signal cleanly * and report that. */ - sp &= ~7UL; + sp &= ~15UL; - return (void __user *)(sp - framesize); + return (void __user *) sp; } static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 7ce1a10..9882df9 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -267,15 +267,17 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re sp = current->sas_ss_sp + current->sas_ss_size; } + sp -= framesize; + /* Always align the stack frame. This handles two cases. First, * sigaltstack need not be mindful of platform specific stack * alignment. Second, if we took this signal because the stack * is not aligned properly, we'd like to take the signal cleanly * and report that. */ - sp &= ~7UL; + sp &= ~15UL; - return (void __user *)(sp - framesize); + return (void __user *) sp; } static inline int diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 647afbd..9fa48c3 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -353,7 +353,7 @@ segv: /* Checks if the fp is valid */ static int invalid_frame_pointer(void __user *fp, int fplen) { - if (((unsigned long) fp) & 7) + if (((unsigned long) fp) & 15) return 1; return 0; } @@ -396,15 +396,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * sp = current->sas_ss_sp + current->sas_ss_size; } + sp -= framesize; + /* Always align the stack frame. This handles two cases. First, * sigaltstack need not be mindful of platform specific stack * alignment. Second, if we took this signal because the stack * is not aligned properly, we'd like to take the signal cleanly * and report that. */ - sp &= ~7UL; + sp &= ~15UL; - return (void __user *)(sp - framesize); + return (void __user *) sp; } static inline void diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index aa36223..eb14844 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -370,7 +370,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu) } else { struct device_node *dp = of_find_node_by_cpuid(cpu); - prom_startcpu(dp->node, entry, cookie); + prom_startcpu(dp->phandle, entry, cookie); } for (timeout = 0; timeout < 50000; timeout++) { diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 68791ca..482f2ab 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -194,7 +194,7 @@ int __cpuinit smp4d_boot_one_cpu(int i) smp_penguin_ctable.reg_size = 0; /* whirrr, whirrr, whirrrrrrrrr... */ - SMP_PRINTK(("Starting CPU %d at %p \n", i, entry)); + SMP_PRINTK(("Starting CPU %d at %p\n", i, entry)); local_flush_cache_all(); prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index dc0ac19..daded3b 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -43,7 +43,6 @@ #include <linux/security.h> #include <linux/compat.h> #include <linux/vfs.h> -#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/ptrace.h> #include <asm/types.h> diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S index 8c91d9b..db15d12 100644 --- a/arch/sparc/kernel/tsb.S +++ b/arch/sparc/kernel/tsb.S @@ -191,10 +191,12 @@ tsb_dtlb_load: tsb_itlb_load: /* Executable bit must be set. */ -661: andcc %g5, _PAGE_EXEC_4U, %g0 - .section .sun4v_1insn_patch, "ax" +661: sethi %hi(_PAGE_EXEC_4U), %g4 + andcc %g5, %g4, %g0 + .section .sun4v_2insn_patch, "ax" .word 661b andcc %g5, _PAGE_EXEC_4V, %g0 + nop .previous be,pn %xcc, tsb_do_fault diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index 378ca82..ebce430 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -21,6 +21,7 @@ #include <linux/smp.h> #include <linux/bitops.h> #include <linux/perf_event.h> +#include <linux/ratelimit.h> #include <asm/fpumacro.h> enum direction { @@ -274,13 +275,9 @@ static void kernel_mna_trap_fault(int fixup_tstate_asi) static void log_unaligned(struct pt_regs *regs) { - static unsigned long count, last_time; + static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5); - if (time_after(jiffies, last_time + 5 * HZ)) - count = 0; - if (count < 5) { - last_time = jiffies; - count++; + if (__ratelimit(&ratelimit)) { printk("Kernel unaligned access at TPC[%lx] %pS\n", regs->tpc, (void *) regs->tpc); } @@ -636,7 +633,6 @@ daex: return; } advance(regs); - return; } void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) @@ -685,5 +681,4 @@ daex: return; } advance(regs); - return; } diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index a3413ac..bd86016 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -35,6 +35,8 @@ extern int prom_node_root; +int show_unhandled_signals = 1; + /* At boot time we determine these two values necessary for setting * up the segment maps and page table entries (pte's). */ @@ -149,6 +151,45 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, return 0; } +static inline void +show_signal_msg(struct pt_regs *regs, int sig, int code, + unsigned long address, struct task_struct *tsk) +{ + if (!unhandled_signal(tsk, sig)) + return; + + if (!printk_ratelimit()) + return; + + printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), address, + (void *)regs->pc, (void *)regs->u_regs[UREG_I7], + (void *)regs->u_regs[UREG_FP], code); + + print_vma_addr(KERN_CONT " in ", regs->pc); + + printk(KERN_CONT "\n"); +} + +static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs, + unsigned long addr) +{ + siginfo_t info; + + info.si_signo = sig; + info.si_code = code; + info.si_errno = 0; + info.si_addr = (void __user *) addr; + info.si_trapno = 0; + + if (unlikely(show_unhandled_signals)) + show_signal_msg(regs, sig, info.si_code, + addr, current); + + force_sig_info (sig, &info, current); +} + extern unsigned long safe_compute_effective_address(struct pt_regs *, unsigned int); @@ -168,6 +209,14 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) return safe_compute_effective_address(regs, insn); } +static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs, + int text_fault) +{ + unsigned long addr = compute_si_addr(regs, text_fault); + + __do_fault_siginfo(code, sig, regs, addr); +} + asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address) { @@ -176,9 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, struct mm_struct *mm = tsk->mm; unsigned int fixup; unsigned long g2; - siginfo_t info; int from_user = !(regs->psr & PSR_PS); - int fault; + int fault, code; if(text_fault) address = regs->pc; @@ -195,7 +243,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, if (!ARCH_SUN4C && address >= TASK_SIZE) goto vmalloc_fault; - info.si_code = SEGV_MAPERR; + code = SEGV_MAPERR; /* * If we're in an interrupt or have no user @@ -229,7 +277,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, * we can handle it.. */ good_area: - info.si_code = SEGV_ACCERR; + code = SEGV_ACCERR; if(write) { if(!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -273,18 +321,8 @@ bad_area: bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ - if(from_user) { -#if 0 - printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n", - tsk->comm, tsk->pid, address, regs->pc); -#endif - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code set above to make clear whether - this was a SEGV_MAPERR or SEGV_ACCERR fault. */ - info.si_addr = (void __user *)compute_si_addr(regs, text_fault); - info.si_trapno = 0; - force_sig_info (SIGSEGV, &info, tsk); + if (from_user) { + do_fault_siginfo(code, SIGSEGV, regs, text_fault); return; } @@ -335,12 +373,7 @@ out_of_memory: do_sigbus: up_read(&mm->mmap_sem); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void __user *) compute_si_addr(regs, text_fault); - info.si_trapno = 0; - force_sig_info (SIGBUS, &info, tsk); + do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault); if (!from_user) goto no_context; @@ -378,7 +411,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address) { extern void sun4c_update_mmu_cache(struct vm_area_struct *, - unsigned long,pte_t); + unsigned long,pte_t *); extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long); struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; @@ -455,7 +488,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write, * on the CPU and doing a shrink_mmap() on this vma. */ sun4c_update_mmu_cache (find_vma(current->mm, address), address, - *ptep); + ptep); else do_sparc_fault(regs, text_fault, write, address); } @@ -466,14 +499,10 @@ static void force_user_fault(unsigned long address, int write) struct vm_area_struct *vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - siginfo_t info; + int code; - info.si_code = SEGV_MAPERR; + code = SEGV_MAPERR; -#if 0 - printk("wf<pid=%d,wr=%d,addr=%08lx>\n", - tsk->pid, write, address); -#endif down_read(&mm->mmap_sem); vma = find_vma(mm, address); if(!vma) @@ -485,7 +514,7 @@ static void force_user_fault(unsigned long address, int write) if(expand_stack(vma, address)) goto bad_area; good_area: - info.si_code = SEGV_ACCERR; + code = SEGV_ACCERR; if(write) { if(!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -502,27 +531,12 @@ good_area: return; bad_area: up_read(&mm->mmap_sem); -#if 0 - printk("Window whee %s [%d]: segfaults at %08lx\n", - tsk->comm, tsk->pid, address); -#endif - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code set above to make clear whether - this was a SEGV_MAPERR or SEGV_ACCERR fault. */ - info.si_addr = (void __user *) address; - info.si_trapno = 0; - force_sig_info (SIGSEGV, &info, tsk); + __do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address); return; do_sigbus: up_read(&mm->mmap_sem); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void __user *) address; - info.si_trapno = 0; - force_sig_info (SIGBUS, &info, tsk); + __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); } void window_overflow_fault(void) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index b9d4ff0..f92ce56 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -32,6 +32,8 @@ #include <asm/sections.h> #include <asm/mmu_context.h> +int show_unhandled_signals = 1; + static inline __kprobes int notify_page_fault(struct pt_regs *regs) { int ret = 0; @@ -128,22 +130,48 @@ outret: return insn; } +static inline void +show_signal_msg(struct pt_regs *regs, int sig, int code, + unsigned long address, struct task_struct *tsk) +{ + if (!unhandled_signal(tsk, sig)) + return; + + if (!printk_ratelimit()) + return; + + printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), address, + (void *)regs->tpc, (void *)regs->u_regs[UREG_I7], + (void *)regs->u_regs[UREG_FP], code); + + print_vma_addr(KERN_CONT " in ", regs->tpc); + + printk(KERN_CONT "\n"); +} + extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int); static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, unsigned int insn, int fault_code) { + unsigned long addr; siginfo_t info; info.si_code = code; info.si_signo = sig; info.si_errno = 0; if (fault_code & FAULT_CODE_ITLB) - info.si_addr = (void __user *) regs->tpc; + addr = regs->tpc; else - info.si_addr = (void __user *) - compute_effective_address(regs, insn, 0); + addr = compute_effective_address(regs, insn, 0); + info.si_addr = (void __user *) addr; info.si_trapno = 0; + + if (unlikely(show_unhandled_signals)) + show_signal_msg(regs, sig, code, addr, current); + force_sig_info(sig, &info, current); } diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 1886d37..9245a82 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -289,12 +289,13 @@ static void flush_dcache(unsigned long pfn) } } -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { struct mm_struct *mm; struct tsb *tsb; unsigned long tag, flags; unsigned long tsb_index, tsb_hash_shift; + pte_t pte = *ptep; if (tlb_type != hypervisor) { unsigned long pfn = pte_pfn(pte); diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c index 196263f..4e62c27 100644 --- a/arch/sparc/mm/nosun4c.c +++ b/arch/sparc/mm/nosun4c.c @@ -62,7 +62,7 @@ pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address) return NULL; } -void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 367321a..df49b20 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -694,7 +694,7 @@ extern void tsunami_setup_blockops(void); * The following code is a deadwood that may be necessary when * we start to make precise page flushes again. --zaitcev */ -static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) +static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t *ptep) { #if 0 static unsigned long last; @@ -703,10 +703,10 @@ static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long ad if (address == last) { val = srmmu_hwprobe(address); - if (val != 0 && pte_val(pte) != val) { + if (val != 0 && pte_val(*ptep) != val) { printk("swift_update_mmu_cache: " "addr %lx put %08x probed %08x from %p\n", - address, pte_val(pte), val, + address, pte_val(*ptep), val, __builtin_return_address(0)); srmmu_flush_whole_tlb(); } diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index a89baf0..1865253 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1887,7 +1887,7 @@ static void sun4c_check_pgt_cache(int low, int high) /* An experiment, turn off by default for now... -DaveM */ #define SUN4C_PRELOAD_PSEG -void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { unsigned long flags; int pseg; @@ -1929,7 +1929,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p start += PAGE_SIZE; } #ifndef SUN4C_PRELOAD_PSEG - sun4c_put_pte(address, pte_val(pte)); + sun4c_put_pte(address, pte_val(*ptep)); #endif local_irq_restore(flags); return; @@ -1940,7 +1940,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p add_lru(entry); } - sun4c_put_pte(address, pte_val(pte)); + sun4c_put_pte(address, pte_val(*ptep)); local_irq_restore(flags); } diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index b3075d7..5340264 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -94,5 +94,4 @@ void prom_putchar(char c) { while(prom_nbputchar(c) == -1) ; - return; } diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index e1c3fc8..f55d58a 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -62,7 +62,6 @@ void prom_putchar(char c) { prom_nbputchar(c); - return; } void diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c index 1e51791..46157d2 100644 --- a/arch/sparc/prom/devmap.c +++ b/arch/sparc/prom/devmap.c @@ -50,5 +50,4 @@ prom_unmapio(char *vaddr, unsigned int num_bytes) (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); - return; } diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c index 9f1a95c..9c5d468 100644 --- a/arch/sparc/prom/devops_32.c +++ b/arch/sparc/prom/devops_32.c @@ -84,6 +84,4 @@ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) }; restore_current(); spin_unlock_irqrestore(&prom_lock, flags); - - return; } diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c index 6193c33..ccb36c7 100644 --- a/arch/sparc/prom/init_32.c +++ b/arch/sparc/prom/init_32.c @@ -75,5 +75,4 @@ void __init prom_init(struct linux_romvec *rp) romvec->pv_romvers, prom_rev); /* Initialization successful. */ - return; } diff --git a/arch/sparc/prom/palloc.c b/arch/sparc/prom/palloc.c index 20be339..2e2a88b 100644 --- a/arch/sparc/prom/palloc.c +++ b/arch/sparc/prom/palloc.c @@ -40,5 +40,4 @@ prom_free(char *vaddr, unsigned int num_bytes) { if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return; (*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes); - return; } diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c index cd57908..aeff43e 100644 --- a/arch/sparc/prom/ranges.c +++ b/arch/sparc/prom/ranges.c @@ -87,8 +87,6 @@ void __init prom_ranges_init(void) if(num_obio_ranges) prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges); - - return; } void diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c index 04fd03a..86a663f 100644 --- a/arch/sparc/prom/segment.c +++ b/arch/sparc/prom/segment.c @@ -25,5 +25,4 @@ prom_putsegment(int ctx, unsigned long vaddr, int segment) (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); - return; } diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c index 646d244..b21592f 100644 --- a/arch/sparc/prom/tree_32.c +++ b/arch/sparc/prom/tree_32.c @@ -173,7 +173,6 @@ void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) len = prom_getproperty(node, prop, user_buf, ubuf_size); if(len != -1) return; user_buf[0] = 0; - return; } EXPORT_SYMBOL(prom_getstring); diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c index 8ea73dd..3c0d2dd 100644 --- a/arch/sparc/prom/tree_64.c +++ b/arch/sparc/prom/tree_64.c @@ -154,7 +154,6 @@ void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) len = prom_getproperty(node, prop, user_buf, ubuf_size); if(len != -1) return; user_buf[0] = 0; - return; } EXPORT_SYMBOL(prom_getstring); |