aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/pci-noop.c4
-rw-r--r--arch/alpha/kernel/pci_iommu.c24
-rw-r--r--arch/alpha/kernel/setup.c1
-rw-r--r--arch/alpha/kernel/systbls.S2
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/smp.c2
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/generic.c93
-rw-r--r--arch/arm/mach-pxa/generic.h1
-rw-r--r--arch/arm/mach-pxa/gpio.c197
-rw-r--r--arch/arm/mach-pxa/irq.c2
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/mm/pgd.c8
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/avr32/kernel/syscall_table.S2
-rw-r--r--arch/avr32/mach-at32ap/pio.c172
-rw-r--r--arch/avr32/mach-at32ap/pio.h2
-rw-r--r--arch/blackfin/mach-common/entry.S2
-rw-r--r--arch/cris/Kconfig5
-rw-r--r--arch/cris/arch-v10/Kconfig4
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig4
-rw-r--r--arch/cris/arch-v10/kernel/entry.S2
-rw-r--r--arch/cris/arch-v32/Kconfig4
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig4
-rw-r--r--arch/cris/arch-v32/drivers/pci/dma.c4
-rw-r--r--arch/frv/Kconfig9
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/vmlinux.lds.S2
-rw-r--r--arch/frv/mm/mmu-context.c2
-rw-r--r--arch/frv/mm/pgalloc.c2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c10
-rw-r--r--arch/ia64/ia32/ia32_support.c5
-rw-r--r--arch/ia64/kernel/efi.c502
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/fsyscall_gtod_data.h4
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c3
-rw-r--r--arch/ia64/kernel/kprobes.c7
-rw-r--r--arch/ia64/kernel/mca.c66
-rw-r--r--arch/ia64/kernel/mca_asm.S46
-rw-r--r--arch/ia64/kernel/mca_drv.c2
-rw-r--r--arch/ia64/kernel/mca_drv.h2
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S2
-rw-r--r--arch/ia64/kernel/perfmon.c6
-rw-r--r--arch/ia64/kernel/sal.c14
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/smpboot.c11
-rw-r--r--arch/ia64/kernel/traps.c35
-rw-r--r--arch/ia64/kernel/unaligned.c13
-rw-r--r--arch/ia64/mm/fault.c8
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c2
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c11
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c4
-rw-r--r--arch/m32r/kernel/syscall_table.S2
-rw-r--r--arch/m68k/Kconfig14
-rw-r--r--arch/m68k/Makefile11
-rw-r--r--arch/m68k/amiga/Makefile2
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c33
-rw-r--r--arch/m68k/amiga/amisound.c5
-rw-r--r--arch/m68k/amiga/chipram.c7
-rw-r--r--arch/m68k/amiga/config.c12
-rw-r--r--arch/m68k/amiga/pcmcia.c9
-rw-r--r--arch/m68k/atari/Makefile2
-rw-r--r--arch/m68k/atari/ataints.c3
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c2
-rw-r--r--arch/m68k/atari/config.c11
-rw-r--r--arch/m68k/atari/debug.c6
-rw-r--r--arch/m68k/atari/hades-pci.c54
-rw-r--r--arch/m68k/atari/stdma.c5
-rw-r--r--arch/m68k/atari/stram.c3
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/hp300/Makefile2
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/mac/Makefile2
-rw-r--r--arch/m68k/mac/config.c2
-rw-r--r--arch/m68k/mac/mac_ksyms.c8
-rw-r--r--arch/m68k/mac/via.c5
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c2
-rw-r--r--arch/m68k/mvme16x/mvme16x_ksyms.c6
-rw-r--r--arch/m68knommu/Kconfig.debug7
-rw-r--r--arch/m68knommu/defconfig1
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c11
-rw-r--r--arch/m68knommu/kernel/setup.c3
-rw-r--r--arch/m68knommu/kernel/syscalltable.S2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/powerpc/Kconfig3
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/dma_64.c8
-rw-r--r--arch/powerpc/kernel/iommu.c93
-rw-r--r--arch/powerpc/kernel/legacy_serial.c3
-rw-r--r--arch/powerpc/kernel/vio.c2
-rw-r--r--arch/powerpc/mm/mem.c7
-rw-r--r--arch/powerpc/mm/pgtable_32.c6
-rw-r--r--arch/powerpc/platforms/82xx/mpc8272_ads.c3
-rw-r--r--arch/powerpc/platforms/82xx/pq2fads.c3
-rw-r--r--arch/powerpc/platforms/cell/Kconfig7
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c99
-rw-r--r--arch/powerpc/platforms/cell/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c29
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c7
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c28
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h5
-rw-r--r--arch/powerpc/platforms/cell/spufs/sputrace.c250
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c1
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c10
-rw-r--r--arch/ppc/mm/pgtable.c6
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Kconfig.debug8
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/entry.S7
-rw-r--r--arch/s390/kernel/entry64.S7
-rw-r--r--arch/s390/kernel/ipl.c27
-rw-r--r--arch/s390/kernel/setup.c14
-rw-r--r--arch/s390/kernel/smp.c13
-rw-r--r--arch/s390/kernel/stacktrace.c31
-rw-r--r--arch/s390/kernel/syscalls.S2
-rw-r--r--arch/s390/kernel/traps.c5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/mm/init.c27
-rw-r--r--arch/s390/mm/vmem.c5
-rw-r--r--arch/sh/kernel/syscalls_32.S2
-rw-r--r--arch/sh/kernel/syscalls_64.S2
-rw-r--r--arch/sparc/kernel/systbls.S2
-rw-r--r--arch/sparc64/kernel/iommu.c2
-rw-r--r--arch/sparc64/kernel/iommu_common.c8
-rw-r--r--arch/sparc64/kernel/iommu_common.h3
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c8
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/um/Kconfig26
-rw-r--r--arch/um/Kconfig.char2
-rw-r--r--arch/um/Kconfig.debug6
-rw-r--r--arch/um/Kconfig.net12
-rw-r--r--arch/um/Makefile12
-rw-r--r--arch/um/Makefile-tt5
-rw-r--r--arch/um/defconfig6
-rw-r--r--arch/um/drivers/line.c28
-rw-r--r--arch/um/drivers/mconsole_kern.c55
-rw-r--r--arch/um/drivers/mconsole_user.c5
-rw-r--r--arch/um/drivers/net_kern.c16
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/port_kern.c7
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c1
-rw-r--r--arch/um/drivers/stdio_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c30
-rw-r--r--arch/um/drivers/ubd_user.c1
-rw-r--r--arch/um/drivers/vde_user.c2
-rw-r--r--arch/um/include/arch.h2
-rw-r--r--arch/um/include/as-layout.h34
-rw-r--r--arch/um/include/chan_user.h2
-rw-r--r--arch/um/include/common-offsets.h1
-rw-r--r--arch/um/include/init.h25
-rw-r--r--arch/um/include/irq_user.h1
-rw-r--r--arch/um/include/kern_util.h120
-rw-r--r--arch/um/include/mem_user.h5
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h41
-rw-r--r--arch/um/include/ptrace_user.h11
-rw-r--r--arch/um/include/registers.h7
-rw-r--r--arch/um/include/signal_kern.h22
-rw-r--r--arch/um/include/skas/mode-skas.h11
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h5
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h9
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h2
-rw-r--r--arch/um/include/um_mmu.h4
-rw-r--r--arch/um/include/um_uaccess.h4
-rw-r--r--arch/um/kernel/exec.c5
-rw-r--r--arch/um/kernel/exitcode.c31
-rw-r--r--arch/um/kernel/gmon_syms.c11
-rw-r--r--arch/um/kernel/gprof_syms.c13
-rw-r--r--arch/um/kernel/initrd.c30
-rw-r--r--arch/um/kernel/irq.c6
-rw-r--r--arch/um/kernel/ksyms.c5
-rw-r--r--arch/um/kernel/mem.c147
-rw-r--r--arch/um/kernel/physmem.c16
-rw-r--r--arch/um/kernel/process.c154
-rw-r--r--arch/um/kernel/reboot.c7
-rw-r--r--arch/um/kernel/sigio.c18
-rw-r--r--arch/um/kernel/signal.c16
-rw-r--r--arch/um/kernel/skas/clone.c32
-rw-r--r--arch/um/kernel/skas/mmu.c127
-rw-r--r--arch/um/kernel/skas/process.c20
-rw-r--r--arch/um/kernel/skas/syscall.c6
-rw-r--r--arch/um/kernel/skas/uaccess.c140
-rw-r--r--arch/um/kernel/smp.c14
-rw-r--r--arch/um/kernel/syscall.c3
-rw-r--r--arch/um/kernel/sysrq.c44
-rw-r--r--arch/um/kernel/time.c14
-rw-r--r--arch/um/kernel/tlb.c51
-rw-r--r--arch/um/kernel/trap.c33
-rw-r--r--arch/um/kernel/uaccess.c11
-rw-r--r--arch/um/kernel/um_arch.c100
-rw-r--r--arch/um/kernel/umid.c15
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/aio.c1
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c5
-rw-r--r--arch/um/os-Linux/file.c287
-rw-r--r--arch/um/os-Linux/helper.c74
-rw-r--r--arch/um/os-Linux/irq.c39
-rw-r--r--arch/um/os-Linux/main.c14
-rw-r--r--arch/um/os-Linux/mem.c13
-rw-r--r--arch/um/os-Linux/process.c5
-rw-r--r--arch/um/os-Linux/registers.c34
-rw-r--r--arch/um/os-Linux/sigio.c244
-rw-r--r--arch/um/os-Linux/signal.c102
-rw-r--r--arch/um/os-Linux/skas/Makefile6
-rw-r--r--arch/um/os-Linux/skas/process.c281
-rw-r--r--arch/um/os-Linux/skas/trap.c69
-rw-r--r--arch/um/os-Linux/start_up.c17
-rw-r--r--arch/um/os-Linux/trap.c23
-rw-r--r--arch/um/os-Linux/tty.c57
-rw-r--r--arch/um/os-Linux/tty_log.c1
-rw-r--r--arch/um/os-Linux/util.c15
-rw-r--r--arch/um/sys-i386/bug.c1
-rw-r--r--arch/um/sys-i386/bugs.c201
-rw-r--r--arch/um/sys-i386/ldt.c19
-rw-r--r--arch/um/sys-i386/ptrace.c6
-rw-r--r--arch/um/sys-i386/ptrace_user.c14
-rw-r--r--arch/um/sys-i386/signal.c18
-rw-r--r--arch/um/sys-i386/stub.S8
-rw-r--r--arch/um/sys-i386/stub_segv.c19
-rw-r--r--arch/um/sys-i386/sys_call_table.S5
-rw-r--r--arch/um/sys-i386/tls.c41
-rw-r--r--arch/um/sys-ppc/Makefile22
-rw-r--r--arch/um/sys-x86_64/bug.c3
-rw-r--r--arch/um/sys-x86_64/bugs.c7
-rw-r--r--arch/um/sys-x86_64/ptrace.c29
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c46
-rw-r--r--arch/um/sys-x86_64/signal.c4
-rw-r--r--arch/um/sys-x86_64/stub.S8
-rw-r--r--arch/um/sys-x86_64/stub_segv.c39
-rw-r--r--arch/um/sys-x86_64/syscall_table.c43
-rw-r--r--arch/um/sys-x86_64/syscalls.c10
-rw-r--r--arch/um/sys-x86_64/sysrq.c29
-rw-r--r--arch/um/sys-x86_64/um_module.c8
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/ia32/ia32entry.S4
-rw-r--r--arch/x86/kernel/pci-calgary_64.c34
-rw-r--r--arch/x86/kernel/pci-gart_64.c48
-rw-r--r--arch/x86/kernel/syscall_table_32.S4
-rw-r--r--arch/x86/kvm/x86.c8
-rw-r--r--arch/x86/lib/Makefile2
-rw-r--r--arch/x86/lib/bitstr_64.c28
-rw-r--r--arch/x86/mm/pageattr.c1
-rw-r--r--arch/x86/mm/pgtable_32.c12
-rw-r--r--arch/x86/pci/i386.c2
258 files changed, 3119 insertions, 2898 deletions
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 468b76ce66a..8ac08311f5a 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -165,7 +165,7 @@ dma_alloc_coherent(struct device *dev, size_t size,
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret) {
memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
+ *dma_handle = virt_to_phys(ret);
}
return ret;
}
@@ -184,7 +184,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
BUG_ON(!sg_page(sg));
va = sg_virt(sg);
- sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
+ sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
sg_dma_len(sg) = sg->length;
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 2d00a08d3f0..26d3789dfdd 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -9,6 +9,7 @@
#include <linux/bootmem.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
@@ -470,22 +471,29 @@ EXPORT_SYMBOL(pci_free_consistent);
#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
static void
-sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
+sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
+ int virt_ok)
{
unsigned long next_paddr;
struct scatterlist *leader;
long leader_flag, leader_length;
+ unsigned int max_seg_size;
leader = sg;
leader_flag = 0;
leader_length = leader->length;
next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
+ /* we will not marge sg without device. */
+ max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
for (++sg; sg < end; ++sg) {
unsigned long addr, len;
addr = SG_ENT_PHYS_ADDRESS(sg);
len = sg->length;
+ if (leader_length + len > max_seg_size)
+ goto new_segment;
+
if (next_paddr == addr) {
sg->dma_address = -1;
leader_length += len;
@@ -494,6 +502,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
leader_flag = 1;
leader_length += len;
} else {
+new_segment:
leader->dma_address = leader_flag;
leader->dma_length = leader_length;
leader = sg;
@@ -512,7 +521,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
in the blanks. */
static int
-sg_fill(struct scatterlist *leader, struct scatterlist *end,
+sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
struct scatterlist *out, struct pci_iommu_arena *arena,
dma_addr_t max_dma, int dac_allowed)
{
@@ -562,8 +571,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
/* Otherwise, break up the remaining virtually contiguous
hunks into individual direct maps and retry. */
- sg_classify(leader, end, 0);
- return sg_fill(leader, end, out, arena, max_dma, dac_allowed);
+ sg_classify(dev, leader, end, 0);
+ return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
}
out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
@@ -619,12 +628,15 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
struct pci_iommu_arena *arena;
dma_addr_t max_dma;
int dac_allowed;
+ struct device *dev;
if (direction == PCI_DMA_NONE)
BUG();
dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ dev = pdev ? &pdev->dev : NULL;
+
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg->dma_length = sg->length;
@@ -638,7 +650,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
end = sg + nents;
/* First, prepare information about the entries. */
- sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
+ sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
/* Second, figure out where we're going to map things. */
if (alpha_mv.mv_pci_tbi) {
@@ -658,7 +670,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
for (out = sg; sg < end; ++sg) {
if ((int) sg->dma_address < 0)
continue;
- if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0)
+ if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
goto error;
out++;
}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bd5e68cd61e..beff6297f78 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -58,7 +58,6 @@ static struct notifier_block alpha_panic_block = {
#include <asm/system.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
-#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/console.h>
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 79de99e32c3..ba914af18c4 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -495,7 +495,7 @@ sys_call_table:
.quad sys_epoll_pwait
.quad sys_utimensat /* 475 */
.quad sys_signalfd
- .quad sys_timerfd
+ .quad sys_ni_syscall
.quad sys_eventfd
.size sys_call_table, . - sys_call_table
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 64d19eff3fa..e19e7744e36 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -385,6 +385,7 @@ config ARCH_PXA
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
+ select HAVE_GPIO_LIB
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
@@ -1122,6 +1123,8 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
+source "drivers/gpio/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/power/Kconfig"
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index cecf658e362..283e14fff99 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -359,7 +359,7 @@
CALL(sys_kexec_load)
CALL(sys_utimensat)
CALL(sys_signalfd)
-/* 350 */ CALL(sys_timerfd)
+/* 350 */ CALL(sys_ni_syscall)
CALL(sys_eventfd)
CALL(sys_fallocate)
#ifndef syscalls_counted
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e9dfbab46cb..eefae1de334 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -150,7 +150,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.pgdir = 0;
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
- pgd_free(pgd);
+ pgd_free(&init_mm, pgd);
if (ret) {
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 8604938bd94..6e0c4f5b5ae 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,8 @@
#
# Common support (must be linked before board specific support)
-obj-y += clock.o devices.o generic.o irq.o dma.o time.o
+obj-y += clock.o devices.o generic.o irq.o dma.o \
+ time.o gpio.o
obj-$(CONFIG_PXA25x) += pxa25x.o
obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 76970598f55..80721c610d4 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -32,7 +32,6 @@
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/gpio.h>
#include "generic.h"
@@ -67,97 +66,6 @@ unsigned int get_memclk_frequency_10khz(void)
EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
- * Handy function to set GPIO alternate functions
- */
-int pxa_last_gpio;
-
-int pxa_gpio_mode(int gpio_mode)
-{
- unsigned long flags;
- int gpio = gpio_mode & GPIO_MD_MASK_NR;
- int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
- int gafr;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- local_irq_save(flags);
- if (gpio_mode & GPIO_DFLT_LOW)
- GPCR(gpio) = GPIO_bit(gpio);
- else if (gpio_mode & GPIO_DFLT_HIGH)
- GPSR(gpio) = GPIO_bit(gpio);
- if (gpio_mode & GPIO_MD_MASK_DIR)
- GPDR(gpio) |= GPIO_bit(gpio);
- else
- GPDR(gpio) &= ~GPIO_bit(gpio);
- gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
- GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(pxa_gpio_mode);
-
-int gpio_direction_input(unsigned gpio)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- GPDR(gpio) &= ~mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- if (value)
- GPSR(gpio) = mask;
- else
- GPCR(gpio) = mask;
- GPDR(gpio) |= mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*
- * Return GPIO level
- */
-int pxa_gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-EXPORT_SYMBOL(pxa_gpio_get_value);
-
-/*
- * Set output GPIO level
- */
-void pxa_gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-EXPORT_SYMBOL(pxa_gpio_set_value);
-
-/*
* Routine to safely enable or disable a clock in the CKEN
*/
void __pxa_set_cken(int clock, int enable)
@@ -172,7 +80,6 @@ void __pxa_set_cken(int clock, int enable)
local_irq_restore(flags);
}
-
EXPORT_SYMBOL(__pxa_set_cken);
/*
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 1a16ad3ecee..b3d10b0e52a 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -16,6 +16,7 @@ extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq_gpio(int gpio_nr);
extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+extern void __init pxa_init_gpio(int gpio_nr);
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
new file mode 100644
index 00000000000..8638dd7dd07
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-pxa/gpio.c
+ *
+ * Generic PXA GPIO handling
+ *
+ * Author: Nicolas Pitre
+ * Created: Jun 15, 2001
+ * Copyright: MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#include "generic.h"
+
+
+struct pxa_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *regbase;
+};
+
+int pxa_last_gpio;
+
+/*
+ * Configure pins for GPIO or other functions
+ */
+int pxa_gpio_mode(int gpio_mode)
+{
+ unsigned long flags;
+ int gpio = gpio_mode & GPIO_MD_MASK_NR;
+ int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+ int gafr;
+
+ if (gpio > pxa_last_gpio)
+ return -EINVAL;
+
+ local_irq_save(flags);
+ if (gpio_mode & GPIO_DFLT_LOW)
+ GPCR(gpio) = GPIO_bit(gpio);
+ else if (gpio_mode & GPIO_DFLT_HIGH)
+ GPSR(gpio) = GPIO_bit(gpio);
+ if (gpio_mode & GPIO_MD_MASK_DIR)
+ GPDR(gpio) |= GPIO_bit(gpio);
+ else
+ GPDR(gpio) &= ~GPIO_bit(gpio);
+ gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+ GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(pxa_gpio_mode);
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 value;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ value = __raw_readl(gpdr);
+ value &= ~mask;
+ __raw_writel(value, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 tmp;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ __raw_writel(mask,
+ pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ tmp = __raw_readl(gpdr);
+ tmp |= mask;
+ __raw_writel(tmp, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/*
+ * Return GPIO level
+ */
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
+}
+
+/*
+ * Set output GPIO level
+ */
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ if (value)
+ __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
+ else
+ __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
+}
+
+static struct pxa_gpio_chip pxa_gpio_chip[] = {
+ [0] = {
+ .regbase = GPIO0_BASE,
+ .chip = {
+ .label = "gpio-0",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 0,
+ .ngpio = 32,
+ },
+ },
+ [1] = {
+ .regbase = GPIO1_BASE,
+ .chip = {
+ .label = "gpio-1",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 32,
+ .ngpio = 32,
+ },
+ },
+ [2] = {
+ .regbase = GPIO2_BASE,
+ .chip = {
+ .label = "gpio-2",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 64,
+ .ngpio = 32, /* 21 for PXA25x */
+ },
+ },
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ [3] = {
+ .regbase = GPIO3_BASE,
+ .chip = {
+ .label = "gpio-3",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 96,
+ .ngpio = 32,
+ },
+ },
+#endif
+};
+
+void __init pxa_init_gpio(int gpio_nr)
+{
+ int i;
+
+ /* add a GPIO chip for each register bank.
+ * the last PXA25x register only contains 21 GPIOs
+ */
+ for (i = 0; i < gpio_nr; i += 32) {
+ if (i+32 > gpio_nr)
+ pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
+ gpiochip_add(&pxa_gpio_chip[i/32].chip);
+ }
+}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 5a1d5eef10a..36c6a68beca 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -311,6 +311,8 @@ void __init pxa_init_irq_gpio(int gpio_nr)
/* Install handler for GPIO>=2 edge detect interrupts */
set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+
+ pxa_init_gpio(gpio_nr);
}
void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 75952779ce1..303a7ff6bfd 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -162,7 +162,7 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
* Free the page table, if there was one.
*/
if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
- pte_free_kernel(pmd_page_vaddr(pmd));
+ pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
}
addr += PGDIR_SIZE;
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 50b9aed6000..500c9610ab3 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -65,14 +65,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
return new_pgd;
no_pte:
- pmd_free(new_pmd);
+ pmd_free(mm, new_pmd);
no_pmd:
free_pages((unsigned long)new_pgd, 2);
no_pgd:
return NULL;
}
-void free_pgd_slow(pgd_t *pgd)
+void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
{
pmd_t *pmd;
struct page *pte;
@@ -94,8 +94,8 @@ void free_pgd_slow(pgd_t *pgd)
pmd_clear(pmd);
dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
pte_lock_deinit(pte);
- pte_free(pte);
- pmd_free(pmd);
+ pte_free(mm, pte);
+ pmd_free(mm, pmd);
free:
free_pages((unsigned long) pgd, 2);
}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c816f29154c..28e0caf4156 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -82,6 +82,7 @@ config PLATFORM_AT32AP
select SUBARCH_AVR32B
select MMU
select PERFORMANCE_COUNTERS
+ select HAVE_GPIO_LIB
#
# CPU types
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 75c81f2dd0b..478bda4c4a0 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -293,6 +293,6 @@ sys_call_table:
.long sys_shmctl
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd /* 280 */
+ .long sys_ni_syscall /* 280, was sys_timerfd */
.long sys_eventfd
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d61a02da898..38a8fa31c0b 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -24,11 +24,11 @@
#define MAX_NR_PIO_DEVICES 8
struct pio_device {
+ struct gpio_chip chip;
void __iomem *regs;
const struct platform_device *pdev;
struct clk *clk;
u32 pinmux_mask;
- u32 gpio_mask;
char name[8];
};
@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
goto fail;
}
- if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
+ || gpiochip_is_requested(&pio->chip, pin_index))) {
printk("%s: pin %u is busy\n", pio->name, pin_index);
goto fail;
}
@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask);
- /* gpio_request NOT allowed */
- set_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
pio_writel(pio, PER, mask);
- /* gpio_request now allowed */
- clear_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -166,96 +161,50 @@ fail:
/* GPIO API */
-int gpio_request(unsigned int gpio, const char *label)
+static int direction_input(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- pin = gpio & 0x1f;
- if (test_and_set_bit(pin, &pio->gpio_mask))
- return -EBUSY;
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ pio_writel(pio, ODR, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_request);
-void gpio_free(unsigned int gpio)
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
- pio = gpio_to_pio(gpio);
- if (!pio) {
- printk(KERN_ERR
- "gpio: attempted to free invalid pin %u\n", gpio);
- return;
- }
-
- pin = gpio & 0x1f;
- if (!test_and_clear_bit(pin, &pio->gpio_mask))
- printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
- pio->name, pin);
+ return (pio_readl(pio, PDSR) >> offset) & 1;
}
-EXPORT_SYMBOL(gpio_free);
-int gpio_direction_input(unsigned int gpio)
-{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
-
- pin = gpio & 0x1f;
- pio_writel(pio, ODR, 1 << pin);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
-int gpio_direction_output(unsigned int gpio, int value)
+static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- gpio_set_value(gpio, value);
-
- pin = gpio & 0x1f;
- pio_writel(pio, OER, 1 << pin);
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ gpio_set(chip, offset, value);
+ pio_writel(pio, OER, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_output);
-int gpio_get_value(unsigned int gpio)
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio = &pio_dev[gpio >> 5];
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned int gpio, int value)
-{
- struct pio_device *pio = &pio_dev[gpio >> 5];
- u32 mask;
-
- mask = 1 << (gpio & 0x1f);
if (value)
pio_writel(pio, SODR, mask);
else
pio_writel(pio, CODR, mask);
}
-EXPORT_SYMBOL(gpio_set_value);
/*--------------------------------------------------------------------------*/
@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
/*--------------------------------------------------------------------------*/
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+/*
+ * This shows more info than the generic gpio dump code:
+ * pullups, deglitching, open drain drive.
+ */
+static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
+ unsigned i;
+ u32 mask;
+ char bank;
+
+ psr = pio_readl(pio, PSR);
+ osr = pio_readl(pio, OSR);
+ imr = pio_readl(pio, IMR);
+ pdsr = pio_readl(pio, PDSR);
+ pusr = pio_readl(pio, PUSR);
+ ifsr = pio_readl(pio, IFSR);
+ mdsr = pio_readl(pio, MDSR);
+
+ bank = 'A' + pio->pdev->id;
+
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
+ const char *label;
+
+ label = gpiochip_is_requested(chip, i);
+ if (!label)
+ continue;
+
+ seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
+ chip->base + i, bank, i,
+ label,
+ (osr & mask) ? "out" : "in ",
+ (mask & pdsr) ? "hi" : "lo",
+ (mask & pusr) ? " " : "up");
+ if (ifsr & mask)
+ seq_printf(s, " deglitch");
+ if ((osr & mdsr) & mask)
+ seq_printf(s, " open-drain");
+ if (imr & mask)
+ seq_printf(s, " irq-%d edge-both",
+ gpio_to_irq(chip->base + i));
+ seq_printf(s, "\n");
+ }
+}
+
+#else
+#define pio_bank_show NULL
+#endif
+
+
+/*--------------------------------------------------------------------------*/
+
static int __init pio_probe(struct platform_device *pdev)
{
struct pio_device *pio = NULL;
@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
pio = &pio_dev[pdev->id];
BUG_ON(!pio->regs);
+ pio->chip.label = pio->name;
+ pio->chip.base = pdev->id * 32;
+ pio->chip.ngpio = 32;
+
+ pio->chip.direction_input = direction_input;
+ pio->chip.get = gpio_get;
+ pio->chip.direction_output = direction_output;
+ pio->chip.set = gpio_set;
+ pio->chip.dbg_show = pio_bank_show;
+
+ gpiochip_add(&pio->chip);
+
gpio_irq_setup(pio, irq, gpio_irq_base);
platform_set_drvdata(pdev, pio);
@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
pio->pdev = pdev;
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
- /*
- * request_gpio() is only valid for pins that have been
- * explicitly configured as GPIO and not previously requested
- */
- pio->gpio_mask = ~0UL;
-
/* start with irqs disabled and acked */
pio_writel(pio, IDR, ~0UL);
(void) pio_readl(pio, ISR);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 50fa3aca32c..7795116a483 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -19,7 +19,7 @@
#define PIO_OSR 0x0018
#define PIO_IFER 0x0020
#define PIO_IFDR 0x0024
-#define PIO_ISFR 0x0028
+#define PIO_IFSR 0x0028
#define PIO_SODR 0x0030
#define PIO_CODR 0x0034
#define PIO_ODSR 0x0038
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 56ff51bc8c2..fdd9bf43361 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -1373,7 +1373,7 @@ ENTRY(_sys_call_table)
.long _sys_epoll_pwait
.long _sys_utimensat
.long _sys_signalfd
- .long _sys_timerfd
+ .long _sys_ni_syscall
.long _sys_eventfd /* 350 */
.long _sys_pread64
.long _sys_pwrite64
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7f0be4cd5e9..27b082ac7f1 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -150,6 +150,7 @@ config ETRAX_FLASH_BUSWIDTH
Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
source arch/cris/arch-v10/Kconfig
+source arch/cris/arch-v32/Kconfig
endmenu
@@ -157,8 +158,8 @@ source "net/Kconfig"
# bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces"
-# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
-source arch/cris/arch/drivers/Kconfig
+source arch/cris/arch-v10/drivers/Kconfig
+source arch/cris/arch-v32/drivers/Kconfig
endmenu
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index f1ce6f64401..1d61faec77c 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V10
+
# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
config CRIS_LOW_MAP
bool
@@ -451,3 +453,5 @@ config ETRAX_POWERBUTTON_BIT
default "25"
help
Configure where power button is connected.
+
+endif
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index e3c0f292814..96740ef497d 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V10
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V10
@@ -806,3 +808,5 @@ config ETRAX_DS1302_TRICKLE_CHARGE
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
4 = 1 diode, 8 = 2 diodes
Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
+
+endif
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ec62c951fa3..d1361dc119e 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -1167,7 +1167,7 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
index 4f79d8ed3e1..d8acaa920e1 100644
--- a/arch/cris/arch-v32/Kconfig
+++ b/arch/cris/arch-v32/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V32
+
config ETRAX_DRAM_VIRTUAL_BASE
hex
depends on ETRAX_ARCH_V32
@@ -294,3 +296,5 @@ config ETRAX_DEF_GIO_PE_OUT
help
Configures the initial data for the general port E bits. Most
products should use 00000 here.
+
+endif
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 9bccb5e2a96..c329cce2a0c 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V32
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V32
@@ -610,3 +612,5 @@ config ETRAX_STREAMCOPROC
help
This option enables a driver for the stream co-processor
for cryptographic operations.
+
+endif
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index 66f9500fbc0..e0364654fc4 100644
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ b/arch/cris/arch-v32/drivers/pci/dma.c
@@ -93,7 +93,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
- goto out;
+ goto iounmap_out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
@@ -110,6 +110,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
free1_out:
kfree(dev->dma_mem);
+ iounmap_out:
+ iounmap(mem_base);
out:
return 0;
}
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index bf0468cbe71..96f7d70f447 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -138,6 +138,15 @@ config UCPAGE_OFFSET_C0000000
endchoice
+config PAGE_OFFSET
+ hex
+ default 0x20000000 if UCPAGE_OFFSET_20000000
+ default 0x40000000 if UCPAGE_OFFSET_40000000
+ default 0x60000000 if UCPAGE_OFFSET_60000000
+ default 0x80000000 if UCPAGE_OFFSET_80000000
+ default 0xA0000000 if UCPAGE_OFFSET_A0000000
+ default 0xC0000000
+
config PROTECT_KERNEL
bool "Protect core kernel against userspace"
depends on !MMU
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 99046b1f51c..ca6a345b87e 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1494,7 +1494,7 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index f42b328b1dd..ef7527b8b0c 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -13,7 +13,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4;
-__page_offset = 0xc0000000; /* start of area covered by struct pages */
+__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */
__kernel_image_start = __page_offset; /* address at which kernel image resides */
SECTIONS
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index 1530a4111e6..81757d55a5b 100644
--- a/arch/frv/mm/mmu-context.c
+++ b/arch/frv/mm/mmu-context.c
@@ -181,7 +181,7 @@ int cxn_pin_by_pid(pid_t pid)
/* get a handle on the mm_struct */
read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
+ tsk = find_task_by_vpid(pid);
if (tsk) {
ret = -EINVAL;
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 7787c3cc52c..1a2e5c8d03a 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -140,7 +140,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
/* in the non-PAE case, clear_page_tables() clears user pgd entries */
quicklist_free(0, pgd_dtor, pgd);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 45bf04eb7d7..a94445422cc 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1265,7 +1265,7 @@ sba_fill_pdir(
* the sglist do both.
*/
static SBA_INLINE int
-sba_coalesce_chunks( struct ioc *ioc,
+sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
struct scatterlist *startsg,
int nents)
{
@@ -1275,6 +1275,7 @@ sba_coalesce_chunks( struct ioc *ioc,
struct scatterlist *dma_sg; /* next DMA stream head */
unsigned long dma_offset, dma_len; /* start/len of DMA stream */
int n_mappings = 0;
+ unsigned int max_seg_size = dma_get_max_seg_size(dev);
while (nents > 0) {
unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1314,6 +1315,9 @@ sba_coalesce_chunks( struct ioc *ioc,
> DMA_CHUNK_SIZE)
break;
+ if (dma_len + startsg->length > max_seg_size)
+ break;
+
/*
** Then look for virtually contiguous blocks.
**
@@ -1441,7 +1445,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
** w/o this association, we wouldn't have coherent DMA!
** Access to the virtual address is what forces a two pass algorithm.
*/
- coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+ coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
/*
** Program the I/O Pdir
@@ -1871,7 +1875,7 @@ ioc_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations ioc_seq_ops = {
+static const struct seq_operations ioc_seq_ops = {
.start = ioc_start,
.next = ioc_next,
.stop = ioc_stop,
diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
index d1d50cd1c38..896b1ebbfb2 100644
--- a/arch/ia64/ia32/ia32_support.c
+++ b/arch/ia64/ia32/ia32_support.c
@@ -27,7 +27,7 @@
#include "ia32priv.h"
-extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel (char *str, struct pt_regs *regs, long err);
struct exec_domain ia32_exec_domain;
struct page *ia32_shared_page[NR_CPUS];
@@ -217,7 +217,8 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
{
siginfo_t siginfo;
- die_if_kernel("Bad IA-32 interrupt", regs, int_num);
+ if (die_if_kernel("Bad IA-32 interrupt", regs, int_num))
+ return;
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 242d7934112..919070a9aed 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -1,7 +1,8 @@
/*
* Extensible Firmware Interface
*
- * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
+ * Based on Extensible Firmware Interface Specification version 0.9
+ * April 30, 1999
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
@@ -48,145 +49,157 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
#define efi_call_virt(f, args...) (*(f))(args)
-#define STUB_GET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_cap_t *atc = NULL; \
- efi_status_t ret; \
- \
- if (tc) \
- atc = adjust_arg(tc); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_time_cap_t *atc = NULL; \
+ efi_status_t ret; \
+ \
+ if (tc) \
+ atc = adjust_arg(tc); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), \
+ adjust_arg(tm), atc); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_time (efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_time (efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), \
+ adjust_arg(tm)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
- adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, \
+ efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
+ adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_t *atm = NULL; \
- efi_status_t ret; \
- \
- if (tm) \
- atm = adjust_arg(tm); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
- enabled, atm); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_time_t *atm = NULL; \
+ efi_status_t ret; \
+ \
+ if (tm) \
+ atm = adjust_arg(tm); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
+ enabled, atm); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
- unsigned long *data_size, void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- u32 *aattr = NULL; \
- efi_status_t ret; \
- \
- if (attr) \
- aattr = adjust_arg(attr); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \
- adjust_arg(name), adjust_arg(vendor), aattr, \
- adjust_arg(data_size), adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
+ unsigned long *data_size, void *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ u32 *aattr = NULL; \
+ efi_status_t ret; \
+ \
+ if (attr) \
+ aattr = adjust_arg(attr); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_variable_t *) __va(runtime->get_variable), \
+ adjust_arg(name), adjust_arg(vendor), aattr, \
+ adjust_arg(data_size), adjust_arg(data)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \
- adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, \
+ efi_guid_t *vendor) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_next_variable_t *) __va(runtime->get_next_variable), \
+ adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \
- unsigned long data_size, void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \
- adjust_arg(name), adjust_arg(vendor), attr, data_size, \
- adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, \
+ unsigned long attr, unsigned long data_size, \
+ void *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_set_variable_t *) __va(runtime->set_variable), \
+ adjust_arg(name), adjust_arg(vendor), attr, data_size, \
+ adjust_arg(data)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_high_mono_count (u32 *count) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
- __va(runtime->get_next_high_mono_count), adjust_arg(count)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_next_high_mono_count (u32 *count) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
+ __va(runtime->get_next_high_mono_count), \
+ adjust_arg(count)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_RESET_SYSTEM(prefix, adjust_arg) \
-static void \
-prefix##_reset_system (int reset_type, efi_status_t status, \
- unsigned long data_size, efi_char16_t *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_char16_t *adata = NULL; \
- \
- if (data) \
- adata = adjust_arg(data); \
- \
- ia64_save_scratch_fpregs(fr); \
- efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \
- reset_type, status, data_size, adata); \
- /* should not return, but just in case... */ \
- ia64_load_scratch_fpregs(fr); \
+#define STUB_RESET_SYSTEM(prefix, adjust_arg) \
+static void \
+prefix##_reset_system (int reset_type, efi_status_t status, \
+ unsigned long data_size, efi_char16_t *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_char16_t *adata = NULL; \
+ \
+ if (data) \
+ adata = adjust_arg(data); \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ efi_call_##prefix( \
+ (efi_reset_system_t *) __va(runtime->reset_system), \
+ reset_type, status, data_size, adata); \
+ /* should not return, but just in case... */ \
+ ia64_load_scratch_fpregs(fr); \
}
#define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg))
@@ -223,7 +236,8 @@ efi_gettimeofday (struct timespec *ts)
return;
}
- ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
+ ts->tv_sec = mktime(tm.year, tm.month, tm.day,
+ tm.hour, tm.minute, tm.second);
ts->tv_nsec = tm.nanosecond;
}
@@ -297,8 +311,8 @@ walk (efi_freemem_callback_t callback, void *arg, u64 attr)
}
/*
- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
- * has memory that is available for OS use.
+ * Walk the EFI memory map and call CALLBACK once for each EFI memory
+ * descriptor that has memory that is available for OS use.
*/
void
efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
@@ -307,8 +321,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
}
/*
- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
- * has memory that is available for uncached allocator.
+ * Walk the EFI memory map and call CALLBACK once for each EFI memory
+ * descriptor that has memory that is available for uncached allocator.
*/
void
efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
@@ -317,11 +331,10 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
}
/*
- * Look for the PAL_CODE region reported by EFI and maps it using an
+ * Look for the PAL_CODE region reported by EFI and map it using an
* ITR to enable safe PAL calls in virtual mode. See IA-64 Processor
* Abstraction Layer chapter 11 in ADAG
*/
-
void *
efi_get_pal_addr (void)
{
@@ -341,45 +354,47 @@ efi_get_pal_addr (void)
continue;
if (++pal_code_count > 1) {
- printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n",
- md->phys_addr);
+ printk(KERN_ERR "Too many EFI Pal Code memory ranges, "
+ "dropped @ %lx\n", md->phys_addr);
continue;
}
/*
- * The only ITLB entry in region 7 that is used is the one installed by
- * __start(). That entry covers a 64MB range.
+ * The only ITLB entry in region 7 that is used is the one
+ * installed by __start(). That entry covers a 64MB range.
*/
mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
vaddr = PAGE_OFFSET + md->phys_addr;
/*
- * We must check that the PAL mapping won't overlap with the kernel
- * mapping.
+ * We must check that the PAL mapping won't overlap with the
+ * kernel mapping.
*
- * PAL code is guaranteed to be aligned on a power of 2 between 4k and
- * 256KB and that only one ITR is needed to map it. This implies that the
- * PAL code is always aligned on its size, i.e., the closest matching page
- * size supported by the TLB. Therefore PAL code is guaranteed never to
- * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for
- * now the following test is enough to determine whether or not we need a
- * dedicated ITR for the PAL code.
+ * PAL code is guaranteed to be aligned on a power of 2 between
+ * 4k and 256KB and that only one ITR is needed to map it. This
+ * implies that the PAL code is always aligned on its size,
+ * i.e., the closest matching page size supported by the TLB.
+ * Therefore PAL code is guaranteed never to cross a 64MB unless
+ * it is bigger than 64MB (very unlikely!). So for now the
+ * following test is enough to determine whether or not we need
+ * a dedicated ITR for the PAL code.
*/
if ((vaddr & mask) == (KERNEL_START & mask)) {
- printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
- __FUNCTION__);
+ printk(KERN_INFO "%s: no need to install ITR for "
+ "PAL code\n", __FUNCTION__);
continue;
}
if (efi_md_size(md) > IA64_GRANULE_SIZE)
- panic("Woah! PAL code size bigger than a granule!");
+ panic("Whoa! PAL code size bigger than a granule!");
#if EFI_DEBUG
mask = ~((1 << IA64_GRANULE_SHIFT) - 1);
- printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
- smp_processor_id(), md->phys_addr,
- md->phys_addr + efi_md_size(md),
- vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
+ printk(KERN_INFO "CPU %d: mapping PAL code "
+ "[0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
+ smp_processor_id(), md->phys_addr,
+ md->phys_addr + efi_md_size(md),
+ vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
#endif
return __va(md->phys_addr);
}
@@ -401,11 +416,11 @@ efi_map_pal_code (void)
* Cannot write to CRx with PSR.ic=1
*/
psr = ia64_clear_ic();
- ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr),
+ ia64_itr(0x1, IA64_TR_PALCODE,
+ GRANULEROUNDDOWN((unsigned long) pal_vaddr),
pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)),
IA64_GRANULE_SHIFT);
ia64_set_psr(psr); /* restore psr */
- ia64_srlz_i();
}
void __init
@@ -418,7 +433,10 @@ efi_init (void)
char *cp, vendor[100] = "unknown";
int i;
- /* it's too early to be able to use the standard kernel command line support... */
+ /*
+ * It's too early to be able to use the standard kernel command line
+ * support...
+ */
for (cp = boot_command_line; *cp; ) {
if (memcmp(cp, "mem=", 4) == 0) {
mem_limit = memparse(cp + 4, &cp);
@@ -434,9 +452,11 @@ efi_init (void)
}
}
if (min_addr != 0UL)
- printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20);
+ printk(KERN_INFO "Ignoring memory below %luMB\n",
+ min_addr >> 20);
if (max_addr != ~0UL)
- printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
+ printk(KERN_INFO "Ignoring memory above %luMB\n",
+ max_addr >> 20);
efi.systab = __va(ia64_boot_param->efi_systab);
@@ -444,9 +464,9 @@ efi_init (void)
* Verify the EFI Table
*/
if (efi.systab == NULL)
- panic("Woah! Can't find EFI system table.\n");
+ panic("Whoa! Can't find EFI system table.\n");
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
- panic("Woah! EFI system table signature incorrect\n");
+ panic("Whoa! EFI system table signature incorrect\n");
if ((efi.systab->hdr.revision >> 16) == 0)
printk(KERN_WARNING "Warning: EFI system table version "
"%d.%02d, expected 1.00 or greater\n",
@@ -464,7 +484,8 @@ efi_init (void)
}
printk(KERN_INFO "EFI v%u.%.02u by %s:",
- efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
+ efi.systab->hdr.revision >> 16,
+ efi.systab->hdr.revision & 0xffff, vendor);
efi.mps = EFI_INVALID_TABLE_ADDR;
efi.acpi = EFI_INVALID_TABLE_ADDR;
@@ -519,9 +540,12 @@ efi_init (void)
efi_memory_desc_t *md;
void *p;
- for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
+ for (i = 0, p = efi_map_start; p < efi_map_end;
+ ++i, p += efi_desc_size)
+ {
md = p;
- printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
+ printk("mem%02u: type=%u, attr=0x%lx, "
+ "range=[0x%016lx-0x%016lx) (%luMB)\n",
i, md->type, md->attribute, md->phys_addr,
md->phys_addr + efi_md_size(md),
md->num_pages >> (20 - EFI_PAGE_SHIFT));
@@ -549,8 +573,8 @@ efi_enter_virtual_mode (void)
md = p;
if (md->attribute & EFI_MEMORY_RUNTIME) {
/*
- * Some descriptors have multiple bits set, so the order of
- * the tests is relevant.
+ * Some descriptors have multiple bits set, so the
+ * order of the tests is relevant.
*/
if (md->attribute & EFI_MEMORY_WB) {
md->virt_addr = (u64) __va(md->phys_addr);
@@ -558,21 +582,26 @@ efi_enter_virtual_mode (void)
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
} else if (md->attribute & EFI_MEMORY_WC) {
#if 0
- md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
- | _PAGE_D
- | _PAGE_MA_WC
- | _PAGE_PL_0
- | _PAGE_AR_RW));
+ md->virt_addr = ia64_remap(md->phys_addr,
+ (_PAGE_A |
+ _PAGE_P |
+ _PAGE_D |
+ _PAGE_MA_WC |
+ _PAGE_PL_0 |
+ _PAGE_AR_RW));
#else
printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
#endif
} else if (md->attribute & EFI_MEMORY_WT) {
#if 0
- md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
- | _PAGE_D | _PAGE_MA_WT
- | _PAGE_PL_0
- | _PAGE_AR_RW));
+ md->virt_addr = ia64_remap(md->phys_addr,
+ (_PAGE_A |
+ _PAGE_P |
+ _PAGE_D |
+ _PAGE_MA_WT |
+ _PAGE_PL_0 |
+ _PAGE_AR_RW));
#else
printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
@@ -583,16 +612,18 @@ efi_enter_virtual_mode (void)
status = efi_call_phys(__va(runtime->set_virtual_address_map),
ia64_boot_param->efi_memmap_size,
- efi_desc_size, ia64_boot_param->efi_memdesc_version,
+ efi_desc_size,
+ ia64_boot_param->efi_memdesc_version,
ia64_boot_param->efi_memmap);
if (status != EFI_SUCCESS) {
- printk(KERN_WARNING "warning: unable to switch EFI into virtual mode "
- "(status=%lu)\n", status);
+ printk(KERN_WARNING "warning: unable to switch EFI into "
+ "virtual mode (status=%lu)\n", status);
return;
}
/*
- * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
+ * Now that EFI is in virtual mode, we call the EFI functions more
+ * efficiently:
*/
efi.get_time = virt_get_time;
efi.set_time = virt_set_time;
@@ -606,8 +637,8 @@ efi_enter_virtual_mode (void)
}
/*
- * Walk the EFI memory map looking for the I/O port range. There can only be one entry of
- * this type, other I/O port ranges should be described via ACPI.
+ * Walk the EFI memory map looking for the I/O port range. There can only be
+ * one entry of this type, other I/O port ranges should be described via ACPI.
*/
u64
efi_get_iobase (void)
@@ -678,7 +709,6 @@ efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
-
if (md->phys_addr < end && efi_md_end(md) > phys_addr)
return 1;
}
@@ -731,7 +761,7 @@ efi_mem_attribute (unsigned long phys_addr, unsigned long size)
if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
return 0;
} while (md);
- return 0;
+ return 0; /* never reached */
}
u64
@@ -767,7 +797,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
if (!md || md->attribute != attr)
return 0;
} while (md);
- return 0;
+ return 0; /* never reached */
}
EXPORT_SYMBOL(kern_mem_attribute);
@@ -883,7 +913,7 @@ efi_uart_console_only(void)
return 1;
uart = 0;
}
- hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length);
+ hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length);
}
printk(KERN_ERR "Malformed %s value\n", name);
return 0;
@@ -921,10 +951,12 @@ find_memmap_space (void)
if (!efi_wb(md)) {
continue;
}
- if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+ if (pmd == NULL || !efi_wb(pmd) ||
+ efi_md_end(pmd) != md->phys_addr) {
contig_low = GRANULEROUNDUP(md->phys_addr);
contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+ for (q = p + efi_desc_size; q < efi_map_end;
+ q += efi_desc_size) {
check_md = q;
if (!efi_wb(check_md))
break;
@@ -988,8 +1020,9 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
md = p;
if (!efi_wb(md)) {
- if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY ||
- md->type == EFI_BOOT_SERVICES_DATA)) {
+ if (efi_uc(md) &&
+ (md->type == EFI_CONVENTIONAL_MEMORY ||
+ md->type == EFI_BOOT_SERVICES_DATA)) {
k->attribute = EFI_MEMORY_UC;
k->start = md->phys_addr;
k->num_pages = md->num_pages;
@@ -997,10 +1030,12 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
}
continue;
}
- if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+ if (pmd == NULL || !efi_wb(pmd) ||
+ efi_md_end(pmd) != md->phys_addr) {
contig_low = GRANULEROUNDUP(md->phys_addr);
contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+ for (q = p + efi_desc_size; q < efi_map_end;
+ q += efi_desc_size) {
check_md = q;
if (!efi_wb(check_md))
break;
@@ -1025,13 +1060,17 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
if (md->phys_addr < contig_low) {
lim = min(efi_md_end(md), contig_low);
if (efi_uc(md)) {
- if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC &&
+ if (k > kern_memmap &&
+ (k-1)->attribute == EFI_MEMORY_UC &&
kmd_end(k-1) == md->phys_addr) {
- (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+ (k-1)->num_pages +=
+ (lim - md->phys_addr)
+ >> EFI_PAGE_SHIFT;
} else {
k->attribute = EFI_MEMORY_UC;
k->start = md->phys_addr;
- k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+ k->num_pages = (lim - md->phys_addr)
+ >> EFI_PAGE_SHIFT;
k++;
}
}
@@ -1049,7 +1088,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
} else {
k->attribute = EFI_MEMORY_UC;
k->start = lim;
- k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT;
+ k->num_pages = (efi_md_end(md) - lim)
+ >> EFI_PAGE_SHIFT;
k++;
}
}
@@ -1151,8 +1191,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
break;
}
- if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "failed to alocate resource for iomem\n");
+ if ((res = kzalloc(sizeof(struct resource),
+ GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR
+ "failed to allocate resource for iomem\n");
return;
}
@@ -1187,44 +1229,44 @@ efi_initialize_iomem_resources(struct resource *code_resource,
rsvd_regions are sorted
*/
unsigned long __init
-kdump_find_rsvd_region (unsigned long size,
- struct rsvd_region *r, int n)
+kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n)
{
- int i;
- u64 start, end;
- u64 alignment = 1UL << _PAGE_SIZE_64M;
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (!efi_wb(md))
- continue;
- start = ALIGN(md->phys_addr, alignment);
- end = efi_md_end(md);
- for (i = 0; i < n; i++) {
- if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
- if (__pa(r[i].start) > start + size)
- return start;
- start = ALIGN(__pa(r[i].end), alignment);
- if (i < n-1 && __pa(r[i+1].start) < start + size)
- continue;
- else
- break;
+ int i;
+ u64 start, end;
+ u64 alignment = 1UL << _PAGE_SIZE_64M;
+ void *efi_map_start, *efi_map_end, *p;
+ efi_memory_desc_t *md;
+ u64 efi_desc_size;
+
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ md = p;
+ if (!efi_wb(md))
+ continue;
+ start = ALIGN(md->phys_addr, alignment);
+ end = efi_md_end(md);
+ for (i = 0; i < n; i++) {
+ if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
+ if (__pa(r[i].start) > start + size)
+ return start;
+ start = ALIGN(__pa(r[i].end), alignment);
+ if (i < n-1 &&
+ __pa(r[i+1].start) < start + size)
+ continue;
+ else
+ break;
+ }
}
- }
- if (end > start + size)
- return start;
- }
-
- printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n",
- size);
- return ~0UL;
+ if (end > start + size)
+ return start;
+ }
+
+ printk(KERN_WARNING
+ "Cannot reserve 0x%lx byte of memory for crashdump\n", size);
+ return ~0UL;
}
#endif
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index c36f43c9460..f5d3efbfbed 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1586,7 +1586,7 @@ sys_call_table:
data8 sys_epoll_pwait // 1305
data8 sys_utimensat
data8 sys_signalfd
- data8 sys_timerfd
+ data8 sys_ni_syscall
data8 sys_eventfd
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/fsyscall_gtod_data.h b/arch/ia64/kernel/fsyscall_gtod_data.h
index 490dab55fba..57d2ee6c83e 100644
--- a/arch/ia64/kernel/fsyscall_gtod_data.h
+++ b/arch/ia64/kernel/fsyscall_gtod_data.h
@@ -14,10 +14,10 @@ struct fsyscall_gtod_data_t {
u32 clk_shift;
void *clk_fsys_mmio;
cycle_t clk_cycle_last;
-} __attribute__ ((aligned (L1_CACHE_BYTES)));
+} ____cacheline_aligned;
struct itc_jitter_data_t {
int itc_jitter;
cycle_t itc_lastcycle;
-} __attribute__ ((aligned (L1_CACHE_BYTES)));
+} ____cacheline_aligned;
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index c3b4412ccc6..8e7193d5552 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -12,6 +12,9 @@ EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(strlen);
+#include<asm/pgtable.h>
+EXPORT_SYMBOL_GPL(empty_zero_page);
+
#include <asm/checksum.h>
EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */
EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index fc4d2676264..b618487cdc8 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -381,9 +381,10 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
unsigned int i;
- i = atomic_sub_return(1, &kcb->prev_kprobe_index);
- __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i].kp;
- kcb->kprobe_status = kcb->prev_kprobe[i].status;
+ i = atomic_read(&kcb->prev_kprobe_index);
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i-1].kp;
+ kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
+ atomic_sub(1, &kcb->prev_kprobe_index);
}
static void __kprobes set_current_kprobe(struct kprobe *p,
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 6dbf5919d2d..846e7e036b1 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2,61 +2,69 @@
* File: mca.c
* Purpose: Generic MCA handling layer
*
- * Updated for latest kernel
* Copyright (C) 2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* Copyright (C) 2002 Dell Inc.
- * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
+ * Copyright (C) Matt Domsch <Matt_Domsch@dell.com>
*
* Copyright (C) 2002 Intel
- * Copyright (C) Jenna Hall (jenna.s.hall@intel.com)
+ * Copyright (C) Jenna Hall <jenna.s.hall@intel.com>
*
* Copyright (C) 2001 Intel
- * Copyright (C) Fred Lewis (frederick.v.lewis@intel.com)
+ * Copyright (C) Fred Lewis <frederick.v.lewis@intel.com>
*
* Copyright (C) 2000 Intel
- * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
+ * Copyright (C) Chuck Fleckenstein <cfleck@co.intel.com>
*
* Copyright (C) 1999, 2004 Silicon Graphics, Inc.
- * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
+ * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
*
- * 03/04/15 D. Mosberger Added INIT backtrace support.
- * 02/03/25 M. Domsch GUID cleanups
+ * Copyright (C) 2006 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*
- * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU
- * error flag, set SAL default return values, changed
- * error record structure to linked list, added init call
- * to sal_get_state_info_size().
+ * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
+ * Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
+ * added min save state dump, added INIT handler.
*
- * 01/01/03 F. Lewis Added setup of CMCI and CPEI IRQs, logging of corrected
- * platform errors, completed code for logging of
- * corrected & uncorrected machine check errors, and
- * updated for conformance with Nov. 2000 revision of the
- * SAL 3.0 spec.
- * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
- * added min save state dump, added INIT handler.
+ * 2001-01-03 Fred Lewis <frederick.v.lewis@intel.com>
+ * Added setup of CMCI and CPEI IRQs, logging of corrected platform
+ * errors, completed code for logging of corrected & uncorrected
+ * machine check errors, and updated for conformance with Nov. 2000
+ * revision of the SAL 3.0 spec.
+ *
+ * 2002-01-04 Jenna Hall <jenna.s.hall@intel.com>
+ * Aligned MCA stack to 16 bytes, added platform vs. CPU error flag,
+ * set SAL default return values, changed error record structure to
+ * linked list, added init call to sal_get_state_info_size().
+ *
+ * 2002-03-25 Matt Domsch <Matt_Domsch@dell.com>
+ * GUID cleanups.
+ *
+ * 2003-04-15 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Added INIT backtrace support.
*
* 2003-12-08 Keith Owens <kaos@sgi.com>
- * smp_call_function() must not be called from interrupt context (can
- * deadlock on tasklist_lock). Use keventd to call smp_call_function().
+ * smp_call_function() must not be called from interrupt context
+ * (can deadlock on tasklist_lock).
+ * Use keventd to call smp_call_function().
*
* 2004-02-01 Keith Owens <kaos@sgi.com>
- * Avoid deadlock when using printk() for MCA and INIT records.
- * Delete all record printing code, moved to salinfo_decode in user space.
- * Mark variables and functions static where possible.
- * Delete dead variables and functions.
- * Reorder to remove the need for forward declarations and to consolidate
- * related code.
+ * Avoid deadlock when using printk() for MCA and INIT records.
+ * Delete all record printing code, moved to salinfo_decode in user
+ * space. Mark variables and functions static where possible.
+ * Delete dead variables and functions. Reorder to remove the need
+ * for forward declarations and to consolidate related code.
*
* 2005-08-12 Keith Owens <kaos@sgi.com>
- * Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
+ * Convert MCA/INIT handlers to use per event stacks and SAL/OS
+ * state.
*
* 2005-10-07 Keith Owens <kaos@sgi.com>
* Add notify_die() hooks.
*
* 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- * Add printing support for MCA/INIT.
+ * Add printing support for MCA/INIT.
*
* 2007-04-27 Russ Anderson <rja@sgi.com>
* Support multiple cpus going through OS_MCA in the same event.
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 0f5965fcdf8..8bc7d259e0c 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -1,24 +1,28 @@
-//
-// assembly portion of the IA64 MCA handling
-//
-// Mods by cfleck to integrate into kernel build
-// 00/03/15 davidm Added various stop bits to get a clean compile
-//
-// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp
-// kstack, switch modes, jump to C INIT handler
-//
-// 02/01/04 J.Hall <jenna.s.hall@intel.com>
-// Before entering virtual mode code:
-// 1. Check for TLB CPU error
-// 2. Restore current thread pointer to kr6
-// 3. Move stack ptr 16 bytes to conform to C calling convention
-//
-// 04/11/12 Russ Anderson <rja@sgi.com>
-// Added per cpu MCA/INIT stack save areas.
-//
-// 12/08/05 Keith Owens <kaos@sgi.com>
-// Use per cpu MCA/INIT stacks for all data.
-//
+/*
+ * File: mca_asm.S
+ * Purpose: assembly portion of the IA64 MCA handling
+ *
+ * Mods by cfleck to integrate into kernel build
+ *
+ * 2000-03-15 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Added various stop bits to get a clean compile
+ *
+ * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
+ * Added code to save INIT handoff state in pt_regs format,
+ * switch to temp kstack, switch modes, jump to C INIT handler
+ *
+ * 2002-01-04 J.Hall <jenna.s.hall@intel.com>
+ * Before entering virtual mode code:
+ * 1. Check for TLB CPU error
+ * 2. Restore current thread pointer to kr6
+ * 3. Move stack ptr 16 bytes to conform to C calling convention
+ *
+ * 2004-11-12 Russ Anderson <rja@sgi.com>
+ * Added per cpu MCA/INIT stack save areas.
+ *
+ * 2005-12-08 Keith Owens <kaos@sgi.com>
+ * Use per cpu MCA/INIT stacks for all data.
+ */
#include <linux/threads.h>
#include <asm/asmmacro.h>
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index aba813c2c15..fab1d21a4f2 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -3,7 +3,7 @@
* Purpose: Generic MCA handling layer
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
* Copyright (C) 2005 Silicon Graphics, Inc
* Copyright (C) 2005 Keith Owens <kaos@sgi.com>
* Copyright (C) 2006 Russ Anderson <rja@sgi.com>
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 485e34d0b19..53b8ecb5b4b 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -3,7 +3,7 @@
* Purpose: Define helpers for Generic MCA handling
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*/
/*
* Processor error section:
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 3bccb06c8d2..767ac2c20d1 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -3,7 +3,7 @@
* Purpose: Assembly portion of Generic MCA handling
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*/
#include <linux/threads.h>
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 5ae177f557d..78acd9fe97e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2654,11 +2654,11 @@ pfm_get_task(pfm_context_t *ctx, pid_t pid, struct task_struct **task)
/* XXX: need to add more checks here */
if (pid < 2) return -EPERM;
- if (pid != current->pid) {
+ if (pid != task_pid_vnr(current)) {
read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+ p = find_task_by_vpid(pid);
/* make sure task cannot go away while we operate on it */
if (p) get_task_struct(p);
@@ -5795,7 +5795,7 @@ pfm_proc_show(struct seq_file *m, void *v)
return 0;
}
-struct seq_operations pfm_seq_ops = {
+const struct seq_operations pfm_seq_ops = {
.start = pfm_proc_start,
.next = pfm_proc_next,
.stop = pfm_proc_stop,
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 27c2ef445a5..f44fe841216 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -284,6 +284,7 @@ ia64_sal_cache_flush (u64 cache_type)
SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
return isrv.status;
}
+EXPORT_SYMBOL_GPL(ia64_sal_cache_flush);
void __init
ia64_sal_init (struct ia64_sal_systab *systab)
@@ -372,3 +373,16 @@ ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
return 0;
}
EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
+
+long
+ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
+ unsigned long *drift_info)
+{
+ struct ia64_sal_retval isrv;
+
+ SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
+ *ticks_per_second = isrv.v0;
+ *drift_info = isrv.v1;
+ return isrv.status;
+}
+EXPORT_SYMBOL_GPL(ia64_sal_freq_base);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 86028c69861..ebd1a09f320 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -654,7 +654,7 @@ c_stop (struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index f0fc4d8465a..480b1a5085d 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -767,17 +767,6 @@ void __cpu_die(unsigned int cpu)
}
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
-#else /* !CONFIG_HOTPLUG_CPU */
-int __cpu_disable(void)
-{
- return -ENOSYS;
-}
-
-void __cpu_die(unsigned int cpu)
-{
- /* We said "no" in __cpu_disable */
- BUG();
-}
#endif /* CONFIG_HOTPLUG_CPU */
void
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 78d65cb947d..f0cda765e68 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -35,7 +35,7 @@ trap_init (void)
fpswa_interface = __va(ia64_boot_param->fpswa);
}
-void
+int
die (const char *str, struct pt_regs *regs, long err)
{
static struct {
@@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err)
if (++die.lock_owner_depth < 3) {
printk("%s[%d]: %s %ld [%d]\n",
current->comm, task_pid_nr(current), str, err, ++die_counter);
- (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
- show_regs(regs);
+ if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV)
+ != NOTIFY_STOP)
+ show_regs(regs);
+ else
+ regs = NULL;
} else
printk(KERN_ERR "Recursive die() failure, output suppressed\n");
@@ -72,17 +75,22 @@ die (const char *str, struct pt_regs *regs, long err)
add_taint(TAINT_DIE);
spin_unlock_irq(&die.lock);
+ if (!regs)
+ return 1;
+
if (panic_on_oops)
panic("Fatal exception");
do_exit(SIGSEGV);
+ return 0;
}
-void
+int
die_if_kernel (char *str, struct pt_regs *regs, long err)
{
if (!user_mode(regs))
- die(str, regs, err);
+ return die(str, regs, err);
+ return 0;
}
void
@@ -102,7 +110,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
== NOTIFY_STOP)
return;
- die_if_kernel("bugcheck!", regs, break_num);
+ if (die_if_kernel("bugcheck!", regs, break_num))
+ return;
sig = SIGILL; code = ILL_ILLOPC;
break;
@@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
break;
default:
- if (break_num < 0x40000 || break_num > 0x100000)
- die_if_kernel("Bad break", regs, break_num);
+ if ((break_num < 0x40000 || break_num > 0x100000)
+ && die_if_kernel("Bad break", regs, break_num))
+ return;
if (break_num < 0x80000) {
sig = SIGILL; code = __ILL_BREAK;
@@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
#endif
sprintf(buf, "IA-64 Illegal operation fault");
- die_if_kernel(buf, &regs, 0);
+ rv.fkt = 0;
+ if (die_if_kernel(buf, &regs, 0))
+ return rv;
memset(&si, 0, sizeof(si));
si.si_signo = SIGILL;
si.si_code = ILL_ILLOPC;
si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
force_sig_info(SIGILL, &si, current);
- rv.fkt = 0;
return rv;
}
@@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
sprintf(buf, "Fault %lu", vector);
break;
}
- die_if_kernel(buf, &regs, error);
- force_sig(SIGILL, current);
+ if (!die_if_kernel(buf, &regs, error))
+ force_sig(SIGILL, current);
}
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index f6a1aeb742b..52f70bbc192 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -23,7 +23,7 @@
#include <asm/uaccess.h>
#include <asm/unaligned.h>
-extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
#undef DEBUG_UNALIGNED_TRAP
@@ -675,8 +675,9 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi
*/
if (ld.x6_op == 1 || ld.x6_op == 3) {
printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__);
- die_if_kernel("unaligned reference on speculative load with register update\n",
- regs, 30);
+ if (die_if_kernel("unaligned reference on speculative load with register update\n",
+ regs, 30))
+ return;
}
@@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (ia64_psr(regs)->be) {
/* we don't support big-endian accesses */
- die_if_kernel("big-endian unaligned accesses are not supported", regs, 0);
+ if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0))
+ return;
goto force_sigbus;
}
@@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
ia64_handle_exception(regs, eh);
goto done;
}
- die_if_kernel("error during unaligned kernel access\n", regs, ret);
+ if (die_if_kernel("error during unaligned kernel access\n", regs, ret))
+ return;
/* NOT_REACHED */
}
force_sigbus:
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 7571076a16a..3e69881648a 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -16,7 +16,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-extern void die (char *, struct pt_regs *, long);
+extern int die(char *, struct pt_regs *, long);
#ifdef CONFIG_KPROBES
static inline int notify_page_fault(struct pt_regs *regs, int trap)
@@ -267,9 +267,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
else
printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address);
- die("Oops", regs, isr);
+ if (die("Oops", regs, isr))
+ regs = NULL;
bust_spinlocks(0);
- do_exit(SIGKILL);
+ if (regs)
+ do_exit(SIGKILL);
return;
out_of_memory:
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index f3c69329e14..dfc6bf1c7b4 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -523,7 +523,7 @@ static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, si
return count;
}
-static struct seq_operations sn2_ptc_seq_ops = {
+static const struct seq_operations sn2_ptc_seq_ops = {
.start = sn2_ptc_seq_start,
.next = sn2_ptc_seq_next,
.stop = sn2_ptc_seq_stop,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 1a8e49607f1..4b0d1538e7e 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -33,6 +33,7 @@
#include <linux/smp_lock.h>
#include <linux/nodemask.h>
#include <linux/smp.h>
+#include <linux/mutex.h>
#include <asm/processor.h>
#include <asm/topology.h>
@@ -50,7 +51,7 @@ static void *sn_hwperf_salheap = NULL;
static int sn_hwperf_obj_cnt = 0;
static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
static int sn_hwperf_init(void);
-static DECLARE_MUTEX(sn_hwperf_init_mutex);
+static DEFINE_MUTEX(sn_hwperf_init_mutex);
#define cnode_possible(n) ((n) < num_cnodes)
@@ -577,7 +578,7 @@ static void sn_topology_stop(struct seq_file *m, void *v)
/*
* /proc/sgi_sn/sn_topology, read-only using seq_file
*/
-static struct seq_operations sn_topology_seq_ops = {
+static const struct seq_operations sn_topology_seq_ops = {
.start = sn_topology_start,
.next = sn_topology_next,
.stop = sn_topology_stop,
@@ -884,10 +885,10 @@ static int sn_hwperf_init(void)
int e = 0;
/* single threaded, once-only initialization */
- down(&sn_hwperf_init_mutex);
+ mutex_lock(&sn_hwperf_init_mutex);
if (sn_hwperf_salheap) {
- up(&sn_hwperf_init_mutex);
+ mutex_unlock(&sn_hwperf_init_mutex);
return e;
}
@@ -936,7 +937,7 @@ out:
sn_hwperf_salheap = NULL;
sn_hwperf_obj_cnt = 0;
}
- up(&sn_hwperf_init_mutex);
+ mutex_unlock(&sn_hwperf_init_mutex);
return e;
}
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index ee3c8be12fa..01d877c6868 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -17,7 +17,7 @@ static int puts(const char *s)
return 0;
}
-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
#include <asm/m32r.h>
#include <asm/io.h>
@@ -52,7 +52,7 @@ static void putc(char c)
}
*BOOT_SIO0TXB = c;
}
-#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#else /* !(CONFIG_PLAT_M32700UT) */
#if defined(CONFIG_PLAT_MAPPI2)
#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S
index 95aa7987484..aa3bf4cfab3 100644
--- a/arch/m32r/kernel/syscall_table.S
+++ b/arch/m32r/kernel/syscall_table.S
@@ -321,6 +321,6 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8236e42ef71..ffabd01c45e 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -577,20 +577,6 @@ config MAC_HID
depends on INPUT_ADBHID
default y
-config MAC_ADBKEYCODES
- bool "Support for ADB raw keycodes"
- depends on INPUT_ADBHID
- help
- This provides support for sending raw ADB keycodes to console
- devices. This is the default up to 2.4.0, but in future this may be
- phased out in favor of generic Linux keycodes. If you say Y here,
- you can dynamically switch via the
- /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
- sysctl and with the "keyboard_sends_linux_keycodes=" kernel
- argument.
-
- If unsure, say Y here.
-
config ADB_KEYBOARD
bool "Support for ADB keyboard (old driver)"
depends on MAC && !INPUT_ADBHID
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 4a1bd44ff16..2cba605cb59 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -13,16 +13,15 @@
# Copyright (C) 1994 by Hamish Macdonald
#
-# test for cross compiling
-COMPILE_ARCH = $(shell uname -m)
-
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(COMPILE_ARCH),$(ARCH))
- # prefix for cross-compiling binaries
- CROSS_COMPILE = m68k-linux-gnu-
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, \
+ m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+ endif
endif
ifdef CONFIG_SUN3
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 8b415651ede..6a0d7650f98 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -2,6 +2,6 @@
# Makefile for Linux arch/m68k/amiga source directory
#
-obj-y := config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o
+obj-y := config.o amiints.o cia.o chipram.o amisound.o
obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
deleted file mode 100644
index 7fdcf6bf3ad..00000000000
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amipcmcia.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(amiga_model);
-EXPORT_SYMBOL(amiga_chipset);
-EXPORT_SYMBOL(amiga_hw_present);
-EXPORT_SYMBOL(amiga_eclock);
-EXPORT_SYMBOL(amiga_colorclock);
-EXPORT_SYMBOL(amiga_chip_alloc);
-EXPORT_SYMBOL(amiga_chip_free);
-EXPORT_SYMBOL(amiga_chip_avail);
-EXPORT_SYMBOL(amiga_chip_size);
-EXPORT_SYMBOL(amiga_audio_period);
-EXPORT_SYMBOL(amiga_audio_min_period);
-
-#ifdef CONFIG_AMIGA_PCMCIA
- EXPORT_SYMBOL(pcmcia_reset);
- EXPORT_SYMBOL(pcmcia_copy_tuple);
- EXPORT_SYMBOL(pcmcia_program_voltage);
- EXPORT_SYMBOL(pcmcia_access_speed);
- EXPORT_SYMBOL(pcmcia_write_enable);
- EXPORT_SYMBOL(pcmcia_write_disable);
-#endif
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 1f5bfb58429..61e5c54625a 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -12,6 +12,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/amigahw.h>
@@ -21,7 +22,7 @@ static const signed char sine_data[] = {
0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
0, -39, -75, -103, -121, -127, -121, -103, -75, -39
};
-#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
+#define DATA_SIZE ARRAY_SIZE(sine_data)
#define custom amiga_custom
@@ -31,6 +32,7 @@ static const signed char sine_data[] = {
*/
volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
+EXPORT_SYMBOL(amiga_audio_min_period);
#define MAX_PERIOD (65535)
@@ -40,6 +42,7 @@ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
*/
unsigned short amiga_audio_period = MAX_PERIOD;
+EXPORT_SYMBOL(amiga_audio_period);
static unsigned long clock_constant;
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index fa015d80161..d10726f9038 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -13,10 +13,13 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/module.h>
+
#include <asm/page.h>
#include <asm/amigahw.h>
unsigned long amiga_chip_size;
+EXPORT_SYMBOL(amiga_chip_size);
static struct resource chipram_res = {
.name = "Chip RAM", .start = CHIP_PHYSADDR
@@ -67,6 +70,7 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
#endif
return (void *)ZTWO_VADDR(res->start);
}
+EXPORT_SYMBOL(amiga_chip_alloc);
/*
@@ -120,6 +124,7 @@ void amiga_chip_free(void *ptr)
}
printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
}
+EXPORT_SYMBOL(amiga_chip_free);
unsigned long amiga_chip_avail(void)
@@ -129,3 +134,5 @@ unsigned long amiga_chip_avail(void)
#endif
return chipavail;
}
+EXPORT_SYMBOL(amiga_chip_avail);
+
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 35748531327..50f5daab46b 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/zorro.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -36,13 +37,24 @@
#include <asm/io.h>
unsigned long amiga_model;
+EXPORT_SYMBOL(amiga_model);
+
unsigned long amiga_eclock;
+EXPORT_SYMBOL(amiga_eclock);
+
unsigned long amiga_masterclock;
+
unsigned long amiga_colorclock;
+EXPORT_SYMBOL(amiga_colorclock);
+
unsigned long amiga_chipset;
+EXPORT_SYMBOL(amiga_chipset);
+
unsigned char amiga_vblank;
unsigned char amiga_psfreq;
+
struct amiga_hw_present amiga_hw_present;
+EXPORT_SYMBOL(amiga_hw_present);
static char s_a500[] __initdata = "A500";
static char s_a500p[] __initdata = "A500+";
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index 186662ca1a8..7106f0c3639 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -15,6 +15,8 @@
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
+#include <linux/module.h>
+
#include <asm/amigayle.h>
#include <asm/amipcmcia.h>
@@ -30,6 +32,7 @@ void pcmcia_reset(void)
while (time_before(jiffies, reset_start_time + 1*HZ/100));
b = gayle_reset;
}
+EXPORT_SYMBOL(pcmcia_reset);
/* copy a tuple, including tuple header. return nb bytes copied */
@@ -61,6 +64,7 @@ int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
return 0;
}
+EXPORT_SYMBOL(pcmcia_copy_tuple);
void pcmcia_program_voltage(int voltage)
{
@@ -84,6 +88,7 @@ void pcmcia_program_voltage(int voltage)
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_program_voltage);
void pcmcia_access_speed(int speed)
{
@@ -101,13 +106,17 @@ void pcmcia_access_speed(int speed)
cfg_byte = (cfg_byte & 0xf3) | s;
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_access_speed);
void pcmcia_write_enable(void)
{
gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
}
+EXPORT_SYMBOL(pcmcia_write_enable);
void pcmcia_write_disable(void)
{
gayle.cardstatus = 0;
}
+EXPORT_SYMBOL(pcmcia_write_disable);
+
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 2cb86191f0a..2cd905efe63 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -3,7 +3,7 @@
#
obj-y := config.o time.o debug.o ataints.o stdma.o \
- atasound.o stram.o atari_ksyms.o
+ atasound.o stram.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_HADES) += hades-pci.o
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index b85ca22024c..b45593a60bd 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,6 +40,7 @@
#include <linux/kernel_stat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -446,6 +447,7 @@ unsigned long atari_register_vme_int(void)
free_vme_vec_bitmap |= 1 << i;
return VME_SOURCE_BASE + i;
}
+EXPORT_SYMBOL(atari_register_vme_int);
void atari_unregister_vme_int(unsigned long irq)
@@ -455,5 +457,6 @@ void atari_unregister_vme_int(unsigned long irq)
free_vme_vec_bitmap &= ~(1 << irq);
}
}
+EXPORT_SYMBOL(atari_unregister_vme_int);
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
deleted file mode 100644
index a0475715153..00000000000
--- a/arch/m68k/atari/atari_ksyms.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/module.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-extern void atari_microwire_cmd( int cmd );
-extern int atari_MFP_init_done;
-extern int atari_SCC_init_done;
-extern int atari_SCC_reset_done;
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_mch_type);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(atari_switches);
-EXPORT_SYMBOL(atari_dont_touch_floppy_select);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-EXPORT_SYMBOL(atari_stram_alloc);
-EXPORT_SYMBOL(atari_stram_free);
-
-EXPORT_SYMBOL(atari_MFP_init_done);
-EXPORT_SYMBOL(atari_SCC_init_done);
-EXPORT_SYMBOL(atari_SCC_reset_done);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index ee04250eb56..d266fe89c12 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -22,6 +22,7 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/system.h>
@@ -43,6 +44,7 @@ void atari_microwire_cmd (int cmd)
while( tt_microwire.mask != 0x7ff)
;
}
+EXPORT_SYMBOL(atari_microwire_cmd);
/* PSG base frequency */
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index e40e5dcaa34..5945e150555 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -31,6 +31,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/vt_kern.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -43,10 +44,20 @@
#include <asm/io.h>
u_long atari_mch_cookie;
+EXPORT_SYMBOL(atari_mch_cookie);
+
u_long atari_mch_type;
+EXPORT_SYMBOL(atari_mch_type);
+
struct atari_hw_present atari_hw_present;
+EXPORT_SYMBOL(atari_hw_present);
+
u_long atari_switches;
+EXPORT_SYMBOL(atari_switches);
+
int atari_dont_touch_floppy_select;
+EXPORT_SYMBOL(atari_dont_touch_floppy_select);
+
int atari_rtc_year_offset;
/* local function prototypes */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index fbeed8c8ecb..043ddbc61c7 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -15,17 +15,23 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
/* Flag that Modem1 port is already initialized and used */
int atari_MFP_init_done;
+EXPORT_SYMBOL(atari_MFP_init_done);
+
/* Flag that Modem1 port is already initialized and used */
int atari_SCC_init_done;
+EXPORT_SYMBOL(atari_SCC_init_done);
+
/* Can be set somewhere, if a SCC master reset has already be done and should
* not be repeated; used by kgdb */
int atari_SCC_reset_done;
+EXPORT_SYMBOL(atari_SCC_reset_done);
static struct console atari_console_driver = {
.name = "debug",
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
index bee2b1443e3..2bbabc00870 100644
--- a/arch/m68k/atari/hades-pci.c
+++ b/arch/m68k/atari/hades-pci.c
@@ -376,8 +376,8 @@ struct pci_bus_info * __init init_hades_pci(void)
*/
bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
- if (!bus)
- return NULL;
+ if (unlikely(!bus))
+ goto iounmap_base_virt;
/*
* Claim resources. The m68k has no separate I/O space, both
@@ -385,43 +385,25 @@ struct pci_bus_info * __init init_hades_pci(void)
* the I/O resources are requested in memory space as well.
*/
- if (request_resource(&iomem_resource, &config_space) != 0)
- {
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
+ goto free_bus;
- if (request_resource(&iomem_resource, &io_space) != 0)
- {
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
+ goto release_config_space;
bus->mem_space.start = HADES_MEM_BASE;
bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
bus->mem_space.name = pci_mem_name;
#if 1
- if (request_resource(&iomem_resource, &bus->mem_space) != 0)
- {
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
+ goto release_io_space;
#endif
bus->io_space.start = pci_io_base_virt;
bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
bus->io_space.name = pci_io_name;
#if 1
- if (request_resource(&ioport_resource, &bus->io_space) != 0)
- {
- release_resource(&bus->mem_space);
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
+ goto release_bus_mem_space;
#endif
/*
* Set hardware dependent functions.
@@ -438,5 +420,21 @@ struct pci_bus_info * __init init_hades_pci(void)
tt_mfp.active_edge &= ~0x27;
return bus;
+
+release_bus_mem_space:
+ release_resource(&bus->mem_space);
+release_io_space:
+ release_resource(&io_space);
+release_config_space:
+ release_resource(&config_space);
+free_bus:
+ kfree(bus);
+iounmap_base_virt:
+ iounmap((void *)pci_io_base_virt);
+
+ for (i = 0; i < N_SLOTS; i++)
+ iounmap((void *)pci_conf_base_virt[i]);
+
+ return NULL;
}
#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ab3fd5202b2..d1bd029a34a 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -91,6 +92,7 @@ void stdma_lock(irq_handler_t handler, void *data)
stdma_isr_data = data;
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_lock);
/*
@@ -117,6 +119,7 @@ void stdma_release(void)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_release);
/*
@@ -134,6 +137,7 @@ int stdma_others_waiting(void)
{
return waitqueue_active(&stdma_wait);
}
+EXPORT_SYMBOL(stdma_others_waiting);
/*
@@ -155,6 +159,7 @@ int stdma_islocked(void)
{
return stdma_locked;
}
+EXPORT_SYMBOL(stdma_islocked);
/*
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index bf4588cbe37..8dda6515887 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
#include <linux/bootmem.h>
#include <linux/mount.h>
#include <linux/blkdev.h>
+#include <linux/module.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -208,6 +209,7 @@ void *atari_stram_alloc(long size, const char *owner)
}
return( addr );
}
+EXPORT_SYMBOL(atari_stram_alloc);
void atari_stram_free( void *addr )
@@ -237,6 +239,7 @@ void atari_stram_free( void *addr )
printk( KERN_ERR "atari_stram_free: cannot free block at %p "
"(called from %p)\n", addr, __builtin_return_address(0) );
}
+EXPORT_SYMBOL(atari_stram_free);
/* ------------------------------------------------------------------------ */
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 15b80abfe94..ff9dffa5b86 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -678,7 +678,6 @@ CONFIG_LOGO_MAC_CLUT224=y
#
CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
-CONFIG_MAC_ADBKEYCODES=y
CONFIG_SERIAL_CONSOLE=y
#
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
index 288b9c67c9b..96d4244c82f 100644
--- a/arch/m68k/hp300/Makefile
+++ b/arch/m68k/hp300/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/hp300 source directory
#
-obj-y := ksyms.o config.o time.o reboot.o
+obj-y := config.o time.o reboot.o
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
deleted file mode 100644
index 8202830763d..00000000000
--- a/arch/m68k/hp300/ksyms.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * linux/arch/m68k/hp300/ksyms.c
- *
- * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
- *
- * This file contains the HP300-specific kernel symbols. None yet. :-)
- */
-
-#include <linux/module.h>
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 918f5dbeaef..6dfa3b3c0e2 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -742,7 +742,7 @@ sys_call_table:
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 995a09d912f..1d265ba365a 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -3,4 +3,4 @@
#
obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
- baboon.o macboing.o debug.o misc.o mac_ksyms.o
+ baboon.o macboing.o debug.o misc.o
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 01b468b9392..735a49b4b93 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -58,8 +58,6 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
extern struct mem_info m68k_ramdisk;
-extern char m68k_command_line[CL_SIZE];
-
void *mac_env; /* Loaded by the boot asm */
/* The phys. video addr. - might be bogus on some machines */
diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c
deleted file mode 100644
index 6e37ceb0f3b..00000000000
--- a/arch/m68k/mac/mac_ksyms.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-
-/* Says whether we're using A/UX interrupts or not */
-extern int via_alt_mapping;
-
-EXPORT_SYMBOL(via_alt_mapping);
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 8df270e950f..fa485df4160 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -41,7 +42,9 @@ volatile __u8 *via1, *via2;
/* See note in mac_via.h about how this is possibly not useful */
volatile long *via_memory_bogon=(long *)&via_memory_bogon;
#endif
-int rbv_present, via_alt_mapping;
+int rbv_present;
+int via_alt_mapping;
+EXPORT_SYMBOL(via_alt_mapping);
__u8 rbv_clear;
/*
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 950e82f2164..edb3f6e6ee6 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/mvme16x source directory
#
-obj-y := config.o rtc.o mvme16x_ksyms.o
+obj-y := config.o rtc.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index daa78516140..24cbc303045 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -25,6 +25,7 @@
#include <linux/genhd.h>
#include <linux/rtc.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -58,6 +59,7 @@ static irq_handler_t tick_handler;
unsigned short mvme16x_config;
+EXPORT_SYMBOL(mvme16x_config);
int mvme16x_parse_bootinfo(const struct bi_record *bi)
diff --git a/arch/m68k/mvme16x/mvme16x_ksyms.c b/arch/m68k/mvme16x/mvme16x_ksyms.c
deleted file mode 100644
index 4a8a3634bb4..00000000000
--- a/arch/m68k/mvme16x/mvme16x_ksyms.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/mvme16xhw.h>
-
-EXPORT_SYMBOL(mvme16x_config);
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
index 9ff47bd09ae..ed6d9a83bfd 100644
--- a/arch/m68knommu/Kconfig.debug
+++ b/arch/m68knommu/Kconfig.debug
@@ -21,13 +21,6 @@ config BOOTPARAM_STRING
default 'console=ttyS0,19200'
depends on BOOTPARAM
-config DUMPTOFLASH
- bool "Panic/Dump to FLASH"
- depends on COLDFIRE
- help
- Dump any panic of trap output into a flash memory segment
- for later analysis.
-
config NO_KERNEL_MSG
bool "Suppress Kernel BUG Messages"
help
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 5a0ecaaee3b..648113075f9 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -597,7 +597,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
# CONFIG_BOOTPARAM is not set
-# CONFIG_DUMPTOFLASH is not set
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f795062aba1..53fad149028 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -24,14 +24,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(ip_fast_csum);
@@ -46,9 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
it's OK to leave it out of version control. */
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 332345d7675..81507c53d4a 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -64,9 +64,6 @@ void (*mach_power_off)(void);
#ifdef CONFIG_M68VZ328
#define CPU "MC68VZ328"
#endif
-#ifdef CONFIG_M68332
- #define CPU "MC68332"
-#endif
#ifdef CONFIG_M68360
#define CPU "MC68360"
#endif
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 9620093514b..1b02b882006 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -336,7 +336,7 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 82480a1717d..f798139e888 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -660,7 +660,7 @@ einval: li v0, -EINVAL
sys sys_ioprio_get 2 /* 4315 */
sys sys_utimensat 4
sys sys_signalfd 3
- sys sys_timerfd 4
+ sys sys_ni_syscall 0
sys sys_eventfd 1
sys sys_fallocate 6 /* 4320 */
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index c2c10876da2..a626be6baea 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -475,7 +475,7 @@ sys_call_table:
PTR sys_ioprio_get
PTR sys_utimensat /* 5275 */
PTR sys_signalfd
- PTR sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 01993ec3368..9d5bcaf1b38 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -401,7 +401,7 @@ EXPORT(sysn32_call_table)
PTR sys_ioprio_get
PTR compat_sys_utimensat
PTR compat_sys_signalfd /* 5280 */
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index dd68afce7da..fd2019c1ec2 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -523,7 +523,7 @@ sys_call_table:
PTR sys_ioprio_get /* 4315 */
PTR compat_sys_utimensat
PTR compat_sys_signalfd
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys32_fallocate /* 4320 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b94d4502a47..cf030b00441 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -256,6 +256,9 @@ config IOMMU_VMERGE
Most drivers don't have this problem; it is safe to say Y here.
+config IOMMU_HELPER
+ def_bool PPC64
+
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index ed083feaf6f..e6e49289f78 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -22,6 +22,7 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/suspend.h>
+#include <linux/hrtimer.h>
#ifdef CONFIG_PPC64
#include <linux/time.h>
#include <linux/hardirq.h>
@@ -312,7 +313,7 @@ int main(void)
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
- DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
+ DEFINE(CLOCK_REALTIME_RES, (KTIME_MONOTONIC_RES).tv64);
#ifdef CONFIG_BUG
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 84239076a5b..3a317cb0636 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -31,8 +31,8 @@ static inline unsigned long device_to_mask(struct device *dev)
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
- device_to_mask(dev), flag,
+ return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
+ dma_handle, device_to_mask(dev), flag,
dev->archdata.numa_node);
}
@@ -52,7 +52,7 @@ static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(dev->archdata.dma_data, vaddr, size,
+ return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
device_to_mask(dev), direction);
}
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
+ return iommu_map_sg(dev, sglist, nelems,
device_to_mask(dev), direction);
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a3c406aca66..8f1f4e539c4 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/dma-mapping.h>
#include <linux/bitops.h>
+#include <linux/iommu-helper.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
@@ -81,17 +82,19 @@ static int __init setup_iommu(char *str)
__setup("protect4gb=", setup_protect4gb);
__setup("iommu=", setup_iommu);
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
unsigned long npages,
unsigned long *handle,
unsigned long mask,
unsigned int align_order)
{
- unsigned long n, end, i, start;
+ unsigned long n, end, start;
unsigned long limit;
int largealloc = npages > 15;
int pass = 0;
unsigned long align_mask;
+ unsigned long boundary_size;
align_mask = 0xffffffffffffffffl >> (64 - align_order);
@@ -136,14 +139,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
start &= mask;
}
- n = find_next_zero_bit(tbl->it_map, limit, start);
-
- /* Align allocation */
- n = (n + align_mask) & ~align_mask;
-
- end = n + npages;
+ if (dev)
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ 1 << IOMMU_PAGE_SHIFT);
+ else
+ boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
+ /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
- if (unlikely(end >= limit)) {
+ n = iommu_area_alloc(tbl->it_map, limit, start, npages,
+ tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
+ align_mask);
+ if (n == -1) {
if (likely(pass < 2)) {
/* First failure, just rescan the half of the table.
* Second failure, rescan the other half of the table.
@@ -158,14 +164,7 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- for (i = n; i < end; i++)
- if (test_bit(i, tbl->it_map)) {
- start = i+1;
- goto again;
- }
-
- for (i = n; i < end; i++)
- __set_bit(i, tbl->it_map);
+ end = n + npages;
/* Bump the hint to a new block for small allocs. */
if (largealloc) {
@@ -184,16 +183,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return n;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
- unsigned int npages, enum dma_data_direction direction,
- unsigned long mask, unsigned int align_order)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *page, unsigned int npages,
+ enum dma_data_direction direction,
+ unsigned long mask, unsigned int align_order)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
spin_lock_irqsave(&(tbl->it_lock), flags);
- entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
+ entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -224,7 +224,6 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry, free_entry;
- unsigned long i;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
free_entry = entry - tbl->it_offset;
@@ -246,9 +245,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
}
ppc_md.tce_free(tbl, entry, npages);
-
- for (i = 0; i < npages; i++)
- __clear_bit(free_entry+i, tbl->it_map);
+ iommu_area_free(tbl->it_map, free_entry, npages);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -270,16 +267,18 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
-int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, unsigned long mask,
enum dma_data_direction direction)
{
+ struct iommu_table *tbl = dev->archdata.dma_data;
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
int outcount, incount, i;
unsigned int align;
unsigned long handle;
+ unsigned int max_seg_size;
BUG_ON(direction == DMA_NONE);
@@ -298,6 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
spin_lock_irqsave(&(tbl->it_lock), flags);
+ max_seg_size = dma_get_max_seg_size(dev);
for_each_sg(sglist, s, nelems, i) {
unsigned long vaddr, npages, entry, slen;
@@ -314,7 +314,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- entry = iommu_range_alloc(tbl, npages, &handle,
+ entry = iommu_range_alloc(dev, tbl, npages, &handle,
mask >> IOMMU_PAGE_SHIFT, align);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -344,7 +344,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
/* We cannot merge if:
* - allocated dma_addr isn't contiguous to previous allocation
*/
- if (novmerge || (dma_addr != dma_next)) {
+ if (novmerge || (dma_addr != dma_next) ||
+ (outs->dma_length + s->length > max_seg_size)) {
/* Can't merge: create a new segment */
segstart = s;
outcount++;
@@ -452,9 +453,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
{
unsigned long sz;
- unsigned long start_index, end_index;
- unsigned long entries_per_4g;
- unsigned long index;
static int welcomed = 0;
struct page *page;
@@ -476,6 +474,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
#ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
+ unsigned long index;
unsigned long tceval;
unsigned long tcecount = 0;
@@ -506,23 +505,6 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
#endif
- /*
- * DMA cannot cross 4 GB boundary. Mark last entry of each 4
- * GB chunk as reserved.
- */
- if (protect4gb) {
- entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
-
- /* Mark the last bit before a 4GB boundary as used */
- start_index = tbl->it_offset | (entries_per_4g - 1);
- start_index -= tbl->it_offset;
-
- end_index = tbl->it_size;
-
- for (index = start_index; index < end_index - 1; index += entries_per_4g)
- __set_bit(index, tbl->it_map);
- }
-
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");
@@ -570,9 +552,9 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
-dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, unsigned long mask,
- enum dma_data_direction direction)
+dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, size_t size, unsigned long mask,
+ enum dma_data_direction direction)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -589,7 +571,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
((unsigned long)vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
mask >> IOMMU_PAGE_SHIFT, align);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
@@ -621,8 +603,9 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
+void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
+ size_t size, dma_addr_t *dma_handle,
+ unsigned long mask, gfp_t flag, int node)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -656,7 +639,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
/* Set up tces to cover the allocated range */
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
- mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
+ mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
mask >> IOMMU_PAGE_SHIFT, io_order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 76b862bd1fe..61dd17449dd 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -36,7 +36,8 @@ static struct legacy_serial_info {
static struct __initdata of_device_id parents[] = {
{.type = "soc",},
{.type = "tsi-bridge",},
- {.type = "opb", .compatible = "ibm,opb",},
+ {.type = "opb", },
+ {.compatible = "ibm,opb",},
{.compatible = "simple-bus",},
{.compatible = "wrs,epld-localbus",},
};
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index f0bad7070fb..f98867252ee 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -176,7 +176,7 @@ static void __devinit vio_dev_release(struct device *dev)
* Returns a pointer to the created vio_dev or NULL if node has
* NULL device_type or compatible fields.
*/
-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
+struct vio_dev *vio_register_device_node(struct device_node *of_node)
{
struct vio_dev *viodev;
const unsigned int *unit_address;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index e8122447f01..c7d7bd43a25 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -483,7 +483,12 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
*/
_tlbie(address, 0 /* 8xx doesn't care about PID */);
#endif
- if (!PageReserved(page)
+ /* The _PAGE_USER test should really be _PAGE_EXEC, but
+ * older glibc versions execute some code from no-exec
+ * pages, which for now we are supporting. If exec-only
+ * pages are ever implemented, this will have to change.
+ */
+ if (!PageReserved(page) && (pte_val(pte) & _PAGE_USER)
&& !test_bit(PG_arch_1, &page->flags)) {
if (vma->vm_mm == current->active_mm) {
__flush_dcache_icache((void *) address);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 64488723162..f80f90c4d58 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -86,7 +86,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -123,7 +123,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -131,7 +131,7 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, struct page *ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 3fce6b375db..7d301875198 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -134,13 +134,12 @@ static void __init mpc8272_ads_setup_arch(void)
}
bcsr = of_iomap(np, 0);
+ of_node_put(np);
if (!bcsr) {
printk(KERN_ERR "Cannot map BCSR registers\n");
return;
}
- of_node_put(np);
-
clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
setbits32(&bcsr[1], BCSR1_FETH_RST);
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index 68196e34999..e1dceeec499 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -130,13 +130,12 @@ static void __init pq2fads_setup_arch(void)
}
bcsr = of_iomap(np, 0);
+ of_node_put(np);
if (!bcsr) {
printk(KERN_ERR "Cannot map BCSR registers\n");
return;
}
- of_node_put(np);
-
/* Enable the serial and ethernet ports */
clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3a963b4a9be..2f169991896 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -54,6 +54,13 @@ config SPU_FS_64K_LS
uses 4K pages. This can improve performances of applications
using multiple SPEs by lowering the TLB pressure on them.
+config SPU_TRACE
+ tristate "SPU event tracing support"
+ depends on SPU_FS && MARKERS
+ help
+ This option allows reading a trace of spu-related events through
+ the sputrace file in procfs.
+
config SPU_BASE
bool
default n
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 095988f13bf..d95e71dee91 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/msi.h>
-#include <linux/reboot.h>
+#include <linux/of_platform.h>
#include <asm/dcr.h>
#include <asm/machdep.h>
@@ -65,14 +65,12 @@
struct axon_msic {
struct irq_host *irq_host;
- __le32 *fifo;
+ __le32 *fifo_virt;
+ dma_addr_t fifo_phys;
dcr_host_t dcr_host;
- struct list_head list;
u32 read_offset;
};
-static LIST_HEAD(axon_msic_list);
-
static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
@@ -94,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
while (msic->read_offset != write_offset) {
idx = msic->read_offset / sizeof(__le32);
- msi = le32_to_cpu(msic->fifo[idx]);
+ msi = le32_to_cpu(msic->fifo_virt[idx]);
msi &= 0xFFFF;
pr_debug("axon_msi: woff %x roff %x msi %x\n",
@@ -139,6 +137,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
tmp = dn;
dn = of_find_node_by_phandle(*ph);
+ of_node_put(tmp);
if (!dn) {
dev_dbg(&dev->dev,
"axon_msi: msi-translator doesn't point to a node\n");
@@ -156,7 +155,6 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
out_error:
of_node_put(dn);
- of_node_put(tmp);
return msic;
}
@@ -292,30 +290,24 @@ static struct irq_host_ops msic_host_ops = {
.map = msic_host_map,
};
-static int axon_msi_notify_reboot(struct notifier_block *nb,
- unsigned long code, void *data)
+static int axon_msi_shutdown(struct of_device *device)
{
- struct axon_msic *msic;
+ struct axon_msic *msic = device->dev.platform_data;
u32 tmp;
- list_for_each_entry(msic, &axon_msic_list, list) {
- pr_debug("axon_msi: disabling %s\n",
- msic->irq_host->of_node->full_name);
- tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
- tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
- msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
- }
+ pr_debug("axon_msi: disabling %s\n",
+ msic->irq_host->of_node->full_name);
+ tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
+ tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
+ msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
return 0;
}
-static struct notifier_block axon_msi_reboot_notifier = {
- .notifier_call = axon_msi_notify_reboot
-};
-
-static int axon_msi_setup_one(struct device_node *dn)
+static int axon_msi_probe(struct of_device *device,
+ const struct of_device_id *device_id)
{
- struct page *page;
+ struct device_node *dn = device->node;
struct axon_msic *msic;
unsigned int virq;
int dcr_base, dcr_len;
@@ -346,16 +338,14 @@ static int axon_msi_setup_one(struct device_node *dn)
goto out_free_msic;
}
- page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
- get_order(MSIC_FIFO_SIZE_BYTES));
- if (!page) {
+ msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
+ &msic->fifo_phys, GFP_KERNEL);
+ if (!msic->fifo_virt) {
printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
dn->full_name);
goto out_free_msic;
}
- msic->fifo = page_address(page);
-
msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
NR_IRQS, &msic_host_ops, 0);
if (!msic->irq_host) {
@@ -378,14 +368,18 @@ static int axon_msi_setup_one(struct device_node *dn)
pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
/* Enable the MSIC hardware */
- msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
+ msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
- (u64)msic->fifo & 0xFFFFFFFF);
+ msic->fifo_phys & 0xFFFFFFFF);
msic_dcr_write(msic, MSIC_CTRL_REG,
MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
MSIC_CTRL_FIFO_SIZE);
- list_add(&msic->list, &axon_msic_list);
+ device->dev.platform_data = msic;
+
+ ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
+ ppc_md.msi_check_device = axon_msi_check_device;
printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name);
@@ -394,7 +388,8 @@ static int axon_msi_setup_one(struct device_node *dn)
out_free_host:
kfree(msic->irq_host);
out_free_fifo:
- __free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
+ dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
+ msic->fifo_phys);
out_free_msic:
kfree(msic);
out:
@@ -402,28 +397,24 @@ out:
return -1;
}
-static int axon_msi_init(void)
-{
- struct device_node *dn;
- int found = 0;
-
- pr_debug("axon_msi: initialising ...\n");
-
- for_each_compatible_node(dn, NULL, "ibm,axon-msic") {
- if (axon_msi_setup_one(dn) == 0)
- found++;
- }
-
- if (found) {
- ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
- ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
- ppc_md.msi_check_device = axon_msi_check_device;
-
- register_reboot_notifier(&axon_msi_reboot_notifier);
+static const struct of_device_id axon_msi_device_id[] = {
+ {
+ .compatible = "ibm,axon-msic"
+ },
+ {}
+};
- pr_debug("axon_msi: registered callbacks!\n");
- }
+static struct of_platform_driver axon_msi_driver = {
+ .match_table = axon_msi_device_id,
+ .probe = axon_msi_probe,
+ .shutdown = axon_msi_shutdown,
+ .driver = {
+ .name = "axon-msi"
+ },
+};
- return 0;
+static int __init axon_msi_init(void)
+{
+ return of_register_platform_driver(&axon_msi_driver);
}
-arch_initcall(axon_msi_init);
+subsys_initcall(axon_msi_init);
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index e6534b519c9..a7f609b3b87 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -98,7 +98,7 @@ static int __init cell_publish_devices(void)
}
return 0;
}
-machine_device_initcall(cell, cell_publish_devices);
+machine_subsys_initcall(cell, cell_publish_devices);
static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
{
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index d3a349fb42e..99610a6361f 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -4,6 +4,8 @@ spufs-y += inode.o file.o context.o syscalls.o coredump.o
spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
spufs-y += switch.o fault.o lscsa_alloc.o
+obj-$(CONFIG_SPU_TRACE) += sputrace.o
+
# Rules to build switch.o with the help of SPU tool chain
SPU_CROSS := spu-
SPU_CC := $(SPU_CROSS)gcc
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 3fcd06418b0..1018acd1746 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -29,6 +29,7 @@
#include <linux/poll.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
+#include <linux/marker.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -358,6 +359,8 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
struct spu_context *ctx = vma->vm_file->private_data;
unsigned long area, offset = address - vma->vm_start;
+ spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx);
+
offset += vma->vm_pgoff << PAGE_SHIFT;
if (offset >= ps_size)
return NOPFN_SIGBUS;
@@ -375,11 +378,14 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
if (ctx->state == SPU_STATE_SAVED) {
up_read(&current->mm->mmap_sem);
+ spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx);
spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
+ spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu);
down_read(&current->mm->mmap_sem);
} else {
area = ctx->spu->problem_phys + ps_offs;
vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
+ spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu);
}
spu_release(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index c0e968a4c21..90784c029f2 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -322,7 +322,7 @@ static struct spu_context *
spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
struct file *filp)
{
- struct spu_context *tmp, *neighbor;
+ struct spu_context *tmp, *neighbor, *err;
int count, node;
int aff_supp;
@@ -354,11 +354,15 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) &&
!list_is_last(&neighbor->aff_list, &gang->aff_list_head) &&
!list_entry(neighbor->aff_list.next, struct spu_context,
- aff_list)->aff_head)
- return ERR_PTR(-EEXIST);
+ aff_list)->aff_head) {
+ err = ERR_PTR(-EEXIST);
+ goto out_put_neighbor;
+ }
- if (gang != neighbor->gang)
- return ERR_PTR(-EINVAL);
+ if (gang != neighbor->gang) {
+ err = ERR_PTR(-EINVAL);
+ goto out_put_neighbor;
+ }
count = 1;
list_for_each_entry(tmp, &gang->aff_list_head, aff_list)
@@ -372,11 +376,17 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
break;
}
- if (node == MAX_NUMNODES)
- return ERR_PTR(-EEXIST);
+ if (node == MAX_NUMNODES) {
+ err = ERR_PTR(-EEXIST);
+ goto out_put_neighbor;
+ }
}
return neighbor;
+
+out_put_neighbor:
+ put_spu_context(neighbor);
+ return err;
}
static void
@@ -454,9 +464,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
if (ret)
goto out_aff_unlock;
- if (affinity)
+ if (affinity) {
spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx,
neighbor);
+ if (neighbor)
+ put_spu_context(neighbor);
+ }
/*
* get references for dget and mntget, will be released
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c01a09da1e5..b4814c740d8 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -410,8 +410,11 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
* since we have TIF_SINGLESTEP set, thus the kernel will do
* it upon return from the syscall anyawy
*/
- if ((status & SPU_STATUS_STOPPED_BY_STOP)
- && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
+ if (unlikely(status & SPU_STATUS_SINGLE_STEP))
+ ret = -ERESTARTSYS;
+
+ else if (unlikely((status & SPU_STATUS_STOPPED_BY_STOP)
+ && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff)) {
force_sig(SIGTRAP, current);
ret = -ERESTARTSYS;
}
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 00d914232af..5915343e259 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -39,6 +39,7 @@
#include <linux/pid_namespace.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/marker.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
@@ -216,8 +217,8 @@ void do_notify_spus_active(void)
*/
static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
{
- pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
- spu->number, spu->node);
+ spu_context_trace(spu_bind_context__enter, ctx, spu);
+
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
if (ctx->flags & SPU_CREATE_NOSCHED)
@@ -399,8 +400,8 @@ static int has_affinity(struct spu_context *ctx)
*/
static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
{
- pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
- spu->pid, spu->number, spu->node);
+ spu_context_trace(spu_unbind_context__enter, ctx, spu);
+
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
if (spu->ctx->flags & SPU_CREATE_NOSCHED)
@@ -528,6 +529,8 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
struct spu *spu, *aff_ref_spu;
int node, n;
+ spu_context_nospu_trace(spu_get_idle__enter, ctx);
+
if (ctx->gang) {
mutex_lock(&ctx->gang->aff_mutex);
if (has_affinity(ctx)) {
@@ -546,8 +549,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
ctx->gang->aff_ref_spu = NULL;
mutex_unlock(&ctx->gang->aff_mutex);
-
- return NULL;
+ goto not_found;
}
mutex_unlock(&ctx->gang->aff_mutex);
}
@@ -565,12 +567,14 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
mutex_unlock(&cbe_spu_info[node].list_mutex);
}
+ not_found:
+ spu_context_nospu_trace(spu_get_idle__not_found, ctx);
return NULL;
found:
spu->alloc_state = SPU_USED;
mutex_unlock(&cbe_spu_info[node].list_mutex);
- pr_debug("Got SPU %d %d\n", spu->number, spu->node);
+ spu_context_trace(spu_get_idle__found, ctx, spu);
spu_init_channels(spu);
return spu;
}
@@ -587,6 +591,8 @@ static struct spu *find_victim(struct spu_context *ctx)
struct spu *spu;
int node, n;
+ spu_context_nospu_trace(spu_find_vitim__enter, ctx);
+
/*
* Look for a possible preemption candidate on the local node first.
* If there is no candidate look at the other nodes. This isn't
@@ -640,6 +646,8 @@ static struct spu *find_victim(struct spu_context *ctx)
goto restart;
}
+ spu_context_trace(__spu_deactivate__unload, ctx, spu);
+
mutex_lock(&cbe_spu_info[node].list_mutex);
cbe_spu_info[node].nr_active--;
spu_unbind_context(spu, victim);
@@ -822,6 +830,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
*/
void spu_deactivate(struct spu_context *ctx)
{
+ spu_context_nospu_trace(spu_deactivate__enter, ctx);
__spu_deactivate(ctx, 1, MAX_PRIO);
}
@@ -835,6 +844,7 @@ void spu_deactivate(struct spu_context *ctx)
*/
void spu_yield(struct spu_context *ctx)
{
+ spu_context_nospu_trace(spu_yield__enter, ctx);
if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
mutex_lock(&ctx->state_mutex);
__spu_deactivate(ctx, 0, MAX_PRIO);
@@ -864,11 +874,15 @@ static noinline void spusched_tick(struct spu_context *ctx)
goto out;
spu = ctx->spu;
+
+ spu_context_trace(spusched_tick__preempt, ctx, spu);
+
new = grab_runnable_context(ctx->prio + 1, spu->node);
if (new) {
spu_unschedule(spu, ctx);
spu_add_to_rq(ctx);
} else {
+ spu_context_nospu_trace(spusched_tick__newslice, ctx);
ctx->time_slice++;
}
out:
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0e114038ea6..795a1b52538 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -325,4 +325,9 @@ extern void spu_free_lscsa(struct spu_state *csa);
extern void spuctx_switch_state(struct spu_context *ctx,
enum spu_utilization_state new_state);
+#define spu_context_trace(name, ctx, spu) \
+ trace_mark(name, "%p %p", ctx, spu);
+#define spu_context_nospu_trace(name, ctx) \
+ trace_mark(name, "%p", ctx);
+
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c
new file mode 100644
index 00000000000..2b1953f6f12
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/sputrace.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH
+ * Released under GPL v2.
+ *
+ * Partially based on net/ipv4/tcp_probe.c.
+ *
+ * Simple tracing facility for spu contexts.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/marker.h>
+#include <linux/proc_fs.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include "spufs.h"
+
+struct spu_probe {
+ const char *name;
+ const char *format;
+ marker_probe_func *probe_func;
+};
+
+struct sputrace {
+ ktime_t tstamp;
+ int owner_tid; /* owner */
+ int curr_tid;
+ const char *name;
+ int number;
+};
+
+static int bufsize __read_mostly = 16384;
+MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)");
+module_param(bufsize, int, 0);
+
+
+static DEFINE_SPINLOCK(sputrace_lock);
+static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait);
+static ktime_t sputrace_start;
+static unsigned long sputrace_head, sputrace_tail;
+static struct sputrace *sputrace_log;
+
+static int sputrace_used(void)
+{
+ return (sputrace_head - sputrace_tail) % bufsize;
+}
+
+static inline int sputrace_avail(void)
+{
+ return bufsize - sputrace_used();
+}
+
+static int sputrace_sprint(char *tbuf, int n)
+{
+ const struct sputrace *t = sputrace_log + sputrace_tail % bufsize;
+ struct timespec tv =
+ ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start));
+
+ return snprintf(tbuf, n,
+ "[%lu.%09lu] %d: %s (thread = %d, spu = %d)\n",
+ (unsigned long) tv.tv_sec,
+ (unsigned long) tv.tv_nsec,
+ t->owner_tid,
+ t->name,
+ t->curr_tid,
+ t->number);
+}
+
+static ssize_t sputrace_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int error = 0, cnt = 0;
+
+ if (!buf || len < 0)
+ return -EINVAL;
+
+ while (cnt < len) {
+ char tbuf[128];
+ int width;
+
+ error = wait_event_interruptible(sputrace_wait,
+ sputrace_used() > 0);
+ if (error)
+ break;
+
+ spin_lock(&sputrace_lock);
+ if (sputrace_head == sputrace_tail) {
+ spin_unlock(&sputrace_lock);
+ continue;
+ }
+
+ width = sputrace_sprint(tbuf, sizeof(tbuf));
+ if (width < len)
+ sputrace_tail = (sputrace_tail + 1) % bufsize;
+ spin_unlock(&sputrace_lock);
+
+ if (width >= len)
+ break;
+
+ error = copy_to_user(buf + cnt, tbuf, width);
+ if (error)
+ break;
+ cnt += width;
+ }
+
+ return cnt == 0 ? error : cnt;
+}
+
+static int sputrace_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sputrace_lock);
+ sputrace_head = sputrace_tail = 0;
+ sputrace_start = ktime_get();
+ spin_unlock(&sputrace_lock);
+
+ return 0;
+}
+
+static const struct file_operations sputrace_fops = {
+ .owner = THIS_MODULE,
+ .open = sputrace_open,
+ .read = sputrace_read,
+};
+
+static void sputrace_log_item(const char *name, struct spu_context *ctx,
+ struct spu *spu)
+{
+ spin_lock(&sputrace_lock);
+ if (sputrace_avail() > 1) {
+ struct sputrace *t = sputrace_log + sputrace_head;
+
+ t->tstamp = ktime_get();
+ t->owner_tid = ctx->tid;
+ t->name = name;
+ t->curr_tid = current->pid;
+ t->number = spu ? spu->number : -1;
+
+ sputrace_head = (sputrace_head + 1) % bufsize;
+ } else {
+ printk(KERN_WARNING
+ "sputrace: lost samples due to full buffer.\n");
+ }
+ spin_unlock(&sputrace_lock);
+
+ wake_up(&sputrace_wait);
+}
+
+static void spu_context_event(const struct marker *mdata,
+ void *private, const char *format, ...)
+{
+ struct spu_probe *p = mdata->private;
+ va_list ap;
+ struct spu_context *ctx;
+ struct spu *spu;
+
+ va_start(ap, format);
+ ctx = va_arg(ap, struct spu_context *);
+ spu = va_arg(ap, struct spu *);
+
+ sputrace_log_item(p->name, ctx, spu);
+ va_end(ap);
+}
+
+static void spu_context_nospu_event(const struct marker *mdata,
+ void *private, const char *format, ...)
+{
+ struct spu_probe *p = mdata->private;
+ va_list ap;
+ struct spu_context *ctx;
+
+ va_start(ap, format);
+ ctx = va_arg(ap, struct spu_context *);
+
+ sputrace_log_item(p->name, ctx, NULL);
+ va_end(ap);
+}
+
+struct spu_probe spu_probes[] = {
+ { "spu_bind_context__enter", "%p %p", spu_context_event },
+ { "spu_unbind_context__enter", "%p %p", spu_context_event },
+ { "spu_get_idle__enter", "%p", spu_context_nospu_event },
+ { "spu_get_idle__found", "%p %p", spu_context_event },
+ { "spu_get_idle__not_found", "%p", spu_context_nospu_event },
+ { "spu_find_victim__enter", "%p", spu_context_nospu_event },
+ { "spusched_tick__preempt", "%p %p", spu_context_event },
+ { "spusched_tick__newslice", "%p", spu_context_nospu_event },
+ { "spu_yield__enter", "%p", spu_context_nospu_event },
+ { "spu_deactivate__enter", "%p", spu_context_nospu_event },
+ { "__spu_deactivate__unload", "%p %p", spu_context_event },
+ { "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event },
+ { "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event },
+ { "spufs_ps_nopfn__wake", "%p %p", spu_context_event },
+ { "spufs_ps_nopfn__insert", "%p %p", spu_context_event },
+ { "spu_acquire_saved__enter", "%p", spu_context_nospu_event },
+ { "destroy_spu_context__enter", "%p", spu_context_nospu_event },
+};
+
+static int __init sputrace_init(void)
+{
+ struct proc_dir_entry *entry;
+ int i, error = -ENOMEM;
+
+ sputrace_log = kcalloc(sizeof(struct sputrace),
+ bufsize, GFP_KERNEL);
+ if (!sputrace_log)
+ goto out;
+
+ entry = create_proc_entry("sputrace", S_IRUSR, NULL);
+ if (!entry)
+ goto out_free_log;
+ entry->proc_fops = &sputrace_fops;
+
+ for (i = 0; i < ARRAY_SIZE(spu_probes); i++) {
+ struct spu_probe *p = &spu_probes[i];
+
+ error = marker_probe_register(p->name, p->format,
+ p->probe_func, p);
+ if (error)
+ printk(KERN_INFO "Unable to register probe %s\n",
+ p->name);
+
+ error = marker_arm(p->name);
+ if (error)
+ printk(KERN_INFO "Unable to arm probe %s\n", p->name);
+ }
+
+ return 0;
+
+out_free_log:
+ kfree(sputrace_log);
+out:
+ return -ENOMEM;
+}
+
+static void __exit sputrace_exit(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(spu_probes); i++)
+ marker_probe_unregister(spu_probes[i].name);
+
+ remove_proc_entry("sputrace", NULL);
+ kfree(sputrace_log);
+}
+
+module_init(sputrace_init);
+module_exit(sputrace_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 6a0c6f6675c..11fa3c772ed 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -199,7 +199,7 @@ static struct iommu_table vio_iommu_table;
void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
DMA_32BIT_MASK, flag, -1);
}
EXPORT_SYMBOL_GPL(iseries_hv_alloc);
@@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(iseries_hv_free);
dma_addr_t iseries_hv_map(void *vaddr, size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(&vio_iommu_table, vaddr, size,
+ return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
DMA_32BIT_MASK, direction);
}
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index c02f8742c54..2800fced8c7 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -167,6 +167,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
if ((child = of_get_next_child(np, NULL))) {
of_node_put(child);
+ of_node_put(parent);
return -EBUSY;
}
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 0e74a4bd982..5d2d5522ef4 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -174,15 +174,19 @@ int mpc8xx_pic_init(void)
goto out;
siu_reg = ioremap(res.start, res.end - res.start + 1);
- if (siu_reg == NULL)
- return -EINVAL;
+ if (siu_reg == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
- mpc8xx_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+ mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
64, &mpc8xx_pic_host_ops, 64);
if (mpc8xx_pic_host == NULL) {
printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
ret = -ENOMEM;
+ goto out;
}
+ return 0;
out:
of_node_put(np);
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index fadacfd1880..409fcaa4994 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -74,7 +74,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -111,7 +111,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -119,7 +119,7 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, struct page *ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 82cbffd0365..92a4f7b4323 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT
config STACKTRACE_SUPPORT
def_bool y
+config HAVE_LATENCYTOP_SUPPORT
+ def_bool y
+
config RWSEM_GENERIC_SPINLOCK
bool
@@ -47,6 +50,11 @@ config NO_IOMEM
config NO_DMA
def_bool y
+config GENERIC_LOCKBREAK
+ bool
+ default y
+ depends on SMP && PREEMPT
+
mainmenu "Linux Kernel Configuration"
config S390
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 2283933a9a9..4599fa06bd8 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -6,4 +6,12 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug"
+config DEBUG_PAGEALLOC
+ bool "Debug page memory allocations"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a slowdown, but helps to find certain types of
+ memory corruptions.
+
endmenu
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 6ee1bedbd1b..062c3d4c039 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1698,14 +1698,6 @@ compat_sys_signalfd_wrapper:
llgfr %r4,%r4 # compat_size_t
jg compat_sys_signalfd
- .globl compat_sys_timerfd_wrapper
-compat_sys_timerfd_wrapper:
- lgfr %r2,%r2 # int
- lgfr %r3,%r3 # int
- lgfr %r4,%r4 # int
- llgtr %r5,%r5 # struct compat_itimerspec *
- jg compat_sys_timerfd
-
.globl sys_eventfd_wrapper
sys_eventfd_wrapper:
llgfr %r2,%r2 # unsigned int
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1a6dac8df6f..6766e37fe8e 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -830,9 +831,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -845,9 +844,7 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index a3e47b893f0..efde6e178f6 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -801,9 +802,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -814,9 +813,7 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index db28cca81fe..60acdc266db 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -439,7 +439,7 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}
-static int ipl_init(void)
+static int __init ipl_init(void)
{
int rc;
@@ -471,8 +471,11 @@ out:
return 0;
}
-static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
- ipl_init};
+static struct shutdown_action __refdata ipl_action = {
+ .name = SHUTDOWN_ACTION_IPL_STR,
+ .fn = ipl_run,
+ .init = ipl_init,
+};
/*
* reipl shutdown action: Reboot Linux on shutdown.
@@ -792,7 +795,7 @@ static int __init reipl_fcp_init(void)
return 0;
}
-static int reipl_init(void)
+static int __init reipl_init(void)
{
int rc;
@@ -819,8 +822,11 @@ static int reipl_init(void)
return 0;
}
-static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
- reipl_run, reipl_init};
+static struct shutdown_action __refdata reipl_action = {
+ .name = SHUTDOWN_ACTION_REIPL_STR,
+ .fn = reipl_run,
+ .init = reipl_init,
+};
/*
* dump shutdown action: Dump Linux on shutdown.
@@ -998,7 +1004,7 @@ static int __init dump_fcp_init(void)
return 0;
}
-static int dump_init(void)
+static int __init dump_init(void)
{
int rc;
@@ -1020,8 +1026,11 @@ static int dump_init(void)
return 0;
}
-static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
- dump_run, dump_init};
+static struct shutdown_action __refdata dump_action = {
+ .name = SHUTDOWN_ACTION_DUMP_STR,
+ .fn = dump_run,
+ .init = dump_init,
+};
/*
* vmcmd shutdown action: Trigger vm command on shutdown.
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 766c783bd7a..29ae165d174 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -77,7 +77,7 @@ unsigned long machine_flags = 0;
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
static unsigned long __initdata memory_end;
@@ -145,7 +145,7 @@ __setup("condev=", condev_setup);
static int __init conmode_setup(char *str)
{
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
SET_CONSOLE_SCLP;
#endif
@@ -183,7 +183,7 @@ static void __init conmode_default(void)
*/
cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
return;
@@ -193,7 +193,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#elif defined(CONFIG_TN3215_CONSOLE)
SET_CONSOLE_3215;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
} else if (strncmp(ptr + 8, "3215", 4) == 0) {
@@ -201,7 +201,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3215;
#elif defined(CONFIG_TN3270_CONSOLE)
SET_CONSOLE_3270;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -212,7 +212,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#endif
} else {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -528,7 +528,7 @@ static void __init setup_memory_end(void)
memory_size = 0;
memory_end &= PAGE_MASK;
- max_mem = memory_end ? min(VMALLOC_START, memory_end) : VMALLOC_START;
+ max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS;
memory_end = min(max_mem, memory_end);
/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index aa37fa15451..85060659fb1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -225,12 +225,11 @@ EXPORT_SYMBOL(smp_call_function_single);
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
-int
-smp_call_function_mask(cpumask_t mask,
- void (*func)(void *), void *info,
- int wait)
+int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
+ int wait)
{
preempt_disable();
+ cpu_clear(smp_processor_id(), mask);
__smp_call_function_map(func, info, 0, wait, mask);
preempt_enable();
return 0;
@@ -1008,7 +1007,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
.notifier_call = smp_cpu_notify,
};
-static int smp_add_present_cpu(int cpu)
+static int __devinit smp_add_present_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
@@ -1036,8 +1035,8 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t rescan_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref rescan_store(struct sys_device *dev,
+ const char *buf, size_t count)
{
cpumask_t newcpus;
int cpu;
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index da692472996..85e46a5d0e0 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -14,7 +14,8 @@
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
unsigned long low,
- unsigned long high)
+ unsigned long high,
+ int savesched)
{
struct stack_frame *sf;
struct pt_regs *regs;
@@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace,
return sp;
regs = (struct pt_regs *)sp;
addr = regs->psw.addr & PSW_ADDR_INSN;
- if (!trace->skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- trace->skip--;
+ if (savesched || !in_sched_functions(addr)) {
+ if (!trace->skip)
+ trace->entries[trace->nr_entries++] = addr;
+ else
+ trace->skip--;
+ }
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace)
orig_sp = sp & PSW_ADDR_INSN;
new_sp = save_context_stack(trace, orig_sp,
S390_lowcore.panic_stack - PAGE_SIZE,
- S390_lowcore.panic_stack);
+ S390_lowcore.panic_stack, 1);
if (new_sp != orig_sp)
return;
new_sp = save_context_stack(trace, new_sp,
S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
+ S390_lowcore.async_stack, 1);
if (new_sp != orig_sp)
return;
save_context_stack(trace, new_sp,
S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+ S390_lowcore.thread_info + THREAD_SIZE, 1);
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+ unsigned long sp, low, high;
+
+ sp = tsk->thread.ksp & PSW_ADDR_INSN;
+ low = (unsigned long) task_stack_page(tsk);
+ high = (unsigned long) task_pt_regs(tsk);
+ save_context_stack(trace, sp, low, high, 0);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 9e26ed9fe4e..25eac7802fc 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -325,5 +325,5 @@ SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
-SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
+NI_SYSCALL /* 317 old sys_timer_fd */
SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 52b8342c6bf..1a2fdb6991d 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -271,7 +271,10 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- printk("SMP");
+ printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 7d43c3cd3ef..b4607155e8d 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -35,7 +35,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x0700
+ } :text = 0x0700
_etext = .; /* End of text section */
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b234bb4a6da..983ec6ec0e7 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -167,6 +167,33 @@ void __init mem_init(void)
PFN_ALIGN((unsigned long)&_eshared) - 1);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long address;
+ int i;
+
+ for (i = 0; i < numpages; i++) {
+ address = page_to_phys(page + i);
+ pgd = pgd_offset_k(address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ pte = pte_offset_kernel(pmd, address);
+ if (!enable) {
+ ptep_invalidate(address, pte);
+ continue;
+ }
+ *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+ /* Flush cpu write queue. */
+ mb();
+ }
+}
+#endif
+
void free_initmem(void)
{
unsigned long addr;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 79d13a166a3..7c1287ccf78 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -62,7 +62,7 @@ void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
}
}
-static void __init_refok *vmem_alloc_pages(unsigned int order)
+static void __ref *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
@@ -250,7 +250,7 @@ static int insert_memory_segment(struct memory_segment *seg)
{
struct memory_segment *tmp;
- if (seg->start + seg->size >= VMALLOC_START ||
+ if (seg->start + seg->size >= VMEM_MAX_PHYS ||
seg->start + seg->size < seg->start)
return -ERANGE;
@@ -360,7 +360,6 @@ void __init vmem_map_init(void)
{
int i;
- BUILD_BUG_ON((unsigned long)VMEM_MAP + VMEM_MAP_SIZE > VMEM_MAP_MAX);
NODE_DATA(0)->node_mem_map = VMEM_MAP;
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 10bec45415b..719e127a7c0 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -338,6 +338,6 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 98a93efe369..12c7340356a 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -376,6 +376,6 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd /* 350 */
+ .long sys_ni_syscall /* 350 */
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 55722840859..ee010f4532a 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -79,7 +79,7 @@ sys_call_table:
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 070a4846c0c..4b9115a4d92 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -580,7 +580,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
/* Step 1: Prepare scatter list. */
- npages = prepare_sg(sglist, nelems);
+ npages = prepare_sg(dev, sglist, nelems);
/* Step 2: Allocate a cluster and context, if necessary. */
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index efd5dff85f6..72a4acfe8c7 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -4,6 +4,7 @@
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
+#include <linux/dma-mapping.h>
#include "iommu_common.h"
/* You are _strongly_ advised to enable the following debugging code
@@ -201,21 +202,24 @@ void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int np
}
#endif
-unsigned long prepare_sg(struct scatterlist *sg, int nents)
+unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
{
struct scatterlist *dma_sg = sg;
unsigned long prev;
u32 dent_addr, dent_len;
+ unsigned int max_seg_size;
prev = (unsigned long) sg_virt(sg);
prev += (unsigned long) (dent_len = sg->length);
dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
+ max_seg_size = dma_get_max_seg_size(dev);
while (--nents) {
unsigned long addr;
sg = sg_next(sg);
addr = (unsigned long) sg_virt(sg);
- if (! VCONTIG(prev, addr)) {
+ if (! VCONTIG(prev, addr) ||
+ dent_len + sg->length > max_seg_size) {
dma_sg->dma_address = dent_addr;
dma_sg->dma_length = dent_len;
dma_sg = sg_next(dma_sg);
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 75b5a581452..a90d046e802 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/device.h>
#include <asm/iommu.h>
#include <asm/scatterlist.h>
@@ -46,4 +47,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int
#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \
(((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
-extern unsigned long prepare_sg(struct scatterlist *sg, int nents);
+extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 1aa8e044b10..5ea2eab1ccd 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -490,7 +490,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
goto bad;
/* Step 1: Prepare scatter list. */
- npages = prepare_sg(sglist, nelems);
+ npages = prepare_sg(dev, sglist, nelems);
/* Step 2: Allocate a cluster and context, if necessary. */
spin_lock_irqsave(&iommu->lock, flags);
@@ -625,8 +625,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
/* XXX register error interrupt handlers XXX */
}
-static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
- struct iommu *iommu)
+static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
+ struct iommu *iommu)
{
struct iommu_arena *arena = &iommu->arena;
unsigned long i, cnt = 0;
@@ -653,7 +653,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
return cnt;
}
-static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
+static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct iommu *iommu = pbm->iommu;
struct property *prop;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 06d10907d8c..b8058906e72 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -80,7 +80,7 @@ sys_call_table32:
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate
+/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
#endif /* CONFIG_COMPAT */
@@ -152,7 +152,7 @@ sys_call_table:
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 55945db1313..99e51d059a0 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD
bool
default y
+config HZ
+ int
+ default 100
+
menu "UML-specific options"
config STATIC_LINK
@@ -95,23 +99,6 @@ config LD_SCRIPT_DYN
default y
depends on !LD_SCRIPT_STATIC
-config NET
- bool "Networking support"
- help
- Unless you really know what you are doing, you should say Y here.
- The reason is that some programs need kernel networking support even
- when running on a stand-alone machine that isn't connected to any
- other computer. If you are upgrading from an older kernel, you
- should consider updating your networking tools too because changes
- in the kernel and the tools often go hand in hand. The tools are
- contained in the package net-tools, the location and version number
- of which are given in <file:Documentation/Changes>.
-
- For a general introduction to Linux networking, it is highly
- recommended to read the NET-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-
source "fs/Kconfig.binfmt"
config HOSTFS
@@ -145,7 +132,7 @@ config HPPFS
by removing or changing anything in /proc which gives away the
identity of a UML.
- See <http://user-mode-linux.sf.net/hppfs.html> for more information.
+ See <http://user-mode-linux.sf.net/old/hppfs.html> for more information.
You only need this if you are setting up a UML honeypot. Otherwise,
it is safe to say 'N' here.
@@ -189,8 +176,7 @@ config MAGIC_SYSRQ
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
- #SMP_BROKEN is for x86_64.
- depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
+ depends on BROKEN
help
This option enables UML SMP support.
It is NOT related to having a real SMP box. Not directly, at least.
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 9a78d354f0b..3a4b396d797 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -18,7 +18,7 @@ config SSL
lines on the UML that are usually made to show up on the host as
ttys or ptys.
- See <http://user-mode-linux.sourceforge.net/input.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/input.html> for more
information and command line examples of how to use this facility.
Unless you have a specific reason for disabling this, say Y.
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 1f6462ffd3e..8fce5e536b0 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -4,12 +4,12 @@ source "lib/Kconfig.debug"
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO
+ depends on DEBUG_INFO && FRAME_POINTER
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gprof,
@@ -22,7 +22,7 @@ config GCOV
This option allows developers to retrieve coverage data from a UML
session.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gcov,
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 66e50026ade..9e9a4aaa703 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -14,7 +14,7 @@ config UML_NET
For more information, including explanations of the networking and
sample configurations, see
- <http://user-mode-linux.sourceforge.net/networking.html>.
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
If you'd like to be able to enable networking in the User-Mode
linux environment, say Y; otherwise say N. Note that you must
@@ -38,7 +38,7 @@ config UML_NET_ETHERTAP
CONFIG_NETLINK_DEV configured as Y or M.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Ethertap
networking.
@@ -72,7 +72,7 @@ config UML_NET_SLIP
To use this, your host must support slip devices.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html>. That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
has examples of the UML command line to use to enable slip
networking, and details of a few quirks with it.
@@ -96,7 +96,7 @@ config UML_NET_DAEMON
networking daemon on the host.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Daemon
networking.
@@ -144,7 +144,7 @@ config UML_NET_MCAST
To use this, your host kernel(s) must support IP Multicasting.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Multicast
networking, and notes about the security of this approach.
@@ -165,7 +165,7 @@ config UML_NET_PCAP
installed in order to build the pcap transport into UML.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable this option.
If you intend to use UML as a network monitor for the host, say
diff --git a/arch/um/Makefile b/arch/um/Makefile
index ba6813a4aa3..cb4af9bf207 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -49,7 +49,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
#
# These apply to USER_CFLAGS to.
-KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Din6addr_loopback=kernel_in6addr_loopback \
-Din6addr_any=kernel_in6addr_any
@@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
- -D_FILE_OFFSET_BITS=64
+ $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -130,7 +130,9 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
# The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
-CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
+LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
+
+CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
define cmd_vmlinux__
$(CC) $(CFLAGS_vmlinux) -o $@ \
-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
@@ -158,7 +160,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
else
- $(Q)cd $(TOPDIR)/$(dir $@) ; \
+ $(Q)cd $(srctree)/$(dir $@) ; \
ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
endif
@@ -168,7 +170,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
else
- $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
+ $(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
endif
$(objtree)/$(ARCH_DIR)/include:
diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
deleted file mode 100644
index 03f7b10cfd0..00000000000
--- a/arch/um/Makefile-tt
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
-#
-
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f609edede06..86db2862f22 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -77,7 +77,7 @@ CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
-# CONFIG_HOSTFS is not set
+CONFIG_HOSTFS=y
# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
@@ -188,7 +188,7 @@ CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pts"
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LEGACY_PTY_COUNT=32
# CONFIG_WATCHDOG is not set
CONFIG_UML_SOUND=m
CONFIG_SOUND=m
@@ -508,7 +508,7 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
-CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SLAB_LEAK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83bf15a3dda..2c898c4d6b6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,6 +8,7 @@
#include "chan_kern.h"
#include "irq_kern.h"
#include "irq_user.h"
+#include "kern_util.h"
#include "os.h"
#define LINE_BUFSIZE 4096
@@ -48,7 +49,7 @@ static int write_room(struct line *line)
n = line->head - line->tail;
if (n <= 0)
- n = LINE_BUFSIZE + n; /* The other case */
+ n += LINE_BUFSIZE; /* The other case */
return n - 1;
}
@@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty)
unsigned long flags;
int room;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
room = write_room(line);
spin_unlock_irqrestore(&line->lock, flags);
- /*XXX: Warning to remove */
- if (0 == room)
- printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
- __FUNCTION__,tty->name);
return room;
}
@@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty)
int ret;
spin_lock_irqsave(&line->lock, flags);
-
- /*write_room subtracts 1 for the needed NULL, so we readd it.*/
+ /* write_room subtracts 1 for the needed NULL, so we readd it.*/
ret = LINE_BUFSIZE - (write_room(line) + 1);
spin_unlock_irqrestore(&line->lock, flags);
@@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty)
unsigned long flags;
int err;
- /*XXX: copied from line_write, verify if it is correct!*/
- if (tty->stopped)
- return;
-
spin_lock_irqsave(&line->lock, flags);
err = flush_buffer(line);
spin_unlock_irqrestore(&line->lock, flags);
@@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
unsigned long flags;
int n, ret = 0;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
if (line->head != line->tail)
ret = buffer_data(line, buf, len);
@@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data)
tty = winch->tty;
if (tty != NULL) {
line = tty->driver_data;
- chan_window_size(&line->chan_list, &tty->winsize.ws_row,
- &tty->winsize.ws_col);
- kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ if (line != NULL) {
+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+ &tty->winsize.ws_col);
+ kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ }
}
out:
if (winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 0f3c7d14a6e..ebb265c07e4 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,23 +1,25 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/console.h"
-#include "linux/ctype.h"
-#include "linux/interrupt.h"
-#include "linux/list.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/notifier.h"
-#include "linux/reboot.h"
-#include "linux/proc_fs.h"
-#include "linux/slab.h"
-#include "linux/syscalls.h"
-#include "linux/utsname.h"
-#include "linux/workqueue.h"
-#include "asm/uaccess.h"
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
#include "init.h"
#include "irq_kern.h"
#include "irq_user.h"
@@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req)
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
os_set_fd_block(req->originating_fd, 1);
mconsole_reply(req, "stopped", 0, 0);
- while (mconsole_get_request(req->originating_fd, req)) {
+ for (;;) {
+ if (!mconsole_get_request(req->originating_fd, req))
+ continue;
if (req->cmd->handler == mconsole_go)
break;
if (req->cmd->handler == mconsole_stop) {
@@ -358,7 +362,7 @@ struct unplugged_pages {
void *pages[UNPLUGGED_PER_PAGE];
};
-static DECLARE_MUTEX(plug_mem_mutex);
+static DEFINE_MUTEX(plug_mem_mutex);
static unsigned long long unplugged_pages_count = 0;
static LIST_HEAD(unplugged_pages);
static int unplug_index = UNPLUGGED_PER_PAGE;
@@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out)
diff /= PAGE_SIZE;
- down(&plug_mem_mutex);
+ mutex_lock(&plug_mem_mutex);
for (i = 0; i < diff; i++) {
struct unplugged_pages *unplugged;
void *addr;
@@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out)
err = 0;
out_unlock:
- up(&plug_mem_mutex);
+ mutex_unlock(&plug_mem_mutex);
out:
return err;
}
@@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req)
{
char *ptr = req->request.data;
int pid_requested= -1;
- struct task_struct *from = NULL;
struct task_struct *to = NULL;
/*
@@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req)
return;
}
- from = current;
-
- to = find_task_by_pid(pid_requested);
+ to = find_task_by_pid_ns(pid_requested, &init_pid_ns);
if ((to == NULL) || (pid_requested == 0)) {
mconsole_reply(req, "Couldn't find that pid", 1, 0);
return;
@@ -795,6 +796,8 @@ static int __init mconsole_init(void)
printk(KERN_ERR "Failed to initialize management console\n");
return 1;
}
+ if (os_set_fd_block(sock, 0))
+ goto out;
register_reboot_notifier(&reboot_notifier);
@@ -803,7 +806,7 @@ static int __init mconsole_init(void)
"mconsole", (void *)sock);
if (err) {
printk(KERN_ERR "Failed to get IRQ for management console\n");
- return 1;
+ goto out;
}
if (notify_socket != NULL) {
@@ -819,6 +822,10 @@ static int __init mconsole_init(void)
printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
MCONSOLE_VERSION, mconsole_socket_name);
return 0;
+
+ out:
+ os_close_file(sock);
+ return 1;
}
__initcall(mconsole_init);
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 430c024a19b..13af2f03ed8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -83,9 +83,8 @@ int mconsole_get_request(int fd, struct mc_request *req)
int len;
req->originlen = sizeof(req->origin);
- req->len = recvfrom(fd, &req->request, sizeof(req->request),
- MSG_DONTWAIT, (struct sockaddr *) req->origin,
- &req->originlen);
+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
+ (struct sockaddr *) req->origin, &req->originlen);
if (req->len < 0)
return 0;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 3c6c44ca1ff..1e8f41a9951 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -318,7 +318,7 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
if (str == NULL)
goto random;
- for (i = 0;i < 6; i++) {
+ for (i = 0; i < 6; i++) {
addr[i] = simple_strtoul(str, &end, 16);
if ((end == str) ||
((*end != ':') && (*end != ',') && (*end != '\0'))) {
@@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
}
if (!is_local_ether_addr(addr)) {
printk(KERN_WARNING
- "Warning: attempt to assign a globally valid ethernet "
+ "Warning: Assigning a globally valid ethernet "
"address to a device\n");
- printk(KERN_WARNING "You should better enable the 2nd "
- "rightmost bit in the first byte of the MAC,\n");
+ printk(KERN_WARNING "You should set the 2nd rightmost bit in "
+ "the first byte of the MAC,\n");
printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
addr[5]);
- goto random;
}
return;
@@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = {
.name = DRIVER_NAME,
},
};
-static int driver_registered;
static void net_device_release(struct device *dev)
{
@@ -383,6 +381,12 @@ static void net_device_release(struct device *dev)
free_netdev(netdev);
}
+/*
+ * Ensures that platform_driver_register is called only once by
+ * eth_configure. Will be set in an initcall.
+ */
+static int driver_registered;
+
static void eth_configure(int n, void *init, char *mac,
struct transport *transport)
{
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 29185cad9ff..abf2653f551 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
close(fds[1]);
if (pid > 0)
- helper_wait(pid, 0, "change_tramp");
+ helper_wait(pid);
return pid;
}
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 330543b3129..19930081d3d 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -6,6 +6,7 @@
#include "linux/completion.h"
#include "linux/interrupt.h"
#include "linux/list.h"
+#include "linux/mutex.h"
#include "asm/atomic.h"
#include "init.h"
#include "irq_kern.h"
@@ -120,7 +121,7 @@ static int port_accept(struct port_list *port)
return 0;
}
-static DECLARE_MUTEX(ports_sem);
+static DEFINE_MUTEX(ports_mutex);
static LIST_HEAD(ports);
static void port_work_proc(struct work_struct *unused)
@@ -161,7 +162,7 @@ void *port_data(int port_num)
struct port_dev *dev = NULL;
int fd;
- down(&ports_sem);
+ mutex_lock(&ports_mutex);
list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
if (port->port == port_num)
@@ -216,7 +217,7 @@ void *port_data(int port_num)
out_free:
kfree(port);
out:
- up(&ports_sem);
+ mutex_unlock(&ports_mutex);
return dev;
}
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index e942e836f99..71f0959c153 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -5,6 +5,7 @@
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
+#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index b8711e50da8..8b80505a3fb 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -109,7 +109,7 @@ static int slip_tramp(char **argv, int fd)
read_output(fds[0], output, output_len);
printk("%s", output);
- err = helper_wait(pid, 0, argv[0]);
+ err = helper_wait(pid);
close(fds[0]);
out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 89c1be225fd..a0ada8fec72 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -98,7 +98,7 @@ static void slirp_close(int fd, void *data)
"(%d)\n", pri->pid, errno);
}
#endif
- err = helper_wait(pri->pid, 1, "slirp_close");
+ err = helper_wait(pri->pid);
if (err < 0)
return;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 875d60d0c6a..f1786e64607 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -15,7 +15,6 @@
#include "line.h"
#include "ssl.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "kern.h"
#include "init.h"
#include "irq_user.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 656036e90b1..cec0c33cdd3 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -22,7 +22,6 @@
#include "stdio_console.h"
#include "line.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 99f9f9605e9..be3a2797dac 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,6 +49,7 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "ubd_user.h"
+#include "kern_util.h"
#include "os.h"
#include "mem.h"
#include "mem_kern.h"
@@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count,
return len;
}
-static void make_ide_entries(char *dev_name)
+static void make_ide_entries(const char *dev_name)
{
struct proc_dir_entry *dir, *ent;
char name[64];
@@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name)
ent->data = NULL;
ent->read_proc = proc_ide_read_media;
ent->write_proc = NULL;
- sprintf(name,"ide0/%s", dev_name);
+ snprintf(name, sizeof(name), "ide0/%s", dev_name);
proc_symlink(dev_name, proc_ide_root, name);
}
@@ -437,7 +438,10 @@ __uml_help(ubd_setup,
" machine by running 'dd' on the device. <n> must be in the range\n"
" 0 to 7. Appending an 'r' to the number will cause that device\n"
" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
-" an 's' will cause data to be written to disk on the host immediately.\n\n"
+" an 's' will cause data to be written to disk on the host immediately.\n"
+" 'c' will cause the device to be treated as being shared between multiple\n"
+" UMLs and file locking will be turned off - this is appropriate for a\n"
+" cluster filesystem and inappropriate at almost all other times.\n\n"
);
static int udb_setup(char *str)
@@ -456,20 +460,6 @@ __uml_help(udb_setup,
" in the boot output.\n\n"
);
-static int fakehd_set = 0;
-static int fakehd(char *str)
-{
- printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
- fakehd_set = 1;
- return 1;
-}
-
-__setup("fakehd", fakehd);
-__uml_help(fakehd,
-"fakehd\n"
-" Change the ubd device name to \"hd\".\n\n"
-);
-
static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
@@ -718,8 +708,10 @@ static int ubd_add(int n, char **error_out)
ubd_disk_register(fake_major, ubd_dev->size, n,
&fake_gendisk[n]);
- /* perhaps this should also be under the "if (fake_major)" above */
- /* using the fake_disk->disk_name and also the fakehd_set name */
+ /*
+ * Perhaps this should also be under the "if (fake_major)" above
+ * using the fake_disk->disk_name
+ */
if (fake_ide)
make_ide_entries(ubd_gendisk[n]->disk_name);
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 48fc7452bc1..b591bb9c41d 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
#include <sys/mman.h>
#include <sys/param.h>
#include "asm/types.h"
-#include "kern_util.h"
#include "user.h"
#include "ubd_user.h"
#include "os.h"
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index d9941fe5f93..56533db2534 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -80,7 +80,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
if (vpri->args == NULL) {
- printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
+ printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
"allocation failed");
return;
}
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 49c601ff2ba..2de92a08a76 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -10,6 +10,6 @@
extern void arch_check_bugs(void);
extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
-extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
+extern void arch_examine_signal(int sig, struct uml_pt_regs *regs);
#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index a5cdf953e04..606bb5c7fdf 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -10,23 +10,31 @@
#include "kern_constants.h"
/*
- * Assembly doesn't want any casting, but C does, so define these
- * without casts here, and define new symbols with casts inside the C
- * section.
+ * Stolen from linux/const.h, which can't be directly included since
+ * this is used in userspace code, which has no access to the kernel
+ * headers. Changed to be suitable for adding casts to the start,
+ * rather than "UL" to the end.
*/
-#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
-#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
-#define ASM_STUB_START ASM_STUB_CODE
-/*
- * This file is included by the assembly stubs, which just want the
- * definitions above.
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally. We
+ * use the following macros to deal with this.
*/
-#ifndef __ASSEMBLY__
-#define STUB_CODE ((unsigned long) ASM_STUB_CODE)
-#define STUB_DATA ((unsigned long) ASM_STUB_DATA)
-#define STUB_START ((unsigned long) ASM_STUB_START)
+#ifdef __ASSEMBLY__
+#define _AC(X, Y) (Y)
+#else
+#define __AC(X, Y) (X (Y))
+#define _AC(X, Y) __AC(X, Y)
+#endif
+
+#define STUB_START _AC(, 0x100000)
+#define STUB_CODE _AC((unsigned long), STUB_START)
+#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
+#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
+
+#ifndef __ASSEMBLY__
#include "sysdep/ptrace.h"
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 5a2263e05bb..9b9ced85b70 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -48,7 +48,7 @@ extern void register_winch_irq(int fd, int tty_fd, int pid,
#define __channel_help(fn, prefix) \
__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
" Attach a console or serial line to a host channel. See\n" \
-" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \
+" http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
" description of this switch.\n\n" \
);
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 0edab695ed4..b54bd35585c 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -18,6 +18,7 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
DEFINE_STR(UM_KERN_INFO, KERN_INFO);
DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+DEFINE_STR(UM_KERN_CONT, KERN_CONT);
DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index cebc6cae919..b00a95741d4 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -40,6 +40,20 @@
typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);
+#ifndef __KERNEL__
+#ifndef __section
+# define __section(S) __attribute__ ((__section__(#S)))
+#endif
+
+#if __GNUC_MINOR__ >= 3
+# define __used __attribute__((__used__))
+#else
+# define __used __attribute__((__unused__))
+#endif
+
+#else
+#include <linux/compiler.h>
+#endif
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text)
@@ -127,14 +141,3 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
#endif
#endif /* _LINUX_UML_INIT_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 884a9c17eea..e60b31873de 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -14,7 +14,6 @@ struct irq_fd {
int fd;
int type;
int irq;
- int pid;
int events;
int current_events;
};
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 74ce8e5370a..3c341222d25 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -9,107 +9,61 @@
#include "sysdep/ptrace.h"
#include "sysdep/faultinfo.h"
-typedef void (*kern_hndl)(int, struct uml_pt_regs *);
-
-struct kern_handlers {
- kern_hndl relay_signal;
- kern_hndl winch;
- kern_hndl bus_handler;
- kern_hndl page_fault;
- kern_hndl sigio_handler;
- kern_hndl timer_handler;
-};
-
-extern const struct kern_handlers handlinfo_kern;
+extern int uml_exitcode;
extern int ncpus;
-extern char *gdb_init;
extern int kmalloc_ok;
-extern int jail;
-extern int nsyscalls;
-#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define UML_ROUND_UP(addr) \
- UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
+ ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
-extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
-extern int kernel_thread_proc(void *data);
-extern void syscall_segv(int sig);
-extern int current_pid(void);
extern unsigned long alloc_stack(int order, int atomic);
+extern void free_stack(unsigned long stack, int order);
+
extern int do_signal(void);
-extern int is_stack_fault(unsigned long sp);
+extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void interrupt_end(void);
+extern void relay_signal(int sig, struct uml_pt_regs *regs);
+
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
int is_user, struct uml_pt_regs *regs);
extern int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out);
-extern void syscall_ready(void);
-extern void set_tracing(void *t, int tracing);
-extern int is_tracing(void *task);
-extern int segv_syscall(void);
-extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
-extern unsigned long page_mask(void);
-extern int need_finish_fork(void);
-extern void free_stack(unsigned long stack, int order);
-extern void add_input_request(int op, void (*proc)(int), void *arg);
-extern char *current_cmd(void);
-extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern int set_signals(int enable);
-extern int pid_to_processor_id(int pid);
-extern void deliver_signals(void *t);
-extern int next_trap_index(int max);
-extern void default_idle(void);
-extern void finish_fork(void);
-extern void paging_init(void);
-extern void init_flush_vm(void);
-extern void *syscall_sp(void *t);
-extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
-extern void interrupt_end(void);
-extern void initial_thread_cb(void (*proc)(void *), void *arg);
-extern int debugger_signal(int status, int pid);
-extern void debugger_parent_signal(int status, int pid);
-extern void child_signal(int pid, int status);
-extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
-extern int init_parent_proxy(int pid);
-extern int singlestepping(void *t);
-extern void check_stack_overflow(void *ptr);
-extern void relay_signal(int sig, struct uml_pt_regs *regs);
-extern int user_context(unsigned long sp);
-extern void timer_irq(struct uml_pt_regs *regs);
-extern void do_uml_exitcalls(void);
-extern int attach_debugger(int idle_pid, int pid, int stop);
-extern int config_gdb(char *str);
-extern int remove_gdb(void);
-extern char *uml_strdup(char *string);
-extern void unprotect_kernel_mem(void);
-extern void protect_kernel_mem(void);
-extern void uml_cleanup(void);
-extern void lock_signalled_task(void *t);
-extern void IPI_handler(int cpu);
-extern int jail_setup(char *line, int *add);
-extern void *get_init_task(void);
-extern int clear_user_proc(void *buf, int size);
-extern int copy_to_user_proc(void *to, void *from, int size);
-extern int copy_from_user_proc(void *to, void *from, int size);
-extern int strlen_user_proc(char *str);
-extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
-extern void *get_current(void);
-extern struct task_struct *get_task(int pid, int require);
-extern void machine_halt(void);
+extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int is_syscall(unsigned long addr);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void free_irq(unsigned int, void *);
-extern int cpu(void);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void time_init_kern(void);
+extern int start_uml(void);
+extern void paging_init(void);
-/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
+extern void uml_cleanup(void);
+extern void do_uml_exitcalls(void);
+
+/*
+ * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
+ * GFP_ATOMIC.
+ */
extern int __cant_sleep(void);
-extern void sigio_handler(int sig, struct uml_pt_regs *regs);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void *get_current(void);
+extern int copy_from_user_proc(void *to, void *from, int size);
+extern int cpu(void);
+extern char *uml_strdup(const char *string);
+
extern unsigned long to_irq_stack(unsigned long *mask_out);
-unsigned long from_irq_stack(int nested);
-extern int start_uml(void);
+extern unsigned long from_irq_stack(int nested);
+
+extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+extern int singlestepping(void *t);
+
+extern void segv_handler(int sig, struct uml_pt_regs *regs);
+extern void bus_handler(int sig, struct uml_pt_regs *regs);
+extern void winch(int sig, struct uml_pt_regs *regs);
+extern void fatal_sigsegv(void) __attribute__ ((noreturn));
+
+
#endif
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index a54514d2cc3..46384acd547 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -46,9 +46,6 @@ extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
-extern unsigned long host_task_size;
-extern unsigned long task_size;
-
extern int init_mem_user(void);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
@@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable,
unsigned long len, unsigned long long highmem);
extern void add_iomem(char *name, int fd, unsigned long size);
extern unsigned long phys_offset(unsigned long phys);
-extern void unmap_physmem(void);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
-extern unsigned long get_kmem_end(void);
#endif
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
deleted file mode 100644
index 989bc08de36..00000000000
--- a/arch/um/include/misc_constants.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MISC_CONSTANT_H_
-#define __MISC_CONSTANT_H_
-
-#include <user_constants.h>
-
-#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 6f0d1c741bc..0b6b6273330 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -8,7 +8,6 @@
#include <stdarg.h>
#include "irq_user.h"
-#include "kern_util.h"
#include "longjmp.h"
#include "mm_id.h"
#include "sysdep/tls.h"
@@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags)
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
-extern int os_get_exec_close(int fd, int *close_on_exec);
extern int os_set_exec_close(int fd);
extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
-extern int os_set_owner(int fd, int pid);
extern int os_mode_fd(int fd, int mode);
extern int os_seek_file(int fd, unsigned long long offset);
-extern int os_open_file(char *file, struct openflags flags, int mode);
+extern int os_open_file(const char *file, struct openflags flags, int mode);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
-extern int os_file_size(char *file, unsigned long long *size_out);
-extern int os_file_modtime(char *file, unsigned long *modtime);
+extern int os_file_size(const char *file, unsigned long long *size_out);
+extern int os_file_modtime(const char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
-extern int os_set_fd_async(int fd, int owner);
+extern int os_set_fd_async(int fd);
extern int os_clear_fd_async(int fd);
extern int os_set_fd_block(int fd, int blocking);
extern int os_accept_connection(int fd);
-extern int os_create_unix_socket(char *file, int len, int close_on_exec);
+extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
extern int os_shutdown_socket(int fd, int r, int w);
extern void os_close_file(int fd);
extern int os_rcv_fd(int fd, int *helper_pid_out);
extern int create_unix_socket(char *file, int len, int close_on_exec);
-extern int os_connect_socket(char *name);
+extern int os_connect_socket(const char *name);
extern int os_file_type(char *file);
-extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_file_mode(const char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
extern void os_flush_stdout(void);
extern int os_stat_filesystem(char *path, long *bsize_out,
@@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
-extern int can_do_skas(void);
+extern void can_do_skas(void);
extern void os_check_bugs(void);
extern void check_host_supports_tls(int *supports_tls, int *tls_min);
-/* Make sure they are clear when running in TT mode. Required by
- * SEGV_MAYBE_FIXABLE */
-#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
-
/* mem.c */
extern int create_mem_file(unsigned long long len);
@@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
extern int run_helper_thread(int (*proc)(void *), void *arg,
unsigned int flags, unsigned long *stack_out);
-extern int helper_wait(int pid, int nohang, char *pname);
+extern int helper_wait(int pid);
/* tls.c */
@@ -237,16 +230,12 @@ extern void unblock_signals(void);
extern int get_signals(void);
extern int set_signals(int enable);
-/* trap.c */
-extern void os_fill_handlinfo(struct kern_handlers h);
-
/* util.c */
extern void stack_protections(unsigned long address);
extern int raw(int fd);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(char *buf, int len);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
-extern void os_dump_core(void);
+extern void os_dump_core(void) __attribute__ ((noreturn));
/* time.c */
extern void idle_sleep(unsigned long long nsecs);
@@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
extern void userspace(struct uml_pt_regs *regs);
-extern void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack);
+extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
extern void switch_threads(jmp_buf *me, jmp_buf *you);
extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
@@ -298,16 +285,12 @@ extern void os_free_irq_later(struct irq_fd *active_fds,
extern int os_get_pollfd(int i);
extern void os_set_pollfd(int i, int fd);
extern void os_set_ioignore(void);
-extern void init_irq_signals(int on_sigstack);
/* sigio.c */
extern int add_sigio_fd(int fd);
extern int ignore_sigio_fd(int fd);
extern void maybe_sigio_broken(int fd, int read);
-/* skas/trap */
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
-
/* sys-x86_64/prctl.c */
extern int os_arch_prctl(int pid, int code, unsigned long *addr);
diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h
index f3450e6bc18..4bce6e01288 100644
--- a/arch/um/include/ptrace_user.h
+++ b/arch/um/include/ptrace_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -10,12 +10,6 @@
extern int ptrace_getregs(long pid, unsigned long *regs_out);
extern int ptrace_setregs(long pid, unsigned long *regs_in);
-extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
-extern int ptrace_setfpregs(long pid, unsigned long *regs);
-extern void arch_enter_kernel(void *task, int pid);
-extern void arch_leave_kernel(void *task, int pid);
-extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
-
/* syscall emulation path in ptrace */
@@ -54,7 +48,8 @@ extern int sysemu_supported;
(((int[3][3] ) { \
{ PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
{ PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
- { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \
+ { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
+ PTRACE_SYSEMU_SINGLESTEP } }) \
[sysemu_mode][singlestep_mode])
#endif
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 0e27406a43a..9ea1ae3c8f4 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,14 +9,13 @@
#include "sysdep/ptrace.h"
#include "sysdep/archsetjmp.h"
-extern void init_thread_registers(struct uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern int save_fpx_registers(int pid, unsigned long *fp_regs);
extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
-extern void init_registers(int pid);
+extern int save_registers(int pid, struct uml_pt_regs *regs);
+extern int restore_registers(int pid, struct uml_pt_regs *regs);
+extern int init_registers(int pid);
extern void get_safe_registers(unsigned long *regs);
extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h
deleted file mode 100644
index aeb5d5ab1df..00000000000
--- a/arch/um/include/signal_kern.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SIGNAL_KERN_H__
-#define __SIGNAL_KERN_H__
-
-extern int have_signals(void *t);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
deleted file mode 100644
index e065feb000d..00000000000
--- a/arch/um/include/skas/mode-skas.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_SKAS_H__
-#define __MODE_SKAS_H__
-
-extern void kill_off_processes_skas(void);
-
-#endif
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 57bd79efbee..905698197e3 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386;
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
- ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+ ((long (*)(struct syscall_args)) \
+ (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index c978b589df4..a307237b796 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -17,16 +17,7 @@
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem));
-#define __NO_STUBS 1
-#undef __SYSCALL
-#undef _ASM_X86_64_UNISTD_H_
-#define __SYSCALL(nr, sym) [nr] = 1,
-static char syscalls[] = {
-#include <asm/arch/unistd.h>
-};
-
void foo(void)
{
#include <common-offsets.h>
-DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1);
}
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index cf72256609e..7cfb0b08565 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -30,6 +30,4 @@ extern long old_mmap(unsigned long addr, unsigned long len,
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_arch_prctl;
-#define NR_syscalls (UM_NR_syscall_max + 1)
-
#endif
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 8855d8df512..82865fcf687 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -12,10 +12,6 @@
typedef struct mm_context {
struct mm_id id;
- unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
- unsigned long last_pmd;
-#endif
struct uml_ldt ldt;
} mm_context_t;
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index fdfc06b8560..2b6fc8e0f07 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -6,7 +6,9 @@
#ifndef __ARCH_UM_UACCESS_H
#define __ARCH_UM_UACCESS_H
-#include "asm/fixmap.h"
+#include <asm/elf.h>
+#include <asm/fixmap.h>
+#include "sysdep/archsetjmp.h"
#define __under_task_size(addr, size) \
(((unsigned long) (addr) < TASK_SIZE) && \
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8196450451c..76a62c0cb2b 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -19,12 +19,13 @@
void flush_thread(void)
{
void *data = NULL;
- unsigned long end = proc_mm ? task_size : STUB_START;
int ret;
arch_flush_thread(&current->thread.arch);
- ret = unmap(&current->mm->context.id, 0, end, 1, &data);
+ ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
+ ret = ret || unmap(&current->mm->context.id, STUB_END,
+ TASK_SIZE - STUB_END, 1, &data);
if (ret) {
printk(KERN_ERR "flush_thread - clearing address space failed, "
"err = %d\n", ret);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index c716b5a6db1..984f80e668c 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,15 +1,17 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/init.h"
-#include "linux/ctype.h"
-#include "linux/proc_fs.h"
-#include "asm/uaccess.h"
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
-/* If read and write race, the read will still atomically read a valid
+/*
+ * If read and write race, the read will still atomically read a valid
* value.
*/
int uml_exitcode = 0;
@@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
{
int len, val;
- /* Save uml_exitcode in a local so that we don't need to guarantee
+ /*
+ * Save uml_exitcode in a local so that we don't need to guarantee
* that sprintf accesses it atomically.
*/
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count)
+ if (len <= off+count)
*eof = 1;
*start = page + off;
- if(len > count)
+ if (len > count)
len = count;
- if(len < 0)
+ if (len < 0)
len = 0;
return len;
}
@@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
char *end, buf[sizeof("nnnnn\0")];
int tmp;
- if(copy_from_user(buf, buffer, count))
+ if (copy_from_user(buf, buffer, count))
return -EFAULT;
tmp = simple_strtol(buf, &end, 0);
- if((*end != '\0') && !isspace(*end))
+ if ((*end != '\0') && !isspace(*end))
return -EINVAL;
uml_exitcode = tmp;
@@ -57,7 +60,7 @@ static int make_proc_exitcode(void)
struct proc_dir_entry *ent;
ent = create_proc_entry("exitcode", 0600, &proc_root);
- if(ent == NULL){
+ if (ent == NULL) {
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
return 0;
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 734f873cab1..72eccd2a411 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,12 +8,13 @@
extern void __bb_init_func(void *) __attribute__((weak));
EXPORT_SYMBOL(__bb_init_func);
-/* This is defined (and referred to in profiling stub code) only by some GCC
+/*
+ * This is defined (and referred to in profiling stub code) only by some GCC
* versions in libgcov.
*
* Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which will
- * be overridden by any other one.
+ * So, unconditionally export it. But also give it a weak declaration, which
+ * will be overridden by any other one.
*/
extern void __gcov_init(void *) __attribute__((weak));
diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c
index 9244f018d44..e2f043d0de6 100644
--- a/arch/um/kernel/gprof_syms.c
+++ b/arch/um/kernel/gprof_syms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,14 +7,3 @@
extern void mcount(void);
EXPORT_SYMBOL(mcount);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 16dc43e9d94..fa015565001 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,7 +7,6 @@
#include "linux/bootmem.h"
#include "linux/initrd.h"
#include "asm/types.h"
-#include "kern_util.h"
#include "initrd.h"
#include "init.h"
#include "os.h"
@@ -21,18 +20,27 @@ static int __init read_initrd(void)
long long size;
int err;
- if(initrd == NULL)
+ if (initrd == NULL)
return 0;
err = os_file_size(initrd, &size);
- if(err)
+ if (err)
return 0;
+ /*
+ * This is necessary because alloc_bootmem craps out if you
+ * ask for no memory.
+ */
+ if (size == 0) {
+ printk(KERN_ERR "\"%\" is a zero-size initrd\n");
+ return 0;
+ }
+
area = alloc_bootmem(size);
- if(area == NULL)
+ if (area == NULL)
return 0;
- if(load_initrd(initrd, area, size) == -1)
+ if (load_initrd(initrd, area, size) == -1)
return 0;
initrd_start = (unsigned long) area;
@@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size)
int fd, n;
fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ if (fd < 0) {
+ printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
+ -fd);
return -1;
}
n = os_read_file(fd, buf, size);
- if(n != size){
- printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ if (n != size) {
+ printk(KERN_ERR "Read of %d bytes from '%s' failed, "
+ "err = %d\n", size,
filename, -n);
return -1;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index ba11ccd6a8a..91587f8db34 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -107,10 +107,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
struct pollfd *tmp_pfd;
struct irq_fd *new_fd, *irq_fd;
unsigned long flags;
- int pid, events, err, n;
+ int events, err, n;
- pid = os_getpid();
- err = os_set_fd_async(fd, pid);
+ err = os_set_fd_async(fd);
if (err < 0)
goto out;
@@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.fd = fd,
.type = type,
.irq = irq,
- .pid = pid,
.events = events,
.current_events = 0 } );
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7c7142ba3bd..5311ee93ede 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -18,15 +18,11 @@ EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(task_size);
EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
-EXPORT_SYMBOL(get_kmem_end);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(um_virt_to_phys);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
@@ -40,7 +36,6 @@ EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
EXPORT_SYMBOL(os_access);
-EXPORT_SYMBOL(os_get_exec_close);
EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
EXPORT_SYMBOL(os_open_file);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 59822dee438..d872fdce1d7 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,49 +1,41 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/mm.h"
-#include "linux/bootmem.h"
-#include "linux/swap.h"
-#include "linux/highmem.h"
-#include "linux/gfp.h"
-#include "asm/page.h"
-#include "asm/fixmap.h"
-#include "asm/pgalloc.h"
-#include "kern_util.h"
+#include <linux/stddef.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
#include "as-layout.h"
+#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
-#include "um_uaccess.h"
#include "os.h"
-#include "linux/types.h"
-#include "linux/string.h"
-#include "init.h"
-#include "kern_constants.h"
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL;
/* allocated in paging_init and unchanged thereafter */
unsigned long *empty_bad_page = NULL;
+
+/*
+ * Initialized during boot, and readonly for initializing page tables
+ * afterwards
+ */
pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* Initialized at boot time, and readonly after that */
unsigned long long highmem;
int kmalloc_ok = 0;
+/* Used during early boot */
static unsigned long brk_end;
-void unmap_physmem(void)
-{
- os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
-
-static void map_cb(void *unused)
-{
- map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
-}
-
#ifdef CONFIG_HIGHMEM
static void setup_highmem(unsigned long highmem_start,
unsigned long highmem_len)
@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
int i;
highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
- for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+ for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
page = &mem_map[highmem_pfn + i];
ClearPageReserved(page);
init_page_count(page);
@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
void __init mem_init(void)
{
/* clear the zero-page */
- memset((void *) empty_zero_page, 0, PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
/* Map in the area just after the brk now that kmalloc is about
* to be turned on.
*/
brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
- map_cb(NULL);
- initial_thread_cb(map_cb, NULL);
+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
@@ -85,7 +76,7 @@ void __init mem_init(void)
#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
- printk(KERN_INFO "Memory: %luk available\n",
+ printk(KERN_INFO "Memory: %luk available\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
kmalloc_ok = 1;
@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
#endif
}
-static void __init fixrange_init(unsigned long start, unsigned long end,
+static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
if (pud_none(*pud))
one_md_table_init(pud);
pmd = pmd_offset(pud, vaddr);
- for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
- (vaddr)), (vaddr))
+ (vaddr)), (vaddr))
static void __init kmap_init(void)
{
@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long paddr, vaddr = FIXADDR_USER_START;
+ phys_t p;
+ unsigned long v, vaddr = FIXADDR_USER_START;
- if ( ! size )
+ if (!size)
return;
fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
- paddr = (unsigned long)alloc_bootmem_low_pages( size);
- memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
- paddr = __pa(paddr);
- for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
+ v = (unsigned long) alloc_bootmem_low_pages(size);
+ memcpy((void *) v , (void *) FIXADDR_USER_START, size);
+ p = __pa(v);
+ for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
+ p += PAGE_SIZE) {
pgd = swapper_pg_dir + pgd_index(vaddr);
pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
- pte_set_val( (*pte), paddr, PAGE_READONLY);
+ pte_set_val(*pte, p, PAGE_READONLY);
}
#endif
}
@@ -223,7 +216,7 @@ void __init paging_init(void)
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
- for(i = 0; i < ARRAY_SIZE(zones_size); i++)
+ for (i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
int i;
again:
- if(page == NULL)
+ if (page == NULL)
return page;
- if(PageHighMem(page))
+ if (PageHighMem(page))
return page;
addr = (unsigned long) page_address(page);
- for(i = 0; i < (1 << order); i++){
+ for (i = 0; i < (1 << order); i++) {
current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void __user *) addr, &zero,
+ if (__do_copy_to_user((void __user *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
- &current->thread.fault_catcher)){
- if(!(mask & __GFP_WAIT))
+ &current->thread.fault_catcher)) {
+ if (!(mask & __GFP_WAIT))
return NULL;
else break;
}
addr += PAGE_SIZE;
}
- if(i == (1 << order))
+ if (i == (1 << order))
return page;
page = alloc_pages(mask, order);
goto again;
}
-/* This can't do anything because nothing in the kernel image can be freed
+/*
+ * This can't do anything because nothing in the kernel image can be freed
* since it's not in kernel physical memory.
*/
@@ -290,8 +284,8 @@ void free_initmem(void)
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
- printk ("Freeing initrd memory: %ldk freed\n",
- (end - start) >> 10);
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+ (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
@@ -308,32 +302,31 @@ void show_mem(void)
int highmem = 0;
struct page *page;
- printk("Mem-info:\n");
+ printk(KERN_INFO "Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Free swap: %6ldkB\n",
+ nr_swap_pages<<(PAGE_SHIFT-10));
pfn = max_mapnr;
- while(pfn-- > 0) {
+ while (pfn-- > 0) {
page = pfn_to_page(pfn);
total++;
- if(PageHighMem(page))
+ if (PageHighMem(page))
highmem++;
- if(PageReserved(page))
+ if (PageReserved(page))
reserved++;
- else if(PageSwapCache(page))
+ else if (PageSwapCache(page))
cached++;
- else if(page_count(page))
+ else if (page_count(page))
shared += page_count(page) - 1;
}
- printk("%d pages of RAM\n", total);
- printk("%d pages of HIGHMEM\n", highmem);
- printk("%d reserved pages\n", reserved);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
}
-/*
- * Allocate and free page tables.
- */
+/* Allocate and free page tables. */
pgd_t *pgd_alloc(struct mm_struct *mm)
{
@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
@@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
+
+#ifdef CONFIG_3_LEVEL_PGTABLES
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd)
+ memset(pmd, 0, PAGE_SIZE);
+
+ return pmd;
+}
+#endif
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index e66432f4248..9757085a022 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -55,16 +55,6 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
return 0;
}
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
- if (kmem_top == 0)
- kmem_top = host_task_size - 1024 * 1024;
- return kmem_top;
-}
-
void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
int r, int w, int x)
{
@@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem,
* setup_iomem, both of which run during early boot. Afterwards, it's
* unchanged.
*/
-struct iomem_region *iomem_regions = NULL;
+struct iomem_region *iomem_regions;
-/* Initialized in parse_iomem */
-int iomem_size = 0;
+/* Initialized in parse_iomem and unchanged thereafter */
+int iomem_size;
unsigned long find_iomem(char *driver, unsigned long *len_out)
{
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 0eae00b3e58..c07961bedb7 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -4,19 +4,21 @@
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/err.h"
-#include "linux/hardirq.h"
-#include "linux/mm.h"
-#include "linux/personality.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/sched.h"
-#include "linux/tick.h"
-#include "linux/threads.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/threads.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
@@ -30,7 +32,7 @@
*/
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-static inline int external_pid(struct task_struct *task)
+static inline int external_pid(void)
{
/* FIXME: Need to look up userspace_pid by cpu */
return userspace_pid[0];
@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
{
int i;
- for(i = 0; i < ncpus; i++) {
+ for (i = 0; i < ncpus; i++) {
if (cpu_tasks[i].pid == pid)
return i;
}
@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
if (atomic)
flags = GFP_ATOMIC;
page = __get_free_pages(flags, order);
- if (page == 0)
- return 0;
return page;
}
@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
static inline void set_current(struct task_struct *task)
{
cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
- { external_pid(task), task });
+ { external_pid(), task });
}
-extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to(struct task_struct *to);
void *_switch_to(void *prev, void *next, void *last)
{
struct task_struct *from = prev;
- struct task_struct *to= next;
+ struct task_struct *to = next;
to->thread.prev_sched = from;
set_current(to);
@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
switch_threads(&from->thread.switch_buf,
&to->thread.switch_buf);
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
if (current->thread.saved_task)
show_regs(&(current->thread.regs));
- next= current->thread.saved_task;
- prev= current;
- } while(current->thread.saved_task);
+ to = current->thread.saved_task;
+ from = current;
+ } while (current->thread.saved_task);
return current->thread.prev_sched;
@@ -163,8 +163,6 @@ void new_thread_handler(void)
void fork_handler(void)
{
force_flush_all();
- if (current->thread.prev_sched == NULL)
- panic("blech");
schedule_tail(current->thread.prev_sched);
@@ -173,7 +171,7 @@ void fork_handler(void)
* arch_switch_to isn't needed. We could want to apply this to
* improve performance. -bb
*/
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
current->thread.prev_sched = NULL;
@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
arch_copy_thread(&current->thread.arch, &p->thread.arch);
}
else {
- init_thread_registers(&p->thread.regs.regs);
+ get_safe_registers(p->thread.regs.regs.gp);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
@@ -237,7 +235,7 @@ void default_idle(void)
{
unsigned long long nsecs;
- while(1) {
+ while (1) {
/* endless idle loop with no priority at all */
/*
@@ -256,53 +254,10 @@ void default_idle(void)
void cpu_idle(void)
{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
+ cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
default_idle();
}
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t ptent;
-
- if (task->mm == NULL)
- return ERR_PTR(-EINVAL);
- pgd = pgd_offset(task->mm, addr);
- if (!pgd_present(*pgd))
- return ERR_PTR(-EINVAL);
-
- pud = pud_offset(pgd, addr);
- if (!pud_present(*pud))
- return ERR_PTR(-EINVAL);
-
- pmd = pmd_offset(pud, addr);
- if (!pmd_present(*pmd))
- return ERR_PTR(-EINVAL);
-
- pte = pte_offset_kernel(pmd, addr);
- ptent = *pte;
- if (!pte_present(ptent))
- return ERR_PTR(-EINVAL);
-
- if (pte_out != NULL)
- *pte_out = ptent;
- return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
- return "(Unknown)";
-#else
- void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
- return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
void dump_thread(struct pt_regs *regs, struct user *u)
{
}
@@ -317,7 +272,7 @@ int user_context(unsigned long sp)
unsigned long stack;
stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
- return stack != (unsigned long) current_thread;
+ return stack != (unsigned long) current_thread_info();
}
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -331,7 +286,7 @@ void do_uml_exitcalls(void)
(*call)();
}
-char *uml_strdup(char *string)
+char *uml_strdup(const char *string)
{
return kstrdup(string, GFP_KERNEL);
}
@@ -359,7 +314,7 @@ int strlen_user_proc(char __user *str)
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
- int cpu = current_thread->cpu;
+ int cpu = current_thread_info()->cpu;
IPI_handler(cpu);
if (cpu != 0)
return 1;
@@ -369,7 +324,7 @@ int smp_sigio_handler(void)
int cpu(void)
{
- return current_thread->cpu;
+ return current_thread_info()->cpu;
}
static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -435,7 +390,7 @@ int singlestepping(void * t)
{
struct task_struct *task = t ? t : current;
- if ( ! (task->ptrace & PT_DTRACE) )
+ if (!(task->ptrace & PT_DTRACE))
return 0;
if (task->thread.singlestep_syscall)
@@ -459,3 +414,46 @@ unsigned long arch_align_stack(unsigned long sp)
return sp & ~0xf;
}
#endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long stack_page, sp, ip;
+ bool seen_sched = 0;
+
+ if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
+ return 0;
+
+ stack_page = (unsigned long) task_stack_page(p);
+ /* Bail if the process has no kernel stack for some reason */
+ if (stack_page == 0)
+ return 0;
+
+ sp = p->thread.switch_buf->JB_SP;
+ /*
+ * Bail if the stack pointer is below the bottom of the kernel
+ * stack for some reason
+ */
+ if (sp < stack_page)
+ return 0;
+
+ while (sp < stack_page + THREAD_SIZE) {
+ ip = *((unsigned long *) sp);
+ if (in_sched_functions(ip))
+ /* Ignore everything until we're above the scheduler */
+ seen_sched = 1;
+ else if (kernel_text_address(ip) && seen_sched)
+ return ip;
+
+ sp += sizeof(unsigned long);
+ }
+
+ return 0;
+}
+
+int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+{
+ int cpu = current_thread_info()->cpu;
+
+ return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+}
+
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 04cebcf0679..00197d3d21e 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
*/
#include "linux/sched.h"
+#include "kern_util.h"
#include "os.h"
#include "skas.h"
@@ -11,7 +12,7 @@ void (*pm_power_off)(void);
static void kill_off_processes(void)
{
- if(proc_mm)
+ if (proc_mm)
/*
* FIXME: need to loop over userspace_pids
*/
@@ -21,8 +22,8 @@ static void kill_off_processes(void)
int pid, me;
me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
+ for_each_process(p) {
+ if (p->mm == NULL)
continue;
pid = p->mm->context.id.u.pid;
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 89f9866a135..2b272b63b51 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -1,18 +1,12 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/list.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "init.h"
-#include "sigio.h"
-#include "irq_user.h"
+#include <linux/interrupt.h>
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
@@ -33,9 +27,9 @@ int write_sigio_irq(int fd)
err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
NULL);
- if(err){
- printk("write_sigio_irq : um_request_irq failed, err = %d\n",
- err);
+ if (err) {
+ printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
+ "err = %d\n", err);
return -1;
}
sigio_irq_fd = fd;
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 19cb9773393..b0fce720c4d 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/module.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "asm/siginfo.h"
-#include "asm/signal.h"
-#include "asm/unistd.h"
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+#include <asm/unistd.h>
#include "frame_kern.h"
#include "kern_util.h"
#include "sigcontext.h"
@@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs)
/* Did we come from a system call? */
if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
/* Restart the system call - no handlers present */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 8d07a7acb90..2c8583c1a34 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -1,17 +1,20 @@
-#include <sched.h>
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#include <signal.h>
-#include <sys/mman.h>
-#include <sys/time.h>
+#include <sched.h>
#include <asm/unistd.h>
+#include <sys/time.h>
#include "as-layout.h"
+#include "kern_constants.h"
#include "ptrace_user.h"
-#include "skas.h"
#include "stub-data.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
-#include "kern_constants.h"
-/* This is in a separate file because it needs to be compiled with any
+/*
+ * This is in a separate file because it needs to be compiled with any
* extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
*
* Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
@@ -26,25 +29,26 @@ stub_clone_handler(void)
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
- if(err != 0)
+ if (err != 0)
goto out;
err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
- if(err)
+ if (err)
goto out;
- err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
+ err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
(long) &data->timer, 0);
- if(err)
+ if (err)
goto out;
remap_stack(data->fd, data->offset);
goto done;
out:
- /* save current result.
- * Parent: pid;
- * child: retcode of mmap already saved and it jumps around this
+ /*
+ * save current result.
+ * Parent: pid;
+ * child: retcode of mmap already saved and it jumps around this
* assignment
*/
data->err = err;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index f859ec306cd..78b3e9f69d5 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -34,33 +34,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;
- /*
- * There's an interaction between the skas0 stub pages, stack
- * randomization, and the BUG at the end of exit_mmap. exit_mmap
- * checks that the number of page tables freed is the same as had
- * been allocated. If the stack is on the last page table page,
- * then the stack pte page will be freed, and if not, it won't. To
- * avoid having to know where the stack is, or if the process mapped
- * something at the top of its address space for some other reason,
- * we set TASK_SIZE to end at the start of the last page table.
- * This keeps exit_mmap off the last page, but introduces a leak
- * of that page. So, we hang onto it here and free it in
- * destroy_context_skas.
- */
-
- mm->context.last_page_table = pmd_page_vaddr(*pmd);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
-#endif
-
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
return 0;
out_pmd:
- pud_free(pud);
+ pud_free(mm, pud);
out_pte:
- pmd_free(pmd);
+ pmd_free(mm, pmd);
out:
return -ENOMEM;
}
@@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
stack = get_zeroed_page(GFP_KERNEL);
if (stack == 0)
goto out;
-
- /*
- * This zeros the entry that pgd_alloc didn't, needed since
- * we are about to reinitialize it, and want mm.nr_ptes to
- * be accurate.
- */
- mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
-
- ret = init_stub_pte(mm, STUB_CODE,
- (unsigned long) &__syscall_stub_start);
- if (ret)
- goto out_free;
-
- ret = init_stub_pte(mm, STUB_DATA, stack);
- if (ret)
- goto out_free;
-
- mm->nr_ptes--;
}
to_mm->id.stack = stack;
@@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
to_mm->id.u.pid = copy_context_skas0(stack,
from_mm->id.u.pid);
else to_mm->id.u.pid = start_userspace(stack);
+
+ if (to_mm->id.u.pid < 0) {
+ ret = to_mm->id.u.pid;
+ goto out_free;
+ }
}
ret = init_new_ldt(to_mm, from_mm);
@@ -132,24 +100,87 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
return ret;
}
+void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+{
+ struct page **pages;
+ int err, ret;
+
+ if (!skas_needs_stub)
+ return;
+
+ ret = init_stub_pte(mm, STUB_CODE,
+ (unsigned long) &__syscall_stub_start);
+ if (ret)
+ goto out;
+
+ ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
+ if (ret)
+ goto out;
+
+ pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL) {
+ printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
+ "pointers\n");
+ goto out;
+ }
+
+ pages[0] = virt_to_page(&__syscall_stub_start);
+ pages[1] = virt_to_page(mm->context.id.stack);
+
+ /* dup_mmap already holds mmap_sem */
+ err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
+ VM_READ | VM_MAYREAD | VM_EXEC |
+ VM_MAYEXEC | VM_DONTCOPY, pages);
+ if (err) {
+ printk(KERN_ERR "install_special_mapping returned %d\n", err);
+ goto out_free;
+ }
+ return;
+
+out_free:
+ kfree(pages);
+out:
+ force_sigsegv(SIGSEGV, current);
+}
+
+void arch_exit_mmap(struct mm_struct *mm)
+{
+ pte_t *pte;
+
+ pte = virt_to_pte(mm, STUB_CODE);
+ if (pte != NULL)
+ pte_clear(mm, STUB_CODE, pte);
+
+ pte = virt_to_pte(mm, STUB_DATA);
+ if (pte == NULL)
+ return;
+
+ pte_clear(mm, STUB_DATA, pte);
+}
+
void destroy_context(struct mm_struct *mm)
{
struct mm_context *mmu = &mm->context;
if (proc_mm)
os_close_file(mmu->id.u.mm_fd);
- else
+ else {
+ /*
+ * If init_new_context wasn't called, this will be
+ * zero, resulting in a kill(0), which will result in the
+ * whole UML suddenly dying. Also, cover negative and
+ * 1 cases, since they shouldn't happen either.
+ */
+ if (mmu->id.u.pid < 2) {
+ printk(KERN_ERR "corrupt mm_context - pid = %d\n",
+ mmu->id.u.pid);
+ return;
+ }
os_kill_ptraced_process(mmu->id.u.pid, 1);
+ }
- if (!proc_mm || !ptrace_faultinfo) {
+ if (skas_needs_stub)
free_page(mmu->id.stack);
- pte_lock_deinit(virt_to_page(mmu->last_page_table));
- pte_free_kernel((pte_t *) mmu->last_page_table);
- dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- pmd_free((pmd_t *) mmu->last_pmd);
-#endif
- }
free_ldt(mmu);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index fce389c2342..2e9852c0d48 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -6,19 +6,25 @@
#include "linux/init.h"
#include "linux/sched.h"
#include "as-layout.h"
+#include "kern.h"
#include "os.h"
#include "skas.h"
int new_mm(unsigned long stack)
{
- int fd;
+ int fd, err;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
if (fd < 0)
return fd;
- if (skas_needs_stub)
- map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (skas_needs_stub) {
+ err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (err) {
+ os_close_file(fd);
+ return err;
+ }
+ }
return fd;
}
@@ -49,8 +55,14 @@ int __init start_uml(void)
{
stack_protections((unsigned long) &cpu0_irqstack);
set_sigstack(cpu0_irqstack, THREAD_SIZE);
- if (proc_mm)
+ if (proc_mm) {
userspace_pid[0] = start_userspace(0);
+ if (userspace_pid[0] < 0) {
+ printf("start_uml - start_userspace returned %d\n",
+ userspace_pid[0]);
+ exit(1);
+ }
+ }
init_new_thread_signals();
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 50b476f2b38..4e3b820bd2b 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -9,6 +9,9 @@
#include "sysdep/ptrace.h"
#include "sysdep/syscalls.h"
+extern int syscall_table_size;
+#define NR_syscalls (syscall_table_size / sizeof(void *))
+
void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
@@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r)
syscall_trace(r, 0);
- current->thread.nsyscalls++;
- nsyscalls++;
-
/*
* This should go in the declaration of syscall, but when I do that,
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 1d8b119f2d0..e22c96993db 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -3,128 +3,130 @@
* Licensed under the GPL
*/
-#include "linux/err.h"
-#include "linux/highmem.h"
-#include "linux/mm.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
+#include <linux/err.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
#include "kern_util.h"
#include "os.h"
-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out);
-
-static unsigned long maybe_map(unsigned long virt, int is_write)
+pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
{
- pte_t pte;
- int err;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ if (mm == NULL)
+ return NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (!pgd_present(*pgd))
+ return NULL;
+
+ pud = pud_offset(pgd, addr);
+ if (!pud_present(*pud))
+ return NULL;
- void *phys = um_virt_to_phys(current, virt, &pte);
- int dummy_code;
+ pmd = pmd_offset(pud, addr);
+ if (!pmd_present(*pmd))
+ return NULL;
+
+ return pte_offset_kernel(pmd, addr);
+}
+
+static pte_t *maybe_map(unsigned long virt, int is_write)
+{
+ pte_t *pte = virt_to_pte(current->mm, virt);
+ int err, dummy_code;
- if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
+ if ((pte == NULL) || !pte_present(*pte) ||
+ (is_write && !pte_write(*pte))) {
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
if (err)
- return -1UL;
- phys = um_virt_to_phys(current, virt, NULL);
+ return NULL;
+ pte = virt_to_pte(current->mm, virt);
}
- if (IS_ERR(phys))
- phys = (void *) -1;
+ if (!pte_present(*pte))
+ pte = NULL;
- return (unsigned long) phys;
+ return pte;
}
static int do_op_one_page(unsigned long addr, int len, int is_write,
int (*op)(unsigned long addr, int len, void *arg), void *arg)
{
+ jmp_buf buf;
struct page *page;
- int n;
+ pte_t *pte;
+ int n, faulted;
- addr = maybe_map(addr, is_write);
- if (addr == -1UL)
+ pte = maybe_map(addr, is_write);
+ if (pte == NULL)
return -1;
- page = phys_to_page(addr);
+ page = pte_page(*pte);
addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
(addr & ~PAGE_MASK);
- n = (*op)(addr, len, arg);
+ current->thread.fault_catcher = &buf;
+
+ faulted = UML_SETJMP(&buf);
+ if (faulted == 0)
+ n = (*op)(addr, len, arg);
+ else
+ n = -1;
+
+ current->thread.fault_catcher = NULL;
kunmap_atomic(page, KM_UML_USERCOPY);
return n;
}
-static void do_buffer_op(void *jmpbuf, void *arg_ptr)
+static int buffer_op(unsigned long addr, int len, int is_write,
+ int (*op)(unsigned long, int, void *), void *arg)
{
- va_list args;
- unsigned long addr;
- int len, is_write, size, remain, n;
- int (*op)(unsigned long, int, void *);
- void *arg;
- int *res;
-
- va_copy(args, *(va_list *)arg_ptr);
- addr = va_arg(args, unsigned long);
- len = va_arg(args, int);
- is_write = va_arg(args, int);
- op = va_arg(args, void *);
- arg = va_arg(args, void *);
- res = va_arg(args, int *);
- va_end(args);
+ int size, remain, n;
+
size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
remain = len;
- current->thread.fault_catcher = jmpbuf;
n = do_op_one_page(addr, size, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += size;
remain -= size;
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
- while(addr < ((addr + remain) & PAGE_MASK)) {
+ while (addr < ((addr + remain) & PAGE_MASK)) {
n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += PAGE_SIZE;
remain -= PAGE_SIZE;
}
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
n = do_op_one_page(addr, remain, is_write, op, arg);
- if (n != 0)
- *res = (n < 0 ? remain : 0);
- else *res = 0;
- out:
- current->thread.fault_catcher = NULL;
-}
-
-static int buffer_op(unsigned long addr, int len, int is_write,
- int (*op)(unsigned long addr, int len, void *arg),
- void *arg)
-{
- int faulted, res;
-
- faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
- &res);
- if (!faulted)
- return res;
+ if (n != 0) {
+ remain = (n < 0 ? remain : 0);
+ goto out;
+ }
- return addr + len - (unsigned long) current->thread.fault_addr;
+ return 0;
+ out:
+ return remain;
}
static int copy_chunk_from_user(unsigned long from, int len, void *arg)
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 36d89cf8d20..e1062ec36d4 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
#include "asm/smp.h"
#include "asm/processor.h"
#include "asm/spinlock.h"
-#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "os.h"
@@ -61,7 +60,7 @@ void smp_send_stop(void)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
- printk(KERN_INFO "done\n");
+ printk(KERN_CONT "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -75,8 +74,7 @@ static int idle_proc(void *cpup)
if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
- os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
@@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- os_set_fd_async(cpu_data[me].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[me].ipi_pipe[0]);
for (cpu = 1; cpu < ncpus; cpu++) {
printk(KERN_INFO "Booting processor %d...\n", cpu);
@@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
cpu_relax();
- if (cpu_isset(cpu, cpu_callin_map))
- printk(KERN_INFO "done\n");
- else printk(KERN_INFO "failed\n");
+ printk(KERN_INFO "%s\n",
+ cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
}
}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index b9d92b2089a..9cffc628a37 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,9 +13,6 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
-/* Unlocked, I don't care if this is a bit off */
-int nsyscalls = 0;
-
long sys_fork(void)
{
long ret;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 93263571d81..56d43d0a396 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -1,38 +1,37 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/kallsyms.h"
-#include "asm/page.h"
-#include "asm/processor.h"
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
#include "sysrq.h"
/* Catch non-i386 SUBARCH's. */
#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
void show_trace(struct task_struct *task, unsigned long * stack)
{
- unsigned long addr;
+ unsigned long addr;
- if (!stack) {
+ if (!stack) {
stack = (unsigned long*) &stack;
WARN_ON(1);
}
- printk("Call Trace: \n");
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- addr = *stack;
+ printk(KERN_INFO "Call Trace: \n");
+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack;
if (__kernel_text_address(addr)) {
- printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
- print_symbol(" %s", addr);
- printk("\n");
- }
- stack++;
- }
- printk("\n");
+ printk(KERN_INFO "%08lx: [<%08lx>]",
+ (unsigned long) stack, addr);
+ print_symbol(KERN_CONT " %s", addr);
+ printk(KERN_CONT "\n");
+ }
+ stack++;
+ }
+ printk(KERN_INFO "\n");
}
#endif
@@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp)
}
stack = esp;
- for(i = 0; i < kstack_depth_to_print; i++) {
+ for (i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(stack))
break;
if (i && ((i % 8) == 0))
- printk("\n ");
+ printk("\n" KERN_INFO " ");
printk("%08lx ", *stack++);
}
- printk("Call Trace: \n");
show_trace(task, esp);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 1ac746a9eae..e066e84493b 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/clockchips.h"
-#include "linux/interrupt.h"
-#include "linux/jiffies.h"
-#include "linux/threads.h"
-#include "asm/irq.h"
-#include "asm/param.h"
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+#include <asm/param.h>
#include "kern_util.h"
#include "os.h"
@@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs)
static void itimer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- switch(mode) {
+ switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
set_interval();
break;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f4a0e407eee..d175d0566af 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -3,9 +3,10 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/pgtable.h"
-#include "asm/tlbflush.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "as-layout.h"
#include "mem_user.h"
#include "os.h"
@@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
for (i = 0; i < end && !ret; i++) {
op = &hvc->ops[i];
- switch(op->type) {
+ switch (op->type) {
case MMAP:
ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
op->u.mmap.prot, op->u.mmap.fd,
@@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
pte = pte_offset_kernel(pmd, addr);
do {
+ if ((addr >= STUB_START) && (addr < STUB_END))
+ continue;
+
r = pte_read(*pte);
w = pte_write(*pte);
x = pte_exec(*pte);
if (!pte_young(*pte)) {
r = 0;
w = 0;
- } else if (!pte_dirty(*pte)) {
+ } else if (!pte_dirty(*pte))
w = 0;
- }
+
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
if (hvc->force || pte_newpage(*pte)) {
if (pte_present(*pte))
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, prot, hvc);
- else ret = add_munmap(addr, PAGE_SIZE, hvc);
- }
- else if (pte_newprot(*pte))
+ else
+ ret = add_munmap(addr, PAGE_SIZE, hvc);
+ } else if (pte_newprot(*pte))
ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
*pte = pte_mkuptodate(*pte);
- } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
+ } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
return ret;
}
@@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
}
}
else ret = update_pte_range(pmd, addr, next, hvc);
- } while (pmd++, addr = next, ((addr != end) && !ret));
+ } while (pmd++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
}
}
else ret = update_pmd_range(pud, addr, next, hvc);
- } while (pud++, addr = next, ((addr != end) && !ret));
+ } while (pud++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
}
}
else ret = update_pud_range(pgd, addr, next, &hvc);
- } while (pgd++, addr = next, ((addr != end_addr) && !ret));
+ } while (pgd++, addr = next, ((addr < end_addr) && !ret));
if (!ret)
ret = do_ops(&hvc, hvc.index, 1);
@@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
- if (!proc_mm && (end_addr > STUB_START))
- end_addr = STUB_START;
-
fix_range_common(mm, start_addr, end_addr, force);
}
@@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
else fix_range(vma->vm_mm, start, end, 0);
}
-void flush_tlb_mm(struct mm_struct *mm)
+void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
{
- unsigned long end;
-
/*
* Don't bother flushing if this address space is about to be
* destroyed.
@@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm)
if (atomic_read(&mm->mm_users) == 0)
return;
- end = proc_mm ? task_size : STUB_START;
- fix_range(mm, 0, end, 0);
+ fix_range(mm, start, end, 0);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ struct vm_area_struct *vma = mm->mmap;
+
+ while (vma != NULL) {
+ fix_range(mm, vma->vm_start, vma->vm_end, 0);
+ vma = vma->vm_next;
+ }
}
void force_flush_all(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index cb3321f8e0a..44e49041949 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -13,6 +13,7 @@
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
+#include "skas.h"
#include "sysdep/sigcontext.h"
/*
@@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
force_sig_info(SIGSEGV, &si, current);
}
-static void segv_handler(int sig, struct uml_pt_regs *regs)
+void fatal_sigsegv(void)
+{
+ force_sigsegv(SIGSEGV, current);
+ do_signal();
+ /*
+ * This is to tell gcc that we're not returning - do_signal
+ * can, in general, return, but in this case, it's not, since
+ * we just got a fatal SIGSEGV queued.
+ */
+ os_dump_core();
+}
+
+void segv_handler(int sig, struct uml_pt_regs *regs)
{
struct faultinfo * fi = UPT_FAULTINFO(regs);
@@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
void relay_signal(int sig, struct uml_pt_regs *regs)
{
- if (arch_handle_signal(sig, regs))
- return;
-
if (!UPT_IS_USER(regs)) {
if (sig == SIGBUS)
printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -226,31 +236,24 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
panic("Kernel mode signal %d", sig);
}
+ arch_examine_signal(sig, regs);
+
current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
-static void bus_handler(int sig, struct uml_pt_regs *regs)
+void bus_handler(int sig, struct uml_pt_regs *regs)
{
if (current->thread.fault_catcher != NULL)
UML_LONGJMP(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
-static void winch(int sig, struct uml_pt_regs *regs)
+void winch(int sig, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
}
-const struct kern_handlers handlinfo_kern = {
- .relay_signal = relay_signal,
- .winch = winch,
- .bus_handler = bus_handler,
- .page_fault = segv_handler,
- .sigio_handler = sigio_handler,
- .timer_handler = timer_handler
-};
-
void trap_init(void)
{
}
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index d7436aacd26..f0f4b040d7c 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -1,10 +1,11 @@
/*
* Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-/* These are here rather than tt/uaccess.c because skas mode needs them in
+/*
+ * These are here rather than tt/uaccess.c because skas mode needs them in
* order to do SIGBUS recovery when a tmpfs mount runs out of room.
*/
@@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n,
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
- if(!faulted) return(0);
- else return(n - (fault - (unsigned long) to));
+ if (!faulted)
+ return 0;
+ else
+ return n - (fault - (unsigned long) to);
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index f1c71393f57..468aba990db 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -3,22 +3,23 @@
* Licensed under the GPL
*/
-#include "linux/delay.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/seq_file.h"
-#include "linux/string.h"
-#include "linux/utsname.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/setup.h"
-#include "arch.h"
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/utsname.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
#include "as-layout.h"
+#include "arch.h"
#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
#include "os.h"
-#include "skas.h"
#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = {
};
/* Set in linux_main */
-unsigned long host_task_size;
-unsigned long task_size;
unsigned long uml_physmem;
unsigned long uml_reserved; /* Also modified in mem_init */
unsigned long start_vm;
@@ -197,20 +196,19 @@ __uml_setup("--help", Usage,
" Prints this message.\n\n"
);
-static int __init uml_checksetup(char *line, int *add)
+static void __init uml_checksetup(char *line, int *add)
{
struct uml_param *p;
p = &__uml_setup_start;
- while(p < &__uml_setup_end) {
+ while (p < &__uml_setup_end) {
int n;
n = strlen(p->str);
if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
- return 1;
+ return;
p++;
}
- return 0;
}
static void __init uml_postsetup(void)
@@ -218,13 +216,30 @@ static void __init uml_postsetup(void)
initcall_t *p;
p = &__uml_postsetup_start;
- while(p < &__uml_postsetup_end) {
+ while (p < &__uml_postsetup_end) {
(*p)();
p++;
}
return;
}
+static int panic_exit(struct notifier_block *self, unsigned long unused1,
+ void *unused2)
+{
+ bust_spinlocks(1);
+ show_regs(&(current->thread.regs));
+ bust_spinlocks(0);
+ uml_exitcode = 1;
+ os_dump_core();
+ return 0;
+}
+
+static struct notifier_block panic_exit_notifier = {
+ .notifier_call = panic_exit,
+ .next = NULL,
+ .priority = 0
+};
+
/* Set during early boot */
unsigned long brk_start;
unsigned long end_iomem;
@@ -234,20 +249,6 @@ EXPORT_SYMBOL(end_iomem);
extern char __binary_start;
-static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
-{
- /* Round up to the nearest 4M */
- unsigned long host_task_size = ROUND_4M((unsigned long)
- &host_task_size);
-
- if (!skas_needs_stub)
- *task_size_out = host_task_size;
- else
- *task_size_out = STUB_START & PGDIR_MASK;
-
- return host_task_size;
-}
-
int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -278,13 +279,6 @@ int __init linux_main(int argc, char **argv)
printf("UML running in %s mode\n", mode);
- host_task_size = set_task_sizes_skas(&task_size);
-
- /*
- * Setting up handlers to 'sig_info' struct
- */
- os_fill_handlinfo(handlinfo_kern);
-
brk_start = (unsigned long) sbrk(0);
/*
@@ -309,7 +303,7 @@ int __init linux_main(int argc, char **argv)
highmem = 0;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
- max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+ max_physmem = CONFIG_TOP_ADDR - uml_physmem - iomem_size - MIN_VMALLOC;
/*
* Zones have to begin on a 1 << MAX_ORDER page boundary,
@@ -341,7 +335,7 @@ int __init linux_main(int argc, char **argv)
}
virtmem_size = physmem_size;
- avail = get_kmem_end() - start_vm;
+ avail = CONFIG_TOP_ADDR - start_vm;
if (physmem_size > avail)
virtmem_size = avail;
end_vm = start_vm + virtmem_size;
@@ -350,6 +344,9 @@ int __init linux_main(int argc, char **argv)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
+
uml_postsetup();
stack_protections((unsigned long) &init_thread_info);
@@ -358,29 +355,8 @@ int __init linux_main(int argc, char **argv)
return start_uml();
}
-extern int uml_exitcode;
-
-static int panic_exit(struct notifier_block *self, unsigned long unused1,
- void *unused2)
-{
- bust_spinlocks(1);
- show_regs(&(current->thread.regs));
- bust_spinlocks(0);
- uml_exitcode = 1;
- os_dump_core();
- return 0;
-}
-
-static struct notifier_block panic_exit_notifier = {
- .notifier_call = panic_exit,
- .next = NULL,
- .priority = 0
-};
-
void __init setup_arch(char **cmdline_p)
{
- atomic_notifier_chain_register(&panic_notifier_list,
- &panic_exit_notifier);
paging_init();
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 039e16efcd5..81e07e2be3a 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -1,13 +1,12 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "asm/errno.h"
+#include <asm/errno.h>
#include "init.h"
-#include "os.h"
#include "kern.h"
-#include "linux/kernel.h"
+#include "os.h"
/* Changed by set_umid_arg */
static int umid_inited = 0;
@@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add)
{
int err;
- if(umid_inited){
+ if (umid_inited) {
printf("umid already set\n");
return 0;
}
*add = 0;
err = set_umid(name);
- if(err == -EEXIST)
+ if (err == -EEXIST)
printf("umid '%s' already in use\n", name);
- else if(!err)
+ else if (!err)
umid_inited = 1;
return 0;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 8e129af8170..8a48d6a3006 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,7 +4,7 @@
#
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
- registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
+ registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
- trap.o tty.o tls.o uaccess.o umid.o util.o
+ tty.o tls.o uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 93dc0c80eba..b8d8c9ca8d4 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -12,6 +12,7 @@
#include "aio.h"
#include "init.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 07ca0cb472a..6fb0b174f53 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -131,7 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
}
if (c != 1) {
printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
- err = helper_wait(pid, 0, "uml_net");
+ err = helper_wait(pid);
}
return err;
}
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 1037a3b6386..2448be03fd7 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -14,6 +14,7 @@
#include <sys/wait.h>
#include <sys/uio.h>
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "tuntap.h"
#include "user.h"
@@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
"errno = %d\n", errno);
return err;
}
- helper_wait(pid, 0, "tuntap_open_tramp");
+ helper_wait(pid);
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
@@ -148,7 +149,7 @@ static int tuntap_open(void *data)
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
- if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) {
+ if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
err = -errno;
printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
errno);
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f8346275862..b5afcfd0f86 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,18 +8,16 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
-#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "kern_constants.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
-static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
{
*dst = ((struct uml_stat) {
.ust_dev = src->st_dev, /* device */
@@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
int err;
CATCH_EINTR(err = fstat64(fd, &sbuf));
- if(err < 0)
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
@@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
struct stat64 sbuf;
int err;
- do {
- err = stat64(file_name, &sbuf);
- } while((err < 0) && (errno == EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = stat64(file_name, &sbuf));
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
-int os_access(const char* file, int mode)
+int os_access(const char *file, int mode)
{
int amode, err;
- amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
- (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+ amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
+ (mode & OS_ACC_W_OK ? W_OK : 0) |
+ (mode & OS_ACC_X_OK ? X_OK : 0) |
+ (mode & OS_ACC_F_OK ? F_OK : 0);
err = access(file, amode);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
@@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
int err;
err = ioctl(fd, cmd, arg);
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
@@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
- if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+ if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
return -errno;
return 0;
@@ -108,37 +105,22 @@ int os_set_slip(int fd)
int disc, sencap;
disc = N_SLIP;
- if(ioctl(fd, TIOCSETD, &disc) < 0)
+ if (ioctl(fd, TIOCSETD, &disc) < 0)
return -errno;
sencap = 0;
- if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+ if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
return -errno;
return 0;
}
-int os_set_owner(int fd, int pid)
-{
- if(fcntl(fd, F_SETOWN, pid) < 0){
- int save_errno = errno;
-
- if(fcntl(fd, F_GETOWN, 0) != pid)
- return -save_errno;
- }
-
- return 0;
-}
-
int os_mode_fd(int fd, int mode)
{
int err;
- do {
- err = fchmod(fd, mode);
- } while((err < 0) && (errno==EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = fchmod(fd, mode));
+ if (err < 0)
return -errno;
return 0;
@@ -150,64 +132,73 @@ int os_file_type(char *file)
int err;
err = os_stat_file(file, &buf);
- if(err < 0)
+ if (err < 0)
return err;
- if(S_ISDIR(buf.ust_mode))
+ if (S_ISDIR(buf.ust_mode))
return OS_TYPE_DIR;
- else if(S_ISLNK(buf.ust_mode))
+ else if (S_ISLNK(buf.ust_mode))
return OS_TYPE_SYMLINK;
- else if(S_ISCHR(buf.ust_mode))
+ else if (S_ISCHR(buf.ust_mode))
return OS_TYPE_CHARDEV;
- else if(S_ISBLK(buf.ust_mode))
+ else if (S_ISBLK(buf.ust_mode))
return OS_TYPE_BLOCKDEV;
- else if(S_ISFIFO(buf.ust_mode))
+ else if (S_ISFIFO(buf.ust_mode))
return OS_TYPE_FIFO;
- else if(S_ISSOCK(buf.ust_mode))
+ else if (S_ISSOCK(buf.ust_mode))
return OS_TYPE_SOCK;
else return OS_TYPE_FILE;
}
-int os_file_mode(char *file, struct openflags *mode_out)
+int os_file_mode(const char *file, struct openflags *mode_out)
{
int err;
*mode_out = OPENFLAGS();
err = access(file, W_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_write(*mode_out);
err = access(file, R_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_read(*mode_out);
return err;
}
-int os_open_file(char *file, struct openflags flags, int mode)
+int os_open_file(const char *file, struct openflags flags, int mode)
{
int fd, err, f = 0;
- if(flags.r && flags.w) f = O_RDWR;
- else if(flags.r) f = O_RDONLY;
- else if(flags.w) f = O_WRONLY;
+ if (flags.r && flags.w)
+ f = O_RDWR;
+ else if (flags.r)
+ f = O_RDONLY;
+ else if (flags.w)
+ f = O_WRONLY;
else f = 0;
- if(flags.s) f |= O_SYNC;
- if(flags.c) f |= O_CREAT;
- if(flags.t) f |= O_TRUNC;
- if(flags.e) f |= O_EXCL;
+ if (flags.s)
+ f |= O_SYNC;
+ if (flags.c)
+ f |= O_CREAT;
+ if (flags.t)
+ f |= O_TRUNC;
+ if (flags.e)
+ f |= O_EXCL;
+ if (flags.a)
+ f |= O_APPEND;
fd = open64(file, f, mode);
- if(fd < 0)
+ if (fd < 0)
return -errno;
- if(flags.cl && fcntl(fd, F_SETFD, 1)){
+ if (flags.cl && fcntl(fd, F_SETFD, 1)) {
err = -errno;
close(fd);
return err;
@@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode)
return fd;
}
-int os_connect_socket(char *name)
+int os_connect_socket(const char *name)
{
struct sockaddr_un sock;
int fd, err;
@@ -225,13 +216,13 @@ int os_connect_socket(char *name)
snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
goto out;
}
err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
- if(err) {
+ if (err) {
err = -errno;
goto out_close;
}
@@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset)
unsigned long long actual;
actual = lseek64(fd, offset, SEEK_SET);
- if(actual != offset)
+ if (actual != offset)
return -errno;
return 0;
}
@@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len)
{
int n = read(fd, buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
@@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len)
{
int n = write(fd, (void *) buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
-int os_file_size(char *file, unsigned long long *size_out)
+int os_file_size(const char *file, unsigned long long *size_out)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
- if(S_ISBLK(buf.ust_mode)){
+ if (S_ISBLK(buf.ust_mode)) {
int fd;
long blocks;
fd = open(file, O_RDONLY, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
- printk("Couldn't open \"%s\", errno = %d\n", file,
- errno);
+ printk(UM_KERN_ERR "Couldn't open \"%s\", "
+ "errno = %d\n", file, errno);
return err;
}
- if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
+ if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
err = -errno;
- printk("Couldn't get the block size of \"%s\", "
- "errno = %d\n", file, errno);
+ printk(UM_KERN_ERR "Couldn't get the block size of "
+ "\"%s\", errno = %d\n", file, errno);
close(fd);
return err;
}
@@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out)
return 0;
}
-int os_file_modtime(char *file, unsigned long *modtime)
+int os_file_modtime(const char *file, unsigned long *modtime)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
@@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime)
return 0;
}
-int os_get_exec_close(int fd, int *close_on_exec)
-{
- int ret;
-
- CATCH_EINTR(ret = fcntl(fd, F_GETFD));
-
- if(ret < 0)
- return -errno;
-
- *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
- return ret;
-}
-
int os_set_exec_close(int fd)
{
int err;
CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
}
@@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
err = socketpair(AF_UNIX, type, 0, fds);
- if(err < 0)
+ if (err < 0)
return -errno;
- if(!close_on_exec)
+ if (!close_on_exec)
return 0;
err = os_set_exec_close(fds[0]);
- if(err < 0)
+ if (err < 0)
goto error;
err = os_set_exec_close(fds[1]);
- if(err < 0)
+ if (err < 0)
goto error;
return 0;
error:
- printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+ printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
+ -err);
close(fds[1]);
close(fds[0]);
return err;
}
-int os_set_fd_async(int fd, int owner)
+int os_set_fd_async(int fd)
{
- int err;
+ int err, flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- /* XXX This should do F_GETFL first */
- if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
+ flags |= O_ASYNC | O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) < 0) {
err = -errno;
- printk("os_set_fd_async : failed to set O_ASYNC and "
- "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
+ "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
return err;
}
-#ifdef notdef
- if(fcntl(fd, F_SETFD, 1) < 0){
- printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
- "errno = %d\n", errno);
- }
-#endif
- if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
- (fcntl(fd, F_SETOWN, owner) < 0)){
+ if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
+ (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
err = -errno;
- printk("os_set_fd_async : Failed to fcntl F_SETOWN "
- "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
- owner, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
+ "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
return err;
}
@@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner)
int os_clear_fd_async(int fd)
{
- int flags = fcntl(fd, F_GETFL);
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
flags &= ~(O_ASYNC | O_NONBLOCK);
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
}
@@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking)
int flags;
flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- if(blocking) flags &= ~O_NONBLOCK;
- else flags |= O_NONBLOCK;
+ if (blocking)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
@@ -441,7 +427,7 @@ int os_accept_connection(int fd)
int new;
new = accept(fd, NULL, 0);
- if(new < 0)
+ if (new < 0)
return -errno;
return new;
}
@@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w)
{
int what, err;
- if(r && w) what = SHUT_RDWR;
- else if(r) what = SHUT_RD;
- else if(w) what = SHUT_WR;
- else {
- printk("os_shutdown_socket : neither r or w was set\n");
+ if (r && w)
+ what = SHUT_RDWR;
+ else if (r)
+ what = SHUT_RD;
+ else if (w)
+ what = SHUT_WR;
+ else
return -EINVAL;
- }
+
err = shutdown(fd, what);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
}
@@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out)
msg.msg_flags = 0;
n = recvmsg(fd, &msg, 0);
- if(n < 0)
+ if (n < 0)
return -errno;
- else if(n != iov.iov_len)
+ else if (n != iov.iov_len)
*helper_pid_out = -1;
cmsg = CMSG_FIRSTHDR(&msg);
- if(cmsg == NULL){
- printk("rcv_fd didn't receive anything, error = %d\n", errno);
+ if (cmsg == NULL) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
+ "error = %d\n", errno);
return -1;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
- (cmsg->cmsg_type != SCM_RIGHTS)){
- printk("rcv_fd didn't receive a descriptor\n");
+ if ((cmsg->cmsg_level != SOL_SOCKET) ||
+ (cmsg->cmsg_type != SCM_RIGHTS)) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
return -1;
}
@@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out)
return new;
}
-int os_create_unix_socket(char *file, int len, int close_on_exec)
+int os_create_unix_socket(const char *file, int len, int close_on_exec)
{
struct sockaddr_un addr;
int sock, err;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if(sock < 0)
+ if (sock < 0)
return -errno;
- if(close_on_exec) {
+ if (close_on_exec) {
err = os_set_exec_close(sock);
- if(err < 0)
- printk("create_unix_socket : close_on_exec failed, "
- "err = %d", -err);
+ if (err < 0)
+ printk(UM_KERN_ERR "create_unix_socket : "
+ "close_on_exec failed, err = %d", -err);
}
addr.sun_family = AF_UNIX;
- /* XXX Be more careful about overflow */
snprintf(addr.sun_path, len, "%s", file);
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
- if(err < 0)
+ if (err < 0)
return -errno;
return sock;
@@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl)
int err, save;
err = fcntl(fd, F_SETLK, &lock);
- if(!err)
+ if (!err)
goto out;
save = -errno;
err = fcntl(fd, F_GETLK, &lock);
- if(err){
+ if (err) {
err = -errno;
goto out;
}
- printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+ printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
+ lock.l_pid);
err = save;
out:
return err;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index fba3f0fefee..f4bd349d441 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -1,22 +1,19 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
-#include <limits.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
#include <sys/socket.h>
-#include "user.h"
+#include <sys/wait.h>
+#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
struct helper_data {
void (*pre_exec)(void*);
@@ -30,21 +27,19 @@ static int helper_child(void *arg)
{
struct helper_data *data = arg;
char **argv = data->argv;
- int errval;
+ int err;
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
- errval = execvp_noalloc(data->buf, argv[0], argv);
- printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
- -errval);
- write(data->fd, &errval, sizeof(errval));
- kill(os_getpid(), SIGKILL);
+ err = execvp_noalloc(data->buf, argv[0], argv);
+
+ /* If the exec succeeds, we don't get here */
+ write(data->fd, &err, sizeof(err));
+
return 0;
}
-/* Returns either the pid of the child process we run or -E* on failure.
- * XXX The alloc_stack here breaks if this is called in the tracing thread, so
- * we need to receive a preallocated stack (a local buffer is ok). */
+/* Returns either the pid of the child process we run or -E* on failure. */
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
{
struct helper_data data;
@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (ret < 0) {
ret = -errno;
- printk("run_helper : pipe failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n",
+ errno);
goto out_free;
}
ret = os_set_exec_close(fds[1]);
if (ret < 0) {
- printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
- -ret);
+ printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, "
+ "ret = %d\n", -ret);
goto out_close;
}
@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
if (pid < 0) {
ret = -errno;
- printk("run_helper : clone failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n",
+ errno);
goto out_free2;
}
@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
} else {
if (n < 0) {
n = -errno;
- printk("run_helper : read on pipe failed, ret = %d\n",
- -n);
+ printk(UM_KERN_ERR "run_helper : read on pipe failed, "
+ "ret = %d\n", -n);
ret = n;
- kill(pid, SIGKILL);
}
CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
}
@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
pid = clone(proc, (void *) sp, flags, arg);
if (pid < 0) {
err = -errno;
- printk("run_helper_thread : clone failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread : clone failed, "
+ "errno = %d\n", errno);
return err;
}
if (stack_out == NULL) {
CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
if (pid < 0) {
err = -errno;
- printk("run_helper_thread - wait failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread - wait failed, "
+ "errno = %d\n", errno);
pid = err;
}
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- printk("run_helper_thread - thread returned status "
- "0x%x\n", status);
+ printk(UM_KERN_ERR "run_helper_thread - thread "
+ "returned status 0x%x\n", status);
free_stack(stack, 0);
} else
*stack_out = stack;
return pid;
}
-int helper_wait(int pid, int nohang, char *pname)
+int helper_wait(int pid)
{
int ret, status;
int wflags = __WCLONE;
- if (nohang)
- wflags |= WNOHANG;
-
- if (!pname)
- pname = "helper_wait";
-
CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
- printk(UM_KERN_ERR "%s : waitpid process %d failed, "
- "errno = %d\n", pname, pid, errno);
+ printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, "
+ "errno = %d\n", pid, errno);
return -errno;
- } else if (nohang && ret == 0) {
- printk(UM_KERN_ERR "%s : process %d has not exited\n",
- pname, pid);
- return -ECHILD;
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- printk(UM_KERN_ERR "%s : process %d didn't exit with "
- "status 0\n", pname, pid);
+ printk(UM_KERN_ERR "helper_wait : process %d exited with "
+ "status 0x%x\n", pid, status);
return -ECHILD;
} else
return 0;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 6aa6f95d652..0348b975e81 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -1,23 +1,19 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
+#include <poll.h>
#include <signal.h>
#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
#include "irq_user.h"
+#include "kern_constants.h"
#include "os.h"
+#include "process.h"
#include "um_malloc.h"
+#include "user.h"
/*
* Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd
@@ -36,7 +32,7 @@ int os_waiting_for_events(struct irq_fd *active_fds)
if (n < 0) {
err = -errno;
if (errno != EINTR)
- printk("sigio_handler: os_waiting_for_events:"
+ printk(UM_KERN_ERR "os_waiting_for_events:"
" poll returned %d, errno = %d\n", n, errno);
return err;
}
@@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
struct irq_fd *old_fd = *prev;
if ((pollfds[i].fd != -1) &&
(pollfds[i].fd != (*prev)->fd)) {
- printk("os_free_irq_by_cb - mismatch between "
- "active_fds and pollfds, fd %d vs %d\n",
+ printk(UM_KERN_ERR "os_free_irq_by_cb - "
+ "mismatch between active_fds and "
+ "pollfds, fd %d vs %d\n",
(*prev)->fd, pollfds[i].fd);
goto out;
}
pollfds_num--;
- /* This moves the *whole* array after pollfds[i]
+ /*
+ * This moves the *whole* array after pollfds[i]
* (though it doesn't spot as such)!
*/
memmove(&pollfds[i], &pollfds[i + 1],
(pollfds_num - i) * sizeof(pollfds[0]));
- if(*last_irq_ptr2 == &old_fd->next)
+ if (*last_irq_ptr2 == &old_fd->next)
*last_irq_ptr2 = prev;
*prev = (*prev)->next;
- if(old_fd->type == IRQ_WRITE)
+ if (old_fd->type == IRQ_WRITE)
ignore_sigio_fd(old_fd->fd);
kfree(old_fd);
continue;
@@ -138,14 +136,3 @@ void os_set_ioignore(void)
{
signal(SIGIO, SIG_IGN);
}
-
-void init_irq_signals(int on_sigstack)
-{
- int flags;
-
- flags = on_sigstack ? SA_ONSTACK : 0;
-
- set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- signal(SIGWINCH, SIG_IGN);
-}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 82c3778627b..abb9b0ffd96 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -73,7 +73,7 @@ static void install_fatal_handler(int sig)
action.sa_handler = last_ditch_exit;
if (sigaction(sig, &action, NULL) < 0) {
printf("failed to install handler for signal %d - errno = %d\n",
- errno);
+ sig, errno);
exit(1);
}
}
@@ -92,7 +92,8 @@ static void setup_env_path(void)
* just use the default + /usr/lib/uml
*/
if (!old_path || (path_len = strlen(old_path)) == 0) {
- putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+ if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH))
+ perror("couldn't putenv");
return;
}
@@ -100,15 +101,16 @@ static void setup_env_path(void)
path_len += strlen("PATH=" UML_LIB_PATH) + 1;
new_path = malloc(path_len);
if (!new_path) {
- perror("coudn't malloc to set a new PATH");
+ perror("couldn't malloc to set a new PATH");
return;
}
snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
- putenv(new_path);
+ if (putenv(new_path)) {
+ perror("couldn't putenv to set a new PATH");
+ free(new_path);
+ }
}
-extern int uml_exitcode;
-
extern void scan_elf_aux( char **envp);
int __init main(int argc, char **argv, char **envp)
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 436f8d20b20..eedc2d88ef8 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -9,7 +9,6 @@
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/statfs.h>
-#include "kern_util.h"
#include "user.h"
#include "mem_user.h"
#include "init.h"
@@ -30,7 +29,7 @@ static char *tempdir = NULL;
static void __init find_tempdir(void)
{
- char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+ const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
int i;
char *dir = NULL;
@@ -59,9 +58,10 @@ static void __init find_tempdir(void)
* read the file as needed. If there's an error, -errno is returned;
* if the end of the file is reached, 0 is returned.
*/
-static int next(int fd, char *buf, int size, char c)
+static int next(int fd, char *buf, size_t size, char c)
{
- int n, len;
+ ssize_t n;
+ size_t len;
char *ptr;
while((ptr = strchr(buf, c)) == NULL){
@@ -172,13 +172,15 @@ int __init make_tempfile(const char *template, char **out_tempname,
which_tmpdir();
tempname = malloc(MAXPATHLEN);
+ if (!tempname)
+ goto out;
find_tempdir();
if (template[0] != '/')
strcpy(tempname, tempdir);
else
tempname[0] = '\0';
- strcat(tempname, template);
+ strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
@@ -268,6 +270,7 @@ void __init check_tmpexec(void)
if(addr == MAP_FAILED){
err = errno;
perror("failed");
+ close(fd);
if(err == EPERM)
printf("%s must be not mounted noexec\n",tempdir);
exit(1);
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index bda5c3150d6..abf6beae3df 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -249,7 +249,10 @@ void init_new_thread_signals(void)
SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(1);
+ set_handler(SIGIO, (__sighandler_t) sig_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
+ SIGVTALRM, -1);
+ signal(SIGWINCH, SIG_IGN);
}
int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index a32ba6ab121..830fe6a1518 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -8,47 +8,41 @@
#include <string.h>
#include <sys/ptrace.h>
#include "sysdep/ptrace.h"
-#include "user.h"
-/* This is set once at boot time and not changed thereafter */
-
-static unsigned long exec_regs[MAX_REG_NR];
-
-void init_thread_registers(struct uml_pt_regs *to)
-{
- memcpy(to->gp, exec_regs, sizeof(to->gp));
-}
-
-void save_registers(int pid, struct uml_pt_regs *regs)
+int save_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("save_registers - saving registers failed, errno = %d\n",
- errno);
+ return -errno;
+ return 0;
}
-void restore_registers(int pid, struct uml_pt_regs *regs)
+int restore_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", errno);
+ return -errno;
+ return 0;
}
-void init_registers(int pid)
+/* This is set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[MAX_REG_NR];
+
+int init_registers(int pid)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
- if (err)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
+ if (err < 0)
+ return -errno;
arch_init_registers(pid);
+ return 0;
}
void get_safe_registers(unsigned long *regs)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index dc03e9cccb6..abf47a7c4ab 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,34 +1,33 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <unistd.h>
-#include <stdlib.h>
-#include <termios.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
#include <pty.h>
+#include <sched.h>
#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
#include <string.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include "init.h"
-#include "user.h"
+#include "kern_constants.h"
#include "kern_util.h"
-#include "sigio.h"
+#include "init.h"
#include "os.h"
+#include "sigio.h"
#include "um_malloc.h"
-#include "init.h"
+#include "user.h"
-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
+/*
+ * Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1;
static unsigned long write_sigio_stack;
-/* These arrays are initialized before the sigio thread is started, and
+/*
+ * These arrays are initialized before the sigio thread is started, and
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
@@ -43,7 +42,8 @@ struct pollfds {
int used;
};
-/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
+/*
+ * Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
static struct pollfds current_poll;
@@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
- signal(SIGWINCH, SIG_IGN);
+ signal(SIGWINCH, SIG_IGN);
fds = &current_poll;
- while(1){
+ while (1) {
n = poll(fds->poll, fds->used, -1);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("write_sigio_thread : poll returned %d, "
- "errno = %d\n", n, errno);
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+ printk(UM_KERN_ERR "write_sigio_thread : poll returned "
+ "%d, errno = %d\n", n, errno);
}
- for(i = 0; i < fds->used; i++){
+ for (i = 0; i < fds->used; i++) {
p = &fds->poll[i];
- if(p->revents == 0) continue;
- if(p->fd == sigio_private[1]){
+ if (p->revents == 0)
+ continue;
+ if (p->fd == sigio_private[1]) {
CATCH_EINTR(n = read(sigio_private[1], &c,
sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : "
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR
+ "write_sigio_thread : "
"read on socket failed, "
"err = %d\n", errno);
tmp = current_poll;
@@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused)
}
CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : write on socket "
- "failed, err = %d\n", errno);
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR "write_sigio_thread : "
+ "write on socket failed, err = %d\n",
+ errno);
}
}
@@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n)
{
struct pollfd *new;
- if(n <= polls->size)
+ if (n <= polls->size)
return 0;
new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
- if(new == NULL){
- printk("need_poll : failed to allocate new pollfds\n");
+ if (new == NULL) {
+ printk(UM_KERN_ERR "need_poll : failed to allocate new "
+ "pollfds\n");
return -ENOMEM;
}
@@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n)
return 0;
}
-/* Must be called with sigio_lock held, because it's needed by the marked
+/*
+ * Must be called with sigio_lock held, because it's needed by the marked
* critical section.
*/
static void update_thread(void)
@@ -129,15 +135,17 @@ static void update_thread(void)
char c;
flags = set_signals(0);
- n = write(sigio_private[0], &c, sizeof(c));
- if(n != sizeof(c)){
- printk("update_thread : write failed, err = %d\n", errno);
+ CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
+ errno);
goto fail;
}
CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
- if(n != sizeof(c)){
- printk("update_thread : read failed, err = %d\n", errno);
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
+ errno);
goto fail;
}
@@ -164,23 +172,23 @@ int add_sigio_fd(int fd)
int err = 0, i, n;
sigio_lock();
- for(i = 0; i < all_sigio_fds.used; i++){
- if(all_sigio_fds.poll[i].fd == fd)
+ for (i = 0; i < all_sigio_fds.used; i++) {
+ if (all_sigio_fds.poll[i].fd == fd)
break;
}
- if(i == all_sigio_fds.used)
+ if (i == all_sigio_fds.used)
goto out;
p = &all_sigio_fds.poll[i];
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd)
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used;
err = need_poll(&next_poll, n + 1);
- if(err)
+ if (err)
goto out;
memcpy(next_poll.poll, current_poll.poll,
@@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd)
struct pollfd *p;
int err = 0, i, n = 0;
- /* This is called from exitcalls elsewhere in UML - if
+ /*
+ * This is called from exitcalls elsewhere in UML - if
* sigio_cleanup has already run, then update_thread will hang
* or fail because the thread is no longer running.
*/
- if(write_sigio_pid == -1)
+ if (write_sigio_pid == -1)
return -EIO;
sigio_lock();
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd) break;
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
+ break;
}
- if(i == current_poll.used)
+ if (i == current_poll.used)
goto out;
err = need_poll(&next_poll, current_poll.used - 1);
- if(err)
+ if (err)
goto out;
- for(i = 0; i < current_poll.used; i++){
+ for (i = 0; i < current_poll.used; i++) {
p = &current_poll.poll[i];
- if(p->fd != fd)
+ if (p->fd != fd)
next_poll.poll[n++] = *p;
}
next_poll.used = current_poll.used - 1;
@@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd)
p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
if (p == NULL) {
- printk("setup_initial_poll : failed to allocate poll\n");
+ printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
+ "poll\n");
return NULL;
}
*p = ((struct pollfd) { .fd = fd,
@@ -261,27 +272,29 @@ static void write_sigio_workaround(void)
return;
err = os_pipe(l_write_sigio_fds, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 1 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
"err = %d\n", -err);
return;
}
err = os_pipe(l_sigio_private, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 2 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
"err = %d\n", -err);
goto out_close1;
}
p = setup_initial_poll(l_sigio_private[1]);
- if(!p)
+ if (!p)
goto out_close2;
sigio_lock();
- /* Did we race? Don't try to optimize this, please, it's not so likely
- * to happen, and no more than once at the boot. */
- if(write_sigio_pid != -1)
+ /*
+ * Did we race? Don't try to optimize this, please, it's not so likely
+ * to happen, and no more than once at the boot.
+ */
+ if (write_sigio_pid != -1)
goto out_free;
current_poll = ((struct pollfds) { .poll = p,
@@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read)
{
int err;
- if(!isatty(fd))
+ if (!isatty(fd))
return;
- if((read || pty_output_sigio) && (!read || pty_close_sigio))
+ if ((read || pty_output_sigio) && (!read || pty_close_sigio))
return;
write_sigio_workaround();
sigio_lock();
err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
- if(err){
- printk("maybe_sigio_broken - failed to add pollfd for "
- "descriptor %d\n", fd);
+ if (err) {
+ printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
+ "for descriptor %d\n", fd);
goto out;
}
@@ -388,7 +401,7 @@ static void openpty_cb(void *arg)
struct openpty_arg *info = arg;
info->err = 0;
- if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
info->err = -errno;
}
@@ -397,17 +410,17 @@ static int async_pty(int master, int slave)
int flags;
flags = fcntl(master, F_GETFL);
- if(flags < 0)
+ if (flags < 0)
return -errno;
- if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
- (fcntl(master, F_SETOWN, os_getpid()) < 0))
+ if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+ (fcntl(master, F_SETOWN, os_getpid()) < 0))
return -errno;
- if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+ if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
return -errno;
- return(0);
+ return 0;
}
static void __init check_one_sigio(void (*proc)(int, int))
@@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int))
int master, slave, err;
initial_thread_cb(openpty_cb, &pty);
- if(pty.err){
- printk("openpty failed, errno = %d\n", -pty.err);
+ if (pty.err) {
+ printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
+ -pty.err);
return;
}
master = pty.master;
slave = pty.slave;
- if((master == -1) || (slave == -1)){
- printk("openpty failed to allocate a pty\n");
+ if ((master == -1) || (slave == -1)) {
+ printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
+ "pty\n");
return;
}
/* Not now, but complain so we now where we failed. */
err = raw(master);
- if (err < 0)
- panic("check_sigio : __raw failed, errno = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
+ -err);
+ return;
+ }
err = async_pty(master, slave);
- if(err < 0)
- panic("tty_fds : sigio_async failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
+ "err = %d\n", -err);
+ return;
+ }
+
+ if (sigaction(SIGIO, NULL, &old) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
- if(sigaction(SIGIO, NULL, &old) < 0)
- panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
new = old;
new.sa_handler = handler;
- if(sigaction(SIGIO, &new, NULL) < 0)
- panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &new, NULL) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
got_sigio = 0;
(*proc)(master, slave);
@@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int))
close(master);
close(slave);
- if(sigaction(SIGIO, &old, NULL) < 0)
- panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &old, NULL) < 0)
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
+ "errno = %d\n", errno);
}
static void tty_output(int master, int slave)
@@ -461,42 +490,45 @@ static void tty_output(int master, int slave)
int n;
char buf[512];
- printk("Checking that host ptys support output SIGIO...");
+ printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
memset(buf, 0, sizeof(buf));
- while(write(master, buf, sizeof(buf)) > 0) ;
- if(errno != EAGAIN)
- panic("tty_output : write failed, errno = %d\n", errno);
- while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+ while (write(master, buf, sizeof(buf)) > 0) ;
+ if (errno != EAGAIN)
+ printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
+ errno);
+ while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
+ ;
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_output_sigio = 1;
- }
- else if(n == -EAGAIN)
- printk("No, enabling workaround\n");
- else panic("tty_output : read failed, err = %d\n", n);
+ } else if (n == -EAGAIN)
+ printk(UM_KERN_CONT "No, enabling workaround\n");
+ else
+ printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
{
- printk("Checking that host ptys support SIGIO on close...");
+ printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
+ "close...");
close(slave);
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_close_sigio = 1;
- }
- else printk("No, enabling workaround\n");
+ } else
+ printk(UM_KERN_CONT "No, enabling workaround\n");
}
void __init check_sigio(void)
{
- if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
- (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
- printk("No pseudo-terminals available - skipping pty SIGIO "
- "check\n");
+ if ((access("/dev/ptmx", R_OK) < 0) &&
+ (access("/dev/ptyp0", R_OK) < 0)) {
+ printk(UM_KERN_WARNING "No pseudo-terminals available - "
+ "skipping pty SIGIO check\n");
return;
}
check_one_sigio(tty_output);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index e9800b0b568..0fb0cc8d475 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -9,11 +9,47 @@
#include <errno.h>
#include <signal.h>
#include <strings.h>
+#include "as-layout.h"
+#include "kern_util.h"
#include "os.h"
#include "sysdep/barrier.h"
#include "sysdep/sigcontext.h"
#include "user.h"
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
+ [SIGTRAP] = relay_signal,
+ [SIGFPE] = relay_signal,
+ [SIGILL] = relay_signal,
+ [SIGWINCH] = winch,
+ [SIGBUS] = bus_handler,
+ [SIGSEGV] = segv_handler,
+ [SIGIO] = sigio_handler,
+ [SIGVTALRM] = timer_handler };
+
+static void sig_handler_common(int sig, struct sigcontext *sc)
+{
+ struct uml_pt_regs r;
+ int save_errno = errno;
+
+ r.is_user = 0;
+ if (sig == SIGSEGV) {
+ /* For segfaults, we want the data from the sigcontext. */
+ copy_sc(&r, sc);
+ GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+ }
+
+ /* enable signals if sig isn't IRQ signal */
+ if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
+ unblock_signals();
+
+ (*sig_info[sig])(sig, &r);
+
+ errno = save_errno;
+}
+
/*
* These are the asynchronous signals. SIGPROF is excluded because we want to
* be able to profile all of UML, not just the non-critical sections. If
@@ -26,13 +62,8 @@
#define SIGVTALRM_BIT 1
#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
-/*
- * These are used by both the signal handlers and
- * block/unblock_signals. I don't want modifications cached in a
- * register - they must go straight to memory.
- */
-static volatile int signals_enabled = 1;
-static volatile int pending = 0;
+static int signals_enabled;
+static unsigned int signals_pending;
void sig_handler(int sig, struct sigcontext *sc)
{
@@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!enabled && (sig == SIGIO)) {
- pending |= SIGIO_MASK;
+ signals_pending |= SIGIO_MASK;
return;
}
block_signals();
- sig_handler_common_skas(sig, sc);
+ sig_handler_common(sig, sc);
set_signals(enabled);
}
@@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!signals_enabled) {
- pending |= SIGVTALRM_MASK;
+ signals_pending |= SIGVTALRM_MASK;
return;
}
@@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
-void remove_sigstack(void)
-{
- stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
- .ss_sp = NULL,
- .ss_size = 0 });
-
- if (sigaltstack(&stack, NULL) != 0)
- panic("disabling signal stack failed, errno = %d\n", errno);
-}
-
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
void handle_signal(int sig, struct sigcontext *sc)
@@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigaddset(&action.sa_mask, mask);
va_end(ap);
+ if (sig == SIGSEGV)
+ flags |= SA_NODEFER;
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if (sigaction(sig, &action, NULL) < 0)
@@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
int change_sig(int signal, int on)
{
- sigset_t sigset, old;
+ sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, signal);
- sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
- return !sigismember(&old, signal);
+ if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
+ return -errno;
+
+ return 0;
}
void block_signals(void)
@@ -196,7 +222,7 @@ void block_signals(void)
* This might matter if gcc figures out how to inline this and
* decides to shuffle this code into the caller.
*/
- mb();
+ barrier();
}
void unblock_signals(void)
@@ -209,36 +235,26 @@ void unblock_signals(void)
/*
* We loop because the IRQ handler returns with interrupts off. So,
* interrupts may have arrived and we need to re-enable them and
- * recheck pending.
+ * recheck signals_pending.
*/
while(1) {
/*
* Save and reset save_pending after enabling signals. This
- * way, pending won't be changed while we're reading it.
+ * way, signals_pending won't be changed while we're reading it.
*/
signals_enabled = 1;
/*
- * Setting signals_enabled and reading pending must
+ * Setting signals_enabled and reading signals_pending must
* happen in this order.
*/
- mb();
-
- save_pending = pending;
- if (save_pending == 0) {
- /*
- * This must return with signals enabled, so
- * this barrier ensures that writes are
- * flushed out before the return. This might
- * matter if gcc figures out how to inline
- * this (unlikely, given its size) and decides
- * to shuffle this code into the caller.
- */
- mb();
+ barrier();
+
+ save_pending = signals_pending;
+ if (save_pending == 0)
return;
- }
- pending = 0;
+ signals_pending = 0;
/*
* We have pending interrupts, so disable signals, as the
@@ -254,7 +270,7 @@ void unblock_signals(void)
* back here.
*/
if (save_pending & SIGIO_MASK)
- sig_handler_common_skas(SIGIO, NULL);
+ sig_handler_common(SIGIO, NULL);
if (save_pending & SIGVTALRM_MASK)
real_alarm_handler(NULL);
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index 5fd8d4dad66..d2ea3409e07 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -1,10 +1,10 @@
#
-# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
# Licensed under the GPL
#
-obj-y := mem.o process.o trap.o
+obj-y := mem.o process.o
-USER_OBJS := mem.o process.o trap.o
+USER_OBJS := $(obj-y)
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index e8b7a97e83d..d36c89c24a4 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -15,6 +15,7 @@
#include "as-layout.h"
#include "chan_user.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "mem.h"
#include "os.h"
#include "process.h"
@@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data)
static int ptrace_dump_regs(int pid)
{
- unsigned long regs[MAX_REG_NR];
- int i;
+ unsigned long regs[MAX_REG_NR];
+ int i;
- if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
- return -errno;
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ return -errno;
printk(UM_KERN_ERR "Stub registers -\n");
for (i = 0; i < ARRAY_SIZE(regs); i++)
printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
- return 0;
+ return 0;
}
/*
* Signals that are OK to receive in the stub - we'll just continue it.
* SIGWINCH will happen when UML is inside a detached screen.
*/
-#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
+#define STUB_SIG_MASK (1 << SIGVTALRM)
/* Signals that the stub will finish with - anything else is an error */
-#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
+#define STUB_DONE_MASK (1 << SIGTRAP)
void wait_stub_done(int pid)
{
@@ -72,9 +73,11 @@ void wait_stub_done(int pid)
break;
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("wait_stub_done : continue failed, errno = %d\n",
- errno);
+ if (err) {
+ printk(UM_KERN_ERR "wait_stub_done : continue failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
@@ -85,8 +88,10 @@ bad_wait:
if (err)
printk(UM_KERN_ERR "Failed to get registers from stub, "
"errno = %d\n", -err);
- panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
- "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
+ printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
+ "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
+ status);
+ fatal_sigsegv();
}
extern unsigned long current_stub_stack(void);
@@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
if (ptrace_faultinfo) {
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
- if (err)
- panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "get_skas_faultinfo - "
+ "PTRACE_FAULTINFO failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
/* Special handling for i386, which has different structs */
if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
@@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
}
else {
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
- if (err)
- panic("Failed to continue stub, pid = %d, errno = %d\n",
- pid, errno);
+ if (err) {
+ printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
+ "errno = %d\n", pid, errno);
+ fatal_sigsegv();
+ }
wait_stub_done(pid);
/*
@@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
int err, status;
+ if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
+ fatal_sigsegv();
+
/* Mark this as a syscall */
UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
@@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid);
- if (err < 0)
- panic("handle_trap - nullifying syscall failed, "
- "errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - nullifying syscall "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
- if (err < 0)
- panic("handle_trap - continuing to end of syscall "
- "failed, errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - continuing to end of "
+ "syscall failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
if ((err < 0) || !WIFSTOPPED(status) ||
- (WSTOPSIG(status) != SIGTRAP + 0x80)) {
- err = ptrace_dump_regs(pid);
- if (err)
- printk(UM_KERN_ERR "Failed to get registers "
+ (WSTOPSIG(status) != SIGTRAP + 0x80)) {
+ err = ptrace_dump_regs(pid);
+ if (err)
+ printk(UM_KERN_ERR "Failed to get registers "
"from process, errno = %d\n", -err);
- panic("handle_trap - failed to wait at end of syscall, "
- "errno = %d, status = %d\n", errno, status);
- }
+ printk(UM_KERN_ERR "handle_trap - failed to wait at "
+ "end of syscall, errno = %d, status = %d\n",
+ errno, status);
+ fatal_sigsegv();
+ }
}
handle_syscall(regs);
@@ -178,10 +196,13 @@ static int userspace_tramp(void *stack)
ptrace(PTRACE_TRACEME, 0, 0, 0);
signal(SIGTERM, SIG_DFL);
+ signal(SIGWINCH, SIG_IGN);
err = set_interval();
- if (err)
- panic("userspace_tramp - setting timer failed, errno = %d\n",
- err);
+ if (err) {
+ printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
+ "errno = %d\n", err);
+ exit(1);
+ }
if (!proc_mm) {
/*
@@ -221,16 +242,14 @@ static int userspace_tramp(void *stack)
set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGIO);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sigaddset(&sa.sa_mask, SIGVTALRM);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sa.sa_flags = SA_ONSTACK;
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER;
sa.sa_handler = (void *) v;
sa.sa_restorer = NULL;
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- panic("userspace_tramp - setting SIGSEGV handler "
- "failed - errno = %d\n", errno);
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
+ "handler failed - errno = %d\n", errno);
+ exit(1);
+ }
}
kill(os_getpid(), SIGSTOP);
@@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack)
{
void *stack;
unsigned long sp;
- int pid, status, n, flags;
+ int pid, status, n, flags, err;
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (stack == MAP_FAILED)
- panic("start_userspace : mmap failed, errno = %d", errno);
+ if (stack == MAP_FAILED) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : mmap failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
+
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES;
@@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack)
flags |= SIGCHLD;
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
- if (pid < 0)
- panic("start_userspace : clone failed, errno = %d", errno);
+ if (pid < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : clone failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
do {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
- if (n < 0)
- panic("start_userspace : wait failed, errno = %d",
- errno);
+ if (n < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : wait failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
- if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
- panic("start_userspace : expected SIGSTOP, got status = %d",
- status);
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
+ err = -EINVAL;
+ printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
+ "status = %d\n", status);
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *) PTRACE_O_TRACESYSGOOD) < 0)
- panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *) PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
- if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
- panic("start_userspace : munmap failed, errno = %d\n", errno);
+ if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : munmap failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
void userspace(struct uml_pt_regs *regs)
@@ -302,7 +347,16 @@ void userspace(struct uml_pt_regs *regs)
nsecs += os_nsecs();
while (1) {
- restore_registers(pid, regs);
+ /*
+ * This can legitimately fail if the process loads a
+ * bogus value into a segment register. It will
+ * segfault and PTRACE_GETREGS will read that value
+ * out of the process. However, PTRACE_SETREGS will
+ * fail. In this case, there is nothing to do but
+ * just kill the process.
+ */
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
+ fatal_sigsegv();
/* Now we set local_using_sysemu to be used for one loop */
local_using_sysemu = get_using_sysemu();
@@ -310,19 +364,26 @@ void userspace(struct uml_pt_regs *regs)
op = SELECT_PTRACE_OPERATION(local_using_sysemu,
singlestepping(NULL));
- err = ptrace(op, pid, 0, 0);
- if (err)
- panic("userspace - could not resume userspace process, "
- "pid=%d, ptrace operation = %d, errno = %d\n",
- pid, op, errno);
+ if (ptrace(op, pid, 0, 0)) {
+ printk(UM_KERN_ERR "userspace - ptrace continue "
+ "failed, op = %d, errno = %d\n", op, errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
- if (err < 0)
- panic("userspace - waitpid failed, errno = %d\n",
- errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "userspace - wait failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
regs->is_user = 1;
- save_registers(pid, regs);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
+ printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
+
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
if (WIFSTOPPED(status)) {
@@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs)
break;
case SIGVTALRM:
now = os_nsecs();
- if(now < nsecs)
+ if (now < nsecs)
break;
block_signals();
(*sig_info[sig])(sig, regs);
@@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs)
default:
printk(UM_KERN_ERR "userspace - child stopped "
"with signal %d\n", sig);
+ fatal_sigsegv();
}
pid = userspace_pid[0];
interrupt_end();
@@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
.it_interval = tv }) });
err = ptrace_setregs(pid, thread_regs);
- if (err < 0)
- panic("copy_context_skas0 : PTRACE_SETREGS failed, "
- "pid = %d, errno = %d\n", pid, -err);
+ if (err < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
+ "failed, pid = %d, errno = %d\n", pid, -err);
+ return err;
+ }
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
@@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* parent's stack, and check, if bad result.
*/
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("Failed to continue new process, pid = %d, "
- "errno = %d\n", pid, errno);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
+ "errno = %d\n", pid, errno);
+ return err;
+ }
+
wait_stub_done(pid);
pid = data->err;
- if (pid < 0)
- panic("copy_context_skas0 - stub-parent reports error %d\n",
- -pid);
+ if (pid < 0) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
+ "error %d\n", -pid);
+ return pid;
+ }
/*
* Wait, until child has finished too: read child's result from
* child's stack and check it.
*/
wait_stub_done(pid);
- if (child_data->err != STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %ld\n",
- child_data->err);
+ if (child_data->err != STUB_DATA) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
+ "error %ld\n", child_data->err);
+ err = child_data->err;
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *)PTRACE_O_TRACESYSGOOD) < 0)
- panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *)PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
/*
@@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* available. Opening /proc/mm creates a new mm_context, which lacks
* the stub-pages. Thus, we map them using /proc/mm-fd
*/
-void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack)
+int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack)
{
struct proc_mm_op mmop;
int n;
@@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code,
printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
"offset = %llx\n", code, code_fd,
(unsigned long long) code_offset);
- panic("map_stub_pages : /proc/mm map for code failed, "
- "err = %d\n", n);
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
+ "failed, err = %d\n", n);
+ return -n;
}
if (stack) {
@@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code,
.offset = map_offset
} } });
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
- if (n != sizeof(mmop))
- panic("map_stub_pages : /proc/mm map for data failed, "
- "err = %d\n", errno);
+ if (n != sizeof(mmop)) {
+ n = errno;
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
+ "data failed, err = %d\n", n);
+ return -n;
+ }
}
+
+ return 0;
}
void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
@@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
kmalloc_ok = 0;
return 1;
default:
- panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+ printk(UM_KERN_ERR "Bad sigsetjmp return in "
+ "start_idle_thread - %d\n", n);
+ fatal_sigsegv();
}
longjmp(*switch_buf, 1);
}
@@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp)
if (proc_mm) {
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
mm_idp->u.mm_fd);
- if (err)
- panic("__switch_mm - PTRACE_SWITCH_MM failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
else userspace_pid[0] = mm_idp->u.pid;
}
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
deleted file mode 100644
index 3b1b9244f46..00000000000
--- a/arch/um/os-Linux/skas/trap.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#if 0
-#include "kern_util.h"
-#include "skas.h"
-#include "ptrace_user.h"
-#include "sysdep/ptrace_user.h"
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include "sysdep/ptrace.h"
-#include "kern_constants.h"
-#include "as-layout.h"
-#include "os.h"
-#include "sigcontext.h"
-#include "task.h"
-
-static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
-
-void sig_handler_common_skas(int sig, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct uml_pt_regs *r;
- void (*handler)(int, struct uml_pt_regs *);
- int save_user, save_errno = errno;
-
- /*
- * This is done because to allow SIGSEGV to be delivered inside a SEGV
- * handler. This can happen in copy_user, and if SEGV is disabled,
- * the process will die.
- * XXX Figure out why this is better than SA_NODEFER
- */
- if (sig == SIGSEGV) {
- change_sig(SIGSEGV, 1);
- /*
- * For segfaults, we want the data from the
- * sigcontext. In this case, we don't want to mangle
- * the process registers, so use a static set of
- * registers. For other signals, the process
- * registers are OK.
- */
- r = &ksig_regs[cpu()];
- copy_sc(r, sc_ptr);
- }
- else r = TASK_REGS(get_current());
-
- save_user = r->is_user;
- r->is_user = 0;
- if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
- (sig == SIGILL) || (sig == SIGTRAP))
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
-
- change_sig(SIGUSR1, 1);
-
- handler = sig_info[sig];
-
- /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
- unblock_signals();
-
- handler(sig, r);
-
- errno = save_errno;
- r->is_user = save_user;
-}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7b81f6c08a5..b616e15638f 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -60,10 +60,11 @@ static int ptrace_child(void)
* the UML code itself.
*/
ret = 2;
- _exit(ret);
+
+ exit(ret);
}
-static void fatal_perror(char *str)
+static void fatal_perror(const char *str)
{
perror(str);
exit(1);
@@ -341,6 +342,8 @@ static void __init check_coredump_limit(void)
void __init os_early_checks(void)
{
+ int pid;
+
/* Print out the core dump limits early */
check_coredump_limit();
@@ -350,6 +353,11 @@ void __init os_early_checks(void)
* kernel is running.
*/
check_tmpexec();
+
+ pid = start_ptraced_child();
+ if (init_registers(pid))
+ fatal("Failed to initialize default registers");
+ stop_ptraced_child(pid, 1, 1);
}
static int __init noprocmm_cmd_param(char *str, int* add)
@@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void)
non_fatal("found\n");
}
- init_registers(pid);
stop_ptraced_child(pid, 1, 1);
}
@@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void)
else non_fatal("found\n");
}
-int can_do_skas(void)
+void can_do_skas(void)
{
non_fatal("Checking for the skas3 patch in the host:\n");
@@ -476,8 +483,6 @@ int can_do_skas(void)
if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
skas_needs_stub = 1;
-
- return 1;
}
int __init parse_iomem(char *str, int *add)
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
deleted file mode 100644
index 2a1c9843e32..00000000000
--- a/arch/um/os-Linux/trap.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "os.h"
-#include "sysdep/ptrace.h"
-
-/* Initialized from linux_main() */
-void (*sig_info[NSIG])(int, struct uml_pt_regs *);
-
-void os_fill_handlinfo(struct kern_handlers h)
-{
- sig_info[SIGTRAP] = h.relay_signal;
- sig_info[SIGFPE] = h.relay_signal;
- sig_info[SIGILL] = h.relay_signal;
- sig_info[SIGWINCH] = h.winch;
- sig_info[SIGBUS] = h.bus_handler;
- sig_info[SIGSEGV] = h.page_fault;
- sig_info[SIGIO] = h.sigio_handler;
- sig_info[SIGVTALRM] = h.timer_handler;
-}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 4cfdd18ea1e..b09ff66a77e 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -1,13 +1,16 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
+#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
struct grantpt_info {
int fd;
@@ -26,36 +29,34 @@ static void grantpt_cb(void *arg)
int get_pty(void)
{
struct grantpt_info info;
- int fd;
-
- fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
- if(fd < 0){
- printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
- return(fd);
+ int fd, err;
+
+ fd = open("/dev/ptmx", O_RDWR);
+ if (fd < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - "
+ "err = %d\n", errno);
+ return err;
}
info.fd = fd;
initial_thread_cb(grantpt_cb, &info);
- if(info.res < 0){
- printk("get_pty : Couldn't grant pty - errno = %d\n",
- -info.err);
- return(-1);
+ if (info.res < 0) {
+ err = -info.err;
+ printk(UM_KERN_ERR "get_pty : Couldn't grant pty - "
+ "errno = %d\n", -info.err);
+ goto out;
}
- if(unlockpt(fd) < 0){
- printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
- return(-1);
+
+ if (unlockpt(fd) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - "
+ "errno = %d\n", errno);
+ goto out;
}
- return(fd);
+ return fd;
+out:
+ close(fd);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
index d11a55baa6b..cc648e6fd3a 100644
--- a/arch/um/os-Linux/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -12,7 +12,6 @@
#include <sys/time.h>
#include "init.h"
#include "user.h"
-#include "kern_util.h"
#include "os.h"
#define TTY_LOG_DIR "./"
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 3e058ce9ffb..a6f31d47699 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -88,21 +88,6 @@ void setup_hostinfo(char *buf, int len)
host.release, host.version, host.machine);
}
-int setjmp_wrapper(void (*proc)(void *, void *), ...)
-{
- va_list args;
- jmp_buf buf;
- int n;
-
- n = UML_SETJMP(&buf);
- if(n == 0){
- va_start(args, proc);
- (*proc)(&buf, &args);
- }
- va_end(args);
- return n;
-}
-
void os_dump_core(void)
{
int pid;
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
index a4360b5207d..8d4f273f121 100644
--- a/arch/um/sys-i386/bug.c
+++ b/arch/um/sys-i386/bug.c
@@ -4,6 +4,7 @@
*/
#include <linux/uaccess.h>
+#include <asm/errno.h>
/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 806895d73bc..a74442d1376 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -3,171 +3,47 @@
* Licensed under the GPL
*/
-#include <errno.h>
#include <signal.h>
-#include <string.h>
#include "kern_constants.h"
-#include "os.h"
+#include "kern_util.h"
+#include "longjmp.h"
#include "task.h"
#include "user.h"
-
-#define MAXTOKEN 64
+#include "sysdep/ptrace.h"
/* Set during early boot */
int host_has_cmov = 1;
-int host_has_xmm = 0;
+static jmp_buf cmov_test_return;
-static char token(int fd, char *buf, int len, char stop)
+static void cmov_sigill_test_handler(int sig)
{
- int n;
- char *ptr, *end, c;
-
- ptr = buf;
- end = &buf[len];
- do {
- n = os_read_file(fd, ptr, sizeof(*ptr));
- c = *ptr++;
- if (n != sizeof(*ptr)) {
- if (n == 0)
- return 0;
- printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
- "err = %d\n", -n);
- if (n < 0)
- return n;
- else return -EIO;
- }
- } while ((c != '\n') && (c != stop) && (ptr < end));
-
- if (ptr == end) {
- printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
- stop);
- return -1;
- }
- *(ptr - 1) = '\0';
- return c;
-}
-
-static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
-{
- int n;
- char c;
-
- scratch[len - 1] = '\0';
- while (1) {
- c = token(fd, scratch, len - 1, ':');
- if (c <= 0)
- return 0;
- else if (c != ':') {
- printk(UM_KERN_ERR "Failed to find ':' in "
- "/proc/cpuinfo\n");
- return 0;
- }
-
- if (!strncmp(scratch, key, strlen(key)))
- return 1;
-
- do {
- n = os_read_file(fd, &c, sizeof(c));
- if (n != sizeof(c)) {
- printk(UM_KERN_ERR "Failed to find newline in "
- "/proc/cpuinfo, err = %d\n", -n);
- return 0;
- }
- } while (c != '\n');
- }
- return 0;
+ host_has_cmov = 0;
+ longjmp(cmov_test_return, 1);
}
-static int check_cpu_flag(char *feature, int *have_it)
-{
- char buf[MAXTOKEN], c;
- int fd, len = ARRAY_SIZE(buf);
-
- printk(UM_KERN_INFO "Checking for host processor %s support...",
- feature);
- fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
- -fd);
- return 0;
- }
-
- *have_it = 0;
- if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
- goto out;
-
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c != ' ') {
- printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
- goto out;
- }
-
- while (1) {
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c == '\n')
- break;
-
- if (!strcmp(buf, feature)) {
- *have_it = 1;
- goto out;
- }
- }
- out:
- if (*have_it == 0)
- printk("No\n");
- else if (*have_it == 1)
- printk("Yes\n");
- os_close_file(fd);
- return 1;
-}
-
-#if 0 /*
- * This doesn't work in tt mode, plus it's causing compilation problems
- * for some people.
- */
-static void disable_lcall(void)
+void arch_check_bugs(void)
{
- struct modify_ldt_ldt_s ldt;
- int err;
+ struct sigaction old, new;
- bzero(&ldt, sizeof(ldt));
- ldt.entry_number = 7;
- ldt.base_addr = 0;
- ldt.limit = 0;
- err = modify_ldt(1, &ldt, sizeof(ldt));
- if (err)
- printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
- errno);
-}
-#endif
+ printk(UM_KERN_INFO "Checking for host processor cmov support...");
+ new.sa_handler = cmov_sigill_test_handler;
-void arch_init_thread(void)
-{
-#if 0
- disable_lcall();
-#endif
-}
+ /* Make sure that SIGILL is enabled after the handler longjmps back */
+ new.sa_flags = SA_NODEFER;
+ sigemptyset(&new.sa_mask);
+ sigaction(SIGILL, &new, &old);
-void arch_check_bugs(void)
-{
- int have_it;
+ if (setjmp(cmov_test_return) == 0) {
+ unsigned long foo = 0;
+ __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+ printk(UM_KERN_CONT "Yes\n");
+ } else
+ printk(UM_KERN_CONT "No\n");
- if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
- printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
- "capability checks\n");
- return;
- }
- if (check_cpu_flag("cmov", &have_it))
- host_has_cmov = have_it;
- if (check_cpu_flag("xmm", &have_it))
- host_has_xmm = have_it;
+ sigaction(SIGILL, &old, &new);
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
unsigned char tmp[2];
@@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
* SIGILL in init.
*/
if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
- return 0;
+ return;
+
+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+ printk(UM_KERN_ERR "SIGILL in init, could not read "
+ "instructions!\n");
+ return;
+ }
- if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
- panic("SIGILL in init, could not read instructions!\n");
if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
- return 0;
+ return;
if (host_has_cmov == 0)
- panic("SIGILL caused by cmov, which this processor doesn't "
- "implement, boot a filesystem compiled for older "
- "processors");
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor doesn't implement. Boot a filesystem "
+ "compiled for older processors");
else if (host_has_cmov == 1)
- panic("SIGILL caused by cmov, which this processor claims to "
- "implement");
- else if (host_has_cmov == -1)
- panic("SIGILL caused by cmov, couldn't tell if this processor "
- "implements it, boot a filesystem compiled for older "
- "processors");
- else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
- return 0;
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor claims to implement");
+ else
+ printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+ host_has_cmov);
}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 67c0958eb98..a34263e6b08 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,8 +3,9 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/unistd.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/unistd.h>
#include "os.h"
#include "proc_mm.h"
#include "skas.h"
@@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
if (ptrace_ldt)
return read_ldt_from_host(ptr, bytecount);
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
if (size > bytecount)
@@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
ptr += size;
}
}
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
if (bytecount == 0 || err == -EFAULT)
goto out;
@@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
}
if (!ptrace_ldt)
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
if (err)
@@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
err = 0;
out_unlock:
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
out:
return err;
}
@@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
if (!ptrace_ldt)
- init_MUTEX(&new_mm->ldt.semaphore);
+ mutex_init(&new_mm->ldt.lock);
if (!from_mm) {
memset(&desc, 0, sizeof(desc));
@@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
* i.e., we have to use the stub for modify_ldt, which
* can't handle the big read buffer of up to 64kB.
*/
- down(&from_mm->ldt.semaphore);
+ mutex_lock(&from_mm->ldt.lock);
if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
sizeof(new_mm->ldt.u.entries));
@@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
}
}
new_mm->ldt.entry_count = from_mm->ldt.entry_count;
- up(&from_mm->ldt.semaphore);
+ mutex_unlock(&from_mm->ldt.lock);
}
out:
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index bd3da8a61f6..6b4499906a6 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -8,11 +8,11 @@
#include "asm/uaccess.h"
#include "skas.h"
-extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
+extern int arch_switch_tls(struct task_struct *to);
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
- int err = arch_switch_tls(from, to);
+ int err = arch_switch_tls(to);
if (!err)
return;
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 5cf97bc229b..0b10c3e7402 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -19,17 +19,3 @@ int ptrace_setregs(long pid, unsigned long *regs)
return -errno;
return 0;
}
-
-int ptrace_getfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
-
-int ptrace_setfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 19053d46cb6..fd0c25ad6af 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -168,12 +168,13 @@ static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
struct sigcontext sc;
- int err;
+ int err, pid;
err = copy_from_user(&sc, from, sizeof(sc));
if (err)
return err;
+ pid = userspace_pid[current_thread_info()->cpu];
copy_sc(&regs->regs, &sc);
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
@@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = restore_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fpx_registers failed, errno = %d\n",
@@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = restore_fp_registers(pid, (unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fp_registers failed, errno = %d\n",
@@ -223,7 +222,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
{
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
- int err;
+ int err, pid;
sc.gs = REGS_GS(regs->regs.gp);
sc.fs = REGS_FS(regs->regs.gp);
@@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to,
to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
sc.fpstate = to_fp;
+ pid = userspace_pid[current_thread_info()->cpu];
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
- err = save_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = save_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0){
printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
"failed, errno = %d\n", err);
@@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
else {
struct user_i387_struct fp;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = save_fp_registers(pid, (unsigned long *) &fp);
if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
return 1;
}
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index e730772c401..7699e89f660 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -7,7 +7,7 @@
.globl batch_syscall_stub
batch_syscall_stub:
/* load pointer to first operation */
- mov $(ASM_STUB_DATA+8), %esp
+ mov $(STUB_DATA+8), %esp
again:
/* load length of additional data */
@@ -15,12 +15,12 @@ again:
/* if(length == 0) : end of list */
/* write possible 0 to header */
- mov %eax, ASM_STUB_DATA+4
+ mov %eax, STUB_DATA+4
cmpl $0, %eax
jz done
/* save current pointer */
- mov %esp, ASM_STUB_DATA+4
+ mov %esp, STUB_DATA+4
/* skip additional data */
add %eax, %esp
@@ -46,7 +46,7 @@ again:
done:
/* save return value */
- mov %eax, ASM_STUB_DATA
+ mov %eax, STUB_DATA
/* stop */
int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index b3999cb76bf..28ccf737a79 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -1,32 +1,17 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
-#include <sys/select.h> /* The only way I can see to get sigset_t */
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
- int pid;
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* Load pointer to sigcontext into esp, since we need to leave
- * the stack in its original form when we do the sigreturn here, by
- * hand.
- */
- __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
- "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+ trap_myself();
}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index 12d4148dba3..00e5f5203ee 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -9,4 +9,9 @@
#define old_mmap old_mmap_i386
+.section .rodata,"a"
+
#include "../../x86/kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index fcaff86b000..c6c7131e563 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -26,6 +26,11 @@ int do_set_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_set_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_get_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task)
* SKAS patch.
*/
-int arch_switch_tls(struct task_struct *from, struct task_struct *to)
+int arch_switch_tls(struct task_struct *to)
{
if (!host_supports_tls)
return 0;
@@ -225,7 +235,8 @@ out:
}
/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+ int idx)
{
struct thread_struct *t = &task->thread;
@@ -263,7 +274,7 @@ clear:
goto out;
}
-asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+int sys_set_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
* i386. However the only possible error are caused by bugs.
*/
int ptrace_set_thread_area(struct task_struct *child, int idx,
- struct user_desc __user *user_desc)
+ struct user_desc __user *user_desc)
{
struct user_desc info;
@@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
return set_tls_entry(child, &info, idx, 0);
}
-asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
+int sys_get_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -355,10 +366,9 @@ out:
return ret;
}
-
/*
- * XXX: This part is probably common to i386 and x86-64. Don't create a common
- * file for now, do that when implementing x86-64 support.
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
*/
static int __init __setup_host_supports_tls(void)
{
@@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void)
printk(KERN_INFO "Host TLS support detected\n");
printk(KERN_INFO "Detected host type: ");
switch (host_gdt_entry_tls_min) {
- case GDT_ENTRY_TLS_MIN_I386:
- printk("i386\n");
- break;
- case GDT_ENTRY_TLS_MIN_X86_64:
- printk("x86_64\n");
- break;
+ case GDT_ENTRY_TLS_MIN_I386:
+ printk(KERN_CONT "i386");
+ break;
+ case GDT_ENTRY_TLS_MIN_X86_64:
+ printk(KERN_CONT "x86_64");
+ break;
}
+ printk(KERN_CONT " (GDT indexes %d to %d)\n",
+ host_gdt_entry_tls_min,
+ host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
} else
printk(KERN_ERR " Host TLS support NOT detected! "
"TLS support inside UML will not work\n");
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index a9814a7ae60..08901526e89 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
ptrace_user.o sysrq.o
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel
+EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
all: $(OBJ)
@@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c
semaphore.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
checksum.S:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/lib/$@ $@
+ ln -s $(srctree)/arch/ppc/lib/$@ $@
mk_defs.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.head:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.h: mk_defs.c ppc_defs.head \
- $(TOPDIR)/include/asm-ppc/mmu.h \
- $(TOPDIR)/include/asm-ppc/processor.h \
- $(TOPDIR)/include/asm-ppc/pgtable.h \
- $(TOPDIR)/include/asm-ppc/ptrace.h
+ $(srctree)/include/asm-ppc/mmu.h \
+ $(srctree)/include/asm-ppc/processor.h \
+ $(srctree)/include/asm-ppc/pgtable.h \
+ $(srctree)/include/asm-ppc/ptrace.h
# $(CC) $(CFLAGS) -S mk_defs.c
cp ppc_defs.head ppc_defs.h
# for bk, this way we can write to the file even if it's not checked out
@@ -56,13 +56,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
checksum.o: checksum.S
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
misc.o: misc.S ppc_defs.h
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
index a4360b5207d..e8034e363d8 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/um/sys-x86_64/bug.c
@@ -5,7 +5,8 @@
#include <linux/uaccess.h>
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
*/
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index 506b6765bbc..44e02ba2a26 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -6,15 +6,10 @@
#include "sysdep/ptrace.h"
-void arch_init_thread(void)
-{
-}
-
void arch_check_bugs(void)
{
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
- return 0;
}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b7631b0e9dd..f3458d7d1c5 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,13 +5,12 @@
* Licensed under the GPL
*/
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
+#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/mm.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
#include <asm/uaccess.h>
-#include <asm/elf.h>
/*
* determines which flags the user has access to.
@@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
unsigned long tmp;
#ifdef TIF_IA32
- /* Some code in the 64bit emulation may not be 64bit clean.
- Don't take any chances. */
+ /*
+ * Some code in the 64bit emulation may not be 64bit clean.
+ * Don't take any chances.
+ */
if (test_tsk_thread_flag(child, TIF_IA32))
value &= 0xffffffff;
#endif
- switch (regno){
+ switch (regno) {
case FS:
case GS:
case DS:
@@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data)
if (addr < MAX_REG_OFFSET)
return putreg(child, addr, data);
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
if ((addr == 4) || (addr == 5))
@@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data)
return -EIO;
tmp = 0; /* Default return condition */
- if (addr < MAX_REG_OFFSET){
+ if (addr < MAX_REG_OFFSET)
tmp = getreg(child, addr);
- }
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
tmp = child->thread.arch.debugregs[addr];
@@ -127,8 +127,9 @@ int is_syscall(unsigned long addr)
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
- if (n){
- /* access_process_vm() grants access to vsyscall and stub,
+ if (n) {
+ /*
+ * access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
@@ -155,7 +156,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
return err;
n = copy_to_user(buf, fpregs, sizeof(fpregs));
- if(n > 0)
+ if (n > 0)
return -EFAULT;
return n;
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index b5f9c33e311..c57a496d3f5 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -4,55 +4,19 @@
* Licensed under the GPL
*/
-#include <stddef.h>
#include <errno.h>
#include "ptrace_user.h"
-#include "user.h"
-#include "kern_constants.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
- if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
- return(-errno);
- return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
- if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
- return(-errno);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+ return -errno;
return(0);
}
-int ptrace_setfpregs(long pid, unsigned long *regs)
+int ptrace_setregs(long pid, unsigned long *regs_out)
{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
return -errno;
- return 0;
-}
-
-void ptrace_pokeuser(unsigned long addr, unsigned long data)
-{
- panic("ptrace_pokeuser");
-}
-
-#define DS 184
-#define ES 192
-#define __USER_DS 0x2b
-
-void arch_enter_kernel(void *task, int pid)
-{
-}
-
-void arch_leave_kernel(void *task, int pid)
-{
-#ifdef UM_USER_CS
- if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
- printk("POKEUSR CS failed");
-#endif
-
- if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
- printk("POKEUSR DS failed");
- if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
- printk("POKEUSR ES failed");
+ return(0);
}
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 14070181407..1a899a7ed7a 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -81,7 +81,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
+ err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
@@ -143,7 +143,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
if (err)
return 1;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
+ err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
index 4afe204a6af..56876876315 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -8,18 +8,18 @@ syscall_stub:
/* We don't have 64-bit constants, so this constructs the address
* we need.
*/
- movq $(ASM_STUB_DATA >> 32), %rbx
+ movq $(STUB_DATA >> 32), %rbx
salq $32, %rbx
- movq $(ASM_STUB_DATA & 0xffffffff), %rcx
+ movq $(STUB_DATA & 0xffffffff), %rcx
or %rcx, %rbx
movq %rax, (%rbx)
int3
.globl batch_syscall_stub
batch_syscall_stub:
- mov $(ASM_STUB_DATA >> 32), %rbx
+ mov $(STUB_DATA >> 32), %rbx
sal $32, %rbx
- mov $(ASM_STUB_DATA & 0xffffffff), %rax
+ mov $(STUB_DATA & 0xffffffff), %rax
or %rax, %rbx
/* load pointer to first operation */
mov %rbx, %rsp
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 3afb590f007..ced051afc70 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -1,51 +1,22 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stddef.h>
#include <signal.h>
-#include <asm/unistd.h>
#include "as-layout.h"
-#include "uml-config.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
#include "sysdep/stub.h"
-
-/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
- * in the libc headers anywhere.
- */
-struct rt_sigframe
-{
- char *pretcode;
- struct ucontext uc;
- struct siginfo info;
-};
-
-/* Copied here from <linux/kernel.h> - we're userspace. */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
+#include "sysdep/faultinfo.h"
+#include "sysdep/sigcontext.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct ucontext *uc;
- int pid;
__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
&uc->uc_mcontext);
-
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* sys_sigreturn expects that the stack pointer will be 8 bytes into
- * the signal frame. So, we use the ucontext pointer, which we know
- * already, to get the signal frame pointer, and add 8 to that.
- */
- __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
- "g" ((unsigned long)
- container_of(uc, struct rt_sigframe, uc) + 8),
- "g" (__NR_rt_sigreturn));
+ trap_myself();
}
+
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index 71b2ae4ad5d..c128eb89700 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -1,5 +1,7 @@
-/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML. */
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
#include <linux/linkage.h>
#include <linux/sys.h>
@@ -8,22 +10,26 @@
#define __NO_STUBS
-/* Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table. */
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
/* Not going to be implemented by UML, since we have no hardware. */
#define stub_iopl sys_ni_syscall
#define sys_ioperm sys_ni_syscall
-/* The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility. */
-/*#define sys_set_thread_area sys_ni_syscall
-#define sys_get_thread_area sys_ni_syscall*/
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
/* On UML we call it this way ("old" means it's not mmap2) */
#define sys_mmap old_mmap
-/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
- * See arch/x86_64/kernel/sys_x86_64.c */
+/*
+ * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
+ * See arch/x86_64/kernel/sys_x86_64.c
+ */
#define sys_uname sys_uname64
#define stub_clone sys_clone
@@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void);
extern void sys_ni_syscall(void);
-sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = {
- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
- [0 ... UM_NR_syscall_max] = &sys_ni_syscall,
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ * [0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
#include <asm-x86/unistd_64.h>
};
+
+int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 86f6b18410e..f1199fd34d3 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
case ARCH_SET_GS:
- restore_registers(pid, &current->thread.regs.regs);
+ ret = restore_registers(pid, &current->thread.regs.regs);
+ if (ret)
+ return ret;
break;
case ARCH_GET_FS:
case ARCH_GET_GS:
@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
current->thread.arch.fs = (unsigned long) ptr;
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_SET_GS:
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_GET_FS:
ret = put_user(tmp, addr);
@@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
return ret;
}
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
return;
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index 76544403181..f4f82beb350 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -4,32 +4,33 @@
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/utsname.h"
-#include "linux/module.h"
-#include "asm/current.h"
-#include "asm/ptrace.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
#include "sysrq.h"
-void __show_regs(struct pt_regs * regs)
+void __show_regs(struct pt_regs *regs)
{
printk("\n");
print_modules();
- printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
current->comm, print_tainted(), init_utsname()->release);
- printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
+ printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
PT_REGS_RIP(regs));
- printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
PT_REGS_EFLAGS(regs));
- printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
- printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
- printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+ printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
- printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
- printk("R13: %016lx R14: %016lx R15: %016lx\n",
+ printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
}
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
index 8b8eff1bd97..3dead392a41 100644
--- a/arch/um/sys-x86_64/um_module.c
+++ b/arch/um/sys-x86_64/um_module.c
@@ -1,7 +1,7 @@
#include <linux/vmalloc.h>
#include <linux/moduleloader.h>
-/*Copied from i386 arch/i386/kernel/module.c */
+/* Copied from i386 arch/i386/kernel/module.c */
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -13,7 +13,9 @@ void *module_alloc(unsigned long size)
void module_free(struct module *mod, void *module_region)
{
vfree(module_region);
- /* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
+ /*
+ * FIXME: If module_region == mod->init_region, trim exception
+ * table entries.
+ */
}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 59eef1c7fda..434821187cf 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -465,6 +465,9 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
Calgary anyway, pass 'iommu=calgary' on the kernel command line.
If unsure, say Y.
+config IOMMU_HELPER
+ def_bool (CALGARY_IOMMU || GART_IOMMU)
+
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
bool
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 0db0a6291bb..8022d3c695c 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -722,7 +722,9 @@ ia32_sys_call_table:
.quad sys_epoll_pwait
.quad compat_sys_utimensat /* 320 */
.quad compat_sys_signalfd
- .quad compat_sys_timerfd
+ .quad sys_timerfd_create
.quad sys_eventfd
.quad sys32_fallocate
+ .quad compat_sys_timerfd_settime /* 325 */
+ .quad compat_sys_timerfd_gettime
ia32_syscall_end:
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 1fe7f043ebd..1b5464c2434 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/gart.h>
#include <asm/calgary.h>
#include <asm/tce.h>
@@ -260,22 +261,28 @@ static void iommu_range_reserve(struct iommu_table *tbl,
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
- unsigned int npages)
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
+ unsigned int npages)
{
unsigned long flags;
unsigned long offset;
+ unsigned long boundary_size;
+
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
BUG_ON(npages == 0);
spin_lock_irqsave(&tbl->it_lock, flags);
- offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
- tbl->it_size, npages);
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, tbl->it_hint,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
tbl->chip_ops->tce_cache_blast(tbl);
- offset = find_next_zero_string(tbl->it_map, 0,
- tbl->it_size, npages);
+
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
printk(KERN_WARNING "Calgary: IOMMU full.\n");
spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -286,7 +293,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- set_bit_string(tbl->it_map, offset, npages);
tbl->it_hint = offset + npages;
BUG_ON(tbl->it_hint > tbl->it_size);
@@ -295,13 +301,13 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return offset;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
- unsigned int npages, int direction)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, unsigned int npages, int direction)
{
unsigned long entry;
dma_addr_t ret = bad_dma_address;
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (unlikely(entry == bad_dma_address))
goto error;
@@ -354,7 +360,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
badbit, tbl, dma_addr, entry, npages);
}
- __clear_bit_string(tbl->it_map, entry, npages);
+ iommu_area_free(tbl->it_map, entry, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
@@ -438,7 +444,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
vaddr = (unsigned long) sg_virt(s);
npages = num_dma_pages(vaddr, s->length);
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (entry == bad_dma_address) {
/* makes sure unmap knows to stop */
s->dma_length = 0;
@@ -476,7 +482,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
npages = num_dma_pages(uaddr, size);
if (translation_enabled(tbl))
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
else
dma_handle = virt_to_bus(vaddr);
@@ -516,7 +522,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
if (translation_enabled(tbl)) {
/* set up tces to cover the allocated range */
- mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
+ mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
if (mapping == bad_dma_address)
goto free;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 845cbecd68e..65f6acb025c 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/kdebug.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -82,17 +83,24 @@ AGPEXTERN __u32 *agp_gatt_table;
static unsigned long next_bit; /* protected by iommu_bitmap_lock */
static int need_flush; /* global flush state. set for each gart wrap */
-static unsigned long alloc_iommu(int size)
+static unsigned long alloc_iommu(struct device *dev, int size)
{
unsigned long offset, flags;
+ unsigned long boundary_size;
+ unsigned long base_index;
+
+ base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
+ PAGE_SIZE) >> PAGE_SHIFT;
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- offset = find_next_zero_string(iommu_gart_bitmap, next_bit,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
+ size, base_index, boundary_size, 0);
if (offset == -1) {
need_flush = 1;
- offset = find_next_zero_string(iommu_gart_bitmap, 0,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
+ size, base_index, boundary_size, 0);
}
if (offset != -1) {
set_bit_string(iommu_gart_bitmap, offset, size);
@@ -114,7 +122,7 @@ static void free_iommu(unsigned long offset, int size)
unsigned long flags;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- __clear_bit_string(iommu_gart_bitmap, offset, size);
+ iommu_area_free(iommu_gart_bitmap, offset, size);
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
}
@@ -235,7 +243,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir)
{
unsigned long npages = to_pages(phys_mem, size);
- unsigned long iommu_page = alloc_iommu(npages);
+ unsigned long iommu_page = alloc_iommu(dev, npages);
int i;
if (iommu_page == -1) {
@@ -355,10 +363,11 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
}
/* Map multiple scatterlist entries continuous into the first. */
-static int __dma_map_cont(struct scatterlist *start, int nelems,
- struct scatterlist *sout, unsigned long pages)
+static int __dma_map_cont(struct device *dev, struct scatterlist *start,
+ int nelems, struct scatterlist *sout,
+ unsigned long pages)
{
- unsigned long iommu_start = alloc_iommu(pages);
+ unsigned long iommu_start = alloc_iommu(dev, pages);
unsigned long iommu_page = iommu_start;
struct scatterlist *s;
int i;
@@ -394,8 +403,8 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
}
static inline int
-dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
- unsigned long pages, int need)
+dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
+ struct scatterlist *sout, unsigned long pages, int need)
{
if (!need) {
BUG_ON(nelems != 1);
@@ -403,7 +412,7 @@ dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
sout->dma_length = start->length;
return 0;
}
- return __dma_map_cont(start, nelems, sout, pages);
+ return __dma_map_cont(dev, start, nelems, sout, pages);
}
/*
@@ -416,6 +425,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
struct scatterlist *s, *ps, *start_sg, *sgmap;
int need = 0, nextneed, i, out, start;
unsigned long pages = 0;
+ unsigned int seg_size;
+ unsigned int max_seg_size;
if (nents == 0)
return 0;
@@ -426,6 +437,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
out = 0;
start = 0;
start_sg = sgmap = sg;
+ seg_size = 0;
+ max_seg_size = dma_get_max_seg_size(dev);
ps = NULL; /* shut up gcc */
for_each_sg(sg, s, nents, i) {
dma_addr_t addr = sg_phys(s);
@@ -443,11 +456,13 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
* offset.
*/
if (!iommu_merge || !nextneed || !need || s->offset ||
+ (s->length + seg_size > max_seg_size) ||
(ps->offset + ps->length) % PAGE_SIZE) {
- if (dma_map_cont(start_sg, i - start, sgmap,
- pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start,
+ sgmap, pages, need) < 0)
goto error;
out++;
+ seg_size = 0;
sgmap = sg_next(sgmap);
pages = 0;
start = i;
@@ -455,11 +470,12 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
}
}
+ seg_size += s->length;
need = nextneed;
pages += to_pages(s->offset, s->length);
ps = s;
}
- if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
goto error;
out++;
flush_gart();
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 8344c70adf6..adff5562f5f 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -321,6 +321,8 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_timerfd_create
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8f94a0b89df..cf530814868 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1739,7 +1739,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
if (bytes == 8) {
gpa_t gpa;
struct page *page;
- char *addr;
+ char *kaddr;
u64 val;
down_read(&current->mm->mmap_sem);
@@ -1754,9 +1754,9 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
val = *(u64 *)new;
page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
- addr = kmap_atomic(page, KM_USER0);
- set_64bit((u64 *)(addr + offset_in_page(gpa)), val);
- kunmap_atomic(addr, KM_USER0);
+ kaddr = kmap_atomic(page, KM_USER0);
+ set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
+ kunmap_atomic(kaddr, KM_USER0);
kvm_release_page_dirty(page);
emul_write:
up_read(&current->mm->mmap_sem);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 4876182daf8..25df1c1989f 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -21,7 +21,7 @@ else
lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
lib-y += thunk_64.o clear_page_64.o copy_page_64.o
- lib-y += bitstr_64.o bitops_64.o
+ lib-y += bitops_64.o
lib-y += memmove_64.o memset_64.o
lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
endif
diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
deleted file mode 100644
index 7445caf1b5d..00000000000
--- a/arch/x86/lib/bitstr_64.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <linux/module.h>
-#include <linux/bitops.h>
-
-/* Find string of zero bits in a bitmap */
-unsigned long
-find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
-{
- unsigned long n, end, i;
-
- again:
- n = find_next_zero_bit(bitmap, nbits, start);
- if (n == -1)
- return -1;
-
- /* could test bitsliced, but it's hardly worth it */
- end = n+len;
- if (end > nbits)
- return -1;
- for (i = n+1; i < end; i++) {
- if (test_bit(i, bitmap)) {
- start = i+1;
- goto again;
- }
- }
- return n;
-}
-
-EXPORT_SYMBOL(find_next_zero_string);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index bb55a78dcd6..16ce841f08d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -237,7 +237,6 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
if (!SHARED_KERNEL_PMD) {
struct page *page;
- address = __pa(address);
list_for_each_entry(page, &pgd_list, lru) {
pgd_t *pgd;
pud_t *pud;
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index c7db504be1e..6c1914622a8 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -272,7 +272,7 @@ static void pgd_dtor(void *pgd)
* preallocate which never got a corresponding vma will need to be
* freed manually.
*/
-static void pgd_mop_up_pmds(pgd_t *pgdp)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
int i;
@@ -285,7 +285,7 @@ static void pgd_mop_up_pmds(pgd_t *pgdp)
pgdp[i] = native_make_pgd(0);
paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
- pmd_free(pmd);
+ pmd_free(mm, pmd);
}
}
}
@@ -313,7 +313,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
pmd_t *pmd = pmd_alloc_one(mm, addr);
if (!pmd) {
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
return 0;
}
@@ -333,7 +333,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
return 1;
}
-static void pgd_mop_up_pmds(pgd_t *pgd)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
}
#endif /* CONFIG_X86_PAE */
@@ -352,9 +352,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
quicklist_free(0, pgd_dtor, pgd);
}
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42ba0e2da1a..103b9dff121 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -72,7 +72,7 @@ pcibios_align_resource(void *data, struct resource *res,
}
}
}
-
+EXPORT_SYMBOL(pcibios_align_resource);
/*
* Handle resources of PCI devices. If the world were perfect, we could