diff options
Diffstat (limited to 'arch')
50 files changed, 650 insertions, 415 deletions
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 968deb58be0..0ecff5a6197 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -223,7 +223,9 @@ static struct platform_device orion5x_eth = { void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) { + eth_data->shared = &orion5x_eth_shared; orion5x_eth.dev.platform_data = eth_data; + platform_device_register(&orion5x_eth_shared); platform_device_register(&orion5x_eth); } diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index 8b9984197ed..a79fbd87021 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -27,25 +27,6 @@ #include <asm/uaccess.h> #include <asm/segment.h> -/* - * 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 __user * fildes) -{ - int fd[2]; - int error; - - lock_kernel(); - error = do_pipe(fd); - unlock_kernel(); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 6d7a80fdad4..305ac852bbe 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -76,26 +76,6 @@ asmlinkage int sys_tas(int __user *addr) return oldval; } -/* - * 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 r0, unsigned long r1, unsigned long r2, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, struct pt_regs regs) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user((void __user *)r0, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index a1ae4d6ec99..72d67564bdf 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts @@ -342,9 +342,14 @@ /* Outbound ranges, one memory and one IO, * later cannot be changed. Chip supports a second * IO range but we don't use it for now + * From the 440EPx user manual: + * PCI 1 Memory 1 8000 0000 1 BFFF FFFF 1GB + * I/O 1 E800 0000 1 E800 FFFF 64KB + * I/O 1 E880 0000 1 EBFF FFFF 56MB */ - ranges = <02000000 0 80000000 1 80000000 0 10000000 - 01000000 0 00000000 1 e8000000 0 00100000>; + ranges = <02000000 0 80000000 1 80000000 0 40000000 + 01000000 0 00000000 1 e8000000 0 00010000 + 01000000 0 00000000 1 e8800000 0 03800000>; /* Inbound 2GB range starting at 0 */ dma-ranges = <42000000 0 0 0 0 0 80000000>; diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 9f937774549..d8f0329b134 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -16,7 +16,6 @@ #include <asm/mmu.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/prom.h> #include <asm/processor.h> #include <asm/udbg.h> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 36080d4d192..81738a4b3c3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1208,6 +1208,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_4xx, .platform = "ppc405", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 40x PPC)", + .cpu_features = CPU_FTRS_40X, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc405", + } #endif /* CONFIG_40x */ #ifdef CONFIG_44x @@ -1421,8 +1433,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_440A, .platform = "ppc440", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 44x PPC)", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc440", + } #endif /* CONFIG_44x */ -#ifdef CONFIG_FSL_BOOKE #ifdef CONFIG_E200 { /* e200z5 */ .pvr_mask = 0xfff00000, @@ -1451,7 +1473,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e200, .platform = "ppc5554", }, -#elif defined(CONFIG_E500) + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic E200 PPC)", + .cpu_features = CPU_FTRS_E200, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_EFP_SINGLE | + PPC_FEATURE_UNIFIED_CACHE, + .dcache_bsize = 32, + .machine_check = machine_check_e200, + .platform = "ppc5554", +#endif /* CONFIG_E200 */ +#ifdef CONFIG_E500 { /* e500 */ .pvr_mask = 0xffff0000, .pvr_value = 0x80200000, @@ -1487,20 +1521,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500, .platform = "ppc8548", }, -#endif -#endif -#if !CLASSIC_PPC { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, - .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTRS_GENERIC_32, - .cpu_user_features = PPC_FEATURE_32, + .cpu_name = "(generic E500 PPC)", + .cpu_features = CPU_FTRS_E500, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE_COMP, .icache_bsize = 32, .dcache_bsize = 32, + .machine_check = machine_check_e500, .platform = "powerpc", - } -#endif /* !CLASSIC_PPC */ +#endif /* CONFIG_E500 */ #endif /* CONFIG_PPC32 */ }; diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index b84ec6a2fc9..c2b9dc4fce5 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -653,7 +653,14 @@ finish_tlb_load: rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ - rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ + + /* + * Clear U0-U3 and WL1 IL1I IL1D IL2I IL2D bits which are added + * on newer 440 cores like the 440x6 used on AMCC 460EX/460GT (see + * include/asm-powerpc/pgtable-ppc32.h for details). + */ + rlwinm r12, r12, 0, 20, 10 + tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 024805e1747..25e84c0e116 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1517,10 +1517,6 @@ _INIT_STATIC(start_here_multiplatform) addi r2,r2,0x4000 add r2,r2,r26 - /* Set initial ptr to current */ - LOAD_REG_IMMEDIATE(r4, init_task) - std r4,PACACURRENT(r13) - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 289af348978..4d5731b2429 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -108,9 +108,6 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, if (size > 0x10000) size = 0x10000; - printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " - "mapping 64k\n"); - __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, size, _PAGE_NO_CACHE|_PAGE_GUARDED); return; diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 25e3fd8606a..098fd96a394 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -170,6 +170,8 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { + /* -------- printk is _NOT_ safe to use here ! ------- */ + /* Fill in any unititialised pacas */ initialise_pacas(); @@ -179,12 +181,14 @@ void __init early_setup(unsigned long dt_ptr) /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); - /* Enable early debugging if any specified (see udbg.h) */ - udbg_early_init(); - /* Initialize lockdep early or else spinlocks will blow */ lockdep_init(); + /* -------- printk is now safe to use ------- */ + + /* Enable early debugging if any specified (see udbg.h) */ + udbg_early_init(); + DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); /* diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 04f74f9f9ab..5bf7df14602 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -35,6 +35,7 @@ #include <linux/percpu.h> #include <linux/types.h> #include <linux/ioport.h> +#include <linux/kernel_stat.h> #include <asm/io.h> #include <asm/pgtable.h> @@ -231,6 +232,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) "IBM,CBEA-Internal-Interrupt-Controller"); } +extern int noirqdebug; + +static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) +{ + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || + !desc->action)) { + desc->status |= IRQ_PENDING; + goto out_eoi; + } + + kstat_cpu(cpu).irqs[irq]++; + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) + goto out_eoi; + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + spin_lock(&desc->lock); + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_eoi: + desc->chip->eoi(irq); + spin_unlock(&desc->lock); +} + static int iic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -240,10 +289,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, break; case IIC_IRQ_TYPE_IOEXC: set_irq_chip_and_handler(virq, &iic_ioexc_chip, - handle_fasteoi_irq); + handle_iic_irq); break; default: - set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); + set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); } return 0; } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 6bab44b7716..70c660121ec 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -141,6 +141,10 @@ static void spu_restart_dma(struct spu *spu) if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags)) out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); + else { + set_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); + mb(); + } } static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb) @@ -226,11 +230,13 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) return 0; } - spu->class_0_pending = 0; - spu->dar = ea; - spu->dsisr = dsisr; + spu->class_1_dar = ea; + spu->class_1_dsisr = dsisr; + + spu->stop_callback(spu, 1); - spu->stop_callback(spu); + spu->class_1_dar = 0; + spu->class_1_dsisr = 0; return 0; } @@ -318,11 +324,15 @@ spu_irq_class_0(int irq, void *data) stat = spu_int_stat_get(spu, 0) & mask; spu->class_0_pending |= stat; - spu->dsisr = spu_mfc_dsisr_get(spu); - spu->dar = spu_mfc_dar_get(spu); + spu->class_0_dsisr = spu_mfc_dsisr_get(spu); + spu->class_0_dar = spu_mfc_dar_get(spu); spin_unlock(&spu->register_lock); - spu->stop_callback(spu); + spu->stop_callback(spu, 0); + + spu->class_0_pending = 0; + spu->class_0_dsisr = 0; + spu->class_0_dar = 0; spu_int_stat_clear(spu, 0, stat); @@ -363,6 +373,9 @@ spu_irq_class_1(int irq, void *data) if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR) ; + spu->class_1_dsisr = 0; + spu->class_1_dar = 0; + return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -396,10 +409,10 @@ spu_irq_class_2(int irq, void *data) spu->ibox_callback(spu); if (stat & CLASS2_SPU_STOP_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_HALT_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR) spu->mfc_callback(spu); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 67fa7247b80..906a0a2a9fe 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -28,6 +28,7 @@ #include <linux/io.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/sched.h> #include <asm/spu.h> #include <asm/spu_priv1.h> @@ -75,8 +76,19 @@ static u64 int_stat_get(struct spu *spu, int class) static void cpu_affinity_set(struct spu *spu, int cpu) { - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; + u64 target; + u64 route; + + if (nr_cpus_node(spu->node)) { + cpumask_t spumask = node_to_cpumask(spu->node); + cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu)); + + if (!cpus_intersects(spumask, cpumask)) + return; + } + + target = iic_get_target_id(cpu); + route = target << 48 | target << 32 | target << 16; out_be64(&spu->priv1->int_route_RW, route); } diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index e46d300e21a..f093a581ac7 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -83,13 +83,18 @@ int spufs_handle_class0(struct spu_context *ctx) return 0; if (stat & CLASS0_DMA_ALIGNMENT_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_DMA_ALIGNMENT); if (stat & CLASS0_INVALID_DMA_COMMAND_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_INVALID_DMA); if (stat & CLASS0_SPU_ERROR_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_SPE_ERROR); + + ctx->csa.class_0_pending = 0; return -EIO; } @@ -119,8 +124,8 @@ int spufs_handle_class1(struct spu_context *ctx) * in time, we can still expect to get the same fault * the immediately after the context restore. */ - ea = ctx->csa.dar; - dsisr = ctx->csa.dsisr; + ea = ctx->csa.class_1_dar; + dsisr = ctx->csa.class_1_dsisr; if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) return 0; @@ -158,7 +163,7 @@ int spufs_handle_class1(struct spu_context *ctx) * time slicing will not preempt the context while the page fault * handler is running. Context switch code removes mappings. */ - ctx->csa.dar = ctx->csa.dsisr = 0; + ctx->csa.class_1_dar = ctx->csa.class_1_dsisr = 0; /* * If we handled the fault successfully and are in runnable diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 0c32a05ab06..f407b247185 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -23,6 +23,7 @@ #include <linux/file.h> #include <linux/fs.h> +#include <linux/fsnotify.h> #include <linux/backing-dev.h> #include <linux/init.h> #include <linux/ioctl.h> @@ -223,7 +224,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) parent = dir->d_parent->d_inode; ctx = SPUFS_I(dir->d_inode)->i_ctx; - mutex_lock(&parent->i_mutex); + mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT); ret = spufs_rmdir(parent, dir); mutex_unlock(&parent->i_mutex); WARN_ON(ret); @@ -618,12 +619,15 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, mode &= ~current->fs->umask; if (flags & SPU_CREATE_GANG) - return spufs_create_gang(nd->path.dentry->d_inode, + ret = spufs_create_gang(nd->path.dentry->d_inode, dentry, nd->path.mnt, mode); else - return spufs_create_context(nd->path.dentry->d_inode, + ret = spufs_create_context(nd->path.dentry->d_inode, dentry, nd->path.mnt, flags, mode, filp); + if (ret >= 0) + fsnotify_mkdir(nd->path.dentry->d_inode, dentry); + return ret; out_dput: dput(dentry); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index a9c35b7b719..b7493b86581 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -11,7 +11,7 @@ #include "spufs.h" /* interrupt-level stop callback function. */ -void spufs_stop_callback(struct spu *spu) +void spufs_stop_callback(struct spu *spu, int irq) { struct spu_context *ctx = spu->ctx; @@ -24,9 +24,19 @@ void spufs_stop_callback(struct spu *spu) */ if (ctx) { /* Copy exception arguments into module specific structure */ - ctx->csa.class_0_pending = spu->class_0_pending; - ctx->csa.dsisr = spu->dsisr; - ctx->csa.dar = spu->dar; + switch(irq) { + case 0 : + ctx->csa.class_0_pending = spu->class_0_pending; + ctx->csa.class_0_dsisr = spu->class_0_dsisr; + ctx->csa.class_0_dar = spu->class_0_dar; + break; + case 1 : + ctx->csa.class_1_dsisr = spu->class_1_dsisr; + ctx->csa.class_1_dar = spu->class_1_dar; + break; + case 2 : + break; + } /* ensure that the exception status has hit memory before a * thread waiting on the context's stop queue is woken */ @@ -34,11 +44,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } - - /* Clear callback arguments from spu structure */ - spu->class_0_pending = 0; - spu->dsisr = 0; - spu->dar = 0; } int spu_stopped(struct spu_context *ctx, u32 *stat) @@ -56,7 +61,11 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) return 1; - dsisr = ctx->csa.dsisr; + dsisr = ctx->csa.class_0_dsisr; + if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) + return 1; + + dsisr = ctx->csa.class_1_dsisr; if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) return 1; @@ -294,7 +303,7 @@ static int spu_process_callback(struct spu_context *ctx) u32 ls_pointer, npc; void __iomem *ls; long spu_ret; - int ret, ret2; + int ret; /* get syscall block from local store */ npc = ctx->ops->npc_read(ctx) & ~3; @@ -316,11 +325,9 @@ static int spu_process_callback(struct spu_context *ctx) if (spu_ret <= -ERESTARTSYS) { ret = spu_handle_restartsys(ctx, &spu_ret, &npc); } - ret2 = spu_acquire(ctx); + mutex_lock(&ctx->state_mutex); if (ret == -ERESTARTSYS) return ret; - if (ret2) - return -EINTR; } /* need to re-get the ls, as it may have changed when we released the @@ -343,13 +350,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) if (mutex_lock_interruptible(&ctx->run_mutex)) return -ERESTARTSYS; - spu_enable_spu(ctx); ctx->event_return = 0; ret = spu_acquire(ctx); if (ret) goto out_unlock; + spu_enable_spu(ctx); + spu_update_sched_info(ctx); ret = spu_run_init(ctx, npc); diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 7298e7db2c8..2e411f23462 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -140,6 +140,9 @@ void __spu_update_sched_info(struct spu_context *ctx) * if it is timesliced or preempted. */ ctx->cpus_allowed = current->cpus_allowed; + + /* Save the current cpu id for spu interrupt routing. */ + ctx->last_ran = raw_smp_processor_id(); } void spu_update_sched_info(struct spu_context *ctx) @@ -243,7 +246,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); spu_restore(&ctx->csa, spu); spu->timestamp = jiffies; - spu_cpu_affinity_set(spu, raw_smp_processor_id()); spu_switch_notify(spu, ctx); ctx->state = SPU_STATE_RUNNABLE; @@ -657,7 +659,8 @@ static struct spu *find_victim(struct spu_context *ctx) victim->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; - spu_add_to_rq(victim); + if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) + spu_add_to_rq(victim); mutex_unlock(&victim->state_mutex); diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 7312745b754..454c277c145 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -121,6 +121,7 @@ struct spu_context { cpumask_t cpus_allowed; int policy; int prio; + int last_ran; /* statistics */ struct { @@ -331,7 +332,7 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data); /* irq callback funcs. */ void spufs_ibox_callback(struct spu *spu); void spufs_wbox_callback(struct spu *spu); -void spufs_stop_callback(struct spu *spu); +void spufs_stop_callback(struct spu *spu, int irq); void spufs_mfc_callback(struct spu *spu); void spufs_dma_callback(struct spu *spu, int type); diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index d2a1249d36d..3df9a36eb2f 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -132,6 +132,14 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu) spu_int_mask_set(spu, 2, 0ul); eieio(); spin_unlock_irq(&spu->register_lock); + + /* + * This flag needs to be set before calling synchronize_irq so + * that the update will be visible to the relevant handlers + * via a simple load. + */ + set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); + clear_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); synchronize_irq(spu->irqs[0]); synchronize_irq(spu->irqs[1]); synchronize_irq(spu->irqs[2]); @@ -166,9 +174,8 @@ static inline void set_switch_pending(struct spu_state *csa, struct spu *spu) /* Save, Step 7: * Restore, Step 5: * Set a software context switch pending flag. + * Done above in Step 3 - disable_interrupts(). */ - set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); - mb(); } static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) @@ -186,20 +193,21 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) MFC_CNTL_SUSPEND_COMPLETE); /* fall through */ case MFC_CNTL_SUSPEND_COMPLETE: - if (csa) { + if (csa) csa->priv2.mfc_control_RW = - MFC_CNTL_SUSPEND_MASK | + 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 = 0; - } + if (csa) + csa->priv2.mfc_control_RW = + in_be64(&priv2->mfc_control_RW) & + ~MFC_CNTL_SUSPEND_DMA_QUEUE & + ~MFC_CNTL_SUSPEND_MASK; break; } } @@ -249,16 +257,21 @@ static inline void save_spu_status(struct spu_state *csa, struct spu *spu) } } -static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu) +static inline void save_mfc_stopped_status(struct spu_state *csa, + struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; + const u64 mask = MFC_CNTL_DECREMENTER_RUNNING | + MFC_CNTL_DMA_QUEUES_EMPTY; /* Save, Step 12: * Read MFC_CNTL[Ds]. Update saved copy of * CSA.MFC_CNTL[Ds]. + * + * update: do the same with MFC_CNTL[Q]. */ - csa->priv2.mfc_control_RW |= - in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DECREMENTER_RUNNING; + csa->priv2.mfc_control_RW &= ~mask; + csa->priv2.mfc_control_RW |= in_be64(&priv2->mfc_control_RW) & mask; } static inline void halt_mfc_decr(struct spu_state *csa, struct spu *spu) @@ -462,7 +475,9 @@ static inline void purge_mfc_queue(struct spu_state *csa, struct spu *spu) * Restore, Step 14. * Write MFC_CNTL[Pc]=1 (purge queue). */ - out_be64(&priv2->mfc_control_RW, MFC_CNTL_PURGE_DMA_REQUEST); + out_be64(&priv2->mfc_control_RW, + MFC_CNTL_PURGE_DMA_REQUEST | + MFC_CNTL_SUSPEND_MASK); eieio(); } @@ -725,10 +740,14 @@ static inline void set_switch_active(struct spu_state *csa, struct spu *spu) /* Save, Step 48: * Restore, Step 23. * Change the software context switch pending flag - * to context switch active. + * to context switch active. This implementation does + * not uses a switch active flag. * - * This implementation does not uses a switch active flag. + * Now that we have saved the mfc in the csa, we can add in the + * restart command if an exception occurred. */ + if (test_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags)) + csa->priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND; clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); mb(); } @@ -1690,6 +1709,13 @@ static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu) eieio(); } +static inline void set_int_route(struct spu_state *csa, struct spu *spu) +{ + struct spu_context *ctx = spu->ctx; + + spu_cpu_affinity_set(spu, ctx->last_ran); +} + static inline void restore_other_spu_access(struct spu_state *csa, struct spu *spu) { @@ -1721,15 +1747,15 @@ static inline void restore_mfc_cntl(struct spu_state *csa, struct spu *spu) */ out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW); eieio(); + /* - * FIXME: this is to restart a DMA that we were processing - * before the save. better remember the fault information - * in the csa instead. + * The queue is put back into the same state that was evident prior to + * the context switch. The suspend flag is added to the saved state in + * the csa, if the operational state was suspending or suspended. In + * this case, the code that suspended the mfc is responsible for + * continuing it. Note that SPE faults do not change the operational + * state of the spu. */ - if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) { - out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); - eieio(); - } } static inline void enable_user_access(struct spu_state *csa, struct spu *spu) @@ -1788,7 +1814,7 @@ static int quiece_spu(struct spu_state *prev, struct spu *spu) save_spu_runcntl(prev, spu); /* Step 9. */ save_mfc_sr1(prev, spu); /* Step 10. */ save_spu_status(prev, spu); /* Step 11. */ - save_mfc_decr(prev, spu); /* Step 12. */ + save_mfc_stopped_status(prev, spu); /* Step 12. */ halt_mfc_decr(prev, spu); /* Step 13. */ save_timebase(prev, spu); /* Step 14. */ remove_other_spu_access(prev, spu); /* Step 15. */ @@ -2000,6 +2026,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu) check_ppuint_mb_stat(next, spu); /* Step 67. */ spu_invalidate_slbs(spu); /* Modified Step 68. */ restore_mfc_sr1(next, spu); /* Step 69. */ + set_int_route(next, spu); /* NEW */ restore_other_spu_access(next, spu); /* Step 70. */ restore_spu_runcntl(next, spu); /* Step 71. */ restore_mfc_cntl(next, spu); /* Step 72. */ diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 5bcc58d9a4d..130ff72d99d 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -58,7 +58,9 @@ static struct resource mv643xx_eth0_resources[] = { static struct mv643xx_eth_platform_data eth0_pd = { + .shared = &mv643xx_eth_shared_device, .port_number = 0, + .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0, .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, @@ -88,7 +90,9 @@ static struct resource mv643xx_eth1_resources[] = { }; static struct mv643xx_eth_platform_data eth1_pd = { + .shared = &mv643xx_eth_shared_device, .port_number = 1, + .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1, .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 41af1223e2a..a132e0de8ca 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -239,6 +239,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id, memset(&pdata, 0, sizeof(pdata)); + pdata.shared = shared_pdev; + prop = of_get_property(np, "reg", NULL); if (!prop) return -ENODEV; diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 1814adbd223..b4a54c52e88 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1387,28 +1387,59 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, resource_size_t size = res->end - res->start + 1; u64 sa; - /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; - if (res->flags & IORESOURCE_PREFETCH) - sa |= 0x8; + if (port->endpoint) { + resource_size_t ep_addr = 0; + resource_size_t ep_size = 32 << 20; + + /* Currently we map a fixed 64MByte window to PLB address + * 0 (SDRAM). This should probably be configurable via a dts + * property. + */ + + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(ep_size));; + + /* Setup BAR0 */ + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) | + PCI_BASE_ADDRESS_MEM_TYPE_64); - out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); - out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + /* Disable BAR1 & BAR2 */ + out_le32(mbase + PECFG_BAR1MPA, 0); + out_le32(mbase + PECFG_BAR2HMPA, 0); + out_le32(mbase + PECFG_BAR2LMPA, 0); - /* The setup of the split looks weird to me ... let's see if it works */ - out_le32(mbase + PECFG_PIM0LAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAH, 0x00000000); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000000); - out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); - out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa)); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); + } else { + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(size));; + if (res->flags & IORESOURCE_PREFETCH) + sa |= 0x8; + + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + + /* The setup of the split looks weird to me ... let's see + * if it works + */ + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); + out_le32(mbase + PECFG_PIM0LAH, 0x00000000); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); + out_le32(mbase + PECFG_PIM1LAH, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); + } /* Enable inbound mapping */ out_le32(mbase + PECFG_PIMEN, 0x1); - out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); - out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); - /* Enable I/O, Mem, and Busmaster cycles */ out_le16(mbase + PCI_COMMAND, in_le16(mbase + PCI_COMMAND) | @@ -1422,13 +1453,8 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) const int *bus_range; int primary = 0, busses; void __iomem *mbase = NULL, *cfg_data = NULL; - - /* XXX FIXME: Handle endpoint mode properly */ - if (port->endpoint) { - printk(KERN_WARNING "PCIE%d: Port in endpoint mode !\n", - port->index); - return; - } + const u32 *pval; + u32 val; /* Check if primary bridge */ if (of_get_property(port->node, "primary", NULL)) @@ -1462,21 +1488,30 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) hose->last_busno = hose->first_busno + busses; } - /* We map the external config space in cfg_data and the host config - * space in cfg_addr. External space is 1M per bus, internal space - * is 4K + if (!port->endpoint) { + /* Only map the external config space in cfg_data for + * PCIe root-complexes. External space is 1M per bus + */ + cfg_data = ioremap(port->cfg_space.start + + (hose->first_busno + 1) * 0x100000, + busses * 0x100000); + if (cfg_data == NULL) { + printk(KERN_ERR "%s: Can't map external config space !", + port->node->full_name); + goto fail; + } + hose->cfg_data = cfg_data; + } + + /* Always map the host config space in cfg_addr. + * Internal space is 4K */ - cfg_data = ioremap(port->cfg_space.start + - (hose->first_busno + 1) * 0x100000, - busses * 0x100000); mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); - if (cfg_data == NULL || mbase == NULL) { - printk(KERN_ERR "%s: Can't map config space !", + if (mbase == NULL) { + printk(KERN_ERR "%s: Can't map internal config space !", port->node->full_name); goto fail; } - - hose->cfg_data = cfg_data; hose->cfg_addr = mbase; pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, @@ -1489,12 +1524,14 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; - /* - * Set bus numbers on our root port - */ - out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); - out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); - out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + if (!port->endpoint) { + /* + * Set bus numbers on our root port + */ + out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); + out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); + out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + } /* * OMRs are already reset, also disable PIMs @@ -1515,17 +1552,49 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); /* The root complex doesn't show up if we don't set some vendor - * and device IDs into it. Those are the same bogus one that the - * initial code in arch/ppc add. We might want to change that. + * and device IDs into it. The defaults below are the same bogus + * one that the initial code in arch/ppc had. This can be + * overwritten by setting the "vendor-id/device-id" properties + * in the pciex node. */ - out_le16(mbase + 0x200, 0xaaa0 + port->index); - out_le16(mbase + 0x202, 0xbed0 + port->index); - /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ - out_le32(mbase + 0x208, 0x06040001); + /* Get the (optional) vendor-/device-id from the device-tree */ + pval = of_get_property(port->node, "vendor-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xaaa0 + port->index; + else + val = 0xeee0 + port->index; + } + out_le16(mbase + 0x200, val); + + pval = of_get_property(port->node, "device-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xbed0 + port->index; + else + val = 0xfed0 + port->index; + } + out_le16(mbase + 0x202, val); + + if (!port->endpoint) { + /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ + out_le32(mbase + 0x208, 0x06040001); + + printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", + port->index); + } else { + /* Set Class Code to Processor/PPC */ + out_le32(mbase + 0x208, 0x0b200001); + + printk(KERN_INFO "PCIE%d: successfully set as endpoint\n", + port->index); + } - printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", - port->index); return; fail: if (hose) @@ -1542,6 +1611,7 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) const u32 *pval; int portno; unsigned int dcrs; + const char *val; /* First, proceed to core initialization as we assume there's * only one PCIe core in the system @@ -1573,8 +1643,20 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) } port->sdr_base = *pval; - /* XXX Currently, we only support root complex mode */ - port->endpoint = 0; + /* Check if device_type property is set to "pci" or "pci-endpoint". + * Resulting from this setup this PCIe port will be configured + * as root-complex or as endpoint. + */ + val = of_get_property(port->node, "device_type", NULL); + if (!strcmp(val, "pci-endpoint")) { + port->endpoint = 1; + } else if (!strcmp(val, "pci")) { + port->endpoint = 0; + } else { + printk(KERN_ERR "PCIE: missing or incorrect device_type for %s\n", + np->full_name); + return; + } /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &port->cfg_space)) { diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 52c74780f40..1702de9395e 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2842,9 +2842,11 @@ static void dump_spu_fields(struct spu *spu) DUMP_FIELD(spu, "0x%lx", ls_size); DUMP_FIELD(spu, "0x%x", node); DUMP_FIELD(spu, "0x%lx", flags); - DUMP_FIELD(spu, "0x%lx", dar); - DUMP_FIELD(spu, "0x%lx", dsisr); DUMP_FIELD(spu, "%d", class_0_pending); + DUMP_FIELD(spu, "0x%lx", class_0_dar); + DUMP_FIELD(spu, "0x%lx", class_0_dsisr); + DUMP_FIELD(spu, "0x%lx", class_1_dar); + DUMP_FIELD(spu, "0x%lx", class_1_dsisr); DUMP_FIELD(spu, "0x%lx", irqs[0]); DUMP_FIELD(spu, "0x%lx", irqs[1]); DUMP_FIELD(spu, "0x%lx", irqs[2]); diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 90fe904d361..418f3053de5 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -341,6 +341,7 @@ static struct resource mv64x60_eth0_resources[] = { }; static struct mv643xx_eth_platform_data eth0_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 0, }; @@ -366,6 +367,7 @@ static struct resource mv64x60_eth1_resources[] = { }; static struct mv643xx_eth_platform_data eth1_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 1, }; @@ -391,6 +393,7 @@ static struct resource mv64x60_eth2_resources[] = { }; static struct mv643xx_eth_platform_data eth2_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 2, }; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 29a7940f284..1d035082e78 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -430,6 +430,13 @@ config CMM_IUCV Select this option to enable the special message interface to the cooperative memory management. +config PAGE_STATES + bool "Unused page notification" + help + This enables the notification of unused pages to the + hypervisor. The ESSA instruction is used to do the states + changes between a page that has content and the unused state. + config VIRT_TIMER bool "Virtual CPU timer support" help diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 743d54f0b8d..d003a6e16af 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -121,7 +121,7 @@ sys32_ptrace_wrapper: lgfr %r3,%r3 # long llgtr %r4,%r4 # long llgfr %r5,%r5 # long - jg sys_ptrace # branch to system call + jg compat_sys_ptrace # branch to system call .globl sys32_alarm_wrapper sys32_alarm_wrapper: diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index bdbb3bcd78a..708cf9cf9a3 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -279,8 +279,6 @@ sysc_do_restart: st %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_WORK_SVC bnz BASED(sysc_work) # there is work to do (signals etc.) sysc_restore: @@ -312,6 +310,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED @@ -602,12 +602,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - bno BASED(io_preempt) # no -> check for preemptive scheduling -#else - bno BASED(io_restore) # no-> skip resched & signal -#endif tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.) io_restore: @@ -629,10 +623,18 @@ io_restore_trace_psw: .long 0, io_restore_trace + 0x80000000 #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# switch to kernel stack, then check the TIF bits +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT + bno BASED(io_restore) # no-> skip resched & signal +#else + bnz BASED(io_work_user) # no -> check for preemptive scheduling + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - bnz BASED(io_restore) + bnz BASED(io_restore) # preemption disabled l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -646,10 +648,7 @@ io_resume_loop: br %r1 # call schedule #endif -# -# switch to kernel stack, then check the TIF bits -# -io_work: +io_work_user: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 5a4a7bcd2bb..fee10177dbf 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -271,8 +271,6 @@ sysc_noemu: stg %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - jno sysc_restore tm __TI_flags+7(%r9),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) sysc_restore: @@ -304,6 +302,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + jno sysc_restore tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED @@ -585,12 +585,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - jno io_preempt # no -> check for preemptive scheduling -#else - jno io_restore # no-> skip resched & signal -#endif tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) io_restore: @@ -612,10 +606,41 @@ io_restore_trace_psw: .quad 0, io_restore_trace #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# There is work todo, we need to check if we return to userspace, then +# check, if we are in SIE, if yes leave it +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + jnz io_work_user # yes -> no need to check for SIE + la %r1, BASED(sie_opcode) # we return to kernel here + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne io_restore # no-> return to kernel + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) + j io_restore # return to kernel +#else + jno io_restore # no-> skip resched & signal +#endif +#else + jnz io_work_user # yes -> do resched & signal +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + la %r1, BASED(sie_opcode) + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne 0f # no -> leave PSW alone + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) +0: +#endif + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - jnz io_restore + jnz io_restore # preemption is disabled # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE @@ -629,10 +654,7 @@ io_resume_loop: jg preempt_schedule_irq #endif -# -# switch to kernel stack, then check TIF bits -# -io_work: +io_work_user: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -653,6 +675,11 @@ io_work_loop: j io_restore io_work_done: +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +sie_opcode: + .long 0xb2140000 +#endif + # # _TIF_MCCK_PENDING is set, call handler # diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 7f427016374..35827b9bd4d 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_normal(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { ptrace_area parea; int copied, ret; @@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - unsigned int tmp; /* 4 bytes !! */ + unsigned long addr = caddr; + unsigned long data = cdata; ptrace_area_emu31 parea; int copied, ret; switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - /* read word at location addr. */ - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned int __force __user *) data); - case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ return peek_user_emu31(child, addr, data); - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - /* write the word at location addr. */ - tmp = data; - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1); - if (copied != sizeof(tmp)) - return -EIO; - return 0; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ return poke_user_emu31(child, addr, data); @@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned int); } return 0; - case PTRACE_GETEVENTMSG: - return put_user((__u32) child->ptrace_message, - (unsigned int __force __user *) data); - case PTRACE_GETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_to_user32((compat_siginfo_t - __force __user *) data, - child->last_siginfo); - case PTRACE_SETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_from_user32(child->last_siginfo, - (compat_siginfo_t - __force __user *) data); } - return ptrace_request(child, request, addr, data); + return compat_ptrace_request(child, request, addr, data); } #endif -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - switch (request) { - case PTRACE_SYSCALL: - /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: - /* restart after signal. */ - if (!valid_signal(data)) - return -EIO; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_KILL: - /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - return 0; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_SINGLESTEP: - /* set the trap flag. */ - if (!valid_signal(data)) - return -EIO; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - user_enable_single_step(child); - /* give it a chance to run. */ - wake_up_process(child); - return 0; - - /* Do requests that differ for 31/64 bit */ - default: -#ifdef CONFIG_COMPAT - if (test_thread_flag(TIF_31BIT)) - return do_ptrace_emu31(child, request, addr, data); -#endif - return do_ptrace_normal(child, request, addr, data); - } - /* Not reached. */ - return -EIO; -} - asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 1761b74d639..e051cad1f1e 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -22,7 +22,6 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select S390_SWITCH_AMODE - select PREEMPT ---help--- Support hosting paravirtualized guest machines using the SIE virtualization capability on the mainframe. This should work diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 349581a2610..47a0b642174 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = { static int handle_noop(struct kvm_vcpu *vcpu) { switch (vcpu->arch.sie_block->icptcode) { + case 0x0: + vcpu->stat.exit_null++; + break; case 0x10: vcpu->stat.exit_external_request++; break; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 98d1e73e01f..0ac36a649eb 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -31,6 +31,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "userspace_handled", VCPU_STAT(exit_userspace) }, + { "exit_null", VCPU_STAT(exit_null) }, { "exit_validity", VCPU_STAT(exit_validity) }, { "exit_stop_request", VCPU_STAT(exit_stop_request) }, { "exit_external_request", VCPU_STAT(exit_external_request) }, @@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK; restore_fp_regs(&vcpu->arch.guest_fpregs); restore_access_regs(vcpu->arch.guest_acrs); - - if (signal_pending(current)) - atomic_set_mask(CPUSTAT_STOP_INT, - &vcpu->arch.sie_block->cpuflags); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index fb988a48a75..2a745813454 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile @@ -5,3 +5,4 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_PAGE_STATES) += page-states.o diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index fa31de6ae97..29f3a63806b 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -126,6 +126,9 @@ void __init mem_init(void) /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); + /* Setup guest page hinting */ + cmma_init(); + /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem(); diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c new file mode 100644 index 00000000000..fc0ad73ffd9 --- /dev/null +++ b/arch/s390/mm/page-states.c @@ -0,0 +1,79 @@ +/* + * arch/s390/mm/page-states.c + * + * Copyright IBM Corp. 2008 + * + * Guest page hinting for unused pages. + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/init.h> + +#define ESSA_SET_STABLE 1 +#define ESSA_SET_UNUSED 2 + +static int cmma_flag; + +static int __init cmma(char *str) +{ + char *parm; + parm = strstrip(str); + if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) { + cmma_flag = 1; + return 1; + } + cmma_flag = 0; + if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0) + return 1; + return 0; +} + +__setup("cmma=", cmma); + +void __init cmma_init(void) +{ + register unsigned long tmp asm("0") = 0; + register int rc asm("1") = -EOPNOTSUPP; + + if (!cmma_flag) + return; + asm volatile( + " .insn rrf,0xb9ab0000,%1,%1,0,0\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "+&d" (rc), "+&d" (tmp)); + if (rc) + cmma_flag = 0; +} + +void arch_free_page(struct page *page, int order) +{ + int i, rc; + + if (!cmma_flag) + return; + for (i = 0; i < (1 << order); i++) + asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" + : "=&d" (rc) + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), + "i" (ESSA_SET_UNUSED)); +} + +void arch_alloc_page(struct page *page, int order) +{ + int i, rc; + + if (!cmma_flag) + return; + for (i = 0; i < (1 << order); i++) + asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" + : "=&d" (rc) + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), + "i" (ESSA_SET_STABLE)); +} diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index e7f35198ae3..36431f377de 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, unsigned long stack_size) { unsigned long parent_tid_ptr, child_tid_ptr; + unsigned long orig_i1 = regs->u_regs[UREG_I1]; + long ret; parent_tid_ptr = regs->u_regs[UREG_I2]; child_tid_ptr = regs->u_regs[UREG_I4]; - return do_fork(clone_flags, stack_start, - regs, stack_size, - (int __user *) parent_tid_ptr, - (int __user *) child_tid_ptr); + ret = do_fork(clone_flags, stack_start, + regs, stack_size, + (int __user *) parent_tid_ptr, + (int __user *) child_tid_ptr); + + /* If we get an error and potentially restart the system + * call, we're screwed because copy_thread() clobbered + * the parent's %o1. So detect that case and restore it + * here. + */ + if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + regs->u_regs[UREG_I1] = orig_i1; + + return ret; } /* Copy a Sparc thread. The fork() return value conventions diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 3c312290c3c..368157926d2 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -245,15 +245,29 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen) static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) { - unsigned long sp; + unsigned long sp = regs->u_regs[UREG_FP]; - sp = regs->u_regs[UREG_FP]; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ if (sa->sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* 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; + return (void __user *)(sp - framesize); } diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index f188b5dc9fd..e995491c443 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -223,8 +223,7 @@ int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) { if (ARCH_SUN4C_SUN4 && (len > 0x20000000 || - ((flags & MAP_FIXED) && - addr < 0xe0000000 && addr + len > 0x20000000))) + (addr < 0xe0000000 && addr + len > 0x20000000))) return -EINVAL; /* See asm-sparc/uaccess.h */ diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 500ac6d483a..4129c044985 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -503,6 +503,8 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, unsigned long stack_size) { int __user *parent_tid_ptr, *child_tid_ptr; + unsigned long orig_i1 = regs->u_regs[UREG_I1]; + long ret; #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { @@ -515,9 +517,19 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; } - return do_fork(clone_flags, stack_start, - regs, stack_size, - parent_tid_ptr, child_tid_ptr); + ret = do_fork(clone_flags, stack_start, + regs, stack_size, + parent_tid_ptr, child_tid_ptr); + + /* If we get an error and potentially restart the system + * call, we're screwed because copy_thread() clobbered + * the parent's %o1. So detect that case and restore it + * here. + */ + if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + regs->u_regs[UREG_I1] = orig_i1; + + return ret; } /* Copy a Sparc thread. The fork() return value conventions diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 45d6bf632da..07c0443ea3f 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -376,16 +376,29 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { - unsigned long sp; + unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; - sp = regs->u_regs[UREG_FP] + STACK_BIAS; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && - !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* 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; + return (void __user *)(sp - framesize); } diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 9415d2c918c..0f6b7b156ef 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -406,11 +406,27 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; sp = regs->u_regs[UREG_FP]; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; + /* This is the X/Open sanctioned signal stack switching. */ if (sa->sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* 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; + return (void __user *)(sp - framesize); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 3aba47624df..0d6403a630a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -865,21 +865,14 @@ void smp_call_function_client(int irq, struct pt_regs *regs) void *info = call_data->info; clear_softint(1 << irq); - - irq_enter(); - - if (!call_data->wait) { - /* let initiator proceed after getting data */ - atomic_inc(&call_data->finished); - } - - func(info); - - irq_exit(); - if (call_data->wait) { /* let initiator proceed only after completion */ + func(info); atomic_inc(&call_data->finished); + } else { + /* let initiator proceed after getting data */ + atomic_inc(&call_data->finished); + func(info); } } @@ -1041,9 +1034,7 @@ void smp_receive_signal(int cpu) void smp_receive_signal_client(int irq, struct pt_regs *regs) { - irq_enter(); clear_softint(1 << irq); - irq_exit(); } void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) @@ -1051,8 +1042,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) struct mm_struct *mm; unsigned long flags; - irq_enter(); - clear_softint(1 << irq); /* See if we need to allocate a new TLB context because @@ -1072,8 +1061,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) load_secondary_context(mm); __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT); - - irq_exit(); } void smp_new_mmu_context_version(void) @@ -1239,8 +1226,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) { clear_softint(1 << irq); - irq_enter(); - preempt_disable(); __asm__ __volatile__("flushw"); @@ -1253,8 +1238,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) prom_world(0); preempt_enable(); - - irq_exit(); } /* /proc/profile writes can call this, don't __init it please. */ diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 8d4761f15fa..0dbc941f130 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -549,13 +549,13 @@ int sparc64_mmap_check(unsigned long addr, unsigned long len, if (len >= STACK_TOP32) return -EINVAL; - if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) + if (addr > STACK_TOP32 - len) return -EINVAL; } else { if (len >= VA_EXCLUDE_START) return -EINVAL; - if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) + if (invalid_64bit_range(addr, len)) return -EINVAL; } diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 161ce4710fe..1aa4288125f 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -236,13 +236,6 @@ asmlinkage long sys32_getegid16(void) /* 32-bit timeval and related flotsam. */ -static long get_tv32(struct timeval *o, struct compat_timeval __user *i) -{ - return (!access_ok(VERIFY_READ, i, sizeof(*i)) || - (__get_user(o->tv_sec, &i->tv_sec) | - __get_user(o->tv_usec, &i->tv_usec))); -} - static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || @@ -757,30 +750,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -asmlinkage long sys32_utimes(char __user *filename, - struct compat_timeval __user *tvs) -{ - struct timespec tv[2]; - - if (tvs) { - struct timeval ktvs[2]; - if (get_tv32(&ktvs[0], tvs) || - get_tv32(&ktvs[1], 1+tvs)) - return -EFAULT; - - if (ktvs[0].tv_usec < 0 || ktvs[0].tv_usec >= 1000000 || - ktvs[1].tv_usec < 0 || ktvs[1].tv_usec >= 1000000) - return -EINVAL; - - tv[0].tv_sec = ktvs[0].tv_sec; - tv[0].tv_nsec = 1000 * ktvs[0].tv_usec; - tv[1].tv_sec = ktvs[1].tv_sec; - tv[1].tv_nsec = 1000 * ktvs[1].tv_usec; - } - - return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0); -} - /* These are here just in case some old sparc32 binary calls it. */ asmlinkage long sys32_pause(void) { diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index a4fef2ba1ae..8b5282d433c 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -45,7 +45,7 @@ sys_call_table32: /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64 + .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64 /*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 4cad0b32b0a..ec3e2c72302 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -771,6 +771,9 @@ static void __init find_ramdisk(unsigned long phys_base) initrd_end = ramdisk_image + sparc_ramdisk_size; lmb_reserve(initrd_start, initrd_end); + + initrd_start += PAGE_OFFSET; + initrd_end += PAGE_OFFSET; } #endif } @@ -2362,16 +2365,3 @@ void __flush_tlb_all(void) __asm__ __volatile__("wrpr %0, 0, %%pstate" : : "r" (pstate)); } - -#ifdef CONFIG_MEMORY_HOTPLUG - -void online_page(struct page *page) -{ - ClearPageReserved(page); - init_page_count(page); - __free_page(page); - totalram_pages++; - num_physpages++; -} - -#endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 10b86e1cc65..5047490fc29 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -191,9 +191,9 @@ void line_flush_chars(struct tty_struct *tty) line_flush_buffer(tty); } -void line_put_char(struct tty_struct *tty, unsigned char ch) +int line_put_char(struct tty_struct *tty, unsigned char ch) { - line_write(tty, &ch, sizeof(ch)); + return line_write(tty, &ch, sizeof(ch)); } int line_write(struct tty_struct *tty, const unsigned char *buf, int len) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 1223f2c844b..979b73e6352 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -71,7 +71,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, char **error_out); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); -extern void line_put_char(struct tty_struct *tty, unsigned char ch); +extern int line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index bbdacb398d4..5e618c3b472 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -83,9 +83,7 @@ obj-$(CONFIG_KVM_GUEST) += kvm.o obj-$(CONFIG_KVM_CLOCK) += kvmclock.o obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o -ifdef CONFIG_INPUT_PCSPKR -obj-y += pcspeaker.o -endif +obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index bfa72a9475b..8545c8a9d10 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -77,19 +77,6 @@ int pcibios_scanned; */ DEFINE_SPINLOCK(pci_config_lock); -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) -{ - struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; - - if (rom_r->parent) - return; - if (rom_r->start) - /* we deal with BIOS assigned ROM later */ - return; - if (!(pci_probe & PCI_ASSIGN_ROMS)) - rom_r->start = rom_r->end = rom_r->flags = 0; -} - static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) { pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; @@ -141,11 +128,7 @@ void __init dmi_check_skip_isa_align(void) void __devinit pcibios_fixup_bus(struct pci_bus *b) { - struct pci_dev *dev; - pci_read_bridge_bases(b); - list_for_each_entry(dev, &b->devices, bus_list) - pcibios_fixup_device_resources(dev); } /* |