aboutsummaryrefslogtreecommitdiffstats
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/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/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.c8
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c4
-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/dma_64.c8
-rw-r--r--arch/powerpc/kernel/iommu.c93
-rw-r--r--arch/powerpc/mm/pgtable_32.c6
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/ppc/mm/pgtable.c6
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/syscalls.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/pgtable_32.c12
-rw-r--r--arch/x86/pci/i386.c2
203 files changed, 2211 insertions, 2431 deletions
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 468b76ce66a1..8ac08311f5a5 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,
165 ret = (void *)__get_free_pages(gfp, get_order(size)); 165 ret = (void *)__get_free_pages(gfp, get_order(size));
166 if (ret) { 166 if (ret) {
167 memset(ret, 0, size); 167 memset(ret, 0, size);
168 *dma_handle = virt_to_bus(ret); 168 *dma_handle = virt_to_phys(ret);
169 } 169 }
170 return ret; 170 return ret;
171} 171}
@@ -184,7 +184,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
184 184
185 BUG_ON(!sg_page(sg)); 185 BUG_ON(!sg_page(sg));
186 va = sg_virt(sg); 186 va = sg_virt(sg);
187 sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va); 187 sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
188 sg_dma_len(sg) = sg->length; 188 sg_dma_len(sg) = sg->length;
189 } 189 }
190 190
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 2d00a08d3f08..26d3789dfdd0 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -9,6 +9,7 @@
9#include <linux/bootmem.h> 9#include <linux/bootmem.h>
10#include <linux/scatterlist.h> 10#include <linux/scatterlist.h>
11#include <linux/log2.h> 11#include <linux/log2.h>
12#include <linux/dma-mapping.h>
12 13
13#include <asm/io.h> 14#include <asm/io.h>
14#include <asm/hwrpb.h> 15#include <asm/hwrpb.h>
@@ -470,22 +471,29 @@ EXPORT_SYMBOL(pci_free_consistent);
470#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG)) 471#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
471 472
472static void 473static void
473sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok) 474sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
475 int virt_ok)
474{ 476{
475 unsigned long next_paddr; 477 unsigned long next_paddr;
476 struct scatterlist *leader; 478 struct scatterlist *leader;
477 long leader_flag, leader_length; 479 long leader_flag, leader_length;
480 unsigned int max_seg_size;
478 481
479 leader = sg; 482 leader = sg;
480 leader_flag = 0; 483 leader_flag = 0;
481 leader_length = leader->length; 484 leader_length = leader->length;
482 next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length; 485 next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
483 486
487 /* we will not marge sg without device. */
488 max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
484 for (++sg; sg < end; ++sg) { 489 for (++sg; sg < end; ++sg) {
485 unsigned long addr, len; 490 unsigned long addr, len;
486 addr = SG_ENT_PHYS_ADDRESS(sg); 491 addr = SG_ENT_PHYS_ADDRESS(sg);
487 len = sg->length; 492 len = sg->length;
488 493
494 if (leader_length + len > max_seg_size)
495 goto new_segment;
496
489 if (next_paddr == addr) { 497 if (next_paddr == addr) {
490 sg->dma_address = -1; 498 sg->dma_address = -1;
491 leader_length += len; 499 leader_length += len;
@@ -494,6 +502,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
494 leader_flag = 1; 502 leader_flag = 1;
495 leader_length += len; 503 leader_length += len;
496 } else { 504 } else {
505new_segment:
497 leader->dma_address = leader_flag; 506 leader->dma_address = leader_flag;
498 leader->dma_length = leader_length; 507 leader->dma_length = leader_length;
499 leader = sg; 508 leader = sg;
@@ -512,7 +521,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
512 in the blanks. */ 521 in the blanks. */
513 522
514static int 523static int
515sg_fill(struct scatterlist *leader, struct scatterlist *end, 524sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
516 struct scatterlist *out, struct pci_iommu_arena *arena, 525 struct scatterlist *out, struct pci_iommu_arena *arena,
517 dma_addr_t max_dma, int dac_allowed) 526 dma_addr_t max_dma, int dac_allowed)
518{ 527{
@@ -562,8 +571,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
562 571
563 /* Otherwise, break up the remaining virtually contiguous 572 /* Otherwise, break up the remaining virtually contiguous
564 hunks into individual direct maps and retry. */ 573 hunks into individual direct maps and retry. */
565 sg_classify(leader, end, 0); 574 sg_classify(dev, leader, end, 0);
566 return sg_fill(leader, end, out, arena, max_dma, dac_allowed); 575 return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
567 } 576 }
568 577
569 out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr; 578 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,
619 struct pci_iommu_arena *arena; 628 struct pci_iommu_arena *arena;
620 dma_addr_t max_dma; 629 dma_addr_t max_dma;
621 int dac_allowed; 630 int dac_allowed;
631 struct device *dev;
622 632
623 if (direction == PCI_DMA_NONE) 633 if (direction == PCI_DMA_NONE)
624 BUG(); 634 BUG();
625 635
626 dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 636 dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
627 637
638 dev = pdev ? &pdev->dev : NULL;
639
628 /* Fast path single entry scatterlists. */ 640 /* Fast path single entry scatterlists. */
629 if (nents == 1) { 641 if (nents == 1) {
630 sg->dma_length = sg->length; 642 sg->dma_length = sg->length;
@@ -638,7 +650,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
638 end = sg + nents; 650 end = sg + nents;
639 651
640 /* First, prepare information about the entries. */ 652 /* First, prepare information about the entries. */
641 sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0); 653 sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
642 654
643 /* Second, figure out where we're going to map things. */ 655 /* Second, figure out where we're going to map things. */
644 if (alpha_mv.mv_pci_tbi) { 656 if (alpha_mv.mv_pci_tbi) {
@@ -658,7 +670,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
658 for (out = sg; sg < end; ++sg) { 670 for (out = sg; sg < end; ++sg) {
659 if ((int) sg->dma_address < 0) 671 if ((int) sg->dma_address < 0)
660 continue; 672 continue;
661 if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0) 673 if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
662 goto error; 674 goto error;
663 out++; 675 out++;
664 } 676 }
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bd5e68cd61e8..beff6297f788 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -58,7 +58,6 @@ static struct notifier_block alpha_panic_block = {
58#include <asm/system.h> 58#include <asm/system.h>
59#include <asm/hwrpb.h> 59#include <asm/hwrpb.h>
60#include <asm/dma.h> 60#include <asm/dma.h>
61#include <asm/io.h>
62#include <asm/mmu_context.h> 61#include <asm/mmu_context.h>
63#include <asm/console.h> 62#include <asm/console.h>
64 63
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 79de99e32c35..ba914af18c4f 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -495,7 +495,7 @@ sys_call_table:
495 .quad sys_epoll_pwait 495 .quad sys_epoll_pwait
496 .quad sys_utimensat /* 475 */ 496 .quad sys_utimensat /* 475 */
497 .quad sys_signalfd 497 .quad sys_signalfd
498 .quad sys_timerfd 498 .quad sys_ni_syscall
499 .quad sys_eventfd 499 .quad sys_eventfd
500 500
501 .size sys_call_table, . - sys_call_table 501 .size sys_call_table, . - sys_call_table
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 64d19eff3faa..e19e7744e366 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -385,6 +385,7 @@ config ARCH_PXA
385 depends on MMU 385 depends on MMU
386 select ARCH_MTD_XIP 386 select ARCH_MTD_XIP
387 select GENERIC_GPIO 387 select GENERIC_GPIO
388 select HAVE_GPIO_LIB
388 select GENERIC_TIME 389 select GENERIC_TIME
389 select GENERIC_CLOCKEVENTS 390 select GENERIC_CLOCKEVENTS
390 select TICK_ONESHOT 391 select TICK_ONESHOT
@@ -1122,6 +1123,8 @@ source "drivers/i2c/Kconfig"
1122 1123
1123source "drivers/spi/Kconfig" 1124source "drivers/spi/Kconfig"
1124 1125
1126source "drivers/gpio/Kconfig"
1127
1125source "drivers/w1/Kconfig" 1128source "drivers/w1/Kconfig"
1126 1129
1127source "drivers/power/Kconfig" 1130source "drivers/power/Kconfig"
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index cecf658e3625..283e14fff993 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -359,7 +359,7 @@
359 CALL(sys_kexec_load) 359 CALL(sys_kexec_load)
360 CALL(sys_utimensat) 360 CALL(sys_utimensat)
361 CALL(sys_signalfd) 361 CALL(sys_signalfd)
362/* 350 */ CALL(sys_timerfd) 362/* 350 */ CALL(sys_ni_syscall)
363 CALL(sys_eventfd) 363 CALL(sys_eventfd)
364 CALL(sys_fallocate) 364 CALL(sys_fallocate)
365#ifndef syscalls_counted 365#ifndef syscalls_counted
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e9dfbab46cb6..eefae1de334c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -150,7 +150,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
150 secondary_data.pgdir = 0; 150 secondary_data.pgdir = 0;
151 151
152 *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0); 152 *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
153 pgd_free(pgd); 153 pgd_free(&init_mm, pgd);
154 154
155 if (ret) { 155 if (ret) {
156 printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu); 156 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 8604938bd948..6e0c4f5b5ae6 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,8 @@
3# 3#
4 4
5# Common support (must be linked before board specific support) 5# Common support (must be linked before board specific support)
6obj-y += clock.o devices.o generic.o irq.o dma.o time.o 6obj-y += clock.o devices.o generic.o irq.o dma.o \
7 time.o gpio.o
7obj-$(CONFIG_PXA25x) += pxa25x.o 8obj-$(CONFIG_PXA25x) += pxa25x.o
8obj-$(CONFIG_PXA27x) += pxa27x.o 9obj-$(CONFIG_PXA27x) += pxa27x.o
9obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o 10obj-$(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 76970598f550..80721c610d41 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -32,7 +32,6 @@
32#include <asm/mach/map.h> 32#include <asm/mach/map.h>
33 33
34#include <asm/arch/pxa-regs.h> 34#include <asm/arch/pxa-regs.h>
35#include <asm/arch/gpio.h>
36 35
37#include "generic.h" 36#include "generic.h"
38 37
@@ -67,97 +66,6 @@ unsigned int get_memclk_frequency_10khz(void)
67EXPORT_SYMBOL(get_memclk_frequency_10khz); 66EXPORT_SYMBOL(get_memclk_frequency_10khz);
68 67
69/* 68/*
70 * Handy function to set GPIO alternate functions
71 */
72int pxa_last_gpio;
73
74int pxa_gpio_mode(int gpio_mode)
75{
76 unsigned long flags;
77 int gpio = gpio_mode & GPIO_MD_MASK_NR;
78 int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
79 int gafr;
80
81 if (gpio > pxa_last_gpio)
82 return -EINVAL;
83
84 local_irq_save(flags);
85 if (gpio_mode & GPIO_DFLT_LOW)
86 GPCR(gpio) = GPIO_bit(gpio);
87 else if (gpio_mode & GPIO_DFLT_HIGH)
88 GPSR(gpio) = GPIO_bit(gpio);
89 if (gpio_mode & GPIO_MD_MASK_DIR)
90 GPDR(gpio) |= GPIO_bit(gpio);
91 else
92 GPDR(gpio) &= ~GPIO_bit(gpio);
93 gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
94 GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
95 local_irq_restore(flags);
96
97 return 0;
98}
99
100EXPORT_SYMBOL(pxa_gpio_mode);
101
102int gpio_direction_input(unsigned gpio)
103{
104 unsigned long flags;
105 u32 mask;
106
107 if (gpio > pxa_last_gpio)
108 return -EINVAL;
109
110 mask = GPIO_bit(gpio);
111 local_irq_save(flags);
112 GPDR(gpio) &= ~mask;
113 local_irq_restore(flags);
114
115 return 0;
116}
117EXPORT_SYMBOL(gpio_direction_input);
118
119int gpio_direction_output(unsigned gpio, int value)
120{
121 unsigned long flags;
122 u32 mask;
123
124 if (gpio > pxa_last_gpio)
125 return -EINVAL;
126
127 mask = GPIO_bit(gpio);
128 local_irq_save(flags);
129 if (value)
130 GPSR(gpio) = mask;
131 else
132 GPCR(gpio) = mask;
133 GPDR(gpio) |= mask;
134 local_irq_restore(flags);
135
136 return 0;
137}
138EXPORT_SYMBOL(gpio_direction_output);
139
140/*
141 * Return GPIO level
142 */
143int pxa_gpio_get_value(unsigned gpio)
144{
145 return __gpio_get_value(gpio);
146}
147
148EXPORT_SYMBOL(pxa_gpio_get_value);
149
150/*
151 * Set output GPIO level
152 */
153void pxa_gpio_set_value(unsigned gpio, int value)
154{
155 __gpio_set_value(gpio, value);
156}
157
158EXPORT_SYMBOL(pxa_gpio_set_value);
159
160/*
161 * Routine to safely enable or disable a clock in the CKEN 69 * Routine to safely enable or disable a clock in the CKEN
162 */ 70 */
163void __pxa_set_cken(int clock, int enable) 71void __pxa_set_cken(int clock, int enable)
@@ -172,7 +80,6 @@ void __pxa_set_cken(int clock, int enable)
172 80
173 local_irq_restore(flags); 81 local_irq_restore(flags);
174} 82}
175
176EXPORT_SYMBOL(__pxa_set_cken); 83EXPORT_SYMBOL(__pxa_set_cken);
177 84
178/* 85/*
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 1a16ad3ecee6..b3d10b0e52a0 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);
16extern void __init pxa_init_irq_high(void); 16extern void __init pxa_init_irq_high(void);
17extern void __init pxa_init_irq_gpio(int gpio_nr); 17extern void __init pxa_init_irq_gpio(int gpio_nr);
18extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)); 18extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
19extern void __init pxa_init_gpio(int gpio_nr);
19extern void __init pxa25x_init_irq(void); 20extern void __init pxa25x_init_irq(void);
20extern void __init pxa27x_init_irq(void); 21extern void __init pxa27x_init_irq(void);
21extern void __init pxa3xx_init_irq(void); 22extern 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 000000000000..8638dd7dd076
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,197 @@
1/*
2 * linux/arch/arm/mach-pxa/gpio.c
3 *
4 * Generic PXA GPIO handling
5 *
6 * Author: Nicolas Pitre
7 * Created: Jun 15, 2001
8 * Copyright: MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17
18#include <asm/gpio.h>
19#include <asm/hardware.h>
20#include <asm/io.h>
21#include <asm/arch/pxa-regs.h>
22
23#include "generic.h"
24
25
26struct pxa_gpio_chip {
27 struct gpio_chip chip;
28 void __iomem *regbase;
29};
30
31int pxa_last_gpio;
32
33/*
34 * Configure pins for GPIO or other functions
35 */
36int pxa_gpio_mode(int gpio_mode)
37{
38 unsigned long flags;
39 int gpio = gpio_mode & GPIO_MD_MASK_NR;
40 int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
41 int gafr;
42
43 if (gpio > pxa_last_gpio)
44 return -EINVAL;
45
46 local_irq_save(flags);
47 if (gpio_mode & GPIO_DFLT_LOW)
48 GPCR(gpio) = GPIO_bit(gpio);
49 else if (gpio_mode & GPIO_DFLT_HIGH)
50 GPSR(gpio) = GPIO_bit(gpio);
51 if (gpio_mode & GPIO_MD_MASK_DIR)
52 GPDR(gpio) |= GPIO_bit(gpio);
53 else
54 GPDR(gpio) &= ~GPIO_bit(gpio);
55 gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
56 GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
57 local_irq_restore(flags);
58
59 return 0;
60}
61EXPORT_SYMBOL(pxa_gpio_mode);
62
63static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
64{
65 unsigned long flags;
66 u32 mask = 1 << offset;
67 u32 value;
68 struct pxa_gpio_chip *pxa;
69 void __iomem *gpdr;
70
71 pxa = container_of(chip, struct pxa_gpio_chip, chip);
72 gpdr = pxa->regbase + GPDR_OFFSET;
73 local_irq_save(flags);
74 value = __raw_readl(gpdr);
75 value &= ~mask;
76 __raw_writel(value, gpdr);
77 local_irq_restore(flags);
78
79 return 0;
80}
81
82static int pxa_gpio_direction_output(struct gpio_chip *chip,
83 unsigned offset, int value)
84{
85 unsigned long flags;
86 u32 mask = 1 << offset;
87 u32 tmp;
88 struct pxa_gpio_chip *pxa;
89 void __iomem *gpdr;
90
91 pxa = container_of(chip, struct pxa_gpio_chip, chip);
92 __raw_writel(mask,
93 pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
94 gpdr = pxa->regbase + GPDR_OFFSET;
95 local_irq_save(flags);
96 tmp = __raw_readl(gpdr);
97 tmp |= mask;
98 __raw_writel(tmp, gpdr);
99 local_irq_restore(flags);
100
101 return 0;
102}
103
104/*
105 * Return GPIO level
106 */
107static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
108{
109 u32 mask = 1 << offset;
110 struct pxa_gpio_chip *pxa;
111
112 pxa = container_of(chip, struct pxa_gpio_chip, chip);
113 return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
114}
115
116/*
117 * Set output GPIO level
118 */
119static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
120{
121 u32 mask = 1 << offset;
122 struct pxa_gpio_chip *pxa;
123
124 pxa = container_of(chip, struct pxa_gpio_chip, chip);
125
126 if (value)
127 __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
128 else
129 __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
130}
131
132static struct pxa_gpio_chip pxa_gpio_chip[] = {
133 [0] = {
134 .regbase = GPIO0_BASE,
135 .chip = {
136 .label = "gpio-0",
137 .direction_input = pxa_gpio_direction_input,
138 .direction_output = pxa_gpio_direction_output,
139 .get = pxa_gpio_get,
140 .set = pxa_gpio_set,
141 .base = 0,
142 .ngpio = 32,
143 },
144 },
145 [1] = {
146 .regbase = GPIO1_BASE,
147 .chip = {
148 .label = "gpio-1",
149 .direction_input = pxa_gpio_direction_input,
150 .direction_output = pxa_gpio_direction_output,
151 .get = pxa_gpio_get,
152 .set = pxa_gpio_set,
153 .base = 32,
154 .ngpio = 32,
155 },
156 },
157 [2] = {
158 .regbase = GPIO2_BASE,
159 .chip = {
160 .label = "gpio-2",
161 .direction_input = pxa_gpio_direction_input,
162 .direction_output = pxa_gpio_direction_output,
163 .get = pxa_gpio_get,
164 .set = pxa_gpio_set,
165 .base = 64,
166 .ngpio = 32, /* 21 for PXA25x */
167 },
168 },
169#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
170 [3] = {
171 .regbase = GPIO3_BASE,
172 .chip = {
173 .label = "gpio-3",
174 .direction_input = pxa_gpio_direction_input,
175 .direction_output = pxa_gpio_direction_output,
176 .get = pxa_gpio_get,
177 .set = pxa_gpio_set,
178 .base = 96,
179 .ngpio = 32,
180 },
181 },
182#endif
183};
184
185void __init pxa_init_gpio(int gpio_nr)
186{
187 int i;
188
189 /* add a GPIO chip for each register bank.
190 * the last PXA25x register only contains 21 GPIOs
191 */
192 for (i = 0; i < gpio_nr; i += 32) {
193 if (i+32 > gpio_nr)
194 pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
195 gpiochip_add(&pxa_gpio_chip[i/32].chip);
196 }
197}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 5a1d5eef10a4..36c6a68beca2 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)
311 /* Install handler for GPIO>=2 edge detect interrupts */ 311 /* Install handler for GPIO>=2 edge detect interrupts */
312 set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); 312 set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
313 set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); 313 set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
314
315 pxa_init_gpio(gpio_nr);
314} 316}
315 317
316void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) 318void __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 75952779ce19..303a7ff6bfd2 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)
162 * Free the page table, if there was one. 162 * Free the page table, if there was one.
163 */ 163 */
164 if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) 164 if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
165 pte_free_kernel(pmd_page_vaddr(pmd)); 165 pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
166 } 166 }
167 167
168 addr += PGDIR_SIZE; 168 addr += PGDIR_SIZE;
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 50b9aed6000d..500c9610ab30 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)
65 return new_pgd; 65 return new_pgd;
66 66
67no_pte: 67no_pte:
68 pmd_free(new_pmd); 68 pmd_free(mm, new_pmd);
69no_pmd: 69no_pmd:
70 free_pages((unsigned long)new_pgd, 2); 70 free_pages((unsigned long)new_pgd, 2);
71no_pgd: 71no_pgd:
72 return NULL; 72 return NULL;
73} 73}
74 74
75void free_pgd_slow(pgd_t *pgd) 75void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
76{ 76{
77 pmd_t *pmd; 77 pmd_t *pmd;
78 struct page *pte; 78 struct page *pte;
@@ -94,8 +94,8 @@ void free_pgd_slow(pgd_t *pgd)
94 pmd_clear(pmd); 94 pmd_clear(pmd);
95 dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE); 95 dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
96 pte_lock_deinit(pte); 96 pte_lock_deinit(pte);
97 pte_free(pte); 97 pte_free(mm, pte);
98 pmd_free(pmd); 98 pmd_free(mm, pmd);
99free: 99free:
100 free_pages((unsigned long) pgd, 2); 100 free_pages((unsigned long) pgd, 2);
101} 101}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c816f29154c9..28e0caf4156c 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -82,6 +82,7 @@ config PLATFORM_AT32AP
82 select SUBARCH_AVR32B 82 select SUBARCH_AVR32B
83 select MMU 83 select MMU
84 select PERFORMANCE_COUNTERS 84 select PERFORMANCE_COUNTERS
85 select HAVE_GPIO_LIB
85 86
86# 87#
87# CPU types 88# CPU types
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d61a02da898c..38a8fa31c0b5 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -24,11 +24,11 @@
24#define MAX_NR_PIO_DEVICES 8 24#define MAX_NR_PIO_DEVICES 8
25 25
26struct pio_device { 26struct pio_device {
27 struct gpio_chip chip;
27 void __iomem *regs; 28 void __iomem *regs;
28 const struct platform_device *pdev; 29 const struct platform_device *pdev;
29 struct clk *clk; 30 struct clk *clk;
30 u32 pinmux_mask; 31 u32 pinmux_mask;
31 u32 gpio_mask;
32 char name[8]; 32 char name[8];
33}; 33};
34 34
@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
64 goto fail; 64 goto fail;
65 } 65 }
66 66
67 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { 67 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
68 || gpiochip_is_requested(&pio->chip, pin_index))) {
68 printk("%s: pin %u is busy\n", pio->name, pin_index); 69 printk("%s: pin %u is busy\n", pio->name, pin_index);
69 goto fail; 70 goto fail;
70 } 71 }
@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
79 if (!(flags & AT32_GPIOF_PULLUP)) 80 if (!(flags & AT32_GPIOF_PULLUP))
80 pio_writel(pio, PUDR, mask); 81 pio_writel(pio, PUDR, mask);
81 82
82 /* gpio_request NOT allowed */
83 set_bit(pin_index, &pio->gpio_mask);
84
85 return; 83 return;
86 84
87fail: 85fail:
@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
130 128
131 pio_writel(pio, PER, mask); 129 pio_writel(pio, PER, mask);
132 130
133 /* gpio_request now allowed */
134 clear_bit(pin_index, &pio->gpio_mask);
135
136 return; 131 return;
137 132
138fail: 133fail:
@@ -166,96 +161,50 @@ fail:
166 161
167/* GPIO API */ 162/* GPIO API */
168 163
169int gpio_request(unsigned int gpio, const char *label) 164static int direction_input(struct gpio_chip *chip, unsigned offset)
170{ 165{
171 struct pio_device *pio; 166 struct pio_device *pio = container_of(chip, struct pio_device, chip);
172 unsigned int pin; 167 u32 mask = 1 << offset;
173
174 pio = gpio_to_pio(gpio);
175 if (!pio)
176 return -ENODEV;
177 168
178 pin = gpio & 0x1f; 169 if (!(pio_readl(pio, PSR) & mask))
179 if (test_and_set_bit(pin, &pio->gpio_mask)) 170 return -EINVAL;
180 return -EBUSY;
181 171
172 pio_writel(pio, ODR, mask);
182 return 0; 173 return 0;
183} 174}
184EXPORT_SYMBOL(gpio_request);
185 175
186void gpio_free(unsigned int gpio) 176static int gpio_get(struct gpio_chip *chip, unsigned offset)
187{ 177{
188 struct pio_device *pio; 178 struct pio_device *pio = container_of(chip, struct pio_device, chip);
189 unsigned int pin;
190 179
191 pio = gpio_to_pio(gpio); 180 return (pio_readl(pio, PDSR) >> offset) & 1;
192 if (!pio) {
193 printk(KERN_ERR
194 "gpio: attempted to free invalid pin %u\n", gpio);
195 return;
196 }
197
198 pin = gpio & 0x1f;
199 if (!test_and_clear_bit(pin, &pio->gpio_mask))
200 printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
201 pio->name, pin);
202} 181}
203EXPORT_SYMBOL(gpio_free);
204 182
205int gpio_direction_input(unsigned int gpio) 183static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
206{
207 struct pio_device *pio;
208 unsigned int pin;
209
210 pio = gpio_to_pio(gpio);
211 if (!pio)
212 return -ENODEV;
213
214 pin = gpio & 0x1f;
215 pio_writel(pio, ODR, 1 << pin);
216
217 return 0;
218}
219EXPORT_SYMBOL(gpio_direction_input);
220 184
221int gpio_direction_output(unsigned int gpio, int value) 185static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
222{ 186{
223 struct pio_device *pio; 187 struct pio_device *pio = container_of(chip, struct pio_device, chip);
224 unsigned int pin; 188 u32 mask = 1 << offset;
225
226 pio = gpio_to_pio(gpio);
227 if (!pio)
228 return -ENODEV;
229 189
230 gpio_set_value(gpio, value); 190 if (!(pio_readl(pio, PSR) & mask))
231 191 return -EINVAL;
232 pin = gpio & 0x1f;
233 pio_writel(pio, OER, 1 << pin);
234 192
193 gpio_set(chip, offset, value);
194 pio_writel(pio, OER, mask);
235 return 0; 195 return 0;
236} 196}
237EXPORT_SYMBOL(gpio_direction_output);
238 197
239int gpio_get_value(unsigned int gpio) 198static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
240{ 199{
241 struct pio_device *pio = &pio_dev[gpio >> 5]; 200 struct pio_device *pio = container_of(chip, struct pio_device, chip);
201 u32 mask = 1 << offset;
242 202
243 return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
244}
245EXPORT_SYMBOL(gpio_get_value);
246
247void gpio_set_value(unsigned int gpio, int value)
248{
249 struct pio_device *pio = &pio_dev[gpio >> 5];
250 u32 mask;
251
252 mask = 1 << (gpio & 0x1f);
253 if (value) 203 if (value)
254 pio_writel(pio, SODR, mask); 204 pio_writel(pio, SODR, mask);
255 else 205 else
256 pio_writel(pio, CODR, mask); 206 pio_writel(pio, CODR, mask);
257} 207}
258EXPORT_SYMBOL(gpio_set_value);
259 208
260/*--------------------------------------------------------------------------*/ 209/*--------------------------------------------------------------------------*/
261 210
@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
339 288
340/*--------------------------------------------------------------------------*/ 289/*--------------------------------------------------------------------------*/
341 290
291#ifdef CONFIG_DEBUG_FS
292
293#include <linux/seq_file.h>
294
295/*
296 * This shows more info than the generic gpio dump code:
297 * pullups, deglitching, open drain drive.
298 */
299static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
300{
301 struct pio_device *pio = container_of(chip, struct pio_device, chip);
302 u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
303 unsigned i;
304 u32 mask;
305 char bank;
306
307 psr = pio_readl(pio, PSR);
308 osr = pio_readl(pio, OSR);
309 imr = pio_readl(pio, IMR);
310 pdsr = pio_readl(pio, PDSR);
311 pusr = pio_readl(pio, PUSR);
312 ifsr = pio_readl(pio, IFSR);
313 mdsr = pio_readl(pio, MDSR);
314
315 bank = 'A' + pio->pdev->id;
316
317 for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
318 const char *label;
319
320 label = gpiochip_is_requested(chip, i);
321 if (!label)
322 continue;
323
324 seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
325 chip->base + i, bank, i,
326 label,
327 (osr & mask) ? "out" : "in ",
328 (mask & pdsr) ? "hi" : "lo",
329 (mask & pusr) ? " " : "up");
330 if (ifsr & mask)
331 seq_printf(s, " deglitch");
332 if ((osr & mdsr) & mask)
333 seq_printf(s, " open-drain");
334 if (imr & mask)
335 seq_printf(s, " irq-%d edge-both",
336 gpio_to_irq(chip->base + i));
337 seq_printf(s, "\n");
338 }
339}
340
341#else
342#define pio_bank_show NULL
343#endif
344
345
346/*--------------------------------------------------------------------------*/
347
342static int __init pio_probe(struct platform_device *pdev) 348static int __init pio_probe(struct platform_device *pdev)
343{ 349{
344 struct pio_device *pio = NULL; 350 struct pio_device *pio = NULL;
@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
349 pio = &pio_dev[pdev->id]; 355 pio = &pio_dev[pdev->id];
350 BUG_ON(!pio->regs); 356 BUG_ON(!pio->regs);
351 357
358 pio->chip.label = pio->name;
359 pio->chip.base = pdev->id * 32;
360 pio->chip.ngpio = 32;
361
362 pio->chip.direction_input = direction_input;
363 pio->chip.get = gpio_get;
364 pio->chip.direction_output = direction_output;
365 pio->chip.set = gpio_set;
366 pio->chip.dbg_show = pio_bank_show;
367
368 gpiochip_add(&pio->chip);
369
352 gpio_irq_setup(pio, irq, gpio_irq_base); 370 gpio_irq_setup(pio, irq, gpio_irq_base);
353 371
354 platform_set_drvdata(pdev, pio); 372 platform_set_drvdata(pdev, pio);
@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
406 pio->pdev = pdev; 424 pio->pdev = pdev;
407 pio->regs = ioremap(regs->start, regs->end - regs->start + 1); 425 pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
408 426
409 /*
410 * request_gpio() is only valid for pins that have been
411 * explicitly configured as GPIO and not previously requested
412 */
413 pio->gpio_mask = ~0UL;
414
415 /* start with irqs disabled and acked */ 427 /* start with irqs disabled and acked */
416 pio_writel(pio, IDR, ~0UL); 428 pio_writel(pio, IDR, ~0UL);
417 (void) pio_readl(pio, ISR); 429 (void) pio_readl(pio, ISR);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 50fa3aca32c5..7795116a483a 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -19,7 +19,7 @@
19#define PIO_OSR 0x0018 19#define PIO_OSR 0x0018
20#define PIO_IFER 0x0020 20#define PIO_IFER 0x0020
21#define PIO_IFDR 0x0024 21#define PIO_IFDR 0x0024
22#define PIO_ISFR 0x0028 22#define PIO_IFSR 0x0028
23#define PIO_SODR 0x0030 23#define PIO_SODR 0x0030
24#define PIO_CODR 0x0034 24#define PIO_CODR 0x0034
25#define PIO_ODSR 0x0038 25#define PIO_ODSR 0x0038
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 56ff51bc8c21..fdd9bf43361e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -1373,7 +1373,7 @@ ENTRY(_sys_call_table)
1373 .long _sys_epoll_pwait 1373 .long _sys_epoll_pwait
1374 .long _sys_utimensat 1374 .long _sys_utimensat
1375 .long _sys_signalfd 1375 .long _sys_signalfd
1376 .long _sys_timerfd 1376 .long _sys_ni_syscall
1377 .long _sys_eventfd /* 350 */ 1377 .long _sys_eventfd /* 350 */
1378 .long _sys_pread64 1378 .long _sys_pread64
1379 .long _sys_pwrite64 1379 .long _sys_pwrite64
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7f0be4cd5e9a..27b082ac7f11 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -150,6 +150,7 @@ config ETRAX_FLASH_BUSWIDTH
150 Width in bytes of the Flash bus (1, 2 or 4). Is usually 2. 150 Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
151 151
152source arch/cris/arch-v10/Kconfig 152source arch/cris/arch-v10/Kconfig
153source arch/cris/arch-v32/Kconfig
153 154
154endmenu 155endmenu
155 156
@@ -157,8 +158,8 @@ source "net/Kconfig"
157 158
158# bring in ETRAX built-in drivers 159# bring in ETRAX built-in drivers
159menu "Drivers for built-in interfaces" 160menu "Drivers for built-in interfaces"
160# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32) 161source arch/cris/arch-v10/drivers/Kconfig
161source arch/cris/arch/drivers/Kconfig 162source arch/cris/arch-v32/drivers/Kconfig
162 163
163endmenu 164endmenu
164 165
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index f1ce6f64401d..1d61faec77cd 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -1,3 +1,5 @@
1if ETRAX_ARCH_V10
2
1# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping 3# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
2config CRIS_LOW_MAP 4config CRIS_LOW_MAP
3 bool 5 bool
@@ -451,3 +453,5 @@ config ETRAX_POWERBUTTON_BIT
451 default "25" 453 default "25"
452 help 454 help
453 Configure where power button is connected. 455 Configure where power button is connected.
456
457endif
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index e3c0f2928149..96740ef497d4 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -1,3 +1,5 @@
1if ETRAX_ARCH_V10
2
1config ETRAX_ETHERNET 3config ETRAX_ETHERNET
2 bool "Ethernet support" 4 bool "Ethernet support"
3 depends on ETRAX_ARCH_V10 5 depends on ETRAX_ARCH_V10
@@ -806,3 +808,5 @@ config ETRAX_DS1302_TRICKLE_CHARGE
806 1 = 2kohm, 2 = 4kohm, 3 = 4kohm 808 1 = 2kohm, 2 = 4kohm, 3 = 4kohm
807 4 = 1 diode, 8 = 2 diodes 809 4 = 1 diode, 8 = 2 diodes
808 Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5 810 Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
811
812endif
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ec62c951fa3c..d1361dc119e2 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -1167,7 +1167,7 @@ sys_call_table:
1167 .long sys_epoll_pwait 1167 .long sys_epoll_pwait
1168 .long sys_utimensat /* 320 */ 1168 .long sys_utimensat /* 320 */
1169 .long sys_signalfd 1169 .long sys_signalfd
1170 .long sys_timerfd 1170 .long sys_ni_syscall
1171 .long sys_eventfd 1171 .long sys_eventfd
1172 .long sys_fallocate 1172 .long sys_fallocate
1173 1173
diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
index 4f79d8ed3e1c..d8acaa920e1c 100644
--- a/arch/cris/arch-v32/Kconfig
+++ b/arch/cris/arch-v32/Kconfig
@@ -1,3 +1,5 @@
1if ETRAX_ARCH_V32
2
1config ETRAX_DRAM_VIRTUAL_BASE 3config ETRAX_DRAM_VIRTUAL_BASE
2 hex 4 hex
3 depends on ETRAX_ARCH_V32 5 depends on ETRAX_ARCH_V32
@@ -294,3 +296,5 @@ config ETRAX_DEF_GIO_PE_OUT
294 help 296 help
295 Configures the initial data for the general port E bits. Most 297 Configures the initial data for the general port E bits. Most
296 products should use 00000 here. 298 products should use 00000 here.
299
300endif
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 9bccb5e2a960..c329cce2a0c3 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -1,3 +1,5 @@
1if ETRAX_ARCH_V32
2
1config ETRAX_ETHERNET 3config ETRAX_ETHERNET
2 bool "Ethernet support" 4 bool "Ethernet support"
3 depends on ETRAX_ARCH_V32 5 depends on ETRAX_ARCH_V32
@@ -610,3 +612,5 @@ config ETRAX_STREAMCOPROC
610 help 612 help
611 This option enables a driver for the stream co-processor 613 This option enables a driver for the stream co-processor
612 for cryptographic operations. 614 for cryptographic operations.
615
616endif
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index 66f9500fbc02..e0364654fc44 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,
93 93
94 dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); 94 dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
95 if (!dev->dma_mem) 95 if (!dev->dma_mem)
96 goto out; 96 goto iounmap_out;
97 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); 97 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
98 if (!dev->dma_mem->bitmap) 98 if (!dev->dma_mem->bitmap)
99 goto free1_out; 99 goto free1_out;
@@ -110,6 +110,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
110 110
111 free1_out: 111 free1_out:
112 kfree(dev->dma_mem); 112 kfree(dev->dma_mem);
113 iounmap_out:
114 iounmap(mem_base);
113 out: 115 out:
114 return 0; 116 return 0;
115} 117}
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index bf0468cbe713..96f7d70f4473 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -138,6 +138,15 @@ config UCPAGE_OFFSET_C0000000
138 138
139endchoice 139endchoice
140 140
141config PAGE_OFFSET
142 hex
143 default 0x20000000 if UCPAGE_OFFSET_20000000
144 default 0x40000000 if UCPAGE_OFFSET_40000000
145 default 0x60000000 if UCPAGE_OFFSET_60000000
146 default 0x80000000 if UCPAGE_OFFSET_80000000
147 default 0xA0000000 if UCPAGE_OFFSET_A0000000
148 default 0xC0000000
149
141config PROTECT_KERNEL 150config PROTECT_KERNEL
142 bool "Protect core kernel against userspace" 151 bool "Protect core kernel against userspace"
143 depends on !MMU 152 depends on !MMU
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index f42b328b1dd0..ef7527b8b0c7 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -13,7 +13,7 @@ ENTRY(_start)
13 13
14jiffies = jiffies_64 + 4; 14jiffies = jiffies_64 + 4;
15 15
16__page_offset = 0xc0000000; /* start of area covered by struct pages */ 16__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */
17__kernel_image_start = __page_offset; /* address at which kernel image resides */ 17__kernel_image_start = __page_offset; /* address at which kernel image resides */
18 18
19SECTIONS 19SECTIONS
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index 1530a4111e6d..81757d55a5b5 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)
181 181
182 /* get a handle on the mm_struct */ 182 /* get a handle on the mm_struct */
183 read_lock(&tasklist_lock); 183 read_lock(&tasklist_lock);
184 tsk = find_task_by_pid(pid); 184 tsk = find_task_by_vpid(pid);
185 if (tsk) { 185 if (tsk) {
186 ret = -EINVAL; 186 ret = -EINVAL;
187 187
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 7787c3cc52c6..1a2e5c8d03a9 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)
140 return pgd; 140 return pgd;
141} 141}
142 142
143void pgd_free(pgd_t *pgd) 143void pgd_free(struct mm_struct *mm, pgd_t *pgd)
144{ 144{
145 /* in the non-PAE case, clear_page_tables() clears user pgd entries */ 145 /* in the non-PAE case, clear_page_tables() clears user pgd entries */
146 quicklist_free(0, pgd_dtor, pgd); 146 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 45bf04eb7d70..c412fe63f8ec 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1265,7 +1265,7 @@ sba_fill_pdir(
1265 * the sglist do both. 1265 * the sglist do both.
1266 */ 1266 */
1267static SBA_INLINE int 1267static SBA_INLINE int
1268sba_coalesce_chunks( struct ioc *ioc, 1268sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
1269 struct scatterlist *startsg, 1269 struct scatterlist *startsg,
1270 int nents) 1270 int nents)
1271{ 1271{
@@ -1275,6 +1275,7 @@ sba_coalesce_chunks( struct ioc *ioc,
1275 struct scatterlist *dma_sg; /* next DMA stream head */ 1275 struct scatterlist *dma_sg; /* next DMA stream head */
1276 unsigned long dma_offset, dma_len; /* start/len of DMA stream */ 1276 unsigned long dma_offset, dma_len; /* start/len of DMA stream */
1277 int n_mappings = 0; 1277 int n_mappings = 0;
1278 unsigned int max_seg_size = dma_get_max_seg_size(dev);
1278 1279
1279 while (nents > 0) { 1280 while (nents > 0) {
1280 unsigned long vaddr = (unsigned long) sba_sg_address(startsg); 1281 unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1314,6 +1315,9 @@ sba_coalesce_chunks( struct ioc *ioc,
1314 > DMA_CHUNK_SIZE) 1315 > DMA_CHUNK_SIZE)
1315 break; 1316 break;
1316 1317
1318 if (dma_len + startsg->length > max_seg_size)
1319 break;
1320
1317 /* 1321 /*
1318 ** Then look for virtually contiguous blocks. 1322 ** Then look for virtually contiguous blocks.
1319 ** 1323 **
@@ -1441,7 +1445,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
1441 ** w/o this association, we wouldn't have coherent DMA! 1445 ** w/o this association, we wouldn't have coherent DMA!
1442 ** Access to the virtual address is what forces a two pass algorithm. 1446 ** Access to the virtual address is what forces a two pass algorithm.
1443 */ 1447 */
1444 coalesced = sba_coalesce_chunks(ioc, sglist, nents); 1448 coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
1445 1449
1446 /* 1450 /*
1447 ** Program the I/O Pdir 1451 ** Program the I/O Pdir
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index c36f43c94600..f5d3efbfbeda 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1586,7 +1586,7 @@ sys_call_table:
1586 data8 sys_epoll_pwait // 1305 1586 data8 sys_epoll_pwait // 1305
1587 data8 sys_utimensat 1587 data8 sys_utimensat
1588 data8 sys_signalfd 1588 data8 sys_signalfd
1589 data8 sys_timerfd 1589 data8 sys_ni_syscall
1590 data8 sys_eventfd 1590 data8 sys_eventfd
1591 1591
1592 .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls 1592 .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index ee3c8be12fa0..01d877c6868f 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)
17 return 0; 17 return 0;
18} 18}
19 19
20#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) 20#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
21#include <asm/m32r.h> 21#include <asm/m32r.h>
22#include <asm/io.h> 22#include <asm/io.h>
23 23
@@ -52,7 +52,7 @@ static void putc(char c)
52 } 52 }
53 *BOOT_SIO0TXB = c; 53 *BOOT_SIO0TXB = c;
54} 54}
55#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */ 55#else /* !(CONFIG_PLAT_M32700UT) */
56#if defined(CONFIG_PLAT_MAPPI2) 56#if defined(CONFIG_PLAT_MAPPI2)
57#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14) 57#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
58#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30) 58#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8236e42ef711..ffabd01c45eb 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -577,20 +577,6 @@ config MAC_HID
577 depends on INPUT_ADBHID 577 depends on INPUT_ADBHID
578 default y 578 default y
579 579
580config MAC_ADBKEYCODES
581 bool "Support for ADB raw keycodes"
582 depends on INPUT_ADBHID
583 help
584 This provides support for sending raw ADB keycodes to console
585 devices. This is the default up to 2.4.0, but in future this may be
586 phased out in favor of generic Linux keycodes. If you say Y here,
587 you can dynamically switch via the
588 /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
589 sysctl and with the "keyboard_sends_linux_keycodes=" kernel
590 argument.
591
592 If unsure, say Y here.
593
594config ADB_KEYBOARD 580config ADB_KEYBOARD
595 bool "Support for ADB keyboard (old driver)" 581 bool "Support for ADB keyboard (old driver)"
596 depends on MAC && !INPUT_ADBHID 582 depends on MAC && !INPUT_ADBHID
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 4a1bd44ff162..2cba605cb59d 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -13,16 +13,15 @@
13# Copyright (C) 1994 by Hamish Macdonald 13# Copyright (C) 1994 by Hamish Macdonald
14# 14#
15 15
16# test for cross compiling
17COMPILE_ARCH = $(shell uname -m)
18
19# override top level makefile 16# override top level makefile
20AS += -m68020 17AS += -m68020
21LDFLAGS := -m m68kelf 18LDFLAGS := -m m68kelf
22LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds 19LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
23ifneq ($(COMPILE_ARCH),$(ARCH)) 20ifneq ($(SUBARCH),$(ARCH))
24 # prefix for cross-compiling binaries 21 ifeq ($(CROSS_COMPILE),)
25 CROSS_COMPILE = m68k-linux-gnu- 22 CROSS_COMPILE := $(call cc-cross-prefix, \
23 m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
24 endif
26endif 25endif
27 26
28ifdef CONFIG_SUN3 27ifdef CONFIG_SUN3
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 8b415651edee..6a0d7650f980 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -2,6 +2,6 @@
2# Makefile for Linux arch/m68k/amiga source directory 2# Makefile for Linux arch/m68k/amiga source directory
3# 3#
4 4
5obj-y := config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o 5obj-y := config.o amiints.o cia.o chipram.o amisound.o
6 6
7obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o 7obj-$(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 7fdcf6bf3ada..000000000000
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ /dev/null
@@ -1,33 +0,0 @@
1#include <linux/module.h>
2#include <linux/types.h>
3#include <asm/ptrace.h>
4#include <asm/amigahw.h>
5#include <asm/amigaints.h>
6#include <asm/amipcmcia.h>
7
8extern volatile u_short amiga_audio_min_period;
9extern u_short amiga_audio_period;
10
11/*
12 * Add things here when you find the need for it.
13 */
14EXPORT_SYMBOL(amiga_model);
15EXPORT_SYMBOL(amiga_chipset);
16EXPORT_SYMBOL(amiga_hw_present);
17EXPORT_SYMBOL(amiga_eclock);
18EXPORT_SYMBOL(amiga_colorclock);
19EXPORT_SYMBOL(amiga_chip_alloc);
20EXPORT_SYMBOL(amiga_chip_free);
21EXPORT_SYMBOL(amiga_chip_avail);
22EXPORT_SYMBOL(amiga_chip_size);
23EXPORT_SYMBOL(amiga_audio_period);
24EXPORT_SYMBOL(amiga_audio_min_period);
25
26#ifdef CONFIG_AMIGA_PCMCIA
27 EXPORT_SYMBOL(pcmcia_reset);
28 EXPORT_SYMBOL(pcmcia_copy_tuple);
29 EXPORT_SYMBOL(pcmcia_program_voltage);
30 EXPORT_SYMBOL(pcmcia_access_speed);
31 EXPORT_SYMBOL(pcmcia_write_enable);
32 EXPORT_SYMBOL(pcmcia_write_disable);
33#endif
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 1f5bfb584297..61e5c54625ae 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -12,6 +12,7 @@
12#include <linux/timer.h> 12#include <linux/timer.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/module.h>
15 16
16#include <asm/system.h> 17#include <asm/system.h>
17#include <asm/amigahw.h> 18#include <asm/amigahw.h>
@@ -21,7 +22,7 @@ static const signed char sine_data[] = {
21 0, 39, 75, 103, 121, 127, 121, 103, 75, 39, 22 0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
22 0, -39, -75, -103, -121, -127, -121, -103, -75, -39 23 0, -39, -75, -103, -121, -127, -121, -103, -75, -39
23}; 24};
24#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0])) 25#define DATA_SIZE ARRAY_SIZE(sine_data)
25 26
26#define custom amiga_custom 27#define custom amiga_custom
27 28
@@ -31,6 +32,7 @@ static const signed char sine_data[] = {
31 */ 32 */
32 33
33volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */ 34volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
35EXPORT_SYMBOL(amiga_audio_min_period);
34 36
35#define MAX_PERIOD (65535) 37#define MAX_PERIOD (65535)
36 38
@@ -40,6 +42,7 @@ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
40 */ 42 */
41 43
42unsigned short amiga_audio_period = MAX_PERIOD; 44unsigned short amiga_audio_period = MAX_PERIOD;
45EXPORT_SYMBOL(amiga_audio_period);
43 46
44static unsigned long clock_constant; 47static unsigned long clock_constant;
45 48
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index fa015d801617..d10726f9038b 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -13,10 +13,13 @@
13#include <linux/ioport.h> 13#include <linux/ioport.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/module.h>
17
16#include <asm/page.h> 18#include <asm/page.h>
17#include <asm/amigahw.h> 19#include <asm/amigahw.h>
18 20
19unsigned long amiga_chip_size; 21unsigned long amiga_chip_size;
22EXPORT_SYMBOL(amiga_chip_size);
20 23
21static struct resource chipram_res = { 24static struct resource chipram_res = {
22 .name = "Chip RAM", .start = CHIP_PHYSADDR 25 .name = "Chip RAM", .start = CHIP_PHYSADDR
@@ -67,6 +70,7 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
67#endif 70#endif
68 return (void *)ZTWO_VADDR(res->start); 71 return (void *)ZTWO_VADDR(res->start);
69} 72}
73EXPORT_SYMBOL(amiga_chip_alloc);
70 74
71 75
72 /* 76 /*
@@ -120,6 +124,7 @@ void amiga_chip_free(void *ptr)
120 } 124 }
121 printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr); 125 printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
122} 126}
127EXPORT_SYMBOL(amiga_chip_free);
123 128
124 129
125unsigned long amiga_chip_avail(void) 130unsigned long amiga_chip_avail(void)
@@ -129,3 +134,5 @@ unsigned long amiga_chip_avail(void)
129#endif 134#endif
130 return chipavail; 135 return chipavail;
131} 136}
137EXPORT_SYMBOL(amiga_chip_avail);
138
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 35748531327d..50f5daab46b7 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -23,6 +23,7 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/zorro.h> 25#include <linux/zorro.h>
26#include <linux/module.h>
26 27
27#include <asm/bootinfo.h> 28#include <asm/bootinfo.h>
28#include <asm/setup.h> 29#include <asm/setup.h>
@@ -36,13 +37,24 @@
36#include <asm/io.h> 37#include <asm/io.h>
37 38
38unsigned long amiga_model; 39unsigned long amiga_model;
40EXPORT_SYMBOL(amiga_model);
41
39unsigned long amiga_eclock; 42unsigned long amiga_eclock;
43EXPORT_SYMBOL(amiga_eclock);
44
40unsigned long amiga_masterclock; 45unsigned long amiga_masterclock;
46
41unsigned long amiga_colorclock; 47unsigned long amiga_colorclock;
48EXPORT_SYMBOL(amiga_colorclock);
49
42unsigned long amiga_chipset; 50unsigned long amiga_chipset;
51EXPORT_SYMBOL(amiga_chipset);
52
43unsigned char amiga_vblank; 53unsigned char amiga_vblank;
44unsigned char amiga_psfreq; 54unsigned char amiga_psfreq;
55
45struct amiga_hw_present amiga_hw_present; 56struct amiga_hw_present amiga_hw_present;
57EXPORT_SYMBOL(amiga_hw_present);
46 58
47static char s_a500[] __initdata = "A500"; 59static char s_a500[] __initdata = "A500";
48static char s_a500p[] __initdata = "A500+"; 60static char s_a500p[] __initdata = "A500+";
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index 186662ca1a89..7106f0c3639b 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -15,6 +15,8 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/jiffies.h> 16#include <linux/jiffies.h>
17#include <linux/timer.h> 17#include <linux/timer.h>
18#include <linux/module.h>
19
18#include <asm/amigayle.h> 20#include <asm/amigayle.h>
19#include <asm/amipcmcia.h> 21#include <asm/amipcmcia.h>
20 22
@@ -30,6 +32,7 @@ void pcmcia_reset(void)
30 while (time_before(jiffies, reset_start_time + 1*HZ/100)); 32 while (time_before(jiffies, reset_start_time + 1*HZ/100));
31 b = gayle_reset; 33 b = gayle_reset;
32} 34}
35EXPORT_SYMBOL(pcmcia_reset);
33 36
34 37
35/* copy a tuple, including tuple header. return nb bytes copied */ 38/* 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)
61 64
62 return 0; 65 return 0;
63} 66}
67EXPORT_SYMBOL(pcmcia_copy_tuple);
64 68
65void pcmcia_program_voltage(int voltage) 69void pcmcia_program_voltage(int voltage)
66{ 70{
@@ -84,6 +88,7 @@ void pcmcia_program_voltage(int voltage)
84 gayle.config = cfg_byte; 88 gayle.config = cfg_byte;
85 89
86} 90}
91EXPORT_SYMBOL(pcmcia_program_voltage);
87 92
88void pcmcia_access_speed(int speed) 93void pcmcia_access_speed(int speed)
89{ 94{
@@ -101,13 +106,17 @@ void pcmcia_access_speed(int speed)
101 cfg_byte = (cfg_byte & 0xf3) | s; 106 cfg_byte = (cfg_byte & 0xf3) | s;
102 gayle.config = cfg_byte; 107 gayle.config = cfg_byte;
103} 108}
109EXPORT_SYMBOL(pcmcia_access_speed);
104 110
105void pcmcia_write_enable(void) 111void pcmcia_write_enable(void)
106{ 112{
107 gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA; 113 gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
108} 114}
115EXPORT_SYMBOL(pcmcia_write_enable);
109 116
110void pcmcia_write_disable(void) 117void pcmcia_write_disable(void)
111{ 118{
112 gayle.cardstatus = 0; 119 gayle.cardstatus = 0;
113} 120}
121EXPORT_SYMBOL(pcmcia_write_disable);
122
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 2cb86191f0aa..2cd905efe63a 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-y := config.o time.o debug.o ataints.o stdma.o \ 5obj-y := config.o time.o debug.o ataints.o stdma.o \
6 atasound.o stram.o atari_ksyms.o 6 atasound.o stram.o
7 7
8ifeq ($(CONFIG_PCI),y) 8ifeq ($(CONFIG_PCI),y)
9obj-$(CONFIG_HADES) += hades-pci.o 9obj-$(CONFIG_HADES) += hades-pci.o
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index b85ca22024c1..b45593a60bdd 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,6 +40,7 @@
40#include <linux/kernel_stat.h> 40#include <linux/kernel_stat.h>
41#include <linux/init.h> 41#include <linux/init.h>
42#include <linux/seq_file.h> 42#include <linux/seq_file.h>
43#include <linux/module.h>
43 44
44#include <asm/system.h> 45#include <asm/system.h>
45#include <asm/traps.h> 46#include <asm/traps.h>
@@ -446,6 +447,7 @@ unsigned long atari_register_vme_int(void)
446 free_vme_vec_bitmap |= 1 << i; 447 free_vme_vec_bitmap |= 1 << i;
447 return VME_SOURCE_BASE + i; 448 return VME_SOURCE_BASE + i;
448} 449}
450EXPORT_SYMBOL(atari_register_vme_int);
449 451
450 452
451void atari_unregister_vme_int(unsigned long irq) 453void atari_unregister_vme_int(unsigned long irq)
@@ -455,5 +457,6 @@ void atari_unregister_vme_int(unsigned long irq)
455 free_vme_vec_bitmap &= ~(1 << irq); 457 free_vme_vec_bitmap &= ~(1 << irq);
456 } 458 }
457} 459}
460EXPORT_SYMBOL(atari_unregister_vme_int);
458 461
459 462
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
deleted file mode 100644
index a04757151538..000000000000
--- a/arch/m68k/atari/atari_ksyms.c
+++ /dev/null
@@ -1,35 +0,0 @@
1#include <linux/module.h>
2
3#include <asm/ptrace.h>
4#include <asm/traps.h>
5#include <asm/atarihw.h>
6#include <asm/atariints.h>
7#include <asm/atarikb.h>
8#include <asm/atari_joystick.h>
9#include <asm/atari_stdma.h>
10#include <asm/atari_stram.h>
11
12extern void atari_microwire_cmd( int cmd );
13extern int atari_MFP_init_done;
14extern int atari_SCC_init_done;
15extern int atari_SCC_reset_done;
16
17EXPORT_SYMBOL(atari_mch_cookie);
18EXPORT_SYMBOL(atari_mch_type);
19EXPORT_SYMBOL(atari_hw_present);
20EXPORT_SYMBOL(atari_switches);
21EXPORT_SYMBOL(atari_dont_touch_floppy_select);
22EXPORT_SYMBOL(atari_register_vme_int);
23EXPORT_SYMBOL(atari_unregister_vme_int);
24EXPORT_SYMBOL(stdma_lock);
25EXPORT_SYMBOL(stdma_release);
26EXPORT_SYMBOL(stdma_others_waiting);
27EXPORT_SYMBOL(stdma_islocked);
28EXPORT_SYMBOL(atari_stram_alloc);
29EXPORT_SYMBOL(atari_stram_free);
30
31EXPORT_SYMBOL(atari_MFP_init_done);
32EXPORT_SYMBOL(atari_SCC_init_done);
33EXPORT_SYMBOL(atari_SCC_reset_done);
34
35EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index ee04250eb56b..d266fe89c125 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -22,6 +22,7 @@
22#include <linux/fcntl.h> 22#include <linux/fcntl.h>
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/mm.h> 24#include <linux/mm.h>
25#include <linux/module.h>
25 26
26#include <asm/atarihw.h> 27#include <asm/atarihw.h>
27#include <asm/system.h> 28#include <asm/system.h>
@@ -43,6 +44,7 @@ void atari_microwire_cmd (int cmd)
43 while( tt_microwire.mask != 0x7ff) 44 while( tt_microwire.mask != 0x7ff)
44 ; 45 ;
45} 46}
47EXPORT_SYMBOL(atari_microwire_cmd);
46 48
47 49
48/* PSG base frequency */ 50/* PSG base frequency */
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index e40e5dcaa347..5945e1505558 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -31,6 +31,7 @@
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/ioport.h> 32#include <linux/ioport.h>
33#include <linux/vt_kern.h> 33#include <linux/vt_kern.h>
34#include <linux/module.h>
34 35
35#include <asm/bootinfo.h> 36#include <asm/bootinfo.h>
36#include <asm/setup.h> 37#include <asm/setup.h>
@@ -43,10 +44,20 @@
43#include <asm/io.h> 44#include <asm/io.h>
44 45
45u_long atari_mch_cookie; 46u_long atari_mch_cookie;
47EXPORT_SYMBOL(atari_mch_cookie);
48
46u_long atari_mch_type; 49u_long atari_mch_type;
50EXPORT_SYMBOL(atari_mch_type);
51
47struct atari_hw_present atari_hw_present; 52struct atari_hw_present atari_hw_present;
53EXPORT_SYMBOL(atari_hw_present);
54
48u_long atari_switches; 55u_long atari_switches;
56EXPORT_SYMBOL(atari_switches);
57
49int atari_dont_touch_floppy_select; 58int atari_dont_touch_floppy_select;
59EXPORT_SYMBOL(atari_dont_touch_floppy_select);
60
50int atari_rtc_year_offset; 61int atari_rtc_year_offset;
51 62
52/* local function prototypes */ 63/* local function prototypes */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index fbeed8c8ecbc..043ddbc61c7b 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -15,17 +15,23 @@
15#include <linux/console.h> 15#include <linux/console.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/module.h>
18 19
19#include <asm/atarihw.h> 20#include <asm/atarihw.h>
20#include <asm/atariints.h> 21#include <asm/atariints.h>
21 22
22/* Flag that Modem1 port is already initialized and used */ 23/* Flag that Modem1 port is already initialized and used */
23int atari_MFP_init_done; 24int atari_MFP_init_done;
25EXPORT_SYMBOL(atari_MFP_init_done);
26
24/* Flag that Modem1 port is already initialized and used */ 27/* Flag that Modem1 port is already initialized and used */
25int atari_SCC_init_done; 28int atari_SCC_init_done;
29EXPORT_SYMBOL(atari_SCC_init_done);
30
26/* Can be set somewhere, if a SCC master reset has already be done and should 31/* Can be set somewhere, if a SCC master reset has already be done and should
27 * not be repeated; used by kgdb */ 32 * not be repeated; used by kgdb */
28int atari_SCC_reset_done; 33int atari_SCC_reset_done;
34EXPORT_SYMBOL(atari_SCC_reset_done);
29 35
30static struct console atari_console_driver = { 36static struct console atari_console_driver = {
31 .name = "debug", 37 .name = "debug",
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
index bee2b1443e36..2bbabc008708 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)
376 */ 376 */
377 377
378 bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL); 378 bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
379 if (!bus) 379 if (unlikely(!bus))
380 return NULL; 380 goto iounmap_base_virt;
381 381
382 /* 382 /*
383 * Claim resources. The m68k has no separate I/O space, both 383 * Claim resources. The m68k has no separate I/O space, both
@@ -385,43 +385,25 @@ struct pci_bus_info * __init init_hades_pci(void)
385 * the I/O resources are requested in memory space as well. 385 * the I/O resources are requested in memory space as well.
386 */ 386 */
387 387
388 if (request_resource(&iomem_resource, &config_space) != 0) 388 if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
389 { 389 goto free_bus;
390 kfree(bus);
391 return NULL;
392 }
393 390
394 if (request_resource(&iomem_resource, &io_space) != 0) 391 if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
395 { 392 goto release_config_space;
396 release_resource(&config_space);
397 kfree(bus);
398 return NULL;
399 }
400 393
401 bus->mem_space.start = HADES_MEM_BASE; 394 bus->mem_space.start = HADES_MEM_BASE;
402 bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1; 395 bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
403 bus->mem_space.name = pci_mem_name; 396 bus->mem_space.name = pci_mem_name;
404#if 1 397#if 1
405 if (request_resource(&iomem_resource, &bus->mem_space) != 0) 398 if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
406 { 399 goto release_io_space;
407 release_resource(&io_space);
408 release_resource(&config_space);
409 kfree(bus);
410 return NULL;
411 }
412#endif 400#endif
413 bus->io_space.start = pci_io_base_virt; 401 bus->io_space.start = pci_io_base_virt;
414 bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1; 402 bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
415 bus->io_space.name = pci_io_name; 403 bus->io_space.name = pci_io_name;
416#if 1 404#if 1
417 if (request_resource(&ioport_resource, &bus->io_space) != 0) 405 if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
418 { 406 goto release_bus_mem_space;
419 release_resource(&bus->mem_space);
420 release_resource(&io_space);
421 release_resource(&config_space);
422 kfree(bus);
423 return NULL;
424 }
425#endif 407#endif
426 /* 408 /*
427 * Set hardware dependent functions. 409 * Set hardware dependent functions.
@@ -438,5 +420,21 @@ struct pci_bus_info * __init init_hades_pci(void)
438 tt_mfp.active_edge &= ~0x27; 420 tt_mfp.active_edge &= ~0x27;
439 421
440 return bus; 422 return bus;
423
424release_bus_mem_space:
425 release_resource(&bus->mem_space);
426release_io_space:
427 release_resource(&io_space);
428release_config_space:
429 release_resource(&config_space);
430free_bus:
431 kfree(bus);
432iounmap_base_virt:
433 iounmap((void *)pci_io_base_virt);
434
435 for (i = 0; i < N_SLOTS; i++)
436 iounmap((void *)pci_conf_base_virt[i]);
437
438 return NULL;
441} 439}
442#endif 440#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ab3fd5202b24..d1bd029a34ac 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -35,6 +35,7 @@
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/interrupt.h> 36#include <linux/interrupt.h>
37#include <linux/wait.h> 37#include <linux/wait.h>
38#include <linux/module.h>
38 39
39#include <asm/atari_stdma.h> 40#include <asm/atari_stdma.h>
40#include <asm/atariints.h> 41#include <asm/atariints.h>
@@ -91,6 +92,7 @@ void stdma_lock(irq_handler_t handler, void *data)
91 stdma_isr_data = data; 92 stdma_isr_data = data;
92 local_irq_restore(flags); 93 local_irq_restore(flags);
93} 94}
95EXPORT_SYMBOL(stdma_lock);
94 96
95 97
96/* 98/*
@@ -117,6 +119,7 @@ void stdma_release(void)
117 119
118 local_irq_restore(flags); 120 local_irq_restore(flags);
119} 121}
122EXPORT_SYMBOL(stdma_release);
120 123
121 124
122/* 125/*
@@ -134,6 +137,7 @@ int stdma_others_waiting(void)
134{ 137{
135 return waitqueue_active(&stdma_wait); 138 return waitqueue_active(&stdma_wait);
136} 139}
140EXPORT_SYMBOL(stdma_others_waiting);
137 141
138 142
139/* 143/*
@@ -155,6 +159,7 @@ int stdma_islocked(void)
155{ 159{
156 return stdma_locked; 160 return stdma_locked;
157} 161}
162EXPORT_SYMBOL(stdma_islocked);
158 163
159 164
160/* 165/*
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index bf4588cbe371..8dda6515887a 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
20#include <linux/bootmem.h> 20#include <linux/bootmem.h>
21#include <linux/mount.h> 21#include <linux/mount.h>
22#include <linux/blkdev.h> 22#include <linux/blkdev.h>
23#include <linux/module.h>
23 24
24#include <asm/setup.h> 25#include <asm/setup.h>
25#include <asm/machdep.h> 26#include <asm/machdep.h>
@@ -208,6 +209,7 @@ void *atari_stram_alloc(long size, const char *owner)
208 } 209 }
209 return( addr ); 210 return( addr );
210} 211}
212EXPORT_SYMBOL(atari_stram_alloc);
211 213
212void atari_stram_free( void *addr ) 214void atari_stram_free( void *addr )
213 215
@@ -237,6 +239,7 @@ void atari_stram_free( void *addr )
237 printk( KERN_ERR "atari_stram_free: cannot free block at %p " 239 printk( KERN_ERR "atari_stram_free: cannot free block at %p "
238 "(called from %p)\n", addr, __builtin_return_address(0) ); 240 "(called from %p)\n", addr, __builtin_return_address(0) );
239} 241}
242EXPORT_SYMBOL(atari_stram_free);
240 243
241 244
242/* ------------------------------------------------------------------------ */ 245/* ------------------------------------------------------------------------ */
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 15b80abfe94a..ff9dffa5b860 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -678,7 +678,6 @@ CONFIG_LOGO_MAC_CLUT224=y
678# 678#
679CONFIG_MAC_SCC=y 679CONFIG_MAC_SCC=y
680CONFIG_MAC_HID=y 680CONFIG_MAC_HID=y
681CONFIG_MAC_ADBKEYCODES=y
682CONFIG_SERIAL_CONSOLE=y 681CONFIG_SERIAL_CONSOLE=y
683 682
684# 683#
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
index 288b9c67c9bf..96d4244c82fd 100644
--- a/arch/m68k/hp300/Makefile
+++ b/arch/m68k/hp300/Makefile
@@ -2,4 +2,4 @@
2# Makefile for Linux arch/m68k/hp300 source directory 2# Makefile for Linux arch/m68k/hp300 source directory
3# 3#
4 4
5obj-y := ksyms.o config.o time.o reboot.o 5obj-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 8202830763d1..000000000000
--- a/arch/m68k/hp300/ksyms.c
+++ /dev/null
@@ -1,9 +0,0 @@
1/*
2 * linux/arch/m68k/hp300/ksyms.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific kernel symbols. None yet. :-)
7 */
8
9#include <linux/module.h>
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 918f5dbeaef6..6dfa3b3c0e2a 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -742,7 +742,7 @@ sys_call_table:
742 .long sys_epoll_pwait /* 315 */ 742 .long sys_epoll_pwait /* 315 */
743 .long sys_utimensat 743 .long sys_utimensat
744 .long sys_signalfd 744 .long sys_signalfd
745 .long sys_timerfd 745 .long sys_ni_syscall
746 .long sys_eventfd 746 .long sys_eventfd
747 .long sys_fallocate /* 320 */ 747 .long sys_fallocate /* 320 */
748 748
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 995a09d912f5..1d265ba365ad 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -3,4 +3,4 @@
3# 3#
4 4
5obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \ 5obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
6 baboon.o macboing.o debug.o misc.o mac_ksyms.o 6 baboon.o macboing.o debug.o misc.o
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 01b468b9392e..735a49b4b936 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];
58 58
59extern struct mem_info m68k_ramdisk; 59extern struct mem_info m68k_ramdisk;
60 60
61extern char m68k_command_line[CL_SIZE];
62
63void *mac_env; /* Loaded by the boot asm */ 61void *mac_env; /* Loaded by the boot asm */
64 62
65/* The phys. video addr. - might be bogus on some machines */ 63/* 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 6e37ceb0f3b5..000000000000
--- a/arch/m68k/mac/mac_ksyms.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <linux/module.h>
2#include <asm/ptrace.h>
3#include <asm/traps.h>
4
5/* Says whether we're using A/UX interrupts or not */
6extern int via_alt_mapping;
7
8EXPORT_SYMBOL(via_alt_mapping);
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 8df270e950fa..fa485df4160e 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -28,6 +28,7 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/ide.h> 30#include <linux/ide.h>
31#include <linux/module.h>
31 32
32#include <asm/bootinfo.h> 33#include <asm/bootinfo.h>
33#include <asm/macintosh.h> 34#include <asm/macintosh.h>
@@ -41,7 +42,9 @@ volatile __u8 *via1, *via2;
41/* See note in mac_via.h about how this is possibly not useful */ 42/* See note in mac_via.h about how this is possibly not useful */
42volatile long *via_memory_bogon=(long *)&via_memory_bogon; 43volatile long *via_memory_bogon=(long *)&via_memory_bogon;
43#endif 44#endif
44int rbv_present, via_alt_mapping; 45int rbv_present;
46int via_alt_mapping;
47EXPORT_SYMBOL(via_alt_mapping);
45__u8 rbv_clear; 48__u8 rbv_clear;
46 49
47/* 50/*
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 950e82f21640..edb3f6e6ee6a 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -2,4 +2,4 @@
2# Makefile for Linux arch/m68k/mvme16x source directory 2# Makefile for Linux arch/m68k/mvme16x source directory
3# 3#
4 4
5obj-y := config.o rtc.o mvme16x_ksyms.o 5obj-y := config.o rtc.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index daa785161401..24cbc3030454 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -25,6 +25,7 @@
25#include <linux/genhd.h> 25#include <linux/genhd.h>
26#include <linux/rtc.h> 26#include <linux/rtc.h>
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/module.h>
28 29
29#include <asm/bootinfo.h> 30#include <asm/bootinfo.h>
30#include <asm/system.h> 31#include <asm/system.h>
@@ -58,6 +59,7 @@ static irq_handler_t tick_handler;
58 59
59 60
60unsigned short mvme16x_config; 61unsigned short mvme16x_config;
62EXPORT_SYMBOL(mvme16x_config);
61 63
62 64
63int mvme16x_parse_bootinfo(const struct bi_record *bi) 65int 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 4a8a3634bb47..000000000000
--- a/arch/m68k/mvme16x/mvme16x_ksyms.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <linux/module.h>
2#include <linux/types.h>
3#include <asm/ptrace.h>
4#include <asm/mvme16xhw.h>
5
6EXPORT_SYMBOL(mvme16x_config);
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
index 9ff47bd09aee..ed6d9a83bfdb 100644
--- a/arch/m68knommu/Kconfig.debug
+++ b/arch/m68knommu/Kconfig.debug
@@ -21,13 +21,6 @@ config BOOTPARAM_STRING
21 default 'console=ttyS0,19200' 21 default 'console=ttyS0,19200'
22 depends on BOOTPARAM 22 depends on BOOTPARAM
23 23
24config DUMPTOFLASH
25 bool "Panic/Dump to FLASH"
26 depends on COLDFIRE
27 help
28 Dump any panic of trap output into a flash memory segment
29 for later analysis.
30
31config NO_KERNEL_MSG 24config NO_KERNEL_MSG
32 bool "Suppress Kernel BUG Messages" 25 bool "Suppress Kernel BUG Messages"
33 help 26 help
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 5a0ecaaee3b0..648113075f97 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -597,7 +597,6 @@ CONFIG_MSDOS_PARTITION=y
597# CONFIG_FULLDEBUG is not set 597# CONFIG_FULLDEBUG is not set
598# CONFIG_HIGHPROFILE is not set 598# CONFIG_HIGHPROFILE is not set
599# CONFIG_BOOTPARAM is not set 599# CONFIG_BOOTPARAM is not set
600# CONFIG_DUMPTOFLASH is not set
601# CONFIG_NO_KERNEL_MSG is not set 600# CONFIG_NO_KERNEL_MSG is not set
602# CONFIG_BDM_DISABLE is not set 601# CONFIG_BDM_DISABLE is not set
603 602
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f795062aba1e..53fad1490282 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 *);
24EXPORT_SYMBOL(__ioremap); 24EXPORT_SYMBOL(__ioremap);
25EXPORT_SYMBOL(iounmap); 25EXPORT_SYMBOL(iounmap);
26EXPORT_SYMBOL(dump_fpu); 26EXPORT_SYMBOL(dump_fpu);
27EXPORT_SYMBOL(strnlen);
28EXPORT_SYMBOL(strrchr);
29EXPORT_SYMBOL(strstr);
30EXPORT_SYMBOL(strchr);
31EXPORT_SYMBOL(strcat);
32EXPORT_SYMBOL(strlen);
33EXPORT_SYMBOL(strcmp);
34EXPORT_SYMBOL(strncmp);
35 27
36EXPORT_SYMBOL(ip_fast_csum); 28EXPORT_SYMBOL(ip_fast_csum);
37 29
@@ -46,9 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
46 it's OK to leave it out of version control. */ 38 it's OK to leave it out of version control. */
47EXPORT_SYMBOL(memcpy); 39EXPORT_SYMBOL(memcpy);
48EXPORT_SYMBOL(memset); 40EXPORT_SYMBOL(memset);
49EXPORT_SYMBOL(memcmp);
50EXPORT_SYMBOL(memscan);
51EXPORT_SYMBOL(memmove);
52 41
53EXPORT_SYMBOL(__down_failed); 42EXPORT_SYMBOL(__down_failed);
54EXPORT_SYMBOL(__down_failed_interruptible); 43EXPORT_SYMBOL(__down_failed_interruptible);
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 332345d7675d..81507c53d4a9 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -64,9 +64,6 @@ void (*mach_power_off)(void);
64#ifdef CONFIG_M68VZ328 64#ifdef CONFIG_M68VZ328
65 #define CPU "MC68VZ328" 65 #define CPU "MC68VZ328"
66#endif 66#endif
67#ifdef CONFIG_M68332
68 #define CPU "MC68332"
69#endif
70#ifdef CONFIG_M68360 67#ifdef CONFIG_M68360
71 #define CPU "MC68360" 68 #define CPU "MC68360"
72#endif 69#endif
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 9620093514bc..1b02b8820068 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -336,7 +336,7 @@ ENTRY(sys_call_table)
336 .long sys_epoll_pwait /* 315 */ 336 .long sys_epoll_pwait /* 315 */
337 .long sys_utimensat 337 .long sys_utimensat
338 .long sys_signalfd 338 .long sys_signalfd
339 .long sys_timerfd 339 .long sys_ni_syscall
340 .long sys_eventfd 340 .long sys_eventfd
341 .long sys_fallocate /* 320 */ 341 .long sys_fallocate /* 320 */
342 342
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 82480a1717d8..f798139e888e 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -660,7 +660,7 @@ einval: li v0, -EINVAL
660 sys sys_ioprio_get 2 /* 4315 */ 660 sys sys_ioprio_get 2 /* 4315 */
661 sys sys_utimensat 4 661 sys sys_utimensat 4
662 sys sys_signalfd 3 662 sys sys_signalfd 3
663 sys sys_timerfd 4 663 sys sys_ni_syscall 0
664 sys sys_eventfd 1 664 sys sys_eventfd 1
665 sys sys_fallocate 6 /* 4320 */ 665 sys sys_fallocate 6 /* 4320 */
666 .endm 666 .endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index c2c10876da2e..a626be6baea3 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -475,7 +475,7 @@ sys_call_table:
475 PTR sys_ioprio_get 475 PTR sys_ioprio_get
476 PTR sys_utimensat /* 5275 */ 476 PTR sys_utimensat /* 5275 */
477 PTR sys_signalfd 477 PTR sys_signalfd
478 PTR sys_timerfd 478 PTR sys_ni_syscall
479 PTR sys_eventfd 479 PTR sys_eventfd
480 PTR sys_fallocate 480 PTR sys_fallocate
481 .size sys_call_table,.-sys_call_table 481 .size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 01993ec3368b..9d5bcaf1b389 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -401,7 +401,7 @@ EXPORT(sysn32_call_table)
401 PTR sys_ioprio_get 401 PTR sys_ioprio_get
402 PTR compat_sys_utimensat 402 PTR compat_sys_utimensat
403 PTR compat_sys_signalfd /* 5280 */ 403 PTR compat_sys_signalfd /* 5280 */
404 PTR compat_sys_timerfd 404 PTR sys_ni_syscall
405 PTR sys_eventfd 405 PTR sys_eventfd
406 PTR sys_fallocate 406 PTR sys_fallocate
407 .size sysn32_call_table,.-sysn32_call_table 407 .size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index dd68afce7da5..fd2019c1ec2d 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -523,7 +523,7 @@ sys_call_table:
523 PTR sys_ioprio_get /* 4315 */ 523 PTR sys_ioprio_get /* 4315 */
524 PTR compat_sys_utimensat 524 PTR compat_sys_utimensat
525 PTR compat_sys_signalfd 525 PTR compat_sys_signalfd
526 PTR compat_sys_timerfd 526 PTR sys_ni_syscall
527 PTR sys_eventfd 527 PTR sys_eventfd
528 PTR sys32_fallocate /* 4320 */ 528 PTR sys32_fallocate /* 4320 */
529 .size sys_call_table,.-sys_call_table 529 .size sys_call_table,.-sys_call_table
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b94d4502a477..cf030b004415 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -256,6 +256,9 @@ config IOMMU_VMERGE
256 256
257 Most drivers don't have this problem; it is safe to say Y here. 257 Most drivers don't have this problem; it is safe to say Y here.
258 258
259config IOMMU_HELPER
260 def_bool PPC64
261
259config HOTPLUG_CPU 262config HOTPLUG_CPU
260 bool "Support for enabling/disabling CPUs" 263 bool "Support for enabling/disabling CPUs"
261 depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC) 264 depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 84239076a5b8..3a317cb0636a 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)
31static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, 31static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
32 dma_addr_t *dma_handle, gfp_t flag) 32 dma_addr_t *dma_handle, gfp_t flag)
33{ 33{
34 return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle, 34 return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
35 device_to_mask(dev), flag, 35 dma_handle, device_to_mask(dev), flag,
36 dev->archdata.numa_node); 36 dev->archdata.numa_node);
37} 37}
38 38
@@ -52,7 +52,7 @@ static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
52 size_t size, 52 size_t size,
53 enum dma_data_direction direction) 53 enum dma_data_direction direction)
54{ 54{
55 return iommu_map_single(dev->archdata.dma_data, vaddr, size, 55 return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
56 device_to_mask(dev), direction); 56 device_to_mask(dev), direction);
57} 57}
58 58
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
68static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, 68static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
69 int nelems, enum dma_data_direction direction) 69 int nelems, enum dma_data_direction direction)
70{ 70{
71 return iommu_map_sg(dev->archdata.dma_data, sglist, nelems, 71 return iommu_map_sg(dev, sglist, nelems,
72 device_to_mask(dev), direction); 72 device_to_mask(dev), direction);
73} 73}
74 74
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a3c406aca664..8f1f4e539c4b 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -31,6 +31,7 @@
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/dma-mapping.h> 32#include <linux/dma-mapping.h>
33#include <linux/bitops.h> 33#include <linux/bitops.h>
34#include <linux/iommu-helper.h>
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/prom.h> 36#include <asm/prom.h>
36#include <asm/iommu.h> 37#include <asm/iommu.h>
@@ -81,17 +82,19 @@ static int __init setup_iommu(char *str)
81__setup("protect4gb=", setup_protect4gb); 82__setup("protect4gb=", setup_protect4gb);
82__setup("iommu=", setup_iommu); 83__setup("iommu=", setup_iommu);
83 84
84static unsigned long iommu_range_alloc(struct iommu_table *tbl, 85static unsigned long iommu_range_alloc(struct device *dev,
86 struct iommu_table *tbl,
85 unsigned long npages, 87 unsigned long npages,
86 unsigned long *handle, 88 unsigned long *handle,
87 unsigned long mask, 89 unsigned long mask,
88 unsigned int align_order) 90 unsigned int align_order)
89{ 91{
90 unsigned long n, end, i, start; 92 unsigned long n, end, start;
91 unsigned long limit; 93 unsigned long limit;
92 int largealloc = npages > 15; 94 int largealloc = npages > 15;
93 int pass = 0; 95 int pass = 0;
94 unsigned long align_mask; 96 unsigned long align_mask;
97 unsigned long boundary_size;
95 98
96 align_mask = 0xffffffffffffffffl >> (64 - align_order); 99 align_mask = 0xffffffffffffffffl >> (64 - align_order);
97 100
@@ -136,14 +139,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
136 start &= mask; 139 start &= mask;
137 } 140 }
138 141
139 n = find_next_zero_bit(tbl->it_map, limit, start); 142 if (dev)
140 143 boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
141 /* Align allocation */ 144 1 << IOMMU_PAGE_SHIFT);
142 n = (n + align_mask) & ~align_mask; 145 else
143 146 boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
144 end = n + npages; 147 /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
145 148
146 if (unlikely(end >= limit)) { 149 n = iommu_area_alloc(tbl->it_map, limit, start, npages,
150 tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
151 align_mask);
152 if (n == -1) {
147 if (likely(pass < 2)) { 153 if (likely(pass < 2)) {
148 /* First failure, just rescan the half of the table. 154 /* First failure, just rescan the half of the table.
149 * Second failure, rescan the other half of the table. 155 * Second failure, rescan the other half of the table.
@@ -158,14 +164,7 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
158 } 164 }
159 } 165 }
160 166
161 for (i = n; i < end; i++) 167 end = n + npages;
162 if (test_bit(i, tbl->it_map)) {
163 start = i+1;
164 goto again;
165 }
166
167 for (i = n; i < end; i++)
168 __set_bit(i, tbl->it_map);
169 168
170 /* Bump the hint to a new block for small allocs. */ 169 /* Bump the hint to a new block for small allocs. */
171 if (largealloc) { 170 if (largealloc) {
@@ -184,16 +183,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
184 return n; 183 return n;
185} 184}
186 185
187static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, 186static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
188 unsigned int npages, enum dma_data_direction direction, 187 void *page, unsigned int npages,
189 unsigned long mask, unsigned int align_order) 188 enum dma_data_direction direction,
189 unsigned long mask, unsigned int align_order)
190{ 190{
191 unsigned long entry, flags; 191 unsigned long entry, flags;
192 dma_addr_t ret = DMA_ERROR_CODE; 192 dma_addr_t ret = DMA_ERROR_CODE;
193 193
194 spin_lock_irqsave(&(tbl->it_lock), flags); 194 spin_lock_irqsave(&(tbl->it_lock), flags);
195 195
196 entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order); 196 entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
197 197
198 if (unlikely(entry == DMA_ERROR_CODE)) { 198 if (unlikely(entry == DMA_ERROR_CODE)) {
199 spin_unlock_irqrestore(&(tbl->it_lock), flags); 199 spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -224,7 +224,6 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
224 unsigned int npages) 224 unsigned int npages)
225{ 225{
226 unsigned long entry, free_entry; 226 unsigned long entry, free_entry;
227 unsigned long i;
228 227
229 entry = dma_addr >> IOMMU_PAGE_SHIFT; 228 entry = dma_addr >> IOMMU_PAGE_SHIFT;
230 free_entry = entry - tbl->it_offset; 229 free_entry = entry - tbl->it_offset;
@@ -246,9 +245,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
246 } 245 }
247 246
248 ppc_md.tce_free(tbl, entry, npages); 247 ppc_md.tce_free(tbl, entry, npages);
249 248 iommu_area_free(tbl->it_map, free_entry, npages);
250 for (i = 0; i < npages; i++)
251 __clear_bit(free_entry+i, tbl->it_map);
252} 249}
253 250
254static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, 251static 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,
270 spin_unlock_irqrestore(&(tbl->it_lock), flags); 267 spin_unlock_irqrestore(&(tbl->it_lock), flags);
271} 268}
272 269
273int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, 270int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
274 int nelems, unsigned long mask, 271 int nelems, unsigned long mask,
275 enum dma_data_direction direction) 272 enum dma_data_direction direction)
276{ 273{
274 struct iommu_table *tbl = dev->archdata.dma_data;
277 dma_addr_t dma_next = 0, dma_addr; 275 dma_addr_t dma_next = 0, dma_addr;
278 unsigned long flags; 276 unsigned long flags;
279 struct scatterlist *s, *outs, *segstart; 277 struct scatterlist *s, *outs, *segstart;
280 int outcount, incount, i; 278 int outcount, incount, i;
281 unsigned int align; 279 unsigned int align;
282 unsigned long handle; 280 unsigned long handle;
281 unsigned int max_seg_size;
283 282
284 BUG_ON(direction == DMA_NONE); 283 BUG_ON(direction == DMA_NONE);
285 284
@@ -298,6 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
298 297
299 spin_lock_irqsave(&(tbl->it_lock), flags); 298 spin_lock_irqsave(&(tbl->it_lock), flags);
300 299
300 max_seg_size = dma_get_max_seg_size(dev);
301 for_each_sg(sglist, s, nelems, i) { 301 for_each_sg(sglist, s, nelems, i) {
302 unsigned long vaddr, npages, entry, slen; 302 unsigned long vaddr, npages, entry, slen;
303 303
@@ -314,7 +314,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
314 if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE && 314 if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
315 (vaddr & ~PAGE_MASK) == 0) 315 (vaddr & ~PAGE_MASK) == 0)
316 align = PAGE_SHIFT - IOMMU_PAGE_SHIFT; 316 align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
317 entry = iommu_range_alloc(tbl, npages, &handle, 317 entry = iommu_range_alloc(dev, tbl, npages, &handle,
318 mask >> IOMMU_PAGE_SHIFT, align); 318 mask >> IOMMU_PAGE_SHIFT, align);
319 319
320 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); 320 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -344,7 +344,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
344 /* We cannot merge if: 344 /* We cannot merge if:
345 * - allocated dma_addr isn't contiguous to previous allocation 345 * - allocated dma_addr isn't contiguous to previous allocation
346 */ 346 */
347 if (novmerge || (dma_addr != dma_next)) { 347 if (novmerge || (dma_addr != dma_next) ||
348 (outs->dma_length + s->length > max_seg_size)) {
348 /* Can't merge: create a new segment */ 349 /* Can't merge: create a new segment */
349 segstart = s; 350 segstart = s;
350 outcount++; 351 outcount++;
@@ -452,9 +453,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
452struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) 453struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
453{ 454{
454 unsigned long sz; 455 unsigned long sz;
455 unsigned long start_index, end_index;
456 unsigned long entries_per_4g;
457 unsigned long index;
458 static int welcomed = 0; 456 static int welcomed = 0;
459 struct page *page; 457 struct page *page;
460 458
@@ -476,6 +474,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
476 474
477#ifdef CONFIG_CRASH_DUMP 475#ifdef CONFIG_CRASH_DUMP
478 if (ppc_md.tce_get) { 476 if (ppc_md.tce_get) {
477 unsigned long index;
479 unsigned long tceval; 478 unsigned long tceval;
480 unsigned long tcecount = 0; 479 unsigned long tcecount = 0;
481 480
@@ -506,23 +505,6 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
506 ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); 505 ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
507#endif 506#endif
508 507
509 /*
510 * DMA cannot cross 4 GB boundary. Mark last entry of each 4
511 * GB chunk as reserved.
512 */
513 if (protect4gb) {
514 entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
515
516 /* Mark the last bit before a 4GB boundary as used */
517 start_index = tbl->it_offset | (entries_per_4g - 1);
518 start_index -= tbl->it_offset;
519
520 end_index = tbl->it_size;
521
522 for (index = start_index; index < end_index - 1; index += entries_per_4g)
523 __set_bit(index, tbl->it_map);
524 }
525
526 if (!welcomed) { 508 if (!welcomed) {
527 printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", 509 printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
528 novmerge ? "disabled" : "enabled"); 510 novmerge ? "disabled" : "enabled");
@@ -570,9 +552,9 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
570 * need not be page aligned, the dma_addr_t returned will point to the same 552 * need not be page aligned, the dma_addr_t returned will point to the same
571 * byte within the page as vaddr. 553 * byte within the page as vaddr.
572 */ 554 */
573dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 555dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
574 size_t size, unsigned long mask, 556 void *vaddr, size_t size, unsigned long mask,
575 enum dma_data_direction direction) 557 enum dma_data_direction direction)
576{ 558{
577 dma_addr_t dma_handle = DMA_ERROR_CODE; 559 dma_addr_t dma_handle = DMA_ERROR_CODE;
578 unsigned long uaddr; 560 unsigned long uaddr;
@@ -589,7 +571,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
589 ((unsigned long)vaddr & ~PAGE_MASK) == 0) 571 ((unsigned long)vaddr & ~PAGE_MASK) == 0)
590 align = PAGE_SHIFT - IOMMU_PAGE_SHIFT; 572 align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
591 573
592 dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 574 dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
593 mask >> IOMMU_PAGE_SHIFT, align); 575 mask >> IOMMU_PAGE_SHIFT, align);
594 if (dma_handle == DMA_ERROR_CODE) { 576 if (dma_handle == DMA_ERROR_CODE) {
595 if (printk_ratelimit()) { 577 if (printk_ratelimit()) {
@@ -621,8 +603,9 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
621 * Returns the virtual address of the buffer and sets dma_handle 603 * Returns the virtual address of the buffer and sets dma_handle
622 * to the dma address (mapping) of the first page. 604 * to the dma address (mapping) of the first page.
623 */ 605 */
624void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 606void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
625 dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node) 607 size_t size, dma_addr_t *dma_handle,
608 unsigned long mask, gfp_t flag, int node)
626{ 609{
627 void *ret = NULL; 610 void *ret = NULL;
628 dma_addr_t mapping; 611 dma_addr_t mapping;
@@ -656,7 +639,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
656 /* Set up tces to cover the allocated range */ 639 /* Set up tces to cover the allocated range */
657 nio_pages = size >> IOMMU_PAGE_SHIFT; 640 nio_pages = size >> IOMMU_PAGE_SHIFT;
658 io_order = get_iommu_order(size); 641 io_order = get_iommu_order(size);
659 mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL, 642 mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
660 mask >> IOMMU_PAGE_SHIFT, io_order); 643 mask >> IOMMU_PAGE_SHIFT, io_order);
661 if (mapping == DMA_ERROR_CODE) { 644 if (mapping == DMA_ERROR_CODE) {
662 free_pages((unsigned long)ret, order); 645 free_pages((unsigned long)ret, order);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 64488723162a..f80f90c4d58b 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)
86 return ret; 86 return ret;
87} 87}
88 88
89void pgd_free(pgd_t *pgd) 89void pgd_free(struct mm_struct *mm, pgd_t *pgd)
90{ 90{
91 free_pages((unsigned long)pgd, PGDIR_ORDER); 91 free_pages((unsigned long)pgd, PGDIR_ORDER);
92} 92}
@@ -123,7 +123,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
123 return ptepage; 123 return ptepage;
124} 124}
125 125
126void pte_free_kernel(pte_t *pte) 126void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
127{ 127{
128#ifdef CONFIG_SMP 128#ifdef CONFIG_SMP
129 hash_page_sync(); 129 hash_page_sync();
@@ -131,7 +131,7 @@ void pte_free_kernel(pte_t *pte)
131 free_page((unsigned long)pte); 131 free_page((unsigned long)pte);
132} 132}
133 133
134void pte_free(struct page *ptepage) 134void pte_free(struct mm_struct *mm, struct page *ptepage)
135{ 135{
136#ifdef CONFIG_SMP 136#ifdef CONFIG_SMP
137 hash_page_sync(); 137 hash_page_sync();
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 6a0c6f6675cd..11fa3c772ed5 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;
199 199
200void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag) 200void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
201{ 201{
202 return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle, 202 return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
203 DMA_32BIT_MASK, flag, -1); 203 DMA_32BIT_MASK, flag, -1);
204} 204}
205EXPORT_SYMBOL_GPL(iseries_hv_alloc); 205EXPORT_SYMBOL_GPL(iseries_hv_alloc);
@@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(iseries_hv_free);
213dma_addr_t iseries_hv_map(void *vaddr, size_t size, 213dma_addr_t iseries_hv_map(void *vaddr, size_t size,
214 enum dma_data_direction direction) 214 enum dma_data_direction direction)
215{ 215{
216 return iommu_map_single(&vio_iommu_table, vaddr, size, 216 return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
217 DMA_32BIT_MASK, direction); 217 DMA_32BIT_MASK, direction);
218} 218}
219 219
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index fadacfd18806..409fcaa4994a 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)
74 return ret; 74 return ret;
75} 75}
76 76
77void pgd_free(pgd_t *pgd) 77void pgd_free(struct mm_struct *mm, pgd_t *pgd)
78{ 78{
79 free_pages((unsigned long)pgd, PGDIR_ORDER); 79 free_pages((unsigned long)pgd, PGDIR_ORDER);
80} 80}
@@ -111,7 +111,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
111 return ptepage; 111 return ptepage;
112} 112}
113 113
114void pte_free_kernel(pte_t *pte) 114void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
115{ 115{
116#ifdef CONFIG_SMP 116#ifdef CONFIG_SMP
117 hash_page_sync(); 117 hash_page_sync();
@@ -119,7 +119,7 @@ void pte_free_kernel(pte_t *pte)
119 free_page((unsigned long)pte); 119 free_page((unsigned long)pte);
120} 120}
121 121
122void pte_free(struct page *ptepage) 122void pte_free(struct mm_struct *mm, struct page *ptepage)
123{ 123{
124#ifdef CONFIG_SMP 124#ifdef CONFIG_SMP
125 hash_page_sync(); 125 hash_page_sync();
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 6ee1bedbd1bf..062c3d4c0394 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1698,14 +1698,6 @@ compat_sys_signalfd_wrapper:
1698 llgfr %r4,%r4 # compat_size_t 1698 llgfr %r4,%r4 # compat_size_t
1699 jg compat_sys_signalfd 1699 jg compat_sys_signalfd
1700 1700
1701 .globl compat_sys_timerfd_wrapper
1702compat_sys_timerfd_wrapper:
1703 lgfr %r2,%r2 # int
1704 lgfr %r3,%r3 # int
1705 lgfr %r4,%r4 # int
1706 llgtr %r5,%r5 # struct compat_itimerspec *
1707 jg compat_sys_timerfd
1708
1709 .globl sys_eventfd_wrapper 1701 .globl sys_eventfd_wrapper
1710sys_eventfd_wrapper: 1702sys_eventfd_wrapper:
1711 llgfr %r2,%r2 # unsigned int 1703 llgfr %r2,%r2 # unsigned int
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 9e26ed9fe4e7..25eac7802fc4 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)
325SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper) 325SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
326SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */ 326SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
327SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper) 327SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
328SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper) 328NI_SYSCALL /* 317 old sys_timer_fd */
329SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper) 329SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 55722840859c..ee010f4532a0 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -79,7 +79,7 @@ sys_call_table:
79/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare 79/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
80/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy 80/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
81/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait 81/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
82/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate 82/*310*/ .long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
83 83
84#ifdef CONFIG_SUNOS_EMUL 84#ifdef CONFIG_SUNOS_EMUL
85 /* Now the SunOS syscall table. */ 85 /* Now the SunOS syscall table. */
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 070a4846c0cb..4b9115a4d92e 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,
580 580
581 /* Step 1: Prepare scatter list. */ 581 /* Step 1: Prepare scatter list. */
582 582
583 npages = prepare_sg(sglist, nelems); 583 npages = prepare_sg(dev, sglist, nelems);
584 584
585 /* Step 2: Allocate a cluster and context, if necessary. */ 585 /* Step 2: Allocate a cluster and context, if necessary. */
586 586
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index efd5dff85f60..72a4acfe8c7b 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com) 4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 */ 5 */
6 6
7#include <linux/dma-mapping.h>
7#include "iommu_common.h" 8#include "iommu_common.h"
8 9
9/* You are _strongly_ advised to enable the following debugging code 10/* 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
201} 202}
202#endif 203#endif
203 204
204unsigned long prepare_sg(struct scatterlist *sg, int nents) 205unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
205{ 206{
206 struct scatterlist *dma_sg = sg; 207 struct scatterlist *dma_sg = sg;
207 unsigned long prev; 208 unsigned long prev;
208 u32 dent_addr, dent_len; 209 u32 dent_addr, dent_len;
210 unsigned int max_seg_size;
209 211
210 prev = (unsigned long) sg_virt(sg); 212 prev = (unsigned long) sg_virt(sg);
211 prev += (unsigned long) (dent_len = sg->length); 213 prev += (unsigned long) (dent_len = sg->length);
212 dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL)); 214 dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
215 max_seg_size = dma_get_max_seg_size(dev);
213 while (--nents) { 216 while (--nents) {
214 unsigned long addr; 217 unsigned long addr;
215 218
216 sg = sg_next(sg); 219 sg = sg_next(sg);
217 addr = (unsigned long) sg_virt(sg); 220 addr = (unsigned long) sg_virt(sg);
218 if (! VCONTIG(prev, addr)) { 221 if (! VCONTIG(prev, addr) ||
222 dent_len + sg->length > max_seg_size) {
219 dma_sg->dma_address = dent_addr; 223 dma_sg->dma_address = dent_addr;
220 dma_sg->dma_length = dent_len; 224 dma_sg->dma_length = dent_len;
221 dma_sg = sg_next(dma_sg); 225 dma_sg = sg_next(dma_sg);
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 75b5a5814522..a90d046e8024 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -9,6 +9,7 @@
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/scatterlist.h> 11#include <linux/scatterlist.h>
12#include <linux/device.h>
12 13
13#include <asm/iommu.h> 14#include <asm/iommu.h>
14#include <asm/scatterlist.h> 15#include <asm/scatterlist.h>
@@ -46,4 +47,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int
46#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ 47#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \
47 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) 48 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
48 49
49extern unsigned long prepare_sg(struct scatterlist *sg, int nents); 50extern 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 1aa8e044b105..5ea2eab1ccda 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,
490 goto bad; 490 goto bad;
491 491
492 /* Step 1: Prepare scatter list. */ 492 /* Step 1: Prepare scatter list. */
493 npages = prepare_sg(sglist, nelems); 493 npages = prepare_sg(dev, sglist, nelems);
494 494
495 /* Step 2: Allocate a cluster and context, if necessary. */ 495 /* Step 2: Allocate a cluster and context, if necessary. */
496 spin_lock_irqsave(&iommu->lock, flags); 496 spin_lock_irqsave(&iommu->lock, flags);
@@ -625,8 +625,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
625 /* XXX register error interrupt handlers XXX */ 625 /* XXX register error interrupt handlers XXX */
626} 626}
627 627
628static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, 628static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
629 struct iommu *iommu) 629 struct iommu *iommu)
630{ 630{
631 struct iommu_arena *arena = &iommu->arena; 631 struct iommu_arena *arena = &iommu->arena;
632 unsigned long i, cnt = 0; 632 unsigned long i, cnt = 0;
@@ -653,7 +653,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
653 return cnt; 653 return cnt;
654} 654}
655 655
656static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) 656static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
657{ 657{
658 struct iommu *iommu = pbm->iommu; 658 struct iommu *iommu = pbm->iommu;
659 struct property *prop; 659 struct property *prop;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 06d10907d8ce..b8058906e727 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -80,7 +80,7 @@ sys_call_table32:
80 .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare 80 .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
81/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy 81/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
82 .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait 82 .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
83/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate 83/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
84 84
85#endif /* CONFIG_COMPAT */ 85#endif /* CONFIG_COMPAT */
86 86
@@ -152,7 +152,7 @@ sys_call_table:
152 .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare 152 .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
153/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy 153/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
154 .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait 154 .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
155/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate 155/*310*/ .word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
156 156
157#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ 157#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
158 defined(CONFIG_SOLARIS_EMUL_MODULE) 158 defined(CONFIG_SOLARIS_EMUL_MODULE)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 55945db1313c..99e51d059a02 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD
68 bool 68 bool
69 default y 69 default y
70 70
71config HZ
72 int
73 default 100
74
71menu "UML-specific options" 75menu "UML-specific options"
72 76
73config STATIC_LINK 77config STATIC_LINK
@@ -95,23 +99,6 @@ config LD_SCRIPT_DYN
95 default y 99 default y
96 depends on !LD_SCRIPT_STATIC 100 depends on !LD_SCRIPT_STATIC
97 101
98config NET
99 bool "Networking support"
100 help
101 Unless you really know what you are doing, you should say Y here.
102 The reason is that some programs need kernel networking support even
103 when running on a stand-alone machine that isn't connected to any
104 other computer. If you are upgrading from an older kernel, you
105 should consider updating your networking tools too because changes
106 in the kernel and the tools often go hand in hand. The tools are
107 contained in the package net-tools, the location and version number
108 of which are given in <file:Documentation/Changes>.
109
110 For a general introduction to Linux networking, it is highly
111 recommended to read the NET-HOWTO, available from
112 <http://www.tldp.org/docs.html#howto>.
113
114
115source "fs/Kconfig.binfmt" 102source "fs/Kconfig.binfmt"
116 103
117config HOSTFS 104config HOSTFS
@@ -145,7 +132,7 @@ config HPPFS
145 by removing or changing anything in /proc which gives away the 132 by removing or changing anything in /proc which gives away the
146 identity of a UML. 133 identity of a UML.
147 134
148 See <http://user-mode-linux.sf.net/hppfs.html> for more information. 135 See <http://user-mode-linux.sf.net/old/hppfs.html> for more information.
149 136
150 You only need this if you are setting up a UML honeypot. Otherwise, 137 You only need this if you are setting up a UML honeypot. Otherwise,
151 it is safe to say 'N' here. 138 it is safe to say 'N' here.
@@ -189,8 +176,7 @@ config MAGIC_SYSRQ
189config SMP 176config SMP
190 bool "Symmetric multi-processing support (EXPERIMENTAL)" 177 bool "Symmetric multi-processing support (EXPERIMENTAL)"
191 default n 178 default n
192 #SMP_BROKEN is for x86_64. 179 depends on BROKEN
193 depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
194 help 180 help
195 This option enables UML SMP support. 181 This option enables UML SMP support.
196 It is NOT related to having a real SMP box. Not directly, at least. 182 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 9a78d354f0b4..3a4b396d7979 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -18,7 +18,7 @@ config SSL
18 lines on the UML that are usually made to show up on the host as 18 lines on the UML that are usually made to show up on the host as
19 ttys or ptys. 19 ttys or ptys.
20 20
21 See <http://user-mode-linux.sourceforge.net/input.html> for more 21 See <http://user-mode-linux.sourceforge.net/old/input.html> for more
22 information and command line examples of how to use this facility. 22 information and command line examples of how to use this facility.
23 23
24 Unless you have a specific reason for disabling this, say Y. 24 Unless you have a specific reason for disabling this, say Y.
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 1f6462ffd3e8..8fce5e536b0f 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -4,12 +4,12 @@ source "lib/Kconfig.debug"
4 4
5config GPROF 5config GPROF
6 bool "Enable gprof support" 6 bool "Enable gprof support"
7 depends on DEBUG_INFO 7 depends on DEBUG_INFO && FRAME_POINTER
8 help 8 help
9 This allows profiling of a User-Mode Linux kernel with the gprof 9 This allows profiling of a User-Mode Linux kernel with the gprof
10 utility. 10 utility.
11 11
12 See <http://user-mode-linux.sourceforge.net/gprof.html> for more 12 See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
13 details. 13 details.
14 14
15 If you're involved in UML kernel development and want to use gprof, 15 If you're involved in UML kernel development and want to use gprof,
@@ -22,7 +22,7 @@ config GCOV
22 This option allows developers to retrieve coverage data from a UML 22 This option allows developers to retrieve coverage data from a UML
23 session. 23 session.
24 24
25 See <http://user-mode-linux.sourceforge.net/gprof.html> for more 25 See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
26 details. 26 details.
27 27
28 If you're involved in UML kernel development and want to use gcov, 28 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 66e50026ade9..9e9a4aaa703d 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -14,7 +14,7 @@ config UML_NET
14 14
15 For more information, including explanations of the networking and 15 For more information, including explanations of the networking and
16 sample configurations, see 16 sample configurations, see
17 <http://user-mode-linux.sourceforge.net/networking.html>. 17 <http://user-mode-linux.sourceforge.net/old/networking.html>.
18 18
19 If you'd like to be able to enable networking in the User-Mode 19 If you'd like to be able to enable networking in the User-Mode
20 linux environment, say Y; otherwise say N. Note that you must 20 linux environment, say Y; otherwise say N. Note that you must
@@ -38,7 +38,7 @@ config UML_NET_ETHERTAP
38 CONFIG_NETLINK_DEV configured as Y or M. 38 CONFIG_NETLINK_DEV configured as Y or M.
39 39
40 For more information, see 40 For more information, see
41 <http://user-mode-linux.sourceforge.net/networking.html> That site 41 <http://user-mode-linux.sourceforge.net/old/networking.html> That site
42 has examples of the UML command line to use to enable Ethertap 42 has examples of the UML command line to use to enable Ethertap
43 networking. 43 networking.
44 44
@@ -72,7 +72,7 @@ config UML_NET_SLIP
72 To use this, your host must support slip devices. 72 To use this, your host must support slip devices.
73 73
74 For more information, see 74 For more information, see
75 <http://user-mode-linux.sourceforge.net/networking.html>. That site 75 <http://user-mode-linux.sourceforge.net/old/networking.html>.
76 has examples of the UML command line to use to enable slip 76 has examples of the UML command line to use to enable slip
77 networking, and details of a few quirks with it. 77 networking, and details of a few quirks with it.
78 78
@@ -96,7 +96,7 @@ config UML_NET_DAEMON
96 networking daemon on the host. 96 networking daemon on the host.
97 97
98 For more information, see 98 For more information, see
99 <http://user-mode-linux.sourceforge.net/networking.html> That site 99 <http://user-mode-linux.sourceforge.net/old/networking.html> That site
100 has examples of the UML command line to use to enable Daemon 100 has examples of the UML command line to use to enable Daemon
101 networking. 101 networking.
102 102
@@ -144,7 +144,7 @@ config UML_NET_MCAST
144 To use this, your host kernel(s) must support IP Multicasting. 144 To use this, your host kernel(s) must support IP Multicasting.
145 145
146 For more information, see 146 For more information, see
147 <http://user-mode-linux.sourceforge.net/networking.html> That site 147 <http://user-mode-linux.sourceforge.net/old/networking.html> That site
148 has examples of the UML command line to use to enable Multicast 148 has examples of the UML command line to use to enable Multicast
149 networking, and notes about the security of this approach. 149 networking, and notes about the security of this approach.
150 150
@@ -165,7 +165,7 @@ config UML_NET_PCAP
165 installed in order to build the pcap transport into UML. 165 installed in order to build the pcap transport into UML.
166 166
167 For more information, see 167 For more information, see
168 <http://user-mode-linux.sourceforge.net/networking.html> That site 168 <http://user-mode-linux.sourceforge.net/old/networking.html> That site
169 has examples of the UML command line to use to enable this option. 169 has examples of the UML command line to use to enable this option.
170 170
171 If you intend to use UML as a network monitor for the host, say 171 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 ba6813a4aa37..cb4af9bf2074 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -49,7 +49,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
49# 49#
50# These apply to USER_CFLAGS to. 50# These apply to USER_CFLAGS to.
51 51
52KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ 52KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
53 $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ 53 $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
54 -Din6addr_loopback=kernel_in6addr_loopback \ 54 -Din6addr_loopback=kernel_in6addr_loopback \
55 -Din6addr_any=kernel_in6addr_any 55 -Din6addr_any=kernel_in6addr_any
@@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
58 58
59USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ 59USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
60 $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ 60 $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
61 -D_FILE_OFFSET_BITS=64 61 $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
62 62
63include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) 63include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
64 64
@@ -130,7 +130,9 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
130# The wrappers will select whether using "malloc" or the kernel allocator. 130# The wrappers will select whether using "malloc" or the kernel allocator.
131LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc 131LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
132 132
133CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) 133LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
134
135CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
134define cmd_vmlinux__ 136define cmd_vmlinux__
135 $(CC) $(CFLAGS_vmlinux) -o $@ \ 137 $(CC) $(CFLAGS_vmlinux) -o $@ \
136 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ 138 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
@@ -158,7 +160,7 @@ ifneq ($(KBUILD_SRC),)
158 $(Q)mkdir -p $(objtree)/include/asm-um 160 $(Q)mkdir -p $(objtree)/include/asm-um
159 $(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@ 161 $(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
160else 162else
161 $(Q)cd $(TOPDIR)/$(dir $@) ; \ 163 $(Q)cd $(srctree)/$(dir $@) ; \
162 ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) 164 ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
163endif 165endif
164 166
@@ -168,7 +170,7 @@ ifneq ($(KBUILD_SRC),)
168 $(Q)mkdir -p $(objtree)/include/asm-um 170 $(Q)mkdir -p $(objtree)/include/asm-um
169 $(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch 171 $(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
170else 172else
171 $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch 173 $(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
172endif 174endif
173 175
174$(objtree)/$(ARCH_DIR)/include: 176$(objtree)/$(ARCH_DIR)/include:
diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
deleted file mode 100644
index 03f7b10cfd0b..000000000000
--- a/arch/um/Makefile-tt
+++ /dev/null
@@ -1,5 +0,0 @@
1#
2# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f609edede065..86db2862f222 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -77,7 +77,7 @@ CONFIG_LD_SCRIPT_DYN=y
77CONFIG_NET=y 77CONFIG_NET=y
78CONFIG_BINFMT_ELF=y 78CONFIG_BINFMT_ELF=y
79CONFIG_BINFMT_MISC=m 79CONFIG_BINFMT_MISC=m
80# CONFIG_HOSTFS is not set 80CONFIG_HOSTFS=y
81# CONFIG_HPPFS is not set 81# CONFIG_HPPFS is not set
82CONFIG_MCONSOLE=y 82CONFIG_MCONSOLE=y
83CONFIG_MAGIC_SYSRQ=y 83CONFIG_MAGIC_SYSRQ=y
@@ -188,7 +188,7 @@ CONFIG_CON_CHAN="xterm"
188CONFIG_SSL_CHAN="pts" 188CONFIG_SSL_CHAN="pts"
189CONFIG_UNIX98_PTYS=y 189CONFIG_UNIX98_PTYS=y
190CONFIG_LEGACY_PTYS=y 190CONFIG_LEGACY_PTYS=y
191CONFIG_LEGACY_PTY_COUNT=256 191CONFIG_LEGACY_PTY_COUNT=32
192# CONFIG_WATCHDOG is not set 192# CONFIG_WATCHDOG is not set
193CONFIG_UML_SOUND=m 193CONFIG_UML_SOUND=m
194CONFIG_SOUND=m 194CONFIG_SOUND=m
@@ -508,7 +508,7 @@ CONFIG_DEBUG_KERNEL=y
508CONFIG_LOG_BUF_SHIFT=14 508CONFIG_LOG_BUF_SHIFT=14
509CONFIG_DETECT_SOFTLOCKUP=y 509CONFIG_DETECT_SOFTLOCKUP=y
510# CONFIG_SCHEDSTATS is not set 510# CONFIG_SCHEDSTATS is not set
511CONFIG_DEBUG_SLAB=y 511# CONFIG_DEBUG_SLAB is not set
512# CONFIG_DEBUG_SLAB_LEAK is not set 512# CONFIG_DEBUG_SLAB_LEAK is not set
513# CONFIG_DEBUG_MUTEXES is not set 513# CONFIG_DEBUG_MUTEXES is not set
514# CONFIG_DEBUG_SPINLOCK is not set 514# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83bf15a3dda8..2c898c4d6b6a 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,6 +8,7 @@
8#include "chan_kern.h" 8#include "chan_kern.h"
9#include "irq_kern.h" 9#include "irq_kern.h"
10#include "irq_user.h" 10#include "irq_user.h"
11#include "kern_util.h"
11#include "os.h" 12#include "os.h"
12 13
13#define LINE_BUFSIZE 4096 14#define LINE_BUFSIZE 4096
@@ -48,7 +49,7 @@ static int write_room(struct line *line)
48 n = line->head - line->tail; 49 n = line->head - line->tail;
49 50
50 if (n <= 0) 51 if (n <= 0)
51 n = LINE_BUFSIZE + n; /* The other case */ 52 n += LINE_BUFSIZE; /* The other case */
52 return n - 1; 53 return n - 1;
53} 54}
54 55
@@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty)
58 unsigned long flags; 59 unsigned long flags;
59 int room; 60 int room;
60 61
61 if (tty->stopped)
62 return 0;
63
64 spin_lock_irqsave(&line->lock, flags); 62 spin_lock_irqsave(&line->lock, flags);
65 room = write_room(line); 63 room = write_room(line);
66 spin_unlock_irqrestore(&line->lock, flags); 64 spin_unlock_irqrestore(&line->lock, flags);
67 65
68 /*XXX: Warning to remove */
69 if (0 == room)
70 printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
71 __FUNCTION__,tty->name);
72 return room; 66 return room;
73} 67}
74 68
@@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty)
79 int ret; 73 int ret;
80 74
81 spin_lock_irqsave(&line->lock, flags); 75 spin_lock_irqsave(&line->lock, flags);
82 76 /* write_room subtracts 1 for the needed NULL, so we readd it.*/
83 /*write_room subtracts 1 for the needed NULL, so we readd it.*/
84 ret = LINE_BUFSIZE - (write_room(line) + 1); 77 ret = LINE_BUFSIZE - (write_room(line) + 1);
85 spin_unlock_irqrestore(&line->lock, flags); 78 spin_unlock_irqrestore(&line->lock, flags);
86 79
@@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty)
184 unsigned long flags; 177 unsigned long flags;
185 int err; 178 int err;
186 179
187 /*XXX: copied from line_write, verify if it is correct!*/
188 if (tty->stopped)
189 return;
190
191 spin_lock_irqsave(&line->lock, flags); 180 spin_lock_irqsave(&line->lock, flags);
192 err = flush_buffer(line); 181 err = flush_buffer(line);
193 spin_unlock_irqrestore(&line->lock, flags); 182 spin_unlock_irqrestore(&line->lock, flags);
@@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
213 unsigned long flags; 202 unsigned long flags;
214 int n, ret = 0; 203 int n, ret = 0;
215 204
216 if (tty->stopped)
217 return 0;
218
219 spin_lock_irqsave(&line->lock, flags); 205 spin_lock_irqsave(&line->lock, flags);
220 if (line->head != line->tail) 206 if (line->head != line->tail)
221 ret = buffer_data(line, buf, len); 207 ret = buffer_data(line, buf, len);
@@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data)
788 tty = winch->tty; 774 tty = winch->tty;
789 if (tty != NULL) { 775 if (tty != NULL) {
790 line = tty->driver_data; 776 line = tty->driver_data;
791 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 777 if (line != NULL) {
792 &tty->winsize.ws_col); 778 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
793 kill_pgrp(tty->pgrp, SIGWINCH, 1); 779 &tty->winsize.ws_col);
780 kill_pgrp(tty->pgrp, SIGWINCH, 1);
781 }
794 } 782 }
795 out: 783 out:
796 if (winch->fd != -1) 784 if (winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 0f3c7d14a6e3..ebb265c07e4d 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,23 +1,25 @@
1/* 1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/console.h" 7#include <linux/console.h>
8#include "linux/ctype.h" 8#include <linux/ctype.h>
9#include "linux/interrupt.h" 9#include <linux/interrupt.h>
10#include "linux/list.h" 10#include <linux/list.h>
11#include "linux/mm.h" 11#include <linux/mm.h>
12#include "linux/module.h" 12#include <linux/module.h>
13#include "linux/notifier.h" 13#include <linux/notifier.h>
14#include "linux/reboot.h" 14#include <linux/reboot.h>
15#include "linux/proc_fs.h" 15#include <linux/proc_fs.h>
16#include "linux/slab.h" 16#include <linux/slab.h>
17#include "linux/syscalls.h" 17#include <linux/syscalls.h>
18#include "linux/utsname.h" 18#include <linux/utsname.h>
19#include "linux/workqueue.h" 19#include <linux/workqueue.h>
20#include "asm/uaccess.h" 20#include <linux/mutex.h>
21#include <asm/uaccess.h>
22
21#include "init.h" 23#include "init.h"
22#include "irq_kern.h" 24#include "irq_kern.h"
23#include "irq_user.h" 25#include "irq_user.h"
@@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req)
305 deactivate_fd(req->originating_fd, MCONSOLE_IRQ); 307 deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
306 os_set_fd_block(req->originating_fd, 1); 308 os_set_fd_block(req->originating_fd, 1);
307 mconsole_reply(req, "stopped", 0, 0); 309 mconsole_reply(req, "stopped", 0, 0);
308 while (mconsole_get_request(req->originating_fd, req)) { 310 for (;;) {
311 if (!mconsole_get_request(req->originating_fd, req))
312 continue;
309 if (req->cmd->handler == mconsole_go) 313 if (req->cmd->handler == mconsole_go)
310 break; 314 break;
311 if (req->cmd->handler == mconsole_stop) { 315 if (req->cmd->handler == mconsole_stop) {
@@ -358,7 +362,7 @@ struct unplugged_pages {
358 void *pages[UNPLUGGED_PER_PAGE]; 362 void *pages[UNPLUGGED_PER_PAGE];
359}; 363};
360 364
361static DECLARE_MUTEX(plug_mem_mutex); 365static DEFINE_MUTEX(plug_mem_mutex);
362static unsigned long long unplugged_pages_count = 0; 366static unsigned long long unplugged_pages_count = 0;
363static LIST_HEAD(unplugged_pages); 367static LIST_HEAD(unplugged_pages);
364static int unplug_index = UNPLUGGED_PER_PAGE; 368static int unplug_index = UNPLUGGED_PER_PAGE;
@@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out)
394 398
395 diff /= PAGE_SIZE; 399 diff /= PAGE_SIZE;
396 400
397 down(&plug_mem_mutex); 401 mutex_lock(&plug_mem_mutex);
398 for (i = 0; i < diff; i++) { 402 for (i = 0; i < diff; i++) {
399 struct unplugged_pages *unplugged; 403 struct unplugged_pages *unplugged;
400 void *addr; 404 void *addr;
@@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out)
451 455
452 err = 0; 456 err = 0;
453out_unlock: 457out_unlock:
454 up(&plug_mem_mutex); 458 mutex_unlock(&plug_mem_mutex);
455out: 459out:
456 return err; 460 return err;
457} 461}
@@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req)
741{ 745{
742 char *ptr = req->request.data; 746 char *ptr = req->request.data;
743 int pid_requested= -1; 747 int pid_requested= -1;
744 struct task_struct *from = NULL;
745 struct task_struct *to = NULL; 748 struct task_struct *to = NULL;
746 749
747 /* 750 /*
@@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req)
763 return; 766 return;
764 } 767 }
765 768
766 from = current; 769 to = find_task_by_pid_ns(pid_requested, &init_pid_ns);
767
768 to = find_task_by_pid(pid_requested);
769 if ((to == NULL) || (pid_requested == 0)) { 770 if ((to == NULL) || (pid_requested == 0)) {
770 mconsole_reply(req, "Couldn't find that pid", 1, 0); 771 mconsole_reply(req, "Couldn't find that pid", 1, 0);
771 return; 772 return;
@@ -795,6 +796,8 @@ static int __init mconsole_init(void)
795 printk(KERN_ERR "Failed to initialize management console\n"); 796 printk(KERN_ERR "Failed to initialize management console\n");
796 return 1; 797 return 1;
797 } 798 }
799 if (os_set_fd_block(sock, 0))
800 goto out;
798 801
799 register_reboot_notifier(&reboot_notifier); 802 register_reboot_notifier(&reboot_notifier);
800 803
@@ -803,7 +806,7 @@ static int __init mconsole_init(void)
803 "mconsole", (void *)sock); 806 "mconsole", (void *)sock);
804 if (err) { 807 if (err) {
805 printk(KERN_ERR "Failed to get IRQ for management console\n"); 808 printk(KERN_ERR "Failed to get IRQ for management console\n");
806 return 1; 809 goto out;
807 } 810 }
808 811
809 if (notify_socket != NULL) { 812 if (notify_socket != NULL) {
@@ -819,6 +822,10 @@ static int __init mconsole_init(void)
819 printk(KERN_INFO "mconsole (version %d) initialized on %s\n", 822 printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
820 MCONSOLE_VERSION, mconsole_socket_name); 823 MCONSOLE_VERSION, mconsole_socket_name);
821 return 0; 824 return 0;
825
826 out:
827 os_close_file(sock);
828 return 1;
822} 829}
823 830
824__initcall(mconsole_init); 831__initcall(mconsole_init);
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 430c024a19b0..13af2f03ed84 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)
83 int len; 83 int len;
84 84
85 req->originlen = sizeof(req->origin); 85 req->originlen = sizeof(req->origin);
86 req->len = recvfrom(fd, &req->request, sizeof(req->request), 86 req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
87 MSG_DONTWAIT, (struct sockaddr *) req->origin, 87 (struct sockaddr *) req->origin, &req->originlen);
88 &req->originlen);
89 if (req->len < 0) 88 if (req->len < 0)
90 return 0; 89 return 0;
91 90
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 3c6c44ca1ffa..1e8f41a99511 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)
318 if (str == NULL) 318 if (str == NULL)
319 goto random; 319 goto random;
320 320
321 for (i = 0;i < 6; i++) { 321 for (i = 0; i < 6; i++) {
322 addr[i] = simple_strtoul(str, &end, 16); 322 addr[i] = simple_strtoul(str, &end, 16);
323 if ((end == str) || 323 if ((end == str) ||
324 ((*end != ':') && (*end != ',') && (*end != '\0'))) { 324 ((*end != ':') && (*end != ',') && (*end != '\0'))) {
@@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
343 } 343 }
344 if (!is_local_ether_addr(addr)) { 344 if (!is_local_ether_addr(addr)) {
345 printk(KERN_WARNING 345 printk(KERN_WARNING
346 "Warning: attempt to assign a globally valid ethernet " 346 "Warning: Assigning a globally valid ethernet "
347 "address to a device\n"); 347 "address to a device\n");
348 printk(KERN_WARNING "You should better enable the 2nd " 348 printk(KERN_WARNING "You should set the 2nd rightmost bit in "
349 "rightmost bit in the first byte of the MAC,\n"); 349 "the first byte of the MAC,\n");
350 printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n", 350 printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
351 addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], 351 addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
352 addr[5]); 352 addr[5]);
353 goto random;
354 } 353 }
355 return; 354 return;
356 355
@@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = {
368 .name = DRIVER_NAME, 367 .name = DRIVER_NAME,
369 }, 368 },
370}; 369};
371static int driver_registered;
372 370
373static void net_device_release(struct device *dev) 371static void net_device_release(struct device *dev)
374{ 372{
@@ -383,6 +381,12 @@ static void net_device_release(struct device *dev)
383 free_netdev(netdev); 381 free_netdev(netdev);
384} 382}
385 383
384/*
385 * Ensures that platform_driver_register is called only once by
386 * eth_configure. Will be set in an initcall.
387 */
388static int driver_registered;
389
386static void eth_configure(int n, void *init, char *mac, 390static void eth_configure(int n, void *init, char *mac,
387 struct transport *transport) 391 struct transport *transport)
388{ 392{
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 29185cad9fff..abf2653f5517 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)
201 close(fds[1]); 201 close(fds[1]);
202 202
203 if (pid > 0) 203 if (pid > 0)
204 helper_wait(pid, 0, "change_tramp"); 204 helper_wait(pid);
205 return pid; 205 return pid;
206} 206}
207 207
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 330543b3129b..19930081d3d8 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -6,6 +6,7 @@
6#include "linux/completion.h" 6#include "linux/completion.h"
7#include "linux/interrupt.h" 7#include "linux/interrupt.h"
8#include "linux/list.h" 8#include "linux/list.h"
9#include "linux/mutex.h"
9#include "asm/atomic.h" 10#include "asm/atomic.h"
10#include "init.h" 11#include "init.h"
11#include "irq_kern.h" 12#include "irq_kern.h"
@@ -120,7 +121,7 @@ static int port_accept(struct port_list *port)
120 return 0; 121 return 0;
121} 122}
122 123
123static DECLARE_MUTEX(ports_sem); 124static DEFINE_MUTEX(ports_mutex);
124static LIST_HEAD(ports); 125static LIST_HEAD(ports);
125 126
126static void port_work_proc(struct work_struct *unused) 127static void port_work_proc(struct work_struct *unused)
@@ -161,7 +162,7 @@ void *port_data(int port_num)
161 struct port_dev *dev = NULL; 162 struct port_dev *dev = NULL;
162 int fd; 163 int fd;
163 164
164 down(&ports_sem); 165 mutex_lock(&ports_mutex);
165 list_for_each(ele, &ports) { 166 list_for_each(ele, &ports) {
166 port = list_entry(ele, struct port_list, list); 167 port = list_entry(ele, struct port_list, list);
167 if (port->port == port_num) 168 if (port->port == port_num)
@@ -216,7 +217,7 @@ void *port_data(int port_num)
216 out_free: 217 out_free:
217 kfree(port); 218 kfree(port);
218 out: 219 out:
219 up(&ports_sem); 220 mutex_unlock(&ports_mutex);
220 return dev; 221 return dev;
221} 222}
222 223
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index e942e836f995..71f0959c1535 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -5,6 +5,7 @@
5 * This software may be used and distributed according to the terms 5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference. 6 * of the GNU General Public License, incorporated herein by reference.
7 */ 7 */
8#include <linux/sched.h>
8#include <linux/module.h> 9#include <linux/module.h>
9#include <linux/fs.h> 10#include <linux/fs.h>
10#include <linux/miscdevice.h> 11#include <linux/miscdevice.h>
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index b8711e50da80..8b80505a3fb0 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)
109 read_output(fds[0], output, output_len); 109 read_output(fds[0], output, output_len);
110 printk("%s", output); 110 printk("%s", output);
111 111
112 err = helper_wait(pid, 0, argv[0]); 112 err = helper_wait(pid);
113 close(fds[0]); 113 close(fds[0]);
114 114
115out_free: 115out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 89c1be225fda..a0ada8fec72a 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)
98 "(%d)\n", pri->pid, errno); 98 "(%d)\n", pri->pid, errno);
99 } 99 }
100#endif 100#endif
101 err = helper_wait(pri->pid, 1, "slirp_close"); 101 err = helper_wait(pri->pid);
102 if (err < 0) 102 if (err < 0)
103 return; 103 return;
104 104
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 875d60d0c6a2..f1786e64607f 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -15,7 +15,6 @@
15#include "line.h" 15#include "line.h"
16#include "ssl.h" 16#include "ssl.h"
17#include "chan_kern.h" 17#include "chan_kern.h"
18#include "kern_util.h"
19#include "kern.h" 18#include "kern.h"
20#include "init.h" 19#include "init.h"
21#include "irq_user.h" 20#include "irq_user.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 656036e90b19..cec0c33cdd39 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -22,7 +22,6 @@
22#include "stdio_console.h" 22#include "stdio_console.h"
23#include "line.h" 23#include "line.h"
24#include "chan_kern.h" 24#include "chan_kern.h"
25#include "kern_util.h"
26#include "irq_user.h" 25#include "irq_user.h"
27#include "mconsole_kern.h" 26#include "mconsole_kern.h"
28#include "init.h" 27#include "init.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 99f9f9605e9c..be3a2797dac4 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,6 +49,7 @@
49#include "irq_user.h" 49#include "irq_user.h"
50#include "irq_kern.h" 50#include "irq_kern.h"
51#include "ubd_user.h" 51#include "ubd_user.h"
52#include "kern_util.h"
52#include "os.h" 53#include "os.h"
53#include "mem.h" 54#include "mem.h"
54#include "mem_kern.h" 55#include "mem_kern.h"
@@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count,
229 return len; 230 return len;
230} 231}
231 232
232static void make_ide_entries(char *dev_name) 233static void make_ide_entries(const char *dev_name)
233{ 234{
234 struct proc_dir_entry *dir, *ent; 235 struct proc_dir_entry *dir, *ent;
235 char name[64]; 236 char name[64];
@@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name)
244 ent->data = NULL; 245 ent->data = NULL;
245 ent->read_proc = proc_ide_read_media; 246 ent->read_proc = proc_ide_read_media;
246 ent->write_proc = NULL; 247 ent->write_proc = NULL;
247 sprintf(name,"ide0/%s", dev_name); 248 snprintf(name, sizeof(name), "ide0/%s", dev_name);
248 proc_symlink(dev_name, proc_ide_root, name); 249 proc_symlink(dev_name, proc_ide_root, name);
249} 250}
250 251
@@ -437,7 +438,10 @@ __uml_help(ubd_setup,
437" machine by running 'dd' on the device. <n> must be in the range\n" 438" machine by running 'dd' on the device. <n> must be in the range\n"
438" 0 to 7. Appending an 'r' to the number will cause that device\n" 439" 0 to 7. Appending an 'r' to the number will cause that device\n"
439" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n" 440" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
440" an 's' will cause data to be written to disk on the host immediately.\n\n" 441" an 's' will cause data to be written to disk on the host immediately.\n"
442" 'c' will cause the device to be treated as being shared between multiple\n"
443" UMLs and file locking will be turned off - this is appropriate for a\n"
444" cluster filesystem and inappropriate at almost all other times.\n\n"
441); 445);
442 446
443static int udb_setup(char *str) 447static int udb_setup(char *str)
@@ -456,20 +460,6 @@ __uml_help(udb_setup,
456" in the boot output.\n\n" 460" in the boot output.\n\n"
457); 461);
458 462
459static int fakehd_set = 0;
460static int fakehd(char *str)
461{
462 printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
463 fakehd_set = 1;
464 return 1;
465}
466
467__setup("fakehd", fakehd);
468__uml_help(fakehd,
469"fakehd\n"
470" Change the ubd device name to \"hd\".\n\n"
471);
472
473static void do_ubd_request(struct request_queue * q); 463static void do_ubd_request(struct request_queue * q);
474 464
475/* Only changed by ubd_init, which is an initcall. */ 465/* Only changed by ubd_init, which is an initcall. */
@@ -718,8 +708,10 @@ static int ubd_add(int n, char **error_out)
718 ubd_disk_register(fake_major, ubd_dev->size, n, 708 ubd_disk_register(fake_major, ubd_dev->size, n,
719 &fake_gendisk[n]); 709 &fake_gendisk[n]);
720 710
721 /* perhaps this should also be under the "if (fake_major)" above */ 711 /*
722 /* using the fake_disk->disk_name and also the fakehd_set name */ 712 * Perhaps this should also be under the "if (fake_major)" above
713 * using the fake_disk->disk_name
714 */
723 if (fake_ide) 715 if (fake_ide)
724 make_ide_entries(ubd_gendisk[n]->disk_name); 716 make_ide_entries(ubd_gendisk[n]->disk_name);
725 717
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 48fc7452bc1d..b591bb9c41dd 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
16#include <sys/mman.h> 16#include <sys/mman.h>
17#include <sys/param.h> 17#include <sys/param.h>
18#include "asm/types.h" 18#include "asm/types.h"
19#include "kern_util.h"
20#include "user.h" 19#include "user.h"
21#include "ubd_user.h" 20#include "ubd_user.h"
22#include "os.h" 21#include "os.h"
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index d9941fe5f931..56533db25343 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)
80 80
81 vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); 81 vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
82 if (vpri->args == NULL) { 82 if (vpri->args == NULL) {
83 printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args" 83 printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
84 "allocation failed"); 84 "allocation failed");
85 return; 85 return;
86 } 86 }
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 49c601ff2bac..2de92a08a76b 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -10,6 +10,6 @@
10 10
11extern void arch_check_bugs(void); 11extern void arch_check_bugs(void);
12extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); 12extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
13extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); 13extern void arch_examine_signal(int sig, struct uml_pt_regs *regs);
14 14
15#endif 15#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index a5cdf953e04a..606bb5c7fdf6 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -10,23 +10,31 @@
10#include "kern_constants.h" 10#include "kern_constants.h"
11 11
12/* 12/*
13 * Assembly doesn't want any casting, but C does, so define these 13 * Stolen from linux/const.h, which can't be directly included since
14 * without casts here, and define new symbols with casts inside the C 14 * this is used in userspace code, which has no access to the kernel
15 * section. 15 * headers. Changed to be suitable for adding casts to the start,
16 * rather than "UL" to the end.
16 */ 17 */
17#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
18#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
19#define ASM_STUB_START ASM_STUB_CODE
20 18
21/* 19/* Some constant macros are used in both assembler and
22 * This file is included by the assembly stubs, which just want the 20 * C code. Therefore we cannot annotate them always with
23 * definitions above. 21 * 'UL' and other type specifiers unilaterally. We
22 * use the following macros to deal with this.
24 */ 23 */
25#ifndef __ASSEMBLY__
26 24
27#define STUB_CODE ((unsigned long) ASM_STUB_CODE) 25#ifdef __ASSEMBLY__
28#define STUB_DATA ((unsigned long) ASM_STUB_DATA) 26#define _AC(X, Y) (Y)
29#define STUB_START ((unsigned long) ASM_STUB_START) 27#else
28#define __AC(X, Y) (X (Y))
29#define _AC(X, Y) __AC(X, Y)
30#endif
31
32#define STUB_START _AC(, 0x100000)
33#define STUB_CODE _AC((unsigned long), STUB_START)
34#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
35#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
36
37#ifndef __ASSEMBLY__
30 38
31#include "sysdep/ptrace.h" 39#include "sysdep/ptrace.h"
32 40
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 5a2263e05bb2..9b9ced85b703 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,
48#define __channel_help(fn, prefix) \ 48#define __channel_help(fn, prefix) \
49__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ 49__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
50" Attach a console or serial line to a host channel. See\n" \ 50" Attach a console or serial line to a host channel. See\n" \
51" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ 51" http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
52" description of this switch.\n\n" \ 52" description of this switch.\n\n" \
53); 53);
54 54
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 0edab695ed4e..b54bd35585c2 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);
18DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); 18DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
19DEFINE_STR(UM_KERN_INFO, KERN_INFO); 19DEFINE_STR(UM_KERN_INFO, KERN_INFO);
20DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); 20DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
21DEFINE_STR(UM_KERN_CONT, KERN_CONT);
21 22
22DEFINE(UM_ELF_CLASS, ELF_CLASS); 23DEFINE(UM_ELF_CLASS, ELF_CLASS);
23DEFINE(UM_ELFCLASS32, ELFCLASS32); 24DEFINE(UM_ELFCLASS32, ELFCLASS32);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index cebc6cae9190..b00a95741d41 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -40,6 +40,20 @@
40typedef int (*initcall_t)(void); 40typedef int (*initcall_t)(void);
41typedef void (*exitcall_t)(void); 41typedef void (*exitcall_t)(void);
42 42
43#ifndef __KERNEL__
44#ifndef __section
45# define __section(S) __attribute__ ((__section__(#S)))
46#endif
47
48#if __GNUC_MINOR__ >= 3
49# define __used __attribute__((__used__))
50#else
51# define __used __attribute__((__unused__))
52#endif
53
54#else
55#include <linux/compiler.h>
56#endif
43/* These are for everybody (although not all archs will actually 57/* These are for everybody (although not all archs will actually
44 discard it in modules) */ 58 discard it in modules) */
45#define __init __section(.init.text) 59#define __init __section(.init.text)
@@ -127,14 +141,3 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
127#endif 141#endif
128 142
129#endif /* _LINUX_UML_INIT_H */ 143#endif /* _LINUX_UML_INIT_H */
130
131/*
132 * Overrides for Emacs so that we follow Linus's tabbing style.
133 * Emacs will notice this stuff at the end of the file and automatically
134 * adjust the settings for this buffer only. This must remain at the end
135 * of the file.
136 * ---------------------------------------------------------------------------
137 * Local variables:
138 * c-file-style: "linux"
139 * End:
140 */
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 884a9c17eea0..e60b31873de1 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -14,7 +14,6 @@ struct irq_fd {
14 int fd; 14 int fd;
15 int type; 15 int type;
16 int irq; 16 int irq;
17 int pid;
18 int events; 17 int events;
19 int current_events; 18 int current_events;
20}; 19};
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 74ce8e5370a6..3c341222d252 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -9,107 +9,61 @@
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/faultinfo.h" 10#include "sysdep/faultinfo.h"
11 11
12typedef void (*kern_hndl)(int, struct uml_pt_regs *); 12extern int uml_exitcode;
13
14struct kern_handlers {
15 kern_hndl relay_signal;
16 kern_hndl winch;
17 kern_hndl bus_handler;
18 kern_hndl page_fault;
19 kern_hndl sigio_handler;
20 kern_hndl timer_handler;
21};
22
23extern const struct kern_handlers handlinfo_kern;
24 13
25extern int ncpus; 14extern int ncpus;
26extern char *gdb_init;
27extern int kmalloc_ok; 15extern int kmalloc_ok;
28extern int jail;
29extern int nsyscalls;
30 16
31#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
32#define UML_ROUND_UP(addr) \ 17#define UML_ROUND_UP(addr) \
33 UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) 18 ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
34 19
35extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
36extern int kernel_thread_proc(void *data);
37extern void syscall_segv(int sig);
38extern int current_pid(void);
39extern unsigned long alloc_stack(int order, int atomic); 20extern unsigned long alloc_stack(int order, int atomic);
21extern void free_stack(unsigned long stack, int order);
22
40extern int do_signal(void); 23extern int do_signal(void);
41extern int is_stack_fault(unsigned long sp); 24extern void copy_sc(struct uml_pt_regs *regs, void *from);
25extern void interrupt_end(void);
26extern void relay_signal(int sig, struct uml_pt_regs *regs);
27
42extern unsigned long segv(struct faultinfo fi, unsigned long ip, 28extern unsigned long segv(struct faultinfo fi, unsigned long ip,
43 int is_user, struct uml_pt_regs *regs); 29 int is_user, struct uml_pt_regs *regs);
44extern int handle_page_fault(unsigned long address, unsigned long ip, 30extern int handle_page_fault(unsigned long address, unsigned long ip,
45 int is_write, int is_user, int *code_out); 31 int is_write, int is_user, int *code_out);
46extern void syscall_ready(void); 32
47extern void set_tracing(void *t, int tracing);
48extern int is_tracing(void *task);
49extern int segv_syscall(void);
50extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
51extern unsigned long page_mask(void);
52extern int need_finish_fork(void);
53extern void free_stack(unsigned long stack, int order);
54extern void add_input_request(int op, void (*proc)(int), void *arg);
55extern char *current_cmd(void);
56extern void timer_handler(int sig, struct uml_pt_regs *regs);
57extern int set_signals(int enable);
58extern int pid_to_processor_id(int pid);
59extern void deliver_signals(void *t);
60extern int next_trap_index(int max);
61extern void default_idle(void);
62extern void finish_fork(void);
63extern void paging_init(void);
64extern void init_flush_vm(void);
65extern void *syscall_sp(void *t);
66extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
67extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); 33extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
68extern void interrupt_end(void);
69extern void initial_thread_cb(void (*proc)(void *), void *arg);
70extern int debugger_signal(int status, int pid);
71extern void debugger_parent_signal(int status, int pid);
72extern void child_signal(int pid, int status);
73extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
74extern int init_parent_proxy(int pid);
75extern int singlestepping(void *t);
76extern void check_stack_overflow(void *ptr);
77extern void relay_signal(int sig, struct uml_pt_regs *regs);
78extern int user_context(unsigned long sp);
79extern void timer_irq(struct uml_pt_regs *regs);
80extern void do_uml_exitcalls(void);
81extern int attach_debugger(int idle_pid, int pid, int stop);
82extern int config_gdb(char *str);
83extern int remove_gdb(void);
84extern char *uml_strdup(char *string);
85extern void unprotect_kernel_mem(void);
86extern void protect_kernel_mem(void);
87extern void uml_cleanup(void);
88extern void lock_signalled_task(void *t);
89extern void IPI_handler(int cpu);
90extern int jail_setup(char *line, int *add);
91extern void *get_init_task(void);
92extern int clear_user_proc(void *buf, int size);
93extern int copy_to_user_proc(void *to, void *from, int size);
94extern int copy_from_user_proc(void *to, void *from, int size);
95extern int strlen_user_proc(char *str);
96extern long execute_syscall(void *r);
97extern int smp_sigio_handler(void); 34extern int smp_sigio_handler(void);
98extern void *get_current(void); 35extern void initial_thread_cb(void (*proc)(void *), void *arg);
99extern struct task_struct *get_task(int pid, int require);
100extern void machine_halt(void);
101extern int is_syscall(unsigned long addr); 36extern int is_syscall(unsigned long addr);
37extern void timer_handler(int sig, struct uml_pt_regs *regs);
102 38
103extern void free_irq(unsigned int, void *); 39extern void timer_handler(int sig, struct uml_pt_regs *regs);
104extern int cpu(void);
105 40
106extern void time_init_kern(void); 41extern int start_uml(void);
42extern void paging_init(void);
107 43
108/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ 44extern void uml_cleanup(void);
45extern void do_uml_exitcalls(void);
46
47/*
48 * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
49 * GFP_ATOMIC.
50 */
109extern int __cant_sleep(void); 51extern int __cant_sleep(void);
110extern void sigio_handler(int sig, struct uml_pt_regs *regs); 52extern void *get_current(void);
111extern void copy_sc(struct uml_pt_regs *regs, void *from); 53extern int copy_from_user_proc(void *to, void *from, int size);
54extern int cpu(void);
55extern char *uml_strdup(const char *string);
56
112extern unsigned long to_irq_stack(unsigned long *mask_out); 57extern unsigned long to_irq_stack(unsigned long *mask_out);
113unsigned long from_irq_stack(int nested); 58extern unsigned long from_irq_stack(int nested);
114extern int start_uml(void); 59
60extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
61extern int singlestepping(void *t);
62
63extern void segv_handler(int sig, struct uml_pt_regs *regs);
64extern void bus_handler(int sig, struct uml_pt_regs *regs);
65extern void winch(int sig, struct uml_pt_regs *regs);
66extern void fatal_sigsegv(void) __attribute__ ((noreturn));
67
68
115#endif 69#endif
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index a54514d2cc3a..46384acd547b 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -46,9 +46,6 @@ extern int iomem_size;
46 46
47#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) 47#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
48 48
49extern unsigned long host_task_size;
50extern unsigned long task_size;
51
52extern int init_mem_user(void); 49extern int init_mem_user(void);
53extern void setup_memory(void *entry); 50extern void setup_memory(void *entry);
54extern unsigned long find_iomem(char *driver, unsigned long *len_out); 51extern unsigned long find_iomem(char *driver, unsigned long *len_out);
@@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable,
59 unsigned long len, unsigned long long highmem); 56 unsigned long len, unsigned long long highmem);
60extern void add_iomem(char *name, int fd, unsigned long size); 57extern void add_iomem(char *name, int fd, unsigned long size);
61extern unsigned long phys_offset(unsigned long phys); 58extern unsigned long phys_offset(unsigned long phys);
62extern void unmap_physmem(void);
63extern void map_memory(unsigned long virt, unsigned long phys, 59extern void map_memory(unsigned long virt, unsigned long phys,
64 unsigned long len, int r, int w, int x); 60 unsigned long len, int r, int w, int x);
65extern unsigned long get_kmem_end(void);
66 61
67#endif 62#endif
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
deleted file mode 100644
index 989bc08de36e..000000000000
--- a/arch/um/include/misc_constants.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __MISC_CONSTANT_H_
2#define __MISC_CONSTANT_H_
3
4#include <user_constants.h>
5
6#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 6f0d1c741bca..0b6b62733303 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -8,7 +8,6 @@
8 8
9#include <stdarg.h> 9#include <stdarg.h>
10#include "irq_user.h" 10#include "irq_user.h"
11#include "kern_util.h"
12#include "longjmp.h" 11#include "longjmp.h"
13#include "mm_id.h" 12#include "mm_id.h"
14#include "sysdep/tls.h" 13#include "sysdep/tls.h"
@@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags)
128extern int os_stat_file(const char *file_name, struct uml_stat *buf); 127extern int os_stat_file(const char *file_name, struct uml_stat *buf);
129extern int os_stat_fd(const int fd, struct uml_stat *buf); 128extern int os_stat_fd(const int fd, struct uml_stat *buf);
130extern int os_access(const char *file, int mode); 129extern int os_access(const char *file, int mode);
131extern int os_get_exec_close(int fd, int *close_on_exec);
132extern int os_set_exec_close(int fd); 130extern int os_set_exec_close(int fd);
133extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); 131extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
134extern int os_get_ifname(int fd, char *namebuf); 132extern int os_get_ifname(int fd, char *namebuf);
135extern int os_set_slip(int fd); 133extern int os_set_slip(int fd);
136extern int os_set_owner(int fd, int pid);
137extern int os_mode_fd(int fd, int mode); 134extern int os_mode_fd(int fd, int mode);
138 135
139extern int os_seek_file(int fd, unsigned long long offset); 136extern int os_seek_file(int fd, unsigned long long offset);
140extern int os_open_file(char *file, struct openflags flags, int mode); 137extern int os_open_file(const char *file, struct openflags flags, int mode);
141extern int os_read_file(int fd, void *buf, int len); 138extern int os_read_file(int fd, void *buf, int len);
142extern int os_write_file(int fd, const void *buf, int count); 139extern int os_write_file(int fd, const void *buf, int count);
143extern int os_file_size(char *file, unsigned long long *size_out); 140extern int os_file_size(const char *file, unsigned long long *size_out);
144extern int os_file_modtime(char *file, unsigned long *modtime); 141extern int os_file_modtime(const char *file, unsigned long *modtime);
145extern int os_pipe(int *fd, int stream, int close_on_exec); 142extern int os_pipe(int *fd, int stream, int close_on_exec);
146extern int os_set_fd_async(int fd, int owner); 143extern int os_set_fd_async(int fd);
147extern int os_clear_fd_async(int fd); 144extern int os_clear_fd_async(int fd);
148extern int os_set_fd_block(int fd, int blocking); 145extern int os_set_fd_block(int fd, int blocking);
149extern int os_accept_connection(int fd); 146extern int os_accept_connection(int fd);
150extern int os_create_unix_socket(char *file, int len, int close_on_exec); 147extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
151extern int os_shutdown_socket(int fd, int r, int w); 148extern int os_shutdown_socket(int fd, int r, int w);
152extern void os_close_file(int fd); 149extern void os_close_file(int fd);
153extern int os_rcv_fd(int fd, int *helper_pid_out); 150extern int os_rcv_fd(int fd, int *helper_pid_out);
154extern int create_unix_socket(char *file, int len, int close_on_exec); 151extern int create_unix_socket(char *file, int len, int close_on_exec);
155extern int os_connect_socket(char *name); 152extern int os_connect_socket(const char *name);
156extern int os_file_type(char *file); 153extern int os_file_type(char *file);
157extern int os_file_mode(char *file, struct openflags *mode_out); 154extern int os_file_mode(const char *file, struct openflags *mode_out);
158extern int os_lock_file(int fd, int excl); 155extern int os_lock_file(int fd, int excl);
159extern void os_flush_stdout(void); 156extern void os_flush_stdout(void);
160extern int os_stat_filesystem(char *path, long *bsize_out, 157extern int os_stat_filesystem(char *path, long *bsize_out,
@@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd);
168 165
169/* start_up.c */ 166/* start_up.c */
170extern void os_early_checks(void); 167extern void os_early_checks(void);
171extern int can_do_skas(void); 168extern void can_do_skas(void);
172extern void os_check_bugs(void); 169extern void os_check_bugs(void);
173extern void check_host_supports_tls(int *supports_tls, int *tls_min); 170extern void check_host_supports_tls(int *supports_tls, int *tls_min);
174 171
175/* Make sure they are clear when running in TT mode. Required by
176 * SEGV_MAYBE_FIXABLE */
177#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
178
179/* mem.c */ 172/* mem.c */
180extern int create_mem_file(unsigned long long len); 173extern int create_mem_file(unsigned long long len);
181 174
@@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
214extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv); 207extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
215extern int run_helper_thread(int (*proc)(void *), void *arg, 208extern int run_helper_thread(int (*proc)(void *), void *arg,
216 unsigned int flags, unsigned long *stack_out); 209 unsigned int flags, unsigned long *stack_out);
217extern int helper_wait(int pid, int nohang, char *pname); 210extern int helper_wait(int pid);
218 211
219 212
220/* tls.c */ 213/* tls.c */
@@ -237,16 +230,12 @@ extern void unblock_signals(void);
237extern int get_signals(void); 230extern int get_signals(void);
238extern int set_signals(int enable); 231extern int set_signals(int enable);
239 232
240/* trap.c */
241extern void os_fill_handlinfo(struct kern_handlers h);
242
243/* util.c */ 233/* util.c */
244extern void stack_protections(unsigned long address); 234extern void stack_protections(unsigned long address);
245extern int raw(int fd); 235extern int raw(int fd);
246extern void setup_machinename(char *machine_out); 236extern void setup_machinename(char *machine_out);
247extern void setup_hostinfo(char *buf, int len); 237extern void setup_hostinfo(char *buf, int len);
248extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 238extern void os_dump_core(void) __attribute__ ((noreturn));
249extern void os_dump_core(void);
250 239
251/* time.c */ 240/* time.c */
252extern void idle_sleep(unsigned long long nsecs); 241extern void idle_sleep(unsigned long long nsecs);
@@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
275extern int is_skas_winch(int pid, int fd, void *data); 264extern int is_skas_winch(int pid, int fd, void *data);
276extern int start_userspace(unsigned long stub_stack); 265extern int start_userspace(unsigned long stub_stack);
277extern int copy_context_skas0(unsigned long stack, int pid); 266extern int copy_context_skas0(unsigned long stack, int pid);
278extern void save_registers(int pid, struct uml_pt_regs *regs);
279extern void restore_registers(int pid, struct uml_pt_regs *regs);
280extern void userspace(struct uml_pt_regs *regs); 267extern void userspace(struct uml_pt_regs *regs);
281extern void map_stub_pages(int fd, unsigned long code, 268extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
282 unsigned long data, unsigned long stack); 269 unsigned long stack);
283extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); 270extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
284extern void switch_threads(jmp_buf *me, jmp_buf *you); 271extern void switch_threads(jmp_buf *me, jmp_buf *you);
285extern int start_idle_thread(void *stack, jmp_buf *switch_buf); 272extern 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,
298extern int os_get_pollfd(int i); 285extern int os_get_pollfd(int i);
299extern void os_set_pollfd(int i, int fd); 286extern void os_set_pollfd(int i, int fd);
300extern void os_set_ioignore(void); 287extern void os_set_ioignore(void);
301extern void init_irq_signals(int on_sigstack);
302 288
303/* sigio.c */ 289/* sigio.c */
304extern int add_sigio_fd(int fd); 290extern int add_sigio_fd(int fd);
305extern int ignore_sigio_fd(int fd); 291extern int ignore_sigio_fd(int fd);
306extern void maybe_sigio_broken(int fd, int read); 292extern void maybe_sigio_broken(int fd, int read);
307 293
308/* skas/trap */
309extern void sig_handler_common_skas(int sig, void *sc_ptr);
310
311/* sys-x86_64/prctl.c */ 294/* sys-x86_64/prctl.c */
312extern int os_arch_prctl(int pid, int code, unsigned long *addr); 295extern int os_arch_prctl(int pid, int code, unsigned long *addr);
313 296
diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h
index f3450e6bc18d..4bce6e012889 100644
--- a/arch/um/include/ptrace_user.h
+++ b/arch/um/include/ptrace_user.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -10,12 +10,6 @@
10 10
11extern int ptrace_getregs(long pid, unsigned long *regs_out); 11extern int ptrace_getregs(long pid, unsigned long *regs_out);
12extern int ptrace_setregs(long pid, unsigned long *regs_in); 12extern int ptrace_setregs(long pid, unsigned long *regs_in);
13extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
14extern int ptrace_setfpregs(long pid, unsigned long *regs);
15extern void arch_enter_kernel(void *task, int pid);
16extern void arch_leave_kernel(void *task, int pid);
17extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
18
19 13
20/* syscall emulation path in ptrace */ 14/* syscall emulation path in ptrace */
21 15
@@ -54,7 +48,8 @@ extern int sysemu_supported;
54 (((int[3][3] ) { \ 48 (((int[3][3] ) { \
55 { PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \ 49 { PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
56 { PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \ 50 { PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
57 { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \ 51 { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
52 PTRACE_SYSEMU_SINGLESTEP } }) \
58 [sysemu_mode][singlestep_mode]) 53 [sysemu_mode][singlestep_mode])
59 54
60#endif 55#endif
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 0e27406a43a4..9ea1ae3c8f46 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,14 +9,13 @@
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/archsetjmp.h" 10#include "sysdep/archsetjmp.h"
11 11
12extern void init_thread_registers(struct uml_pt_regs *to);
13extern int save_fp_registers(int pid, unsigned long *fp_regs); 12extern int save_fp_registers(int pid, unsigned long *fp_regs);
14extern int restore_fp_registers(int pid, unsigned long *fp_regs); 13extern int restore_fp_registers(int pid, unsigned long *fp_regs);
15extern int save_fpx_registers(int pid, unsigned long *fp_regs); 14extern int save_fpx_registers(int pid, unsigned long *fp_regs);
16extern int restore_fpx_registers(int pid, unsigned long *fp_regs); 15extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
17extern void save_registers(int pid, struct uml_pt_regs *regs); 16extern int save_registers(int pid, struct uml_pt_regs *regs);
18extern void restore_registers(int pid, struct uml_pt_regs *regs); 17extern int restore_registers(int pid, struct uml_pt_regs *regs);
19extern void init_registers(int pid); 18extern int init_registers(int pid);
20extern void get_safe_registers(unsigned long *regs); 19extern void get_safe_registers(unsigned long *regs);
21extern unsigned long get_thread_reg(int reg, jmp_buf *buf); 20extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
22 21
diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h
deleted file mode 100644
index aeb5d5ab1dfd..000000000000
--- a/arch/um/include/signal_kern.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SIGNAL_KERN_H__
7#define __SIGNAL_KERN_H__
8
9extern int have_signals(void *t);
10
11#endif
12
13/*
14 * Overrides for Emacs so that we follow Linus's tabbing style.
15 * Emacs will notice this stuff at the end of the file and automatically
16 * adjust the settings for this buffer only. This must remain at the end
17 * of the file.
18 * ---------------------------------------------------------------------------
19 * Local variables:
20 * c-file-style: "linux"
21 * End:
22 */
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
deleted file mode 100644
index e065feb000df..000000000000
--- a/arch/um/include/skas/mode-skas.h
+++ /dev/null
@@ -1,11 +0,0 @@
1/*
2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9extern void kill_off_processes_skas(void);
10
11#endif
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 57bd79efbee3..905698197e35 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386;
18extern syscall_handler_t *sys_call_table[]; 18extern syscall_handler_t *sys_call_table[];
19 19
20#define EXECUTE_SYSCALL(syscall, regs) \ 20#define EXECUTE_SYSCALL(syscall, regs) \
21 ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs)) 21 ((long (*)(struct syscall_args)) \
22 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
22 23
23extern long sys_mmap2(unsigned long addr, unsigned long len, 24extern long sys_mmap2(unsigned long addr, unsigned long len,
24 unsigned long prot, unsigned long flags, 25 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 c978b589df41..a307237b7964 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 @@
17#define OFFSET(sym, str, mem) \ 17#define OFFSET(sym, str, mem) \
18 DEFINE(sym, offsetof(struct str, mem)); 18 DEFINE(sym, offsetof(struct str, mem));
19 19
20#define __NO_STUBS 1
21#undef __SYSCALL
22#undef _ASM_X86_64_UNISTD_H_
23#define __SYSCALL(nr, sym) [nr] = 1,
24static char syscalls[] = {
25#include <asm/arch/unistd.h>
26};
27
28void foo(void) 20void foo(void)
29{ 21{
30#include <common-offsets.h> 22#include <common-offsets.h>
31DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1);
32} 23}
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index cf72256609e4..7cfb0b085655 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,
30extern syscall_handler_t sys_modify_ldt; 30extern syscall_handler_t sys_modify_ldt;
31extern syscall_handler_t sys_arch_prctl; 31extern syscall_handler_t sys_arch_prctl;
32 32
33#define NR_syscalls (UM_NR_syscall_max + 1)
34
35#endif 33#endif
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 8855d8df512f..82865fcf6872 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -12,10 +12,6 @@
12 12
13typedef struct mm_context { 13typedef struct mm_context {
14 struct mm_id id; 14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 struct uml_ldt ldt; 15 struct uml_ldt ldt;
20} mm_context_t; 16} mm_context_t;
21 17
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index fdfc06b85605..2b6fc8e0f071 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -6,7 +6,9 @@
6#ifndef __ARCH_UM_UACCESS_H 6#ifndef __ARCH_UM_UACCESS_H
7#define __ARCH_UM_UACCESS_H 7#define __ARCH_UM_UACCESS_H
8 8
9#include "asm/fixmap.h" 9#include <asm/elf.h>
10#include <asm/fixmap.h>
11#include "sysdep/archsetjmp.h"
10 12
11#define __under_task_size(addr, size) \ 13#define __under_task_size(addr, size) \
12 (((unsigned long) (addr) < TASK_SIZE) && \ 14 (((unsigned long) (addr) < TASK_SIZE) && \
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8196450451cd..76a62c0cb2bc 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -19,12 +19,13 @@
19void flush_thread(void) 19void flush_thread(void)
20{ 20{
21 void *data = NULL; 21 void *data = NULL;
22 unsigned long end = proc_mm ? task_size : STUB_START;
23 int ret; 22 int ret;
24 23
25 arch_flush_thread(&current->thread.arch); 24 arch_flush_thread(&current->thread.arch);
26 25
27 ret = unmap(&current->mm->context.id, 0, end, 1, &data); 26 ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
27 ret = ret || unmap(&current->mm->context.id, STUB_END,
28 TASK_SIZE - STUB_END, 1, &data);
28 if (ret) { 29 if (ret) {
29 printk(KERN_ERR "flush_thread - clearing address space failed, " 30 printk(KERN_ERR "flush_thread - clearing address space failed, "
30 "err = %d\n", ret); 31 "err = %d\n", ret);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index c716b5a6db13..984f80e668ca 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,15 +1,17 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/kernel.h" 6#include <linux/ctype.h>
7#include "linux/init.h" 7#include <linux/init.h>
8#include "linux/ctype.h" 8#include <linux/kernel.h>
9#include "linux/proc_fs.h" 9#include <linux/proc_fs.h>
10#include "asm/uaccess.h" 10#include <linux/types.h>
11#include <asm/uaccess.h>
11 12
12/* If read and write race, the read will still atomically read a valid 13/*
14 * If read and write race, the read will still atomically read a valid
13 * value. 15 * value.
14 */ 16 */
15int uml_exitcode = 0; 17int uml_exitcode = 0;
@@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
19{ 21{
20 int len, val; 22 int len, val;
21 23
22 /* Save uml_exitcode in a local so that we don't need to guarantee 24 /*
25 * Save uml_exitcode in a local so that we don't need to guarantee
23 * that sprintf accesses it atomically. 26 * that sprintf accesses it atomically.
24 */ 27 */
25 val = uml_exitcode; 28 val = uml_exitcode;
26 len = sprintf(page, "%d\n", val); 29 len = sprintf(page, "%d\n", val);
27 len -= off; 30 len -= off;
28 if(len <= off+count) 31 if (len <= off+count)
29 *eof = 1; 32 *eof = 1;
30 *start = page + off; 33 *start = page + off;
31 if(len > count) 34 if (len > count)
32 len = count; 35 len = count;
33 if(len < 0) 36 if (len < 0)
34 len = 0; 37 len = 0;
35 return len; 38 return len;
36} 39}
@@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
41 char *end, buf[sizeof("nnnnn\0")]; 44 char *end, buf[sizeof("nnnnn\0")];
42 int tmp; 45 int tmp;
43 46
44 if(copy_from_user(buf, buffer, count)) 47 if (copy_from_user(buf, buffer, count))
45 return -EFAULT; 48 return -EFAULT;
46 49
47 tmp = simple_strtol(buf, &end, 0); 50 tmp = simple_strtol(buf, &end, 0);
48 if((*end != '\0') && !isspace(*end)) 51 if ((*end != '\0') && !isspace(*end))
49 return -EINVAL; 52 return -EINVAL;
50 53
51 uml_exitcode = tmp; 54 uml_exitcode = tmp;
@@ -57,7 +60,7 @@ static int make_proc_exitcode(void)
57 struct proc_dir_entry *ent; 60 struct proc_dir_entry *ent;
58 61
59 ent = create_proc_entry("exitcode", 0600, &proc_root); 62 ent = create_proc_entry("exitcode", 0600, &proc_root);
60 if(ent == NULL){ 63 if (ent == NULL) {
61 printk(KERN_WARNING "make_proc_exitcode : Failed to register " 64 printk(KERN_WARNING "make_proc_exitcode : Failed to register "
62 "/proc/exitcode\n"); 65 "/proc/exitcode\n");
63 return 0; 66 return 0;
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 734f873cab12..72eccd2a4113 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -8,12 +8,13 @@
8extern void __bb_init_func(void *) __attribute__((weak)); 8extern void __bb_init_func(void *) __attribute__((weak));
9EXPORT_SYMBOL(__bb_init_func); 9EXPORT_SYMBOL(__bb_init_func);
10 10
11/* This is defined (and referred to in profiling stub code) only by some GCC 11/*
12 * This is defined (and referred to in profiling stub code) only by some GCC
12 * versions in libgcov. 13 * versions in libgcov.
13 * 14 *
14 * Since SuSE backported the fix, we cannot handle it depending on GCC version. 15 * Since SuSE backported the fix, we cannot handle it depending on GCC version.
15 * So, unconditionally export it. But also give it a weak declaration, which will 16 * So, unconditionally export it. But also give it a weak declaration, which
16 * be overridden by any other one. 17 * will be overridden by any other one.
17 */ 18 */
18 19
19extern void __gcov_init(void *) __attribute__((weak)); 20extern void __gcov_init(void *) __attribute__((weak));
diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c
index 9244f018d44c..e2f043d0de6c 100644
--- a/arch/um/kernel/gprof_syms.c
+++ b/arch/um/kernel/gprof_syms.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -7,14 +7,3 @@
7 7
8extern void mcount(void); 8extern void mcount(void);
9EXPORT_SYMBOL(mcount); 9EXPORT_SYMBOL(mcount);
10
11/*
12 * Overrides for Emacs so that we follow Linus's tabbing style.
13 * Emacs will notice this stuff at the end of the file and automatically
14 * adjust the settings for this buffer only. This must remain at the end
15 * of the file.
16 * ---------------------------------------------------------------------------
17 * Local variables:
18 * c-file-style: "linux"
19 * End:
20 */
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 16dc43e9d940..fa015565001b 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -7,7 +7,6 @@
7#include "linux/bootmem.h" 7#include "linux/bootmem.h"
8#include "linux/initrd.h" 8#include "linux/initrd.h"
9#include "asm/types.h" 9#include "asm/types.h"
10#include "kern_util.h"
11#include "initrd.h" 10#include "initrd.h"
12#include "init.h" 11#include "init.h"
13#include "os.h" 12#include "os.h"
@@ -21,18 +20,27 @@ static int __init read_initrd(void)
21 long long size; 20 long long size;
22 int err; 21 int err;
23 22
24 if(initrd == NULL) 23 if (initrd == NULL)
25 return 0; 24 return 0;
26 25
27 err = os_file_size(initrd, &size); 26 err = os_file_size(initrd, &size);
28 if(err) 27 if (err)
29 return 0; 28 return 0;
30 29
30 /*
31 * This is necessary because alloc_bootmem craps out if you
32 * ask for no memory.
33 */
34 if (size == 0) {
35 printk(KERN_ERR "\"%\" is a zero-size initrd\n");
36 return 0;
37 }
38
31 area = alloc_bootmem(size); 39 area = alloc_bootmem(size);
32 if(area == NULL) 40 if (area == NULL)
33 return 0; 41 return 0;
34 42
35 if(load_initrd(initrd, area, size) == -1) 43 if (load_initrd(initrd, area, size) == -1)
36 return 0; 44 return 0;
37 45
38 initrd_start = (unsigned long) area; 46 initrd_start = (unsigned long) area;
@@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size)
59 int fd, n; 67 int fd, n;
60 68
61 fd = os_open_file(filename, of_read(OPENFLAGS()), 0); 69 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
62 if(fd < 0){ 70 if (fd < 0) {
63 printk("Opening '%s' failed - err = %d\n", filename, -fd); 71 printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
72 -fd);
64 return -1; 73 return -1;
65 } 74 }
66 n = os_read_file(fd, buf, size); 75 n = os_read_file(fd, buf, size);
67 if(n != size){ 76 if (n != size) {
68 printk("Read of %d bytes from '%s' failed, err = %d\n", size, 77 printk(KERN_ERR "Read of %d bytes from '%s' failed, "
78 "err = %d\n", size,
69 filename, -n); 79 filename, -n);
70 return -1; 80 return -1;
71 } 81 }
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index ba11ccd6a8a3..91587f8db340 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)
107 struct pollfd *tmp_pfd; 107 struct pollfd *tmp_pfd;
108 struct irq_fd *new_fd, *irq_fd; 108 struct irq_fd *new_fd, *irq_fd;
109 unsigned long flags; 109 unsigned long flags;
110 int pid, events, err, n; 110 int events, err, n;
111 111
112 pid = os_getpid(); 112 err = os_set_fd_async(fd);
113 err = os_set_fd_async(fd, pid);
114 if (err < 0) 113 if (err < 0)
115 goto out; 114 goto out;
116 115
@@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
127 .fd = fd, 126 .fd = fd,
128 .type = type, 127 .type = type,
129 .irq = irq, 128 .irq = irq,
130 .pid = pid,
131 .events = events, 129 .events = events,
132 .current_events = 0 } ); 130 .current_events = 0 } );
133 131
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7c7142ba3bd7..5311ee93ede3 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -18,15 +18,11 @@ EXPORT_SYMBOL(set_signals);
18EXPORT_SYMBOL(get_signals); 18EXPORT_SYMBOL(get_signals);
19EXPORT_SYMBOL(kernel_thread); 19EXPORT_SYMBOL(kernel_thread);
20EXPORT_SYMBOL(sys_waitpid); 20EXPORT_SYMBOL(sys_waitpid);
21EXPORT_SYMBOL(task_size);
22EXPORT_SYMBOL(flush_tlb_range); 21EXPORT_SYMBOL(flush_tlb_range);
23EXPORT_SYMBOL(host_task_size);
24EXPORT_SYMBOL(arch_validate); 22EXPORT_SYMBOL(arch_validate);
25EXPORT_SYMBOL(get_kmem_end);
26 23
27EXPORT_SYMBOL(high_physmem); 24EXPORT_SYMBOL(high_physmem);
28EXPORT_SYMBOL(empty_zero_page); 25EXPORT_SYMBOL(empty_zero_page);
29EXPORT_SYMBOL(um_virt_to_phys);
30EXPORT_SYMBOL(handle_page_fault); 26EXPORT_SYMBOL(handle_page_fault);
31EXPORT_SYMBOL(find_iomem); 27EXPORT_SYMBOL(find_iomem);
32 28
@@ -40,7 +36,6 @@ EXPORT_SYMBOL(uml_strdup);
40EXPORT_SYMBOL(os_stat_fd); 36EXPORT_SYMBOL(os_stat_fd);
41EXPORT_SYMBOL(os_stat_file); 37EXPORT_SYMBOL(os_stat_file);
42EXPORT_SYMBOL(os_access); 38EXPORT_SYMBOL(os_access);
43EXPORT_SYMBOL(os_get_exec_close);
44EXPORT_SYMBOL(os_set_exec_close); 39EXPORT_SYMBOL(os_set_exec_close);
45EXPORT_SYMBOL(os_getpid); 40EXPORT_SYMBOL(os_getpid);
46EXPORT_SYMBOL(os_open_file); 41EXPORT_SYMBOL(os_open_file);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 59822dee438a..d872fdce1d7e 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,49 +1,41 @@
1/* 1/*
2 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/stddef.h" 6#include <linux/stddef.h>
7#include "linux/kernel.h" 7#include <linux/bootmem.h>
8#include "linux/mm.h" 8#include <linux/gfp.h>
9#include "linux/bootmem.h" 9#include <linux/highmem.h>
10#include "linux/swap.h" 10#include <linux/mm.h>
11#include "linux/highmem.h" 11#include <linux/swap.h>
12#include "linux/gfp.h" 12#include <asm/fixmap.h>
13#include "asm/page.h" 13#include <asm/page.h>
14#include "asm/fixmap.h"
15#include "asm/pgalloc.h"
16#include "kern_util.h"
17#include "as-layout.h" 14#include "as-layout.h"
15#include "init.h"
18#include "kern.h" 16#include "kern.h"
17#include "kern_util.h"
19#include "mem_user.h" 18#include "mem_user.h"
20#include "um_uaccess.h"
21#include "os.h" 19#include "os.h"
22#include "linux/types.h"
23#include "linux/string.h"
24#include "init.h"
25#include "kern_constants.h"
26 20
27/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ 21/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
28unsigned long *empty_zero_page = NULL; 22unsigned long *empty_zero_page = NULL;
29/* allocated in paging_init and unchanged thereafter */ 23/* allocated in paging_init and unchanged thereafter */
30unsigned long *empty_bad_page = NULL; 24unsigned long *empty_bad_page = NULL;
25
26/*
27 * Initialized during boot, and readonly for initializing page tables
28 * afterwards
29 */
31pgd_t swapper_pg_dir[PTRS_PER_PGD]; 30pgd_t swapper_pg_dir[PTRS_PER_PGD];
31
32/* Initialized at boot time, and readonly after that */
32unsigned long long highmem; 33unsigned long long highmem;
33int kmalloc_ok = 0; 34int kmalloc_ok = 0;
34 35
36/* Used during early boot */
35static unsigned long brk_end; 37static unsigned long brk_end;
36 38
37void unmap_physmem(void)
38{
39 os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
40}
41
42static void map_cb(void *unused)
43{
44 map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
45}
46
47#ifdef CONFIG_HIGHMEM 39#ifdef CONFIG_HIGHMEM
48static void setup_highmem(unsigned long highmem_start, 40static void setup_highmem(unsigned long highmem_start,
49 unsigned long highmem_len) 41 unsigned long highmem_len)
@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
53 int i; 45 int i;
54 46
55 highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; 47 highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
56 for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ 48 for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
57 page = &mem_map[highmem_pfn + i]; 49 page = &mem_map[highmem_pfn + i];
58 ClearPageReserved(page); 50 ClearPageReserved(page);
59 init_page_count(page); 51 init_page_count(page);
@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
65void __init mem_init(void) 57void __init mem_init(void)
66{ 58{
67 /* clear the zero-page */ 59 /* clear the zero-page */
68 memset((void *) empty_zero_page, 0, PAGE_SIZE); 60 memset(empty_zero_page, 0, PAGE_SIZE);
69 61
70 /* Map in the area just after the brk now that kmalloc is about 62 /* Map in the area just after the brk now that kmalloc is about
71 * to be turned on. 63 * to be turned on.
72 */ 64 */
73 brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); 65 brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
74 map_cb(NULL); 66 map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
75 initial_thread_cb(map_cb, NULL);
76 free_bootmem(__pa(brk_end), uml_reserved - brk_end); 67 free_bootmem(__pa(brk_end), uml_reserved - brk_end);
77 uml_reserved = brk_end; 68 uml_reserved = brk_end;
78 69
@@ -85,7 +76,7 @@ void __init mem_init(void)
85#endif 76#endif
86 num_physpages = totalram_pages; 77 num_physpages = totalram_pages;
87 max_pfn = totalram_pages; 78 max_pfn = totalram_pages;
88 printk(KERN_INFO "Memory: %luk available\n", 79 printk(KERN_INFO "Memory: %luk available\n",
89 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); 80 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
90 kmalloc_ok = 1; 81 kmalloc_ok = 1;
91 82
@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
119#endif 110#endif
120} 111}
121 112
122static void __init fixrange_init(unsigned long start, unsigned long end, 113static void __init fixrange_init(unsigned long start, unsigned long end,
123 pgd_t *pgd_base) 114 pgd_t *pgd_base)
124{ 115{
125 pgd_t *pgd; 116 pgd_t *pgd;
@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
138 if (pud_none(*pud)) 129 if (pud_none(*pud))
139 one_md_table_init(pud); 130 one_md_table_init(pud);
140 pmd = pmd_offset(pud, vaddr); 131 pmd = pmd_offset(pud, vaddr);
141 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { 132 for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
142 one_page_table_init(pmd); 133 one_page_table_init(pmd);
143 vaddr += PMD_SIZE; 134 vaddr += PMD_SIZE;
144 } 135 }
@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
152 143
153#define kmap_get_fixmap_pte(vaddr) \ 144#define kmap_get_fixmap_pte(vaddr) \
154 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ 145 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
155 (vaddr)), (vaddr)) 146 (vaddr)), (vaddr))
156 147
157static void __init kmap_init(void) 148static void __init kmap_init(void)
158{ 149{
@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
197 pud_t *pud; 188 pud_t *pud;
198 pmd_t *pmd; 189 pmd_t *pmd;
199 pte_t *pte; 190 pte_t *pte;
200 unsigned long paddr, vaddr = FIXADDR_USER_START; 191 phys_t p;
192 unsigned long v, vaddr = FIXADDR_USER_START;
201 193
202 if ( ! size ) 194 if (!size)
203 return; 195 return;
204 196
205 fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir); 197 fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
206 paddr = (unsigned long)alloc_bootmem_low_pages( size); 198 v = (unsigned long) alloc_bootmem_low_pages(size);
207 memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size); 199 memcpy((void *) v , (void *) FIXADDR_USER_START, size);
208 paddr = __pa(paddr); 200 p = __pa(v);
209 for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){ 201 for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
202 p += PAGE_SIZE) {
210 pgd = swapper_pg_dir + pgd_index(vaddr); 203 pgd = swapper_pg_dir + pgd_index(vaddr);
211 pud = pud_offset(pgd, vaddr); 204 pud = pud_offset(pgd, vaddr);
212 pmd = pmd_offset(pud, vaddr); 205 pmd = pmd_offset(pud, vaddr);
213 pte = pte_offset_kernel(pmd, vaddr); 206 pte = pte_offset_kernel(pmd, vaddr);
214 pte_set_val( (*pte), paddr, PAGE_READONLY); 207 pte_set_val(*pte, p, PAGE_READONLY);
215 } 208 }
216#endif 209#endif
217} 210}
@@ -223,7 +216,7 @@ void __init paging_init(void)
223 216
224 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 217 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
225 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 218 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
226 for(i = 0; i < ARRAY_SIZE(zones_size); i++) 219 for (i = 0; i < ARRAY_SIZE(zones_size); i++)
227 zones_size[i] = 0; 220 zones_size[i] = 0;
228 221
229 zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) - 222 zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
253 int i; 246 int i;
254 247
255 again: 248 again:
256 if(page == NULL) 249 if (page == NULL)
257 return page; 250 return page;
258 if(PageHighMem(page)) 251 if (PageHighMem(page))
259 return page; 252 return page;
260 253
261 addr = (unsigned long) page_address(page); 254 addr = (unsigned long) page_address(page);
262 for(i = 0; i < (1 << order); i++){ 255 for (i = 0; i < (1 << order); i++) {
263 current->thread.fault_addr = (void *) addr; 256 current->thread.fault_addr = (void *) addr;
264 if(__do_copy_to_user((void __user *) addr, &zero, 257 if (__do_copy_to_user((void __user *) addr, &zero,
265 sizeof(zero), 258 sizeof(zero),
266 &current->thread.fault_addr, 259 &current->thread.fault_addr,
267 &current->thread.fault_catcher)){ 260 &current->thread.fault_catcher)) {
268 if(!(mask & __GFP_WAIT)) 261 if (!(mask & __GFP_WAIT))
269 return NULL; 262 return NULL;
270 else break; 263 else break;
271 } 264 }
272 addr += PAGE_SIZE; 265 addr += PAGE_SIZE;
273 } 266 }
274 267
275 if(i == (1 << order)) 268 if (i == (1 << order))
276 return page; 269 return page;
277 page = alloc_pages(mask, order); 270 page = alloc_pages(mask, order);
278 goto again; 271 goto again;
279} 272}
280 273
281/* This can't do anything because nothing in the kernel image can be freed 274/*
275 * This can't do anything because nothing in the kernel image can be freed
282 * since it's not in kernel physical memory. 276 * since it's not in kernel physical memory.
283 */ 277 */
284 278
@@ -290,8 +284,8 @@ void free_initmem(void)
290void free_initrd_mem(unsigned long start, unsigned long end) 284void free_initrd_mem(unsigned long start, unsigned long end)
291{ 285{
292 if (start < end) 286 if (start < end)
293 printk ("Freeing initrd memory: %ldk freed\n", 287 printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
294 (end - start) >> 10); 288 (end - start) >> 10);
295 for (; start < end; start += PAGE_SIZE) { 289 for (; start < end; start += PAGE_SIZE) {
296 ClearPageReserved(virt_to_page(start)); 290 ClearPageReserved(virt_to_page(start));
297 init_page_count(virt_to_page(start)); 291 init_page_count(virt_to_page(start));
@@ -308,32 +302,31 @@ void show_mem(void)
308 int highmem = 0; 302 int highmem = 0;
309 struct page *page; 303 struct page *page;
310 304
311 printk("Mem-info:\n"); 305 printk(KERN_INFO "Mem-info:\n");
312 show_free_areas(); 306 show_free_areas();
313 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); 307 printk(KERN_INFO "Free swap: %6ldkB\n",
308 nr_swap_pages<<(PAGE_SHIFT-10));
314 pfn = max_mapnr; 309 pfn = max_mapnr;
315 while(pfn-- > 0) { 310 while (pfn-- > 0) {
316 page = pfn_to_page(pfn); 311 page = pfn_to_page(pfn);
317 total++; 312 total++;
318 if(PageHighMem(page)) 313 if (PageHighMem(page))
319 highmem++; 314 highmem++;
320 if(PageReserved(page)) 315 if (PageReserved(page))
321 reserved++; 316 reserved++;
322 else if(PageSwapCache(page)) 317 else if (PageSwapCache(page))
323 cached++; 318 cached++;
324 else if(page_count(page)) 319 else if (page_count(page))
325 shared += page_count(page) - 1; 320 shared += page_count(page) - 1;
326 } 321 }
327 printk("%d pages of RAM\n", total); 322 printk(KERN_INFO "%d pages of RAM\n", total);
328 printk("%d pages of HIGHMEM\n", highmem); 323 printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
329 printk("%d reserved pages\n", reserved); 324 printk(KERN_INFO "%d reserved pages\n", reserved);
330 printk("%d pages shared\n", shared); 325 printk(KERN_INFO "%d pages shared\n", shared);
331 printk("%d pages swap cached\n", cached); 326 printk(KERN_INFO "%d pages swap cached\n", cached);
332} 327}
333 328
334/* 329/* Allocate and free page tables. */
335 * Allocate and free page tables.
336 */
337 330
338pgd_t *pgd_alloc(struct mm_struct *mm) 331pgd_t *pgd_alloc(struct mm_struct *mm)
339{ 332{
@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
341 334
342 if (pgd) { 335 if (pgd) {
343 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); 336 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
344 memcpy(pgd + USER_PTRS_PER_PGD, 337 memcpy(pgd + USER_PTRS_PER_PGD,
345 swapper_pg_dir + USER_PTRS_PER_PGD, 338 swapper_pg_dir + USER_PTRS_PER_PGD,
346 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 339 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
347 } 340 }
348 return pgd; 341 return pgd;
349} 342}
350 343
351void pgd_free(pgd_t *pgd) 344void pgd_free(struct mm_struct *mm, pgd_t *pgd)
352{ 345{
353 free_page((unsigned long) pgd); 346 free_page((unsigned long) pgd);
354} 347}
@@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
368 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); 361 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
369 return pte; 362 return pte;
370} 363}
364
365#ifdef CONFIG_3_LEVEL_PGTABLES
366pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
367{
368 pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
369
370 if (pmd)
371 memset(pmd, 0, PAGE_SIZE);
372
373 return pmd;
374}
375#endif
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index e66432f42485..9757085a0220 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,
55 return 0; 55 return 0;
56} 56}
57 57
58/* Changed during early boot */
59static unsigned long kmem_top = 0;
60
61unsigned long get_kmem_end(void)
62{
63 if (kmem_top == 0)
64 kmem_top = host_task_size - 1024 * 1024;
65 return kmem_top;
66}
67
68void map_memory(unsigned long virt, unsigned long phys, unsigned long len, 58void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
69 int r, int w, int x) 59 int r, int w, int x)
70{ 60{
@@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem,
174 * setup_iomem, both of which run during early boot. Afterwards, it's 164 * setup_iomem, both of which run during early boot. Afterwards, it's
175 * unchanged. 165 * unchanged.
176 */ 166 */
177struct iomem_region *iomem_regions = NULL; 167struct iomem_region *iomem_regions;
178 168
179/* Initialized in parse_iomem */ 169/* Initialized in parse_iomem and unchanged thereafter */
180int iomem_size = 0; 170int iomem_size;
181 171
182unsigned long find_iomem(char *driver, unsigned long *len_out) 172unsigned long find_iomem(char *driver, unsigned long *len_out)
183{ 173{
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 0eae00b3e588..c07961bedb75 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -4,19 +4,21 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/stddef.h" 7#include <linux/stddef.h>
8#include "linux/err.h" 8#include <linux/err.h>
9#include "linux/hardirq.h" 9#include <linux/hardirq.h>
10#include "linux/mm.h" 10#include <linux/gfp.h>
11#include "linux/personality.h" 11#include <linux/mm.h>
12#include "linux/proc_fs.h" 12#include <linux/personality.h>
13#include "linux/ptrace.h" 13#include <linux/proc_fs.h>
14#include "linux/random.h" 14#include <linux/ptrace.h>
15#include "linux/sched.h" 15#include <linux/random.h>
16#include "linux/tick.h" 16#include <linux/sched.h>
17#include "linux/threads.h" 17#include <linux/tick.h>
18#include "asm/pgtable.h" 18#include <linux/threads.h>
19#include "asm/uaccess.h" 19#include <asm/current.h>
20#include <asm/pgtable.h>
21#include <asm/uaccess.h>
20#include "as-layout.h" 22#include "as-layout.h"
21#include "kern_util.h" 23#include "kern_util.h"
22#include "os.h" 24#include "os.h"
@@ -30,7 +32,7 @@
30 */ 32 */
31struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; 33struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
32 34
33static inline int external_pid(struct task_struct *task) 35static inline int external_pid(void)
34{ 36{
35 /* FIXME: Need to look up userspace_pid by cpu */ 37 /* FIXME: Need to look up userspace_pid by cpu */
36 return userspace_pid[0]; 38 return userspace_pid[0];
@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
40{ 42{
41 int i; 43 int i;
42 44
43 for(i = 0; i < ncpus; i++) { 45 for (i = 0; i < ncpus; i++) {
44 if (cpu_tasks[i].pid == pid) 46 if (cpu_tasks[i].pid == pid)
45 return i; 47 return i;
46 } 48 }
@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
60 if (atomic) 62 if (atomic)
61 flags = GFP_ATOMIC; 63 flags = GFP_ATOMIC;
62 page = __get_free_pages(flags, order); 64 page = __get_free_pages(flags, order);
63 if (page == 0)
64 return 0;
65 65
66 return page; 66 return page;
67} 67}
@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
80static inline void set_current(struct task_struct *task) 80static inline void set_current(struct task_struct *task)
81{ 81{
82 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) 82 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
83 { external_pid(task), task }); 83 { external_pid(), task });
84} 84}
85 85
86extern void arch_switch_to(struct task_struct *from, struct task_struct *to); 86extern void arch_switch_to(struct task_struct *to);
87 87
88void *_switch_to(void *prev, void *next, void *last) 88void *_switch_to(void *prev, void *next, void *last)
89{ 89{
90 struct task_struct *from = prev; 90 struct task_struct *from = prev;
91 struct task_struct *to= next; 91 struct task_struct *to = next;
92 92
93 to->thread.prev_sched = from; 93 to->thread.prev_sched = from;
94 set_current(to); 94 set_current(to);
@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
99 switch_threads(&from->thread.switch_buf, 99 switch_threads(&from->thread.switch_buf,
100 &to->thread.switch_buf); 100 &to->thread.switch_buf);
101 101
102 arch_switch_to(current->thread.prev_sched, current); 102 arch_switch_to(current);
103 103
104 if (current->thread.saved_task) 104 if (current->thread.saved_task)
105 show_regs(&(current->thread.regs)); 105 show_regs(&(current->thread.regs));
106 next= current->thread.saved_task; 106 to = current->thread.saved_task;
107 prev= current; 107 from = current;
108 } while(current->thread.saved_task); 108 } while (current->thread.saved_task);
109 109
110 return current->thread.prev_sched; 110 return current->thread.prev_sched;
111 111
@@ -163,8 +163,6 @@ void new_thread_handler(void)
163void fork_handler(void) 163void fork_handler(void)
164{ 164{
165 force_flush_all(); 165 force_flush_all();
166 if (current->thread.prev_sched == NULL)
167 panic("blech");
168 166
169 schedule_tail(current->thread.prev_sched); 167 schedule_tail(current->thread.prev_sched);
170 168
@@ -173,7 +171,7 @@ void fork_handler(void)
173 * arch_switch_to isn't needed. We could want to apply this to 171 * arch_switch_to isn't needed. We could want to apply this to
174 * improve performance. -bb 172 * improve performance. -bb
175 */ 173 */
176 arch_switch_to(current->thread.prev_sched, current); 174 arch_switch_to(current);
177 175
178 current->thread.prev_sched = NULL; 176 current->thread.prev_sched = NULL;
179 177
@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
204 arch_copy_thread(&current->thread.arch, &p->thread.arch); 202 arch_copy_thread(&current->thread.arch, &p->thread.arch);
205 } 203 }
206 else { 204 else {
207 init_thread_registers(&p->thread.regs.regs); 205 get_safe_registers(p->thread.regs.regs.gp);
208 p->thread.request.u.thread = current->thread.request.u.thread; 206 p->thread.request.u.thread = current->thread.request.u.thread;
209 handler = new_thread_handler; 207 handler = new_thread_handler;
210 } 208 }
@@ -237,7 +235,7 @@ void default_idle(void)
237{ 235{
238 unsigned long long nsecs; 236 unsigned long long nsecs;
239 237
240 while(1) { 238 while (1) {
241 /* endless idle loop with no priority at all */ 239 /* endless idle loop with no priority at all */
242 240
243 /* 241 /*
@@ -256,53 +254,10 @@ void default_idle(void)
256 254
257void cpu_idle(void) 255void cpu_idle(void)
258{ 256{
259 cpu_tasks[current_thread->cpu].pid = os_getpid(); 257 cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
260 default_idle(); 258 default_idle();
261} 259}
262 260
263void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
264 pte_t *pte_out)
265{
266 pgd_t *pgd;
267 pud_t *pud;
268 pmd_t *pmd;
269 pte_t *pte;
270 pte_t ptent;
271
272 if (task->mm == NULL)
273 return ERR_PTR(-EINVAL);
274 pgd = pgd_offset(task->mm, addr);
275 if (!pgd_present(*pgd))
276 return ERR_PTR(-EINVAL);
277
278 pud = pud_offset(pgd, addr);
279 if (!pud_present(*pud))
280 return ERR_PTR(-EINVAL);
281
282 pmd = pmd_offset(pud, addr);
283 if (!pmd_present(*pmd))
284 return ERR_PTR(-EINVAL);
285
286 pte = pte_offset_kernel(pmd, addr);
287 ptent = *pte;
288 if (!pte_present(ptent))
289 return ERR_PTR(-EINVAL);
290
291 if (pte_out != NULL)
292 *pte_out = ptent;
293 return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
294}
295
296char *current_cmd(void)
297{
298#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
299 return "(Unknown)";
300#else
301 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
302 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
303#endif
304}
305
306void dump_thread(struct pt_regs *regs, struct user *u) 261void dump_thread(struct pt_regs *regs, struct user *u)
307{ 262{
308} 263}
@@ -317,7 +272,7 @@ int user_context(unsigned long sp)
317 unsigned long stack; 272 unsigned long stack;
318 273
319 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); 274 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
320 return stack != (unsigned long) current_thread; 275 return stack != (unsigned long) current_thread_info();
321} 276}
322 277
323extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 278extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -331,7 +286,7 @@ void do_uml_exitcalls(void)
331 (*call)(); 286 (*call)();
332} 287}
333 288
334char *uml_strdup(char *string) 289char *uml_strdup(const char *string)
335{ 290{
336 return kstrdup(string, GFP_KERNEL); 291 return kstrdup(string, GFP_KERNEL);
337} 292}
@@ -359,7 +314,7 @@ int strlen_user_proc(char __user *str)
359int smp_sigio_handler(void) 314int smp_sigio_handler(void)
360{ 315{
361#ifdef CONFIG_SMP 316#ifdef CONFIG_SMP
362 int cpu = current_thread->cpu; 317 int cpu = current_thread_info()->cpu;
363 IPI_handler(cpu); 318 IPI_handler(cpu);
364 if (cpu != 0) 319 if (cpu != 0)
365 return 1; 320 return 1;
@@ -369,7 +324,7 @@ int smp_sigio_handler(void)
369 324
370int cpu(void) 325int cpu(void)
371{ 326{
372 return current_thread->cpu; 327 return current_thread_info()->cpu;
373} 328}
374 329
375static atomic_t using_sysemu = ATOMIC_INIT(0); 330static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -435,7 +390,7 @@ int singlestepping(void * t)
435{ 390{
436 struct task_struct *task = t ? t : current; 391 struct task_struct *task = t ? t : current;
437 392
438 if ( ! (task->ptrace & PT_DTRACE) ) 393 if (!(task->ptrace & PT_DTRACE))
439 return 0; 394 return 0;
440 395
441 if (task->thread.singlestep_syscall) 396 if (task->thread.singlestep_syscall)
@@ -459,3 +414,46 @@ unsigned long arch_align_stack(unsigned long sp)
459 return sp & ~0xf; 414 return sp & ~0xf;
460} 415}
461#endif 416#endif
417
418unsigned long get_wchan(struct task_struct *p)
419{
420 unsigned long stack_page, sp, ip;
421 bool seen_sched = 0;
422
423 if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
424 return 0;
425
426 stack_page = (unsigned long) task_stack_page(p);
427 /* Bail if the process has no kernel stack for some reason */
428 if (stack_page == 0)
429 return 0;
430
431 sp = p->thread.switch_buf->JB_SP;
432 /*
433 * Bail if the stack pointer is below the bottom of the kernel
434 * stack for some reason
435 */
436 if (sp < stack_page)
437 return 0;
438
439 while (sp < stack_page + THREAD_SIZE) {
440 ip = *((unsigned long *) sp);
441 if (in_sched_functions(ip))
442 /* Ignore everything until we're above the scheduler */
443 seen_sched = 1;
444 else if (kernel_text_address(ip) && seen_sched)
445 return ip;
446
447 sp += sizeof(unsigned long);
448 }
449
450 return 0;
451}
452
453int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
454{
455 int cpu = current_thread_info()->cpu;
456
457 return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
458}
459
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 04cebcf0679f..00197d3d21ec 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include "linux/sched.h" 6#include "linux/sched.h"
7#include "kern_util.h"
7#include "os.h" 8#include "os.h"
8#include "skas.h" 9#include "skas.h"
9 10
@@ -11,7 +12,7 @@ void (*pm_power_off)(void);
11 12
12static void kill_off_processes(void) 13static void kill_off_processes(void)
13{ 14{
14 if(proc_mm) 15 if (proc_mm)
15 /* 16 /*
16 * FIXME: need to loop over userspace_pids 17 * FIXME: need to loop over userspace_pids
17 */ 18 */
@@ -21,8 +22,8 @@ static void kill_off_processes(void)
21 int pid, me; 22 int pid, me;
22 23
23 me = os_getpid(); 24 me = os_getpid();
24 for_each_process(p){ 25 for_each_process(p) {
25 if(p->mm == NULL) 26 if (p->mm == NULL)
26 continue; 27 continue;
27 28
28 pid = p->mm->context.id.u.pid; 29 pid = p->mm->context.id.u.pid;
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 89f9866a1354..2b272b63b514 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -1,18 +1,12 @@
1/* 1/*
2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/kernel.h" 6#include <linux/interrupt.h>
7#include "linux/list.h"
8#include "linux/slab.h"
9#include "linux/signal.h"
10#include "linux/interrupt.h"
11#include "init.h"
12#include "sigio.h"
13#include "irq_user.h"
14#include "irq_kern.h" 7#include "irq_kern.h"
15#include "os.h" 8#include "os.h"
9#include "sigio.h"
16 10
17/* Protected by sigio_lock() called from write_sigio_workaround */ 11/* Protected by sigio_lock() called from write_sigio_workaround */
18static int sigio_irq_fd = -1; 12static int sigio_irq_fd = -1;
@@ -33,9 +27,9 @@ int write_sigio_irq(int fd)
33 err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, 27 err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
34 IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", 28 IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
35 NULL); 29 NULL);
36 if(err){ 30 if (err) {
37 printk("write_sigio_irq : um_request_irq failed, err = %d\n", 31 printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
38 err); 32 "err = %d\n", err);
39 return -1; 33 return -1;
40 } 34 }
41 sigio_irq_fd = fd; 35 sigio_irq_fd = fd;
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 19cb97733937..b0fce720c4d0 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -3,12 +3,12 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/module.h" 6#include <linux/module.h>
7#include "linux/ptrace.h" 7#include <linux/ptrace.h>
8#include "linux/sched.h" 8#include <linux/sched.h>
9#include "asm/siginfo.h" 9#include <asm/siginfo.h>
10#include "asm/signal.h" 10#include <asm/signal.h>
11#include "asm/unistd.h" 11#include <asm/unistd.h>
12#include "frame_kern.h" 12#include "frame_kern.h"
13#include "kern_util.h" 13#include "kern_util.h"
14#include "sigcontext.h" 14#include "sigcontext.h"
@@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
36 /* Did we come from a system call? */ 36 /* Did we come from a system call? */
37 if (PT_REGS_SYSCALL_NR(regs) >= 0) { 37 if (PT_REGS_SYSCALL_NR(regs) >= 0) {
38 /* If so, check system call restarting.. */ 38 /* If so, check system call restarting.. */
39 switch(PT_REGS_SYSCALL_RET(regs)) { 39 switch (PT_REGS_SYSCALL_RET(regs)) {
40 case -ERESTART_RESTARTBLOCK: 40 case -ERESTART_RESTARTBLOCK:
41 case -ERESTARTNOHAND: 41 case -ERESTARTNOHAND:
42 PT_REGS_SYSCALL_RET(regs) = -EINTR; 42 PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs)
116 /* Did we come from a system call? */ 116 /* Did we come from a system call? */
117 if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { 117 if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
118 /* Restart the system call - no handlers present */ 118 /* Restart the system call - no handlers present */
119 switch(PT_REGS_SYSCALL_RET(regs)) { 119 switch (PT_REGS_SYSCALL_RET(regs)) {
120 case -ERESTARTNOHAND: 120 case -ERESTARTNOHAND:
121 case -ERESTARTSYS: 121 case -ERESTARTSYS:
122 case -ERESTARTNOINTR: 122 case -ERESTARTNOINTR:
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 8d07a7acb909..2c8583c1a344 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -1,17 +1,20 @@
1#include <sched.h> 1/*
2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
2#include <signal.h> 6#include <signal.h>
3#include <sys/mman.h> 7#include <sched.h>
4#include <sys/time.h>
5#include <asm/unistd.h> 8#include <asm/unistd.h>
9#include <sys/time.h>
6#include "as-layout.h" 10#include "as-layout.h"
11#include "kern_constants.h"
7#include "ptrace_user.h" 12#include "ptrace_user.h"
8#include "skas.h"
9#include "stub-data.h" 13#include "stub-data.h"
10#include "uml-config.h"
11#include "sysdep/stub.h" 14#include "sysdep/stub.h"
12#include "kern_constants.h"
13 15
14/* This is in a separate file because it needs to be compiled with any 16/*
17 * This is in a separate file because it needs to be compiled with any
15 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled 18 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
16 * 19 *
17 * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize 20 * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
@@ -26,25 +29,26 @@ stub_clone_handler(void)
26 29
27 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, 30 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
28 STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); 31 STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
29 if(err != 0) 32 if (err != 0)
30 goto out; 33 goto out;
31 34
32 err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); 35 err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
33 if(err) 36 if (err)
34 goto out; 37 goto out;
35 38
36 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, 39 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
37 (long) &data->timer, 0); 40 (long) &data->timer, 0);
38 if(err) 41 if (err)
39 goto out; 42 goto out;
40 43
41 remap_stack(data->fd, data->offset); 44 remap_stack(data->fd, data->offset);
42 goto done; 45 goto done;
43 46
44 out: 47 out:
45 /* save current result. 48 /*
46 * Parent: pid; 49 * save current result.
47 * child: retcode of mmap already saved and it jumps around this 50 * Parent: pid;
51 * child: retcode of mmap already saved and it jumps around this
48 * assignment 52 * assignment
49 */ 53 */
50 data->err = err; 54 data->err = err;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index f859ec306cd5..78b3e9f69d57 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,
34 if (!pte) 34 if (!pte)
35 goto out_pte; 35 goto out_pte;
36 36
37 /*
38 * There's an interaction between the skas0 stub pages, stack
39 * randomization, and the BUG at the end of exit_mmap. exit_mmap
40 * checks that the number of page tables freed is the same as had
41 * been allocated. If the stack is on the last page table page,
42 * then the stack pte page will be freed, and if not, it won't. To
43 * avoid having to know where the stack is, or if the process mapped
44 * something at the top of its address space for some other reason,
45 * we set TASK_SIZE to end at the start of the last page table.
46 * This keeps exit_mmap off the last page, but introduces a leak
47 * of that page. So, we hang onto it here and free it in
48 * destroy_context_skas.
49 */
50
51 mm->context.last_page_table = pmd_page_vaddr(*pmd);
52#ifdef CONFIG_3_LEVEL_PGTABLES
53 mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
54#endif
55
56 *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); 37 *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
57 *pte = pte_mkread(*pte); 38 *pte = pte_mkread(*pte);
58 return 0; 39 return 0;
59 40
60 out_pmd: 41 out_pmd:
61 pud_free(pud); 42 pud_free(mm, pud);
62 out_pte: 43 out_pte:
63 pmd_free(pmd); 44 pmd_free(mm, pmd);
64 out: 45 out:
65 return -ENOMEM; 46 return -ENOMEM;
66} 47}
@@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
76 stack = get_zeroed_page(GFP_KERNEL); 57 stack = get_zeroed_page(GFP_KERNEL);
77 if (stack == 0) 58 if (stack == 0)
78 goto out; 59 goto out;
79
80 /*
81 * This zeros the entry that pgd_alloc didn't, needed since
82 * we are about to reinitialize it, and want mm.nr_ptes to
83 * be accurate.
84 */
85 mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
86
87 ret = init_stub_pte(mm, STUB_CODE,
88 (unsigned long) &__syscall_stub_start);
89 if (ret)
90 goto out_free;
91
92 ret = init_stub_pte(mm, STUB_DATA, stack);
93 if (ret)
94 goto out_free;
95
96 mm->nr_ptes--;
97 } 60 }
98 61
99 to_mm->id.stack = stack; 62 to_mm->id.stack = stack;
@@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
114 to_mm->id.u.pid = copy_context_skas0(stack, 77 to_mm->id.u.pid = copy_context_skas0(stack,
115 from_mm->id.u.pid); 78 from_mm->id.u.pid);
116 else to_mm->id.u.pid = start_userspace(stack); 79 else to_mm->id.u.pid = start_userspace(stack);
80
81 if (to_mm->id.u.pid < 0) {
82 ret = to_mm->id.u.pid;
83 goto out_free;
84 }
117 } 85 }
118 86
119 ret = init_new_ldt(to_mm, from_mm); 87 ret = init_new_ldt(to_mm, from_mm);
@@ -132,24 +100,87 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
132 return ret; 100 return ret;
133} 101}
134 102
103void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
104{
105 struct page **pages;
106 int err, ret;
107
108 if (!skas_needs_stub)
109 return;
110
111 ret = init_stub_pte(mm, STUB_CODE,
112 (unsigned long) &__syscall_stub_start);
113 if (ret)
114 goto out;
115
116 ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
117 if (ret)
118 goto out;
119
120 pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
121 if (pages == NULL) {
122 printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
123 "pointers\n");
124 goto out;
125 }
126
127 pages[0] = virt_to_page(&__syscall_stub_start);
128 pages[1] = virt_to_page(mm->context.id.stack);
129
130 /* dup_mmap already holds mmap_sem */
131 err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
132 VM_READ | VM_MAYREAD | VM_EXEC |
133 VM_MAYEXEC | VM_DONTCOPY, pages);
134 if (err) {
135 printk(KERN_ERR "install_special_mapping returned %d\n", err);
136 goto out_free;
137 }
138 return;
139
140out_free:
141 kfree(pages);
142out:
143 force_sigsegv(SIGSEGV, current);
144}
145
146void arch_exit_mmap(struct mm_struct *mm)
147{
148 pte_t *pte;
149
150 pte = virt_to_pte(mm, STUB_CODE);
151 if (pte != NULL)
152 pte_clear(mm, STUB_CODE, pte);
153
154 pte = virt_to_pte(mm, STUB_DATA);
155 if (pte == NULL)
156 return;
157
158 pte_clear(mm, STUB_DATA, pte);
159}
160
135void destroy_context(struct mm_struct *mm) 161void destroy_context(struct mm_struct *mm)
136{ 162{
137 struct mm_context *mmu = &mm->context; 163 struct mm_context *mmu = &mm->context;
138 164
139 if (proc_mm) 165 if (proc_mm)
140 os_close_file(mmu->id.u.mm_fd); 166 os_close_file(mmu->id.u.mm_fd);
141 else 167 else {
168 /*
169 * If init_new_context wasn't called, this will be
170 * zero, resulting in a kill(0), which will result in the
171 * whole UML suddenly dying. Also, cover negative and
172 * 1 cases, since they shouldn't happen either.
173 */
174 if (mmu->id.u.pid < 2) {
175 printk(KERN_ERR "corrupt mm_context - pid = %d\n",
176 mmu->id.u.pid);
177 return;
178 }
142 os_kill_ptraced_process(mmu->id.u.pid, 1); 179 os_kill_ptraced_process(mmu->id.u.pid, 1);
180 }
143 181
144 if (!proc_mm || !ptrace_faultinfo) { 182 if (skas_needs_stub)
145 free_page(mmu->id.stack); 183 free_page(mmu->id.stack);
146 pte_lock_deinit(virt_to_page(mmu->last_page_table));
147 pte_free_kernel((pte_t *) mmu->last_page_table);
148 dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
149#ifdef CONFIG_3_LEVEL_PGTABLES
150 pmd_free((pmd_t *) mmu->last_pmd);
151#endif
152 }
153 184
154 free_ldt(mmu); 185 free_ldt(mmu);
155} 186}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index fce389c2342f..2e9852c0d487 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -6,19 +6,25 @@
6#include "linux/init.h" 6#include "linux/init.h"
7#include "linux/sched.h" 7#include "linux/sched.h"
8#include "as-layout.h" 8#include "as-layout.h"
9#include "kern.h"
9#include "os.h" 10#include "os.h"
10#include "skas.h" 11#include "skas.h"
11 12
12int new_mm(unsigned long stack) 13int new_mm(unsigned long stack)
13{ 14{
14 int fd; 15 int fd, err;
15 16
16 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 17 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
17 if (fd < 0) 18 if (fd < 0)
18 return fd; 19 return fd;
19 20
20 if (skas_needs_stub) 21 if (skas_needs_stub) {
21 map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); 22 err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
23 if (err) {
24 os_close_file(fd);
25 return err;
26 }
27 }
22 28
23 return fd; 29 return fd;
24} 30}
@@ -49,8 +55,14 @@ int __init start_uml(void)
49{ 55{
50 stack_protections((unsigned long) &cpu0_irqstack); 56 stack_protections((unsigned long) &cpu0_irqstack);
51 set_sigstack(cpu0_irqstack, THREAD_SIZE); 57 set_sigstack(cpu0_irqstack, THREAD_SIZE);
52 if (proc_mm) 58 if (proc_mm) {
53 userspace_pid[0] = start_userspace(0); 59 userspace_pid[0] = start_userspace(0);
60 if (userspace_pid[0] < 0) {
61 printf("start_uml - start_userspace returned %d\n",
62 userspace_pid[0]);
63 exit(1);
64 }
65 }
54 66
55 init_new_thread_signals(); 67 init_new_thread_signals();
56 68
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 50b476f2b38d..4e3b820bd2be 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -9,6 +9,9 @@
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/syscalls.h" 10#include "sysdep/syscalls.h"
11 11
12extern int syscall_table_size;
13#define NR_syscalls (syscall_table_size / sizeof(void *))
14
12void handle_syscall(struct uml_pt_regs *r) 15void handle_syscall(struct uml_pt_regs *r)
13{ 16{
14 struct pt_regs *regs = container_of(r, struct pt_regs, regs); 17 struct pt_regs *regs = container_of(r, struct pt_regs, regs);
@@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r)
17 20
18 syscall_trace(r, 0); 21 syscall_trace(r, 0);
19 22
20 current->thread.nsyscalls++;
21 nsyscalls++;
22
23 /* 23 /*
24 * This should go in the declaration of syscall, but when I do that, 24 * This should go in the declaration of syscall, but when I do that,
25 * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing 25 * 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 1d8b119f2d0e..e22c96993db3 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -3,128 +3,130 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/err.h" 6#include <linux/err.h>
7#include "linux/highmem.h" 7#include <linux/highmem.h>
8#include "linux/mm.h" 8#include <linux/mm.h>
9#include "asm/current.h" 9#include <linux/sched.h>
10#include "asm/page.h" 10#include <asm/current.h>
11#include "asm/pgtable.h" 11#include <asm/page.h>
12#include <asm/pgtable.h>
12#include "kern_util.h" 13#include "kern_util.h"
13#include "os.h" 14#include "os.h"
14 15
15extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 16pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
16 pte_t *pte_out);
17
18static unsigned long maybe_map(unsigned long virt, int is_write)
19{ 17{
20 pte_t pte; 18 pgd_t *pgd;
21 int err; 19 pud_t *pud;
20 pmd_t *pmd;
21
22 if (mm == NULL)
23 return NULL;
24
25 pgd = pgd_offset(mm, addr);
26 if (!pgd_present(*pgd))
27 return NULL;
28
29 pud = pud_offset(pgd, addr);
30 if (!pud_present(*pud))
31 return NULL;
22 32
23 void *phys = um_virt_to_phys(current, virt, &pte); 33 pmd = pmd_offset(pud, addr);
24 int dummy_code; 34 if (!pmd_present(*pmd))
35 return NULL;
36
37 return pte_offset_kernel(pmd, addr);
38}
39
40static pte_t *maybe_map(unsigned long virt, int is_write)
41{
42 pte_t *pte = virt_to_pte(current->mm, virt);
43 int err, dummy_code;
25 44
26 if (IS_ERR(phys) || (is_write && !pte_write(pte))) { 45 if ((pte == NULL) || !pte_present(*pte) ||
46 (is_write && !pte_write(*pte))) {
27 err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); 47 err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
28 if (err) 48 if (err)
29 return -1UL; 49 return NULL;
30 phys = um_virt_to_phys(current, virt, NULL); 50 pte = virt_to_pte(current->mm, virt);
31 } 51 }
32 if (IS_ERR(phys)) 52 if (!pte_present(*pte))
33 phys = (void *) -1; 53 pte = NULL;
34 54
35 return (unsigned long) phys; 55 return pte;
36} 56}
37 57
38static int do_op_one_page(unsigned long addr, int len, int is_write, 58static int do_op_one_page(unsigned long addr, int len, int is_write,
39 int (*op)(unsigned long addr, int len, void *arg), void *arg) 59 int (*op)(unsigned long addr, int len, void *arg), void *arg)
40{ 60{
61 jmp_buf buf;
41 struct page *page; 62 struct page *page;
42 int n; 63 pte_t *pte;
64 int n, faulted;
43 65
44 addr = maybe_map(addr, is_write); 66 pte = maybe_map(addr, is_write);
45 if (addr == -1UL) 67 if (pte == NULL)
46 return -1; 68 return -1;
47 69
48 page = phys_to_page(addr); 70 page = pte_page(*pte);
49 addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + 71 addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
50 (addr & ~PAGE_MASK); 72 (addr & ~PAGE_MASK);
51 73
52 n = (*op)(addr, len, arg); 74 current->thread.fault_catcher = &buf;
75
76 faulted = UML_SETJMP(&buf);
77 if (faulted == 0)
78 n = (*op)(addr, len, arg);
79 else
80 n = -1;
81
82 current->thread.fault_catcher = NULL;
53 83
54 kunmap_atomic(page, KM_UML_USERCOPY); 84 kunmap_atomic(page, KM_UML_USERCOPY);
55 85
56 return n; 86 return n;
57} 87}
58 88
59static void do_buffer_op(void *jmpbuf, void *arg_ptr) 89static int buffer_op(unsigned long addr, int len, int is_write,
90 int (*op)(unsigned long, int, void *), void *arg)
60{ 91{
61 va_list args; 92 int size, remain, n;
62 unsigned long addr; 93
63 int len, is_write, size, remain, n;
64 int (*op)(unsigned long, int, void *);
65 void *arg;
66 int *res;
67
68 va_copy(args, *(va_list *)arg_ptr);
69 addr = va_arg(args, unsigned long);
70 len = va_arg(args, int);
71 is_write = va_arg(args, int);
72 op = va_arg(args, void *);
73 arg = va_arg(args, void *);
74 res = va_arg(args, int *);
75 va_end(args);
76 size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); 94 size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
77 remain = len; 95 remain = len;
78 96
79 current->thread.fault_catcher = jmpbuf;
80 n = do_op_one_page(addr, size, is_write, op, arg); 97 n = do_op_one_page(addr, size, is_write, op, arg);
81 if (n != 0) { 98 if (n != 0) {
82 *res = (n < 0 ? remain : 0); 99 remain = (n < 0 ? remain : 0);
83 goto out; 100 goto out;
84 } 101 }
85 102
86 addr += size; 103 addr += size;
87 remain -= size; 104 remain -= size;
88 if (remain == 0) { 105 if (remain == 0)
89 *res = 0;
90 goto out; 106 goto out;
91 }
92 107
93 while(addr < ((addr + remain) & PAGE_MASK)) { 108 while (addr < ((addr + remain) & PAGE_MASK)) {
94 n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); 109 n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
95 if (n != 0) { 110 if (n != 0) {
96 *res = (n < 0 ? remain : 0); 111 remain = (n < 0 ? remain : 0);
97 goto out; 112 goto out;
98 } 113 }
99 114
100 addr += PAGE_SIZE; 115 addr += PAGE_SIZE;
101 remain -= PAGE_SIZE; 116 remain -= PAGE_SIZE;
102 } 117 }
103 if (remain == 0) { 118 if (remain == 0)
104 *res = 0;
105 goto out; 119 goto out;
106 }
107 120
108 n = do_op_one_page(addr, remain, is_write, op, arg); 121 n = do_op_one_page(addr, remain, is_write, op, arg);
109 if (n != 0) 122 if (n != 0) {
110 *res = (n < 0 ? remain : 0); 123 remain = (n < 0 ? remain : 0);
111 else *res = 0; 124 goto out;
112 out: 125 }
113 current->thread.fault_catcher = NULL;
114}
115
116static int buffer_op(unsigned long addr, int len, int is_write,
117 int (*op)(unsigned long addr, int len, void *arg),
118 void *arg)
119{
120 int faulted, res;
121
122 faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
123 &res);
124 if (!faulted)
125 return res;
126 126
127 return addr + len - (unsigned long) current->thread.fault_addr; 127 return 0;
128 out:
129 return remain;
128} 130}
129 131
130static int copy_chunk_from_user(unsigned long from, int len, void *arg) 132static 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 36d89cf8d20b..e1062ec36d40 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);
21#include "asm/smp.h" 21#include "asm/smp.h"
22#include "asm/processor.h" 22#include "asm/processor.h"
23#include "asm/spinlock.h" 23#include "asm/spinlock.h"
24#include "kern_util.h"
25#include "kern.h" 24#include "kern.h"
26#include "irq_user.h" 25#include "irq_user.h"
27#include "os.h" 26#include "os.h"
@@ -61,7 +60,7 @@ void smp_send_stop(void)
61 continue; 60 continue;
62 os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); 61 os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
63 } 62 }
64 printk(KERN_INFO "done\n"); 63 printk(KERN_CONT "done\n");
65} 64}
66 65
67static cpumask_t smp_commenced_mask = CPU_MASK_NONE; 66static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -75,8 +74,7 @@ static int idle_proc(void *cpup)
75 if (err < 0) 74 if (err < 0)
76 panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); 75 panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
77 76
78 os_set_fd_async(cpu_data[cpu].ipi_pipe[0], 77 os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
79 current->thread.mode.tt.extern_pid);
80 78
81 wmb(); 79 wmb();
82 if (cpu_test_and_set(cpu, cpu_callin_map)) { 80 if (cpu_test_and_set(cpu, cpu_callin_map)) {
@@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
129 if (err < 0) 127 if (err < 0)
130 panic("CPU#0 failed to create IPI pipe, errno = %d", -err); 128 panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
131 129
132 os_set_fd_async(cpu_data[me].ipi_pipe[0], 130 os_set_fd_async(cpu_data[me].ipi_pipe[0]);
133 current->thread.mode.tt.extern_pid);
134 131
135 for (cpu = 1; cpu < ncpus; cpu++) { 132 for (cpu = 1; cpu < ncpus; cpu++) {
136 printk(KERN_INFO "Booting processor %d...\n", cpu); 133 printk(KERN_INFO "Booting processor %d...\n", cpu);
@@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
143 while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) 140 while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
144 cpu_relax(); 141 cpu_relax();
145 142
146 if (cpu_isset(cpu, cpu_callin_map)) 143 printk(KERN_INFO "%s\n",
147 printk(KERN_INFO "done\n"); 144 cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
148 else printk(KERN_INFO "failed\n");
149 } 145 }
150} 146}
151 147
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index b9d92b2089ae..9cffc628a37e 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,9 +13,6 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/unistd.h" 14#include "asm/unistd.h"
15 15
16/* Unlocked, I don't care if this is a bit off */
17int nsyscalls = 0;
18
19long sys_fork(void) 16long sys_fork(void)
20{ 17{
21 long ret; 18 long ret;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 93263571d813..56d43d0a3960 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -1,38 +1,37 @@
1/* 1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/sched.h" 6#include <linux/kallsyms.h>
7#include "linux/kernel.h" 7#include <linux/kernel.h>
8#include "linux/module.h" 8#include <linux/module.h>
9#include "linux/kallsyms.h" 9#include <linux/sched.h>
10#include "asm/page.h"
11#include "asm/processor.h"
12#include "sysrq.h" 10#include "sysrq.h"
13 11
14/* Catch non-i386 SUBARCH's. */ 12/* Catch non-i386 SUBARCH's. */
15#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) 13#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
16void show_trace(struct task_struct *task, unsigned long * stack) 14void show_trace(struct task_struct *task, unsigned long * stack)
17{ 15{
18 unsigned long addr; 16 unsigned long addr;
19 17
20 if (!stack) { 18 if (!stack) {
21 stack = (unsigned long*) &stack; 19 stack = (unsigned long*) &stack;
22 WARN_ON(1); 20 WARN_ON(1);
23 } 21 }
24 22
25 printk("Call Trace: \n"); 23 printk(KERN_INFO "Call Trace: \n");
26 while (((long) stack & (THREAD_SIZE-1)) != 0) { 24 while (((long) stack & (THREAD_SIZE-1)) != 0) {
27 addr = *stack; 25 addr = *stack;
28 if (__kernel_text_address(addr)) { 26 if (__kernel_text_address(addr)) {
29 printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); 27 printk(KERN_INFO "%08lx: [<%08lx>]",
30 print_symbol(" %s", addr); 28 (unsigned long) stack, addr);
31 printk("\n"); 29 print_symbol(KERN_CONT " %s", addr);
32 } 30 printk(KERN_CONT "\n");
33 stack++; 31 }
34 } 32 stack++;
35 printk("\n"); 33 }
34 printk(KERN_INFO "\n");
36} 35}
37#endif 36#endif
38 37
@@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp)
67 } 66 }
68 67
69 stack = esp; 68 stack = esp;
70 for(i = 0; i < kstack_depth_to_print; i++) { 69 for (i = 0; i < kstack_depth_to_print; i++) {
71 if (kstack_end(stack)) 70 if (kstack_end(stack))
72 break; 71 break;
73 if (i && ((i % 8) == 0)) 72 if (i && ((i % 8) == 0))
74 printk("\n "); 73 printk("\n" KERN_INFO " ");
75 printk("%08lx ", *stack++); 74 printk("%08lx ", *stack++);
76 } 75 }
77 76
78 printk("Call Trace: \n");
79 show_trace(task, esp); 77 show_trace(task, esp);
80} 78}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 1ac746a9eae1..e066e84493b1 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -3,12 +3,12 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/clockchips.h" 6#include <linux/clockchips.h>
7#include "linux/interrupt.h" 7#include <linux/interrupt.h>
8#include "linux/jiffies.h" 8#include <linux/jiffies.h>
9#include "linux/threads.h" 9#include <linux/threads.h>
10#include "asm/irq.h" 10#include <asm/irq.h>
11#include "asm/param.h" 11#include <asm/param.h>
12#include "kern_util.h" 12#include "kern_util.h"
13#include "os.h" 13#include "os.h"
14 14
@@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs)
32static void itimer_set_mode(enum clock_event_mode mode, 32static void itimer_set_mode(enum clock_event_mode mode,
33 struct clock_event_device *evt) 33 struct clock_event_device *evt)
34{ 34{
35 switch(mode) { 35 switch (mode) {
36 case CLOCK_EVT_MODE_PERIODIC: 36 case CLOCK_EVT_MODE_PERIODIC:
37 set_interval(); 37 set_interval();
38 break; 38 break;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f4a0e407eee4..d175d0566af0 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -3,9 +3,10 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/mm.h" 6#include <linux/mm.h>
7#include "asm/pgtable.h" 7#include <linux/sched.h>
8#include "asm/tlbflush.h" 8#include <asm/pgtable.h>
9#include <asm/tlbflush.h>
9#include "as-layout.h" 10#include "as-layout.h"
10#include "mem_user.h" 11#include "mem_user.h"
11#include "os.h" 12#include "os.h"
@@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
56 57
57 for (i = 0; i < end && !ret; i++) { 58 for (i = 0; i < end && !ret; i++) {
58 op = &hvc->ops[i]; 59 op = &hvc->ops[i];
59 switch(op->type) { 60 switch (op->type) {
60 case MMAP: 61 case MMAP:
61 ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, 62 ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
62 op->u.mmap.prot, op->u.mmap.fd, 63 op->u.mmap.prot, op->u.mmap.fd,
@@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
183 184
184 pte = pte_offset_kernel(pmd, addr); 185 pte = pte_offset_kernel(pmd, addr);
185 do { 186 do {
187 if ((addr >= STUB_START) && (addr < STUB_END))
188 continue;
189
186 r = pte_read(*pte); 190 r = pte_read(*pte);
187 w = pte_write(*pte); 191 w = pte_write(*pte);
188 x = pte_exec(*pte); 192 x = pte_exec(*pte);
189 if (!pte_young(*pte)) { 193 if (!pte_young(*pte)) {
190 r = 0; 194 r = 0;
191 w = 0; 195 w = 0;
192 } else if (!pte_dirty(*pte)) { 196 } else if (!pte_dirty(*pte))
193 w = 0; 197 w = 0;
194 } 198
195 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | 199 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
196 (x ? UM_PROT_EXEC : 0)); 200 (x ? UM_PROT_EXEC : 0));
197 if (hvc->force || pte_newpage(*pte)) { 201 if (hvc->force || pte_newpage(*pte)) {
198 if (pte_present(*pte)) 202 if (pte_present(*pte))
199 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, 203 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
200 PAGE_SIZE, prot, hvc); 204 PAGE_SIZE, prot, hvc);
201 else ret = add_munmap(addr, PAGE_SIZE, hvc); 205 else
202 } 206 ret = add_munmap(addr, PAGE_SIZE, hvc);
203 else if (pte_newprot(*pte)) 207 } else if (pte_newprot(*pte))
204 ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); 208 ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
205 *pte = pte_mkuptodate(*pte); 209 *pte = pte_mkuptodate(*pte);
206 } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); 210 } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
207 return ret; 211 return ret;
208} 212}
209 213
@@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
225 } 229 }
226 } 230 }
227 else ret = update_pte_range(pmd, addr, next, hvc); 231 else ret = update_pte_range(pmd, addr, next, hvc);
228 } while (pmd++, addr = next, ((addr != end) && !ret)); 232 } while (pmd++, addr = next, ((addr < end) && !ret));
229 return ret; 233 return ret;
230} 234}
231 235
@@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
247 } 251 }
248 } 252 }
249 else ret = update_pmd_range(pud, addr, next, hvc); 253 else ret = update_pmd_range(pud, addr, next, hvc);
250 } while (pud++, addr = next, ((addr != end) && !ret)); 254 } while (pud++, addr = next, ((addr < end) && !ret));
251 return ret; 255 return ret;
252} 256}
253 257
@@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
270 } 274 }
271 } 275 }
272 else ret = update_pud_range(pgd, addr, next, &hvc); 276 else ret = update_pud_range(pgd, addr, next, &hvc);
273 } while (pgd++, addr = next, ((addr != end_addr) && !ret)); 277 } while (pgd++, addr = next, ((addr < end_addr) && !ret));
274 278
275 if (!ret) 279 if (!ret)
276 ret = do_ops(&hvc, hvc.index, 1); 280 ret = do_ops(&hvc, hvc.index, 1);
@@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
485static void fix_range(struct mm_struct *mm, unsigned long start_addr, 489static void fix_range(struct mm_struct *mm, unsigned long start_addr,
486 unsigned long end_addr, int force) 490 unsigned long end_addr, int force)
487{ 491{
488 if (!proc_mm && (end_addr > STUB_START))
489 end_addr = STUB_START;
490
491 fix_range_common(mm, start_addr, end_addr, force); 492 fix_range_common(mm, start_addr, end_addr, force);
492} 493}
493 494
@@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
499 else fix_range(vma->vm_mm, start, end, 0); 500 else fix_range(vma->vm_mm, start, end, 0);
500} 501}
501 502
502void flush_tlb_mm(struct mm_struct *mm) 503void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
504 unsigned long end)
503{ 505{
504 unsigned long end;
505
506 /* 506 /*
507 * Don't bother flushing if this address space is about to be 507 * Don't bother flushing if this address space is about to be
508 * destroyed. 508 * destroyed.
@@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm)
510 if (atomic_read(&mm->mm_users) == 0) 510 if (atomic_read(&mm->mm_users) == 0)
511 return; 511 return;
512 512
513 end = proc_mm ? task_size : STUB_START; 513 fix_range(mm, start, end, 0);
514 fix_range(mm, 0, end, 0); 514}
515
516void flush_tlb_mm(struct mm_struct *mm)
517{
518 struct vm_area_struct *vma = mm->mmap;
519
520 while (vma != NULL) {
521 fix_range(mm, vma->vm_start, vma->vm_end, 0);
522 vma = vma->vm_next;
523 }
515} 524}
516 525
517void force_flush_all(void) 526void force_flush_all(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index cb3321f8e0a9..44e490419495 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -13,6 +13,7 @@
13#include "as-layout.h" 13#include "as-layout.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "os.h" 15#include "os.h"
16#include "skas.h"
16#include "sysdep/sigcontext.h" 17#include "sysdep/sigcontext.h"
17 18
18/* 19/*
@@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
128 force_sig_info(SIGSEGV, &si, current); 129 force_sig_info(SIGSEGV, &si, current);
129} 130}
130 131
131static void segv_handler(int sig, struct uml_pt_regs *regs) 132void fatal_sigsegv(void)
133{
134 force_sigsegv(SIGSEGV, current);
135 do_signal();
136 /*
137 * This is to tell gcc that we're not returning - do_signal
138 * can, in general, return, but in this case, it's not, since
139 * we just got a fatal SIGSEGV queued.
140 */
141 os_dump_core();
142}
143
144void segv_handler(int sig, struct uml_pt_regs *regs)
132{ 145{
133 struct faultinfo * fi = UPT_FAULTINFO(regs); 146 struct faultinfo * fi = UPT_FAULTINFO(regs);
134 147
@@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
216 229
217void relay_signal(int sig, struct uml_pt_regs *regs) 230void relay_signal(int sig, struct uml_pt_regs *regs)
218{ 231{
219 if (arch_handle_signal(sig, regs))
220 return;
221
222 if (!UPT_IS_USER(regs)) { 232 if (!UPT_IS_USER(regs)) {
223 if (sig == SIGBUS) 233 if (sig == SIGBUS)
224 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " 234 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)
226 panic("Kernel mode signal %d", sig); 236 panic("Kernel mode signal %d", sig);
227 } 237 }
228 238
239 arch_examine_signal(sig, regs);
240
229 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 241 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
230 force_sig(sig, current); 242 force_sig(sig, current);
231} 243}
232 244
233static void bus_handler(int sig, struct uml_pt_regs *regs) 245void bus_handler(int sig, struct uml_pt_regs *regs)
234{ 246{
235 if (current->thread.fault_catcher != NULL) 247 if (current->thread.fault_catcher != NULL)
236 UML_LONGJMP(current->thread.fault_catcher, 1); 248 UML_LONGJMP(current->thread.fault_catcher, 1);
237 else relay_signal(sig, regs); 249 else relay_signal(sig, regs);
238} 250}
239 251
240static void winch(int sig, struct uml_pt_regs *regs) 252void winch(int sig, struct uml_pt_regs *regs)
241{ 253{
242 do_IRQ(WINCH_IRQ, regs); 254 do_IRQ(WINCH_IRQ, regs);
243} 255}
244 256
245const struct kern_handlers handlinfo_kern = {
246 .relay_signal = relay_signal,
247 .winch = winch,
248 .bus_handler = bus_handler,
249 .page_fault = segv_handler,
250 .sigio_handler = sigio_handler,
251 .timer_handler = timer_handler
252};
253
254void trap_init(void) 257void trap_init(void)
255{ 258{
256} 259}
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index d7436aacd26f..f0f4b040d7c5 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -1,10 +1,11 @@
1/* 1/*
2 * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) 2 * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
3 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7/* These are here rather than tt/uaccess.c because skas mode needs them in 7/*
8 * These are here rather than tt/uaccess.c because skas mode needs them in
8 * order to do SIGBUS recovery when a tmpfs mount runs out of room. 9 * order to do SIGBUS recovery when a tmpfs mount runs out of room.
9 */ 10 */
10 11
@@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n,
25 26
26 fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, 27 fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
27 __do_copy, &faulted); 28 __do_copy, &faulted);
28 if(!faulted) return(0); 29 if (!faulted)
29 else return(n - (fault - (unsigned long) to)); 30 return 0;
31 else
32 return n - (fault - (unsigned long) to);
30} 33}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index f1c71393f578..468aba990dbd 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -3,22 +3,23 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/delay.h" 6#include <linux/delay.h>
7#include "linux/mm.h" 7#include <linux/init.h>
8#include "linux/module.h" 8#include <linux/mm.h>
9#include "linux/seq_file.h" 9#include <linux/module.h>
10#include "linux/string.h" 10#include <linux/seq_file.h>
11#include "linux/utsname.h" 11#include <linux/string.h>
12#include "asm/pgtable.h" 12#include <linux/utsname.h>
13#include "asm/processor.h" 13#include <asm/pgtable.h>
14#include "asm/setup.h" 14#include <asm/processor.h>
15#include "arch.h" 15#include <asm/setup.h>
16#include "as-layout.h" 16#include "as-layout.h"
17#include "arch.h"
17#include "init.h" 18#include "init.h"
18#include "kern.h" 19#include "kern.h"
20#include "kern_util.h"
19#include "mem_user.h" 21#include "mem_user.h"
20#include "os.h" 22#include "os.h"
21#include "skas.h"
22 23
23#define DEFAULT_COMMAND_LINE "root=98:0" 24#define DEFAULT_COMMAND_LINE "root=98:0"
24 25
@@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = {
100}; 101};
101 102
102/* Set in linux_main */ 103/* Set in linux_main */
103unsigned long host_task_size;
104unsigned long task_size;
105unsigned long uml_physmem; 104unsigned long uml_physmem;
106unsigned long uml_reserved; /* Also modified in mem_init */ 105unsigned long uml_reserved; /* Also modified in mem_init */
107unsigned long start_vm; 106unsigned long start_vm;
@@ -197,20 +196,19 @@ __uml_setup("--help", Usage,
197" Prints this message.\n\n" 196" Prints this message.\n\n"
198); 197);
199 198
200static int __init uml_checksetup(char *line, int *add) 199static void __init uml_checksetup(char *line, int *add)
201{ 200{
202 struct uml_param *p; 201 struct uml_param *p;
203 202
204 p = &__uml_setup_start; 203 p = &__uml_setup_start;
205 while(p < &__uml_setup_end) { 204 while (p < &__uml_setup_end) {
206 int n; 205 int n;
207 206
208 n = strlen(p->str); 207 n = strlen(p->str);
209 if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) 208 if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
210 return 1; 209 return;
211 p++; 210 p++;
212 } 211 }
213 return 0;
214} 212}
215 213
216static void __init uml_postsetup(void) 214static void __init uml_postsetup(void)
@@ -218,13 +216,30 @@ static void __init uml_postsetup(void)
218 initcall_t *p; 216 initcall_t *p;
219 217
220 p = &__uml_postsetup_start; 218 p = &__uml_postsetup_start;
221 while(p < &__uml_postsetup_end) { 219 while (p < &__uml_postsetup_end) {
222 (*p)(); 220 (*p)();
223 p++; 221 p++;
224 } 222 }
225 return; 223 return;
226} 224}
227 225
226static int panic_exit(struct notifier_block *self, unsigned long unused1,
227 void *unused2)
228{
229 bust_spinlocks(1);
230 show_regs(&(current->thread.regs));
231 bust_spinlocks(0);
232 uml_exitcode = 1;
233 os_dump_core();
234 return 0;
235}
236
237static struct notifier_block panic_exit_notifier = {
238 .notifier_call = panic_exit,
239 .next = NULL,
240 .priority = 0
241};
242
228/* Set during early boot */ 243/* Set during early boot */
229unsigned long brk_start; 244unsigned long brk_start;
230unsigned long end_iomem; 245unsigned long end_iomem;
@@ -234,20 +249,6 @@ EXPORT_SYMBOL(end_iomem);
234 249
235extern char __binary_start; 250extern char __binary_start;
236 251
237static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
238{
239 /* Round up to the nearest 4M */
240 unsigned long host_task_size = ROUND_4M((unsigned long)
241 &host_task_size);
242
243 if (!skas_needs_stub)
244 *task_size_out = host_task_size;
245 else
246 *task_size_out = STUB_START & PGDIR_MASK;
247
248 return host_task_size;
249}
250
251int __init linux_main(int argc, char **argv) 252int __init linux_main(int argc, char **argv)
252{ 253{
253 unsigned long avail, diff; 254 unsigned long avail, diff;
@@ -278,13 +279,6 @@ int __init linux_main(int argc, char **argv)
278 279
279 printf("UML running in %s mode\n", mode); 280 printf("UML running in %s mode\n", mode);
280 281
281 host_task_size = set_task_sizes_skas(&task_size);
282
283 /*
284 * Setting up handlers to 'sig_info' struct
285 */
286 os_fill_handlinfo(handlinfo_kern);
287
288 brk_start = (unsigned long) sbrk(0); 282 brk_start = (unsigned long) sbrk(0);
289 283
290 /* 284 /*
@@ -309,7 +303,7 @@ int __init linux_main(int argc, char **argv)
309 303
310 highmem = 0; 304 highmem = 0;
311 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 305 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
312 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 306 max_physmem = CONFIG_TOP_ADDR - uml_physmem - iomem_size - MIN_VMALLOC;
313 307
314 /* 308 /*
315 * Zones have to begin on a 1 << MAX_ORDER page boundary, 309 * Zones have to begin on a 1 << MAX_ORDER page boundary,
@@ -341,7 +335,7 @@ int __init linux_main(int argc, char **argv)
341 } 335 }
342 336
343 virtmem_size = physmem_size; 337 virtmem_size = physmem_size;
344 avail = get_kmem_end() - start_vm; 338 avail = CONFIG_TOP_ADDR - start_vm;
345 if (physmem_size > avail) 339 if (physmem_size > avail)
346 virtmem_size = avail; 340 virtmem_size = avail;
347 end_vm = start_vm + virtmem_size; 341 end_vm = start_vm + virtmem_size;
@@ -350,6 +344,9 @@ int __init linux_main(int argc, char **argv)
350 printf("Kernel virtual memory size shrunk to %lu bytes\n", 344 printf("Kernel virtual memory size shrunk to %lu bytes\n",
351 virtmem_size); 345 virtmem_size);
352 346
347 atomic_notifier_chain_register(&panic_notifier_list,
348 &panic_exit_notifier);
349
353 uml_postsetup(); 350 uml_postsetup();
354 351
355 stack_protections((unsigned long) &init_thread_info); 352 stack_protections((unsigned long) &init_thread_info);
@@ -358,29 +355,8 @@ int __init linux_main(int argc, char **argv)
358 return start_uml(); 355 return start_uml();
359} 356}
360 357
361extern int uml_exitcode;
362
363static int panic_exit(struct notifier_block *self, unsigned long unused1,
364 void *unused2)
365{
366 bust_spinlocks(1);
367 show_regs(&(current->thread.regs));
368 bust_spinlocks(0);
369 uml_exitcode = 1;
370 os_dump_core();
371 return 0;
372}
373
374static struct notifier_block panic_exit_notifier = {
375 .notifier_call = panic_exit,
376 .next = NULL,
377 .priority = 0
378};
379
380void __init setup_arch(char **cmdline_p) 358void __init setup_arch(char **cmdline_p)
381{ 359{
382 atomic_notifier_chain_register(&panic_notifier_list,
383 &panic_exit_notifier);
384 paging_init(); 360 paging_init();
385 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 361 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
386 *cmdline_p = command_line; 362 *cmdline_p = command_line;
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 039e16efcd55..81e07e2be3ae 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -1,13 +1,12 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "asm/errno.h" 6#include <asm/errno.h>
7#include "init.h" 7#include "init.h"
8#include "os.h"
9#include "kern.h" 8#include "kern.h"
10#include "linux/kernel.h" 9#include "os.h"
11 10
12/* Changed by set_umid_arg */ 11/* Changed by set_umid_arg */
13static int umid_inited = 0; 12static int umid_inited = 0;
@@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add)
16{ 15{
17 int err; 16 int err;
18 17
19 if(umid_inited){ 18 if (umid_inited) {
20 printf("umid already set\n"); 19 printf("umid already set\n");
21 return 0; 20 return 0;
22 } 21 }
23 22
24 *add = 0; 23 *add = 0;
25 err = set_umid(name); 24 err = set_umid(name);
26 if(err == -EEXIST) 25 if (err == -EEXIST)
27 printf("umid '%s' already in use\n", name); 26 printf("umid '%s' already in use\n", name);
28 else if(!err) 27 else if (!err)
29 umid_inited = 1; 28 umid_inited = 1;
30 29
31 return 0; 30 return 0;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 8e129af8170d..8a48d6a30064 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,7 +4,7 @@
4# 4#
5 5
6obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ 6obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
7 registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ 7 registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
8 umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ 8 umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
9 9
10obj-$(CONFIG_TTY_LOG) += tty_log.o 10obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
12 12
13USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ 13USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
14 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ 14 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
15 trap.o tty.o tls.o uaccess.o umid.o util.o 15 tty.o tls.o uaccess.o umid.o util.o
16 16
17CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) 17CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
18 18
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 93dc0c80ebaf..b8d8c9ca8d4a 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -12,6 +12,7 @@
12#include "aio.h" 12#include "aio.h"
13#include "init.h" 13#include "init.h"
14#include "kern_constants.h" 14#include "kern_constants.h"
15#include "kern_util.h"
15#include "os.h" 16#include "os.h"
16#include "user.h" 17#include "user.h"
17 18
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 07ca0cb472ac..6fb0b174f538 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,
131 } 131 }
132 if (c != 1) { 132 if (c != 1) {
133 printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); 133 printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
134 err = helper_wait(pid, 0, "uml_net"); 134 err = helper_wait(pid);
135 } 135 }
136 return err; 136 return err;
137} 137}
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 1037a3b6386e..2448be03fd7a 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -14,6 +14,7 @@
14#include <sys/wait.h> 14#include <sys/wait.h>
15#include <sys/uio.h> 15#include <sys/uio.h>
16#include "kern_constants.h" 16#include "kern_constants.h"
17#include "kern_util.h"
17#include "os.h" 18#include "os.h"
18#include "tuntap.h" 19#include "tuntap.h"
19#include "user.h" 20#include "user.h"
@@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
107 "errno = %d\n", errno); 108 "errno = %d\n", errno);
108 return err; 109 return err;
109 } 110 }
110 helper_wait(pid, 0, "tuntap_open_tramp"); 111 helper_wait(pid);
111 112
112 cmsg = CMSG_FIRSTHDR(&msg); 113 cmsg = CMSG_FIRSTHDR(&msg);
113 if (cmsg == NULL) { 114 if (cmsg == NULL) {
@@ -148,7 +149,7 @@ static int tuntap_open(void *data)
148 memset(&ifr, 0, sizeof(ifr)); 149 memset(&ifr, 0, sizeof(ifr));
149 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 150 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
150 strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); 151 strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
151 if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) { 152 if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
152 err = -errno; 153 err = -errno;
153 printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", 154 printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
154 errno); 155 errno);
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f83462758627..b5afcfd0f861 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -8,18 +8,16 @@
8#include <errno.h> 8#include <errno.h>
9#include <fcntl.h> 9#include <fcntl.h>
10#include <signal.h> 10#include <signal.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <sys/socket.h>
14#include <sys/un.h>
15#include <sys/ioctl.h> 11#include <sys/ioctl.h>
16#include <sys/mount.h> 12#include <sys/mount.h>
17#include <sys/uio.h> 13#include <sys/socket.h>
14#include <sys/stat.h>
15#include <sys/un.h>
16#include "kern_constants.h"
18#include "os.h" 17#include "os.h"
19#include "user.h" 18#include "user.h"
20#include "kern_util.h"
21 19
22static void copy_stat(struct uml_stat *dst, struct stat64 *src) 20static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
23{ 21{
24 *dst = ((struct uml_stat) { 22 *dst = ((struct uml_stat) {
25 .ust_dev = src->st_dev, /* device */ 23 .ust_dev = src->st_dev, /* device */
@@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
43 int err; 41 int err;
44 42
45 CATCH_EINTR(err = fstat64(fd, &sbuf)); 43 CATCH_EINTR(err = fstat64(fd, &sbuf));
46 if(err < 0) 44 if (err < 0)
47 return -errno; 45 return -errno;
48 46
49 if(ubuf != NULL) 47 if (ubuf != NULL)
50 copy_stat(ubuf, &sbuf); 48 copy_stat(ubuf, &sbuf);
51 return err; 49 return err;
52} 50}
@@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
56 struct stat64 sbuf; 54 struct stat64 sbuf;
57 int err; 55 int err;
58 56
59 do { 57 CATCH_EINTR(err = stat64(file_name, &sbuf));
60 err = stat64(file_name, &sbuf); 58 if (err < 0)
61 } while((err < 0) && (errno == EINTR)) ;
62
63 if(err < 0)
64 return -errno; 59 return -errno;
65 60
66 if(ubuf != NULL) 61 if (ubuf != NULL)
67 copy_stat(ubuf, &sbuf); 62 copy_stat(ubuf, &sbuf);
68 return err; 63 return err;
69} 64}
70 65
71int os_access(const char* file, int mode) 66int os_access(const char *file, int mode)
72{ 67{
73 int amode, err; 68 int amode, err;
74 69
75 amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | 70 amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
76 (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; 71 (mode & OS_ACC_W_OK ? W_OK : 0) |
72 (mode & OS_ACC_X_OK ? X_OK : 0) |
73 (mode & OS_ACC_F_OK ? F_OK : 0);
77 74
78 err = access(file, amode); 75 err = access(file, amode);
79 if(err < 0) 76 if (err < 0)
80 return -errno; 77 return -errno;
81 78
82 return 0; 79 return 0;
@@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
88 int err; 85 int err;
89 86
90 err = ioctl(fd, cmd, arg); 87 err = ioctl(fd, cmd, arg);
91 if(err < 0) 88 if (err < 0)
92 return -errno; 89 return -errno;
93 90
94 return err; 91 return err;
@@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
97/* FIXME: ensure namebuf in os_get_if_name is big enough */ 94/* FIXME: ensure namebuf in os_get_if_name is big enough */
98int os_get_ifname(int fd, char* namebuf) 95int os_get_ifname(int fd, char* namebuf)
99{ 96{
100 if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) 97 if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
101 return -errno; 98 return -errno;
102 99
103 return 0; 100 return 0;
@@ -108,37 +105,22 @@ int os_set_slip(int fd)
108 int disc, sencap; 105 int disc, sencap;
109 106
110 disc = N_SLIP; 107 disc = N_SLIP;
111 if(ioctl(fd, TIOCSETD, &disc) < 0) 108 if (ioctl(fd, TIOCSETD, &disc) < 0)
112 return -errno; 109 return -errno;
113 110
114 sencap = 0; 111 sencap = 0;
115 if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) 112 if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
116 return -errno; 113 return -errno;
117 114
118 return 0; 115 return 0;
119} 116}
120 117
121int os_set_owner(int fd, int pid)
122{
123 if(fcntl(fd, F_SETOWN, pid) < 0){
124 int save_errno = errno;
125
126 if(fcntl(fd, F_GETOWN, 0) != pid)
127 return -save_errno;
128 }
129
130 return 0;
131}
132
133int os_mode_fd(int fd, int mode) 118int os_mode_fd(int fd, int mode)
134{ 119{
135 int err; 120 int err;
136 121
137 do { 122 CATCH_EINTR(err = fchmod(fd, mode));
138 err = fchmod(fd, mode); 123 if (err < 0)
139 } while((err < 0) && (errno==EINTR)) ;
140
141 if(err < 0)
142 return -errno; 124 return -errno;
143 125
144 return 0; 126 return 0;
@@ -150,64 +132,73 @@ int os_file_type(char *file)
150 int err; 132 int err;
151 133
152 err = os_stat_file(file, &buf); 134 err = os_stat_file(file, &buf);
153 if(err < 0) 135 if (err < 0)
154 return err; 136 return err;
155 137
156 if(S_ISDIR(buf.ust_mode)) 138 if (S_ISDIR(buf.ust_mode))
157 return OS_TYPE_DIR; 139 return OS_TYPE_DIR;
158 else if(S_ISLNK(buf.ust_mode)) 140 else if (S_ISLNK(buf.ust_mode))
159 return OS_TYPE_SYMLINK; 141 return OS_TYPE_SYMLINK;
160 else if(S_ISCHR(buf.ust_mode)) 142 else if (S_ISCHR(buf.ust_mode))
161 return OS_TYPE_CHARDEV; 143 return OS_TYPE_CHARDEV;
162 else if(S_ISBLK(buf.ust_mode)) 144 else if (S_ISBLK(buf.ust_mode))
163 return OS_TYPE_BLOCKDEV; 145 return OS_TYPE_BLOCKDEV;
164 else if(S_ISFIFO(buf.ust_mode)) 146 else if (S_ISFIFO(buf.ust_mode))
165 return OS_TYPE_FIFO; 147 return OS_TYPE_FIFO;
166 else if(S_ISSOCK(buf.ust_mode)) 148 else if (S_ISSOCK(buf.ust_mode))
167 return OS_TYPE_SOCK; 149 return OS_TYPE_SOCK;
168 else return OS_TYPE_FILE; 150 else return OS_TYPE_FILE;
169} 151}
170 152
171int os_file_mode(char *file, struct openflags *mode_out) 153int os_file_mode(const char *file, struct openflags *mode_out)
172{ 154{
173 int err; 155 int err;
174 156
175 *mode_out = OPENFLAGS(); 157 *mode_out = OPENFLAGS();
176 158
177 err = access(file, W_OK); 159 err = access(file, W_OK);
178 if(err && (errno != EACCES)) 160 if (err && (errno != EACCES))
179 return -errno; 161 return -errno;
180 else if(!err) 162 else if (!err)
181 *mode_out = of_write(*mode_out); 163 *mode_out = of_write(*mode_out);
182 164
183 err = access(file, R_OK); 165 err = access(file, R_OK);
184 if(err && (errno != EACCES)) 166 if (err && (errno != EACCES))
185 return -errno; 167 return -errno;
186 else if(!err) 168 else if (!err)
187 *mode_out = of_read(*mode_out); 169 *mode_out = of_read(*mode_out);
188 170
189 return err; 171 return err;
190} 172}
191 173
192int os_open_file(char *file, struct openflags flags, int mode) 174int os_open_file(const char *file, struct openflags flags, int mode)
193{ 175{
194 int fd, err, f = 0; 176 int fd, err, f = 0;
195 177
196 if(flags.r && flags.w) f = O_RDWR; 178 if (flags.r && flags.w)
197 else if(flags.r) f = O_RDONLY; 179 f = O_RDWR;
198 else if(flags.w) f = O_WRONLY; 180 else if (flags.r)
181 f = O_RDONLY;
182 else if (flags.w)
183 f = O_WRONLY;
199 else f = 0; 184 else f = 0;
200 185
201 if(flags.s) f |= O_SYNC; 186 if (flags.s)
202 if(flags.c) f |= O_CREAT; 187 f |= O_SYNC;
203 if(flags.t) f |= O_TRUNC; 188 if (flags.c)
204 if(flags.e) f |= O_EXCL; 189 f |= O_CREAT;
190 if (flags.t)
191 f |= O_TRUNC;
192 if (flags.e)
193 f |= O_EXCL;
194 if (flags.a)
195 f |= O_APPEND;
205 196
206 fd = open64(file, f, mode); 197 fd = open64(file, f, mode);
207 if(fd < 0) 198 if (fd < 0)
208 return -errno; 199 return -errno;
209 200
210 if(flags.cl && fcntl(fd, F_SETFD, 1)){ 201 if (flags.cl && fcntl(fd, F_SETFD, 1)) {
211 err = -errno; 202 err = -errno;
212 close(fd); 203 close(fd);
213 return err; 204 return err;
@@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode)
216 return fd; 207 return fd;
217} 208}
218 209
219int os_connect_socket(char *name) 210int os_connect_socket(const char *name)
220{ 211{
221 struct sockaddr_un sock; 212 struct sockaddr_un sock;
222 int fd, err; 213 int fd, err;
@@ -225,13 +216,13 @@ int os_connect_socket(char *name)
225 snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); 216 snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
226 217
227 fd = socket(AF_UNIX, SOCK_STREAM, 0); 218 fd = socket(AF_UNIX, SOCK_STREAM, 0);
228 if(fd < 0) { 219 if (fd < 0) {
229 err = -errno; 220 err = -errno;
230 goto out; 221 goto out;
231 } 222 }
232 223
233 err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); 224 err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
234 if(err) { 225 if (err) {
235 err = -errno; 226 err = -errno;
236 goto out_close; 227 goto out_close;
237 } 228 }
@@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset)
254 unsigned long long actual; 245 unsigned long long actual;
255 246
256 actual = lseek64(fd, offset, SEEK_SET); 247 actual = lseek64(fd, offset, SEEK_SET);
257 if(actual != offset) 248 if (actual != offset)
258 return -errno; 249 return -errno;
259 return 0; 250 return 0;
260} 251}
@@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len)
263{ 254{
264 int n = read(fd, buf, len); 255 int n = read(fd, buf, len);
265 256
266 if(n < 0) 257 if (n < 0)
267 return -errno; 258 return -errno;
268 return n; 259 return n;
269} 260}
@@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len)
272{ 263{
273 int n = write(fd, (void *) buf, len); 264 int n = write(fd, (void *) buf, len);
274 265
275 if(n < 0) 266 if (n < 0)
276 return -errno; 267 return -errno;
277 return n; 268 return n;
278} 269}
279 270
280int os_file_size(char *file, unsigned long long *size_out) 271int os_file_size(const char *file, unsigned long long *size_out)
281{ 272{
282 struct uml_stat buf; 273 struct uml_stat buf;
283 int err; 274 int err;
284 275
285 err = os_stat_file(file, &buf); 276 err = os_stat_file(file, &buf);
286 if(err < 0){ 277 if (err < 0) {
287 printk("Couldn't stat \"%s\" : err = %d\n", file, -err); 278 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
279 -err);
288 return err; 280 return err;
289 } 281 }
290 282
291 if(S_ISBLK(buf.ust_mode)){ 283 if (S_ISBLK(buf.ust_mode)) {
292 int fd; 284 int fd;
293 long blocks; 285 long blocks;
294 286
295 fd = open(file, O_RDONLY, 0); 287 fd = open(file, O_RDONLY, 0);
296 if(fd < 0) { 288 if (fd < 0) {
297 err = -errno; 289 err = -errno;
298 printk("Couldn't open \"%s\", errno = %d\n", file, 290 printk(UM_KERN_ERR "Couldn't open \"%s\", "
299 errno); 291 "errno = %d\n", file, errno);
300 return err; 292 return err;
301 } 293 }
302 if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ 294 if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
303 err = -errno; 295 err = -errno;
304 printk("Couldn't get the block size of \"%s\", " 296 printk(UM_KERN_ERR "Couldn't get the block size of "
305 "errno = %d\n", file, errno); 297 "\"%s\", errno = %d\n", file, errno);
306 close(fd); 298 close(fd);
307 return err; 299 return err;
308 } 300 }
@@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out)
314 return 0; 306 return 0;
315} 307}
316 308
317int os_file_modtime(char *file, unsigned long *modtime) 309int os_file_modtime(const char *file, unsigned long *modtime)
318{ 310{
319 struct uml_stat buf; 311 struct uml_stat buf;
320 int err; 312 int err;
321 313
322 err = os_stat_file(file, &buf); 314 err = os_stat_file(file, &buf);
323 if(err < 0){ 315 if (err < 0) {
324 printk("Couldn't stat \"%s\" : err = %d\n", file, -err); 316 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
317 -err);
325 return err; 318 return err;
326 } 319 }
327 320
@@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime)
329 return 0; 322 return 0;
330} 323}
331 324
332int os_get_exec_close(int fd, int *close_on_exec)
333{
334 int ret;
335
336 CATCH_EINTR(ret = fcntl(fd, F_GETFD));
337
338 if(ret < 0)
339 return -errno;
340
341 *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
342 return ret;
343}
344
345int os_set_exec_close(int fd) 325int os_set_exec_close(int fd)
346{ 326{
347 int err; 327 int err;
348 328
349 CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); 329 CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
350 330
351 if(err < 0) 331 if (err < 0)
352 return -errno; 332 return -errno;
353 return err; 333 return err;
354} 334}
@@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec)
358 int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; 338 int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
359 339
360 err = socketpair(AF_UNIX, type, 0, fds); 340 err = socketpair(AF_UNIX, type, 0, fds);
361 if(err < 0) 341 if (err < 0)
362 return -errno; 342 return -errno;
363 343
364 if(!close_on_exec) 344 if (!close_on_exec)
365 return 0; 345 return 0;
366 346
367 err = os_set_exec_close(fds[0]); 347 err = os_set_exec_close(fds[0]);
368 if(err < 0) 348 if (err < 0)
369 goto error; 349 goto error;
370 350
371 err = os_set_exec_close(fds[1]); 351 err = os_set_exec_close(fds[1]);
372 if(err < 0) 352 if (err < 0)
373 goto error; 353 goto error;
374 354
375 return 0; 355 return 0;
376 356
377 error: 357 error:
378 printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); 358 printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
359 -err);
379 close(fds[1]); 360 close(fds[1]);
380 close(fds[0]); 361 close(fds[0]);
381 return err; 362 return err;
382} 363}
383 364
384int os_set_fd_async(int fd, int owner) 365int os_set_fd_async(int fd)
385{ 366{
386 int err; 367 int err, flags;
368
369 flags = fcntl(fd, F_GETFL);
370 if (flags < 0)
371 return -errno;
387 372
388 /* XXX This should do F_GETFL first */ 373 flags |= O_ASYNC | O_NONBLOCK;
389 if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ 374 if (fcntl(fd, F_SETFL, flags) < 0) {
390 err = -errno; 375 err = -errno;
391 printk("os_set_fd_async : failed to set O_ASYNC and " 376 printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
392 "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); 377 "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
393 return err; 378 return err;
394 } 379 }
395#ifdef notdef
396 if(fcntl(fd, F_SETFD, 1) < 0){
397 printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
398 "errno = %d\n", errno);
399 }
400#endif
401 380
402 if((fcntl(fd, F_SETSIG, SIGIO) < 0) || 381 if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
403 (fcntl(fd, F_SETOWN, owner) < 0)){ 382 (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
404 err = -errno; 383 err = -errno;
405 printk("os_set_fd_async : Failed to fcntl F_SETOWN " 384 printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
406 "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, 385 "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
407 owner, errno);
408 return err; 386 return err;
409 } 387 }
410 388
@@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner)
413 391
414int os_clear_fd_async(int fd) 392int os_clear_fd_async(int fd)
415{ 393{
416 int flags = fcntl(fd, F_GETFL); 394 int flags;
395
396 flags = fcntl(fd, F_GETFL);
397 if (flags < 0)
398 return -errno;
417 399
418 flags &= ~(O_ASYNC | O_NONBLOCK); 400 flags &= ~(O_ASYNC | O_NONBLOCK);
419 if(fcntl(fd, F_SETFL, flags) < 0) 401 if (fcntl(fd, F_SETFL, flags) < 0)
420 return -errno; 402 return -errno;
421 return 0; 403 return 0;
422} 404}
@@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking)
426 int flags; 408 int flags;
427 409
428 flags = fcntl(fd, F_GETFL); 410 flags = fcntl(fd, F_GETFL);
411 if (flags < 0)
412 return -errno;
429 413
430 if(blocking) flags &= ~O_NONBLOCK; 414 if (blocking)
431 else flags |= O_NONBLOCK; 415 flags &= ~O_NONBLOCK;
416 else
417 flags |= O_NONBLOCK;
432 418
433 if(fcntl(fd, F_SETFL, flags) < 0) 419 if (fcntl(fd, F_SETFL, flags) < 0)
434 return -errno; 420 return -errno;
435 421
436 return 0; 422 return 0;
@@ -441,7 +427,7 @@ int os_accept_connection(int fd)
441 int new; 427 int new;
442 428
443 new = accept(fd, NULL, 0); 429 new = accept(fd, NULL, 0);
444 if(new < 0) 430 if (new < 0)
445 return -errno; 431 return -errno;
446 return new; 432 return new;
447} 433}
@@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w)
462{ 448{
463 int what, err; 449 int what, err;
464 450
465 if(r && w) what = SHUT_RDWR; 451 if (r && w)
466 else if(r) what = SHUT_RD; 452 what = SHUT_RDWR;
467 else if(w) what = SHUT_WR; 453 else if (r)
468 else { 454 what = SHUT_RD;
469 printk("os_shutdown_socket : neither r or w was set\n"); 455 else if (w)
456 what = SHUT_WR;
457 else
470 return -EINVAL; 458 return -EINVAL;
471 } 459
472 err = shutdown(fd, what); 460 err = shutdown(fd, what);
473 if(err < 0) 461 if (err < 0)
474 return -errno; 462 return -errno;
475 return 0; 463 return 0;
476} 464}
@@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out)
494 msg.msg_flags = 0; 482 msg.msg_flags = 0;
495 483
496 n = recvmsg(fd, &msg, 0); 484 n = recvmsg(fd, &msg, 0);
497 if(n < 0) 485 if (n < 0)
498 return -errno; 486 return -errno;
499 else if(n != iov.iov_len) 487 else if (n != iov.iov_len)
500 *helper_pid_out = -1; 488 *helper_pid_out = -1;
501 489
502 cmsg = CMSG_FIRSTHDR(&msg); 490 cmsg = CMSG_FIRSTHDR(&msg);
503 if(cmsg == NULL){ 491 if (cmsg == NULL) {
504 printk("rcv_fd didn't receive anything, error = %d\n", errno); 492 printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
493 "error = %d\n", errno);
505 return -1; 494 return -1;
506 } 495 }
507 if((cmsg->cmsg_level != SOL_SOCKET) || 496 if ((cmsg->cmsg_level != SOL_SOCKET) ||
508 (cmsg->cmsg_type != SCM_RIGHTS)){ 497 (cmsg->cmsg_type != SCM_RIGHTS)) {
509 printk("rcv_fd didn't receive a descriptor\n"); 498 printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
510 return -1; 499 return -1;
511 } 500 }
512 501
@@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out)
514 return new; 503 return new;
515} 504}
516 505
517int os_create_unix_socket(char *file, int len, int close_on_exec) 506int os_create_unix_socket(const char *file, int len, int close_on_exec)
518{ 507{
519 struct sockaddr_un addr; 508 struct sockaddr_un addr;
520 int sock, err; 509 int sock, err;
521 510
522 sock = socket(PF_UNIX, SOCK_DGRAM, 0); 511 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
523 if(sock < 0) 512 if (sock < 0)
524 return -errno; 513 return -errno;
525 514
526 if(close_on_exec) { 515 if (close_on_exec) {
527 err = os_set_exec_close(sock); 516 err = os_set_exec_close(sock);
528 if(err < 0) 517 if (err < 0)
529 printk("create_unix_socket : close_on_exec failed, " 518 printk(UM_KERN_ERR "create_unix_socket : "
530 "err = %d", -err); 519 "close_on_exec failed, err = %d", -err);
531 } 520 }
532 521
533 addr.sun_family = AF_UNIX; 522 addr.sun_family = AF_UNIX;
534 523
535 /* XXX Be more careful about overflow */
536 snprintf(addr.sun_path, len, "%s", file); 524 snprintf(addr.sun_path, len, "%s", file);
537 525
538 err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); 526 err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
539 if(err < 0) 527 if (err < 0)
540 return -errno; 528 return -errno;
541 529
542 return sock; 530 return sock;
@@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl)
557 int err, save; 545 int err, save;
558 546
559 err = fcntl(fd, F_SETLK, &lock); 547 err = fcntl(fd, F_SETLK, &lock);
560 if(!err) 548 if (!err)
561 goto out; 549 goto out;
562 550
563 save = -errno; 551 save = -errno;
564 err = fcntl(fd, F_GETLK, &lock); 552 err = fcntl(fd, F_GETLK, &lock);
565 if(err){ 553 if (err) {
566 err = -errno; 554 err = -errno;
567 goto out; 555 goto out;
568 } 556 }
569 557
570 printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); 558 printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
559 lock.l_pid);
571 err = save; 560 err = save;
572 out: 561 out:
573 return err; 562 return err;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index fba3f0fefeef..f4bd349d4412 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -1,22 +1,19 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdio.h>
7#include <stdlib.h> 6#include <stdlib.h>
8#include <unistd.h> 7#include <unistd.h>
9#include <errno.h> 8#include <errno.h>
10#include <sched.h> 9#include <sched.h>
11#include <limits.h>
12#include <sys/signal.h>
13#include <sys/wait.h>
14#include <sys/socket.h> 10#include <sys/socket.h>
15#include "user.h" 11#include <sys/wait.h>
12#include "kern_constants.h"
16#include "kern_util.h" 13#include "kern_util.h"
17#include "os.h" 14#include "os.h"
18#include "um_malloc.h" 15#include "um_malloc.h"
19#include "kern_constants.h" 16#include "user.h"
20 17
21struct helper_data { 18struct helper_data {
22 void (*pre_exec)(void*); 19 void (*pre_exec)(void*);
@@ -30,21 +27,19 @@ static int helper_child(void *arg)
30{ 27{
31 struct helper_data *data = arg; 28 struct helper_data *data = arg;
32 char **argv = data->argv; 29 char **argv = data->argv;
33 int errval; 30 int err;
34 31
35 if (data->pre_exec != NULL) 32 if (data->pre_exec != NULL)
36 (*data->pre_exec)(data->pre_data); 33 (*data->pre_exec)(data->pre_data);
37 errval = execvp_noalloc(data->buf, argv[0], argv); 34 err = execvp_noalloc(data->buf, argv[0], argv);
38 printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], 35
39 -errval); 36 /* If the exec succeeds, we don't get here */
40 write(data->fd, &errval, sizeof(errval)); 37 write(data->fd, &err, sizeof(err));
41 kill(os_getpid(), SIGKILL); 38
42 return 0; 39 return 0;
43} 40}
44 41
45/* Returns either the pid of the child process we run or -E* on failure. 42/* Returns either the pid of the child process we run or -E* on failure. */
46 * XXX The alloc_stack here breaks if this is called in the tracing thread, so
47 * we need to receive a preallocated stack (a local buffer is ok). */
48int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) 43int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
49{ 44{
50 struct helper_data data; 45 struct helper_data data;
@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
58 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 53 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
59 if (ret < 0) { 54 if (ret < 0) {
60 ret = -errno; 55 ret = -errno;
61 printk("run_helper : pipe failed, errno = %d\n", errno); 56 printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n",
57 errno);
62 goto out_free; 58 goto out_free;
63 } 59 }
64 60
65 ret = os_set_exec_close(fds[1]); 61 ret = os_set_exec_close(fds[1]);
66 if (ret < 0) { 62 if (ret < 0) {
67 printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", 63 printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, "
68 -ret); 64 "ret = %d\n", -ret);
69 goto out_close; 65 goto out_close;
70 } 66 }
71 67
@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
79 pid = clone(helper_child, (void *) sp, CLONE_VM, &data); 75 pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
80 if (pid < 0) { 76 if (pid < 0) {
81 ret = -errno; 77 ret = -errno;
82 printk("run_helper : clone failed, errno = %d\n", errno); 78 printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n",
79 errno);
83 goto out_free2; 80 goto out_free2;
84 } 81 }
85 82
@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
96 } else { 93 } else {
97 if (n < 0) { 94 if (n < 0) {
98 n = -errno; 95 n = -errno;
99 printk("run_helper : read on pipe failed, ret = %d\n", 96 printk(UM_KERN_ERR "run_helper : read on pipe failed, "
100 -n); 97 "ret = %d\n", -n);
101 ret = n; 98 ret = n;
102 kill(pid, SIGKILL);
103 } 99 }
104 CATCH_EINTR(waitpid(pid, NULL, __WCLONE)); 100 CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
105 } 101 }
@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
129 pid = clone(proc, (void *) sp, flags, arg); 125 pid = clone(proc, (void *) sp, flags, arg);
130 if (pid < 0) { 126 if (pid < 0) {
131 err = -errno; 127 err = -errno;
132 printk("run_helper_thread : clone failed, errno = %d\n", 128 printk(UM_KERN_ERR "run_helper_thread : clone failed, "
133 errno); 129 "errno = %d\n", errno);
134 return err; 130 return err;
135 } 131 }
136 if (stack_out == NULL) { 132 if (stack_out == NULL) {
137 CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE)); 133 CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
138 if (pid < 0) { 134 if (pid < 0) {
139 err = -errno; 135 err = -errno;
140 printk("run_helper_thread - wait failed, errno = %d\n", 136 printk(UM_KERN_ERR "run_helper_thread - wait failed, "
141 errno); 137 "errno = %d\n", errno);
142 pid = err; 138 pid = err;
143 } 139 }
144 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) 140 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
145 printk("run_helper_thread - thread returned status " 141 printk(UM_KERN_ERR "run_helper_thread - thread "
146 "0x%x\n", status); 142 "returned status 0x%x\n", status);
147 free_stack(stack, 0); 143 free_stack(stack, 0);
148 } else 144 } else
149 *stack_out = stack; 145 *stack_out = stack;
150 return pid; 146 return pid;
151} 147}
152 148
153int helper_wait(int pid, int nohang, char *pname) 149int helper_wait(int pid)
154{ 150{
155 int ret, status; 151 int ret, status;
156 int wflags = __WCLONE; 152 int wflags = __WCLONE;
157 153
158 if (nohang)
159 wflags |= WNOHANG;
160
161 if (!pname)
162 pname = "helper_wait";
163
164 CATCH_EINTR(ret = waitpid(pid, &status, wflags)); 154 CATCH_EINTR(ret = waitpid(pid, &status, wflags));
165 if (ret < 0) { 155 if (ret < 0) {
166 printk(UM_KERN_ERR "%s : waitpid process %d failed, " 156 printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, "
167 "errno = %d\n", pname, pid, errno); 157 "errno = %d\n", pid, errno);
168 return -errno; 158 return -errno;
169 } else if (nohang && ret == 0) {
170 printk(UM_KERN_ERR "%s : process %d has not exited\n",
171 pname, pid);
172 return -ECHILD;
173 } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 159 } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
174 printk(UM_KERN_ERR "%s : process %d didn't exit with " 160 printk(UM_KERN_ERR "helper_wait : process %d exited with "
175 "status 0\n", pname, pid); 161 "status 0x%x\n", pid, status);
176 return -ECHILD; 162 return -ECHILD;
177 } else 163 } else
178 return 0; 164 return 0;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 6aa6f95d6524..0348b975e81c 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -1,23 +1,19 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <unistd.h>
8#include <errno.h> 7#include <errno.h>
8#include <poll.h>
9#include <signal.h> 9#include <signal.h>
10#include <string.h> 10#include <string.h>
11#include <sys/poll.h>
12#include <sys/types.h>
13#include <sys/time.h>
14#include "kern_util.h"
15#include "user.h"
16#include "process.h"
17#include "sigio.h"
18#include "irq_user.h" 11#include "irq_user.h"
12#include "kern_constants.h"
19#include "os.h" 13#include "os.h"
14#include "process.h"
20#include "um_malloc.h" 15#include "um_malloc.h"
16#include "user.h"
21 17
22/* 18/*
23 * Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd 19 * 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)
36 if (n < 0) { 32 if (n < 0) {
37 err = -errno; 33 err = -errno;
38 if (errno != EINTR) 34 if (errno != EINTR)
39 printk("sigio_handler: os_waiting_for_events:" 35 printk(UM_KERN_ERR "os_waiting_for_events:"
40 " poll returned %d, errno = %d\n", n, errno); 36 " poll returned %d, errno = %d\n", n, errno);
41 return err; 37 return err;
42 } 38 }
@@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
95 struct irq_fd *old_fd = *prev; 91 struct irq_fd *old_fd = *prev;
96 if ((pollfds[i].fd != -1) && 92 if ((pollfds[i].fd != -1) &&
97 (pollfds[i].fd != (*prev)->fd)) { 93 (pollfds[i].fd != (*prev)->fd)) {
98 printk("os_free_irq_by_cb - mismatch between " 94 printk(UM_KERN_ERR "os_free_irq_by_cb - "
99 "active_fds and pollfds, fd %d vs %d\n", 95 "mismatch between active_fds and "
96 "pollfds, fd %d vs %d\n",
100 (*prev)->fd, pollfds[i].fd); 97 (*prev)->fd, pollfds[i].fd);
101 goto out; 98 goto out;
102 } 99 }
103 100
104 pollfds_num--; 101 pollfds_num--;
105 102
106 /* This moves the *whole* array after pollfds[i] 103 /*
104 * This moves the *whole* array after pollfds[i]
107 * (though it doesn't spot as such)! 105 * (though it doesn't spot as such)!
108 */ 106 */
109 memmove(&pollfds[i], &pollfds[i + 1], 107 memmove(&pollfds[i], &pollfds[i + 1],
110 (pollfds_num - i) * sizeof(pollfds[0])); 108 (pollfds_num - i) * sizeof(pollfds[0]));
111 if(*last_irq_ptr2 == &old_fd->next) 109 if (*last_irq_ptr2 == &old_fd->next)
112 *last_irq_ptr2 = prev; 110 *last_irq_ptr2 = prev;
113 111
114 *prev = (*prev)->next; 112 *prev = (*prev)->next;
115 if(old_fd->type == IRQ_WRITE) 113 if (old_fd->type == IRQ_WRITE)
116 ignore_sigio_fd(old_fd->fd); 114 ignore_sigio_fd(old_fd->fd);
117 kfree(old_fd); 115 kfree(old_fd);
118 continue; 116 continue;
@@ -138,14 +136,3 @@ void os_set_ioignore(void)
138{ 136{
139 signal(SIGIO, SIG_IGN); 137 signal(SIGIO, SIG_IGN);
140} 138}
141
142void init_irq_signals(int on_sigstack)
143{
144 int flags;
145
146 flags = on_sigstack ? SA_ONSTACK : 0;
147
148 set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
149 SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
150 signal(SIGWINCH, SIG_IGN);
151}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 82c3778627b8..abb9b0ffd960 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)
73 action.sa_handler = last_ditch_exit; 73 action.sa_handler = last_ditch_exit;
74 if (sigaction(sig, &action, NULL) < 0) { 74 if (sigaction(sig, &action, NULL) < 0) {
75 printf("failed to install handler for signal %d - errno = %d\n", 75 printf("failed to install handler for signal %d - errno = %d\n",
76 errno); 76 sig, errno);
77 exit(1); 77 exit(1);
78 } 78 }
79} 79}
@@ -92,7 +92,8 @@ static void setup_env_path(void)
92 * just use the default + /usr/lib/uml 92 * just use the default + /usr/lib/uml
93 */ 93 */
94 if (!old_path || (path_len = strlen(old_path)) == 0) { 94 if (!old_path || (path_len = strlen(old_path)) == 0) {
95 putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH); 95 if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH))
96 perror("couldn't putenv");
96 return; 97 return;
97 } 98 }
98 99
@@ -100,15 +101,16 @@ static void setup_env_path(void)
100 path_len += strlen("PATH=" UML_LIB_PATH) + 1; 101 path_len += strlen("PATH=" UML_LIB_PATH) + 1;
101 new_path = malloc(path_len); 102 new_path = malloc(path_len);
102 if (!new_path) { 103 if (!new_path) {
103 perror("coudn't malloc to set a new PATH"); 104 perror("couldn't malloc to set a new PATH");
104 return; 105 return;
105 } 106 }
106 snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path); 107 snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
107 putenv(new_path); 108 if (putenv(new_path)) {
109 perror("couldn't putenv to set a new PATH");
110 free(new_path);
111 }
108} 112}
109 113
110extern int uml_exitcode;
111
112extern void scan_elf_aux( char **envp); 114extern void scan_elf_aux( char **envp);
113 115
114int __init main(int argc, char **argv, char **envp) 116int __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 436f8d20b20f..eedc2d88ef8a 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -9,7 +9,6 @@
9#include <sys/types.h> 9#include <sys/types.h>
10#include <sys/mman.h> 10#include <sys/mman.h>
11#include <sys/statfs.h> 11#include <sys/statfs.h>
12#include "kern_util.h"
13#include "user.h" 12#include "user.h"
14#include "mem_user.h" 13#include "mem_user.h"
15#include "init.h" 14#include "init.h"
@@ -30,7 +29,7 @@ static char *tempdir = NULL;
30 29
31static void __init find_tempdir(void) 30static void __init find_tempdir(void)
32{ 31{
33 char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; 32 const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
34 int i; 33 int i;
35 char *dir = NULL; 34 char *dir = NULL;
36 35
@@ -59,9 +58,10 @@ static void __init find_tempdir(void)
59 * read the file as needed. If there's an error, -errno is returned; 58 * read the file as needed. If there's an error, -errno is returned;
60 * if the end of the file is reached, 0 is returned. 59 * if the end of the file is reached, 0 is returned.
61 */ 60 */
62static int next(int fd, char *buf, int size, char c) 61static int next(int fd, char *buf, size_t size, char c)
63{ 62{
64 int n, len; 63 ssize_t n;
64 size_t len;
65 char *ptr; 65 char *ptr;
66 66
67 while((ptr = strchr(buf, c)) == NULL){ 67 while((ptr = strchr(buf, c)) == NULL){
@@ -172,13 +172,15 @@ int __init make_tempfile(const char *template, char **out_tempname,
172 172
173 which_tmpdir(); 173 which_tmpdir();
174 tempname = malloc(MAXPATHLEN); 174 tempname = malloc(MAXPATHLEN);
175 if (!tempname)
176 goto out;
175 177
176 find_tempdir(); 178 find_tempdir();
177 if (template[0] != '/') 179 if (template[0] != '/')
178 strcpy(tempname, tempdir); 180 strcpy(tempname, tempdir);
179 else 181 else
180 tempname[0] = '\0'; 182 tempname[0] = '\0';
181 strcat(tempname, template); 183 strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
182 fd = mkstemp(tempname); 184 fd = mkstemp(tempname);
183 if(fd < 0){ 185 if(fd < 0){
184 fprintf(stderr, "open - cannot create %s: %s\n", tempname, 186 fprintf(stderr, "open - cannot create %s: %s\n", tempname,
@@ -268,6 +270,7 @@ void __init check_tmpexec(void)
268 if(addr == MAP_FAILED){ 270 if(addr == MAP_FAILED){
269 err = errno; 271 err = errno;
270 perror("failed"); 272 perror("failed");
273 close(fd);
271 if(err == EPERM) 274 if(err == EPERM)
272 printf("%s must be not mounted noexec\n",tempdir); 275 printf("%s must be not mounted noexec\n",tempdir);
273 exit(1); 276 exit(1);
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index bda5c3150d6c..abf6beae3df1 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)
249 SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); 249 SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
250 signal(SIGHUP, SIG_IGN); 250 signal(SIGHUP, SIG_IGN);
251 251
252 init_irq_signals(1); 252 set_handler(SIGIO, (__sighandler_t) sig_handler,
253 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
254 SIGVTALRM, -1);
255 signal(SIGWINCH, SIG_IGN);
253} 256}
254 257
255int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) 258int 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 a32ba6ab1211..830fe6a1518a 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -8,47 +8,41 @@
8#include <string.h> 8#include <string.h>
9#include <sys/ptrace.h> 9#include <sys/ptrace.h>
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11#include "user.h"
12 11
13/* This is set once at boot time and not changed thereafter */ 12int save_registers(int pid, struct uml_pt_regs *regs)
14
15static unsigned long exec_regs[MAX_REG_NR];
16
17void init_thread_registers(struct uml_pt_regs *to)
18{
19 memcpy(to->gp, exec_regs, sizeof(to->gp));
20}
21
22void save_registers(int pid, struct uml_pt_regs *regs)
23{ 13{
24 int err; 14 int err;
25 15
26 err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); 16 err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
27 if (err < 0) 17 if (err < 0)
28 panic("save_registers - saving registers failed, errno = %d\n", 18 return -errno;
29 errno); 19 return 0;
30} 20}
31 21
32void restore_registers(int pid, struct uml_pt_regs *regs) 22int restore_registers(int pid, struct uml_pt_regs *regs)
33{ 23{
34 int err; 24 int err;
35 25
36 err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); 26 err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
37 if (err < 0) 27 if (err < 0)
38 panic("restore_registers - saving registers failed, " 28 return -errno;
39 "errno = %d\n", errno); 29 return 0;
40} 30}
41 31
42void init_registers(int pid) 32/* This is set once at boot time and not changed thereafter */
33
34static unsigned long exec_regs[MAX_REG_NR];
35
36int init_registers(int pid)
43{ 37{
44 int err; 38 int err;
45 39
46 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); 40 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
47 if (err) 41 if (err < 0)
48 panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", 42 return -errno;
49 errno);
50 43
51 arch_init_registers(pid); 44 arch_init_registers(pid);
45 return 0;
52} 46}
53 47
54void get_safe_registers(unsigned long *regs) 48void get_safe_registers(unsigned long *regs)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index dc03e9cccb63..abf47a7c4abd 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,34 +1,33 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <unistd.h> 6#include <unistd.h>
7#include <stdlib.h> 7#include <errno.h>
8#include <termios.h> 8#include <fcntl.h>
9#include <poll.h>
9#include <pty.h> 10#include <pty.h>
11#include <sched.h>
10#include <signal.h> 12#include <signal.h>
11#include <fcntl.h>
12#include <errno.h>
13#include <string.h> 13#include <string.h>
14#include <sched.h> 14#include "kern_constants.h"
15#include <sys/socket.h>
16#include <sys/poll.h>
17#include "init.h"
18#include "user.h"
19#include "kern_util.h" 15#include "kern_util.h"
20#include "sigio.h" 16#include "init.h"
21#include "os.h" 17#include "os.h"
18#include "sigio.h"
22#include "um_malloc.h" 19#include "um_malloc.h"
23#include "init.h" 20#include "user.h"
24 21
25/* Protected by sigio_lock(), also used by sigio_cleanup, which is an 22/*
23 * Protected by sigio_lock(), also used by sigio_cleanup, which is an
26 * exitcall. 24 * exitcall.
27 */ 25 */
28static int write_sigio_pid = -1; 26static int write_sigio_pid = -1;
29static unsigned long write_sigio_stack; 27static unsigned long write_sigio_stack;
30 28
31/* These arrays are initialized before the sigio thread is started, and 29/*
30 * These arrays are initialized before the sigio thread is started, and
32 * the descriptors closed after it is killed. So, it can't see them change. 31 * the descriptors closed after it is killed. So, it can't see them change.
33 * On the UML side, they are changed under the sigio_lock. 32 * On the UML side, they are changed under the sigio_lock.
34 */ 33 */
@@ -43,7 +42,8 @@ struct pollfds {
43 int used; 42 int used;
44}; 43};
45 44
46/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread 45/*
46 * Protected by sigio_lock(). Used by the sigio thread, but the UML thread
47 * synchronizes with it. 47 * synchronizes with it.
48 */ 48 */
49static struct pollfds current_poll; 49static struct pollfds current_poll;
@@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused)
57 int i, n, respond_fd; 57 int i, n, respond_fd;
58 char c; 58 char c;
59 59
60 signal(SIGWINCH, SIG_IGN); 60 signal(SIGWINCH, SIG_IGN);
61 fds = &current_poll; 61 fds = &current_poll;
62 while(1){ 62 while (1) {
63 n = poll(fds->poll, fds->used, -1); 63 n = poll(fds->poll, fds->used, -1);
64 if(n < 0){ 64 if (n < 0) {
65 if(errno == EINTR) continue; 65 if (errno == EINTR)
66 printk("write_sigio_thread : poll returned %d, " 66 continue;
67 "errno = %d\n", n, errno); 67 printk(UM_KERN_ERR "write_sigio_thread : poll returned "
68 "%d, errno = %d\n", n, errno);
68 } 69 }
69 for(i = 0; i < fds->used; i++){ 70 for (i = 0; i < fds->used; i++) {
70 p = &fds->poll[i]; 71 p = &fds->poll[i];
71 if(p->revents == 0) continue; 72 if (p->revents == 0)
72 if(p->fd == sigio_private[1]){ 73 continue;
74 if (p->fd == sigio_private[1]) {
73 CATCH_EINTR(n = read(sigio_private[1], &c, 75 CATCH_EINTR(n = read(sigio_private[1], &c,
74 sizeof(c))); 76 sizeof(c)));
75 if(n != sizeof(c)) 77 if (n != sizeof(c))
76 printk("write_sigio_thread : " 78 printk(UM_KERN_ERR
79 "write_sigio_thread : "
77 "read on socket failed, " 80 "read on socket failed, "
78 "err = %d\n", errno); 81 "err = %d\n", errno);
79 tmp = current_poll; 82 tmp = current_poll;
@@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused)
89 } 92 }
90 93
91 CATCH_EINTR(n = write(respond_fd, &c, sizeof(c))); 94 CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
92 if(n != sizeof(c)) 95 if (n != sizeof(c))
93 printk("write_sigio_thread : write on socket " 96 printk(UM_KERN_ERR "write_sigio_thread : "
94 "failed, err = %d\n", errno); 97 "write on socket failed, err = %d\n",
98 errno);
95 } 99 }
96 } 100 }
97 101
@@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n)
102{ 106{
103 struct pollfd *new; 107 struct pollfd *new;
104 108
105 if(n <= polls->size) 109 if (n <= polls->size)
106 return 0; 110 return 0;
107 111
108 new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); 112 new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
109 if(new == NULL){ 113 if (new == NULL) {
110 printk("need_poll : failed to allocate new pollfds\n"); 114 printk(UM_KERN_ERR "need_poll : failed to allocate new "
115 "pollfds\n");
111 return -ENOMEM; 116 return -ENOMEM;
112 } 117 }
113 118
@@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n)
119 return 0; 124 return 0;
120} 125}
121 126
122/* Must be called with sigio_lock held, because it's needed by the marked 127/*
128 * Must be called with sigio_lock held, because it's needed by the marked
123 * critical section. 129 * critical section.
124 */ 130 */
125static void update_thread(void) 131static void update_thread(void)
@@ -129,15 +135,17 @@ static void update_thread(void)
129 char c; 135 char c;
130 136
131 flags = set_signals(0); 137 flags = set_signals(0);
132 n = write(sigio_private[0], &c, sizeof(c)); 138 CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
133 if(n != sizeof(c)){ 139 if (n != sizeof(c)) {
134 printk("update_thread : write failed, err = %d\n", errno); 140 printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
141 errno);
135 goto fail; 142 goto fail;
136 } 143 }
137 144
138 CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c))); 145 CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
139 if(n != sizeof(c)){ 146 if (n != sizeof(c)) {
140 printk("update_thread : read failed, err = %d\n", errno); 147 printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
148 errno);
141 goto fail; 149 goto fail;
142 } 150 }
143 151
@@ -164,23 +172,23 @@ int add_sigio_fd(int fd)
164 int err = 0, i, n; 172 int err = 0, i, n;
165 173
166 sigio_lock(); 174 sigio_lock();
167 for(i = 0; i < all_sigio_fds.used; i++){ 175 for (i = 0; i < all_sigio_fds.used; i++) {
168 if(all_sigio_fds.poll[i].fd == fd) 176 if (all_sigio_fds.poll[i].fd == fd)
169 break; 177 break;
170 } 178 }
171 if(i == all_sigio_fds.used) 179 if (i == all_sigio_fds.used)
172 goto out; 180 goto out;
173 181
174 p = &all_sigio_fds.poll[i]; 182 p = &all_sigio_fds.poll[i];
175 183
176 for(i = 0; i < current_poll.used; i++){ 184 for (i = 0; i < current_poll.used; i++) {
177 if(current_poll.poll[i].fd == fd) 185 if (current_poll.poll[i].fd == fd)
178 goto out; 186 goto out;
179 } 187 }
180 188
181 n = current_poll.used; 189 n = current_poll.used;
182 err = need_poll(&next_poll, n + 1); 190 err = need_poll(&next_poll, n + 1);
183 if(err) 191 if (err)
184 goto out; 192 goto out;
185 193
186 memcpy(next_poll.poll, current_poll.poll, 194 memcpy(next_poll.poll, current_poll.poll,
@@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd)
198 struct pollfd *p; 206 struct pollfd *p;
199 int err = 0, i, n = 0; 207 int err = 0, i, n = 0;
200 208
201 /* This is called from exitcalls elsewhere in UML - if 209 /*
210 * This is called from exitcalls elsewhere in UML - if
202 * sigio_cleanup has already run, then update_thread will hang 211 * sigio_cleanup has already run, then update_thread will hang
203 * or fail because the thread is no longer running. 212 * or fail because the thread is no longer running.
204 */ 213 */
205 if(write_sigio_pid == -1) 214 if (write_sigio_pid == -1)
206 return -EIO; 215 return -EIO;
207 216
208 sigio_lock(); 217 sigio_lock();
209 for(i = 0; i < current_poll.used; i++){ 218 for (i = 0; i < current_poll.used; i++) {
210 if(current_poll.poll[i].fd == fd) break; 219 if (current_poll.poll[i].fd == fd)
220 break;
211 } 221 }
212 if(i == current_poll.used) 222 if (i == current_poll.used)
213 goto out; 223 goto out;
214 224
215 err = need_poll(&next_poll, current_poll.used - 1); 225 err = need_poll(&next_poll, current_poll.used - 1);
216 if(err) 226 if (err)
217 goto out; 227 goto out;
218 228
219 for(i = 0; i < current_poll.used; i++){ 229 for (i = 0; i < current_poll.used; i++) {
220 p = &current_poll.poll[i]; 230 p = &current_poll.poll[i];
221 if(p->fd != fd) 231 if (p->fd != fd)
222 next_poll.poll[n++] = *p; 232 next_poll.poll[n++] = *p;
223 } 233 }
224 next_poll.used = current_poll.used - 1; 234 next_poll.used = current_poll.used - 1;
@@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd)
235 245
236 p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); 246 p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
237 if (p == NULL) { 247 if (p == NULL) {
238 printk("setup_initial_poll : failed to allocate poll\n"); 248 printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
249 "poll\n");
239 return NULL; 250 return NULL;
240 } 251 }
241 *p = ((struct pollfd) { .fd = fd, 252 *p = ((struct pollfd) { .fd = fd,
@@ -261,27 +272,29 @@ static void write_sigio_workaround(void)
261 return; 272 return;
262 273
263 err = os_pipe(l_write_sigio_fds, 1, 1); 274 err = os_pipe(l_write_sigio_fds, 1, 1);
264 if(err < 0){ 275 if (err < 0) {
265 printk("write_sigio_workaround - os_pipe 1 failed, " 276 printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
266 "err = %d\n", -err); 277 "err = %d\n", -err);
267 return; 278 return;
268 } 279 }
269 err = os_pipe(l_sigio_private, 1, 1); 280 err = os_pipe(l_sigio_private, 1, 1);
270 if(err < 0){ 281 if (err < 0) {
271 printk("write_sigio_workaround - os_pipe 2 failed, " 282 printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
272 "err = %d\n", -err); 283 "err = %d\n", -err);
273 goto out_close1; 284 goto out_close1;
274 } 285 }
275 286
276 p = setup_initial_poll(l_sigio_private[1]); 287 p = setup_initial_poll(l_sigio_private[1]);
277 if(!p) 288 if (!p)
278 goto out_close2; 289 goto out_close2;
279 290
280 sigio_lock(); 291 sigio_lock();
281 292
282 /* Did we race? Don't try to optimize this, please, it's not so likely 293 /*
283 * to happen, and no more than once at the boot. */ 294 * Did we race? Don't try to optimize this, please, it's not so likely
284 if(write_sigio_pid != -1) 295 * to happen, and no more than once at the boot.
296 */
297 if (write_sigio_pid != -1)
285 goto out_free; 298 goto out_free;
286 299
287 current_poll = ((struct pollfds) { .poll = p, 300 current_poll = ((struct pollfds) { .poll = p,
@@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read)
333{ 346{
334 int err; 347 int err;
335 348
336 if(!isatty(fd)) 349 if (!isatty(fd))
337 return; 350 return;
338 351
339 if((read || pty_output_sigio) && (!read || pty_close_sigio)) 352 if ((read || pty_output_sigio) && (!read || pty_close_sigio))
340 return; 353 return;
341 354
342 write_sigio_workaround(); 355 write_sigio_workaround();
343 356
344 sigio_lock(); 357 sigio_lock();
345 err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); 358 err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
346 if(err){ 359 if (err) {
347 printk("maybe_sigio_broken - failed to add pollfd for " 360 printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
348 "descriptor %d\n", fd); 361 "for descriptor %d\n", fd);
349 goto out; 362 goto out;
350 } 363 }
351 364
@@ -388,7 +401,7 @@ static void openpty_cb(void *arg)
388 struct openpty_arg *info = arg; 401 struct openpty_arg *info = arg;
389 402
390 info->err = 0; 403 info->err = 0;
391 if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) 404 if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
392 info->err = -errno; 405 info->err = -errno;
393} 406}
394 407
@@ -397,17 +410,17 @@ static int async_pty(int master, int slave)
397 int flags; 410 int flags;
398 411
399 flags = fcntl(master, F_GETFL); 412 flags = fcntl(master, F_GETFL);
400 if(flags < 0) 413 if (flags < 0)
401 return -errno; 414 return -errno;
402 415
403 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || 416 if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
404 (fcntl(master, F_SETOWN, os_getpid()) < 0)) 417 (fcntl(master, F_SETOWN, os_getpid()) < 0))
405 return -errno; 418 return -errno;
406 419
407 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) 420 if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
408 return -errno; 421 return -errno;
409 422
410 return(0); 423 return 0;
411} 424}
412 425
413static void __init check_one_sigio(void (*proc)(int, int)) 426static void __init check_one_sigio(void (*proc)(int, int))
@@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int))
417 int master, slave, err; 430 int master, slave, err;
418 431
419 initial_thread_cb(openpty_cb, &pty); 432 initial_thread_cb(openpty_cb, &pty);
420 if(pty.err){ 433 if (pty.err) {
421 printk("openpty failed, errno = %d\n", -pty.err); 434 printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
435 -pty.err);
422 return; 436 return;
423 } 437 }
424 438
425 master = pty.master; 439 master = pty.master;
426 slave = pty.slave; 440 slave = pty.slave;
427 441
428 if((master == -1) || (slave == -1)){ 442 if ((master == -1) || (slave == -1)) {
429 printk("openpty failed to allocate a pty\n"); 443 printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
444 "pty\n");
430 return; 445 return;
431 } 446 }
432 447
433 /* Not now, but complain so we now where we failed. */ 448 /* Not now, but complain so we now where we failed. */
434 err = raw(master); 449 err = raw(master);
435 if (err < 0) 450 if (err < 0) {
436 panic("check_sigio : __raw failed, errno = %d\n", -err); 451 printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
452 -err);
453 return;
454 }
437 455
438 err = async_pty(master, slave); 456 err = async_pty(master, slave);
439 if(err < 0) 457 if (err < 0) {
440 panic("tty_fds : sigio_async failed, err = %d\n", -err); 458 printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
459 "err = %d\n", -err);
460 return;
461 }
462
463 if (sigaction(SIGIO, NULL, &old) < 0) {
464 printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
465 "errno = %d\n", errno);
466 return;
467 }
441 468
442 if(sigaction(SIGIO, NULL, &old) < 0)
443 panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
444 new = old; 469 new = old;
445 new.sa_handler = handler; 470 new.sa_handler = handler;
446 if(sigaction(SIGIO, &new, NULL) < 0) 471 if (sigaction(SIGIO, &new, NULL) < 0) {
447 panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); 472 printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
473 "errno = %d\n", errno);
474 return;
475 }
448 476
449 got_sigio = 0; 477 got_sigio = 0;
450 (*proc)(master, slave); 478 (*proc)(master, slave);
@@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int))
452 close(master); 480 close(master);
453 close(slave); 481 close(slave);
454 482
455 if(sigaction(SIGIO, &old, NULL) < 0) 483 if (sigaction(SIGIO, &old, NULL) < 0)
456 panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); 484 printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
485 "errno = %d\n", errno);
457} 486}
458 487
459static void tty_output(int master, int slave) 488static void tty_output(int master, int slave)
@@ -461,42 +490,45 @@ static void tty_output(int master, int slave)
461 int n; 490 int n;
462 char buf[512]; 491 char buf[512];
463 492
464 printk("Checking that host ptys support output SIGIO..."); 493 printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
465 494
466 memset(buf, 0, sizeof(buf)); 495 memset(buf, 0, sizeof(buf));
467 496
468 while(write(master, buf, sizeof(buf)) > 0) ; 497 while (write(master, buf, sizeof(buf)) > 0) ;
469 if(errno != EAGAIN) 498 if (errno != EAGAIN)
470 panic("tty_output : write failed, errno = %d\n", errno); 499 printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
471 while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; 500 errno);
501 while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
502 ;
472 503
473 if(got_sigio){ 504 if (got_sigio) {
474 printk("Yes\n"); 505 printk(UM_KERN_CONT "Yes\n");
475 pty_output_sigio = 1; 506 pty_output_sigio = 1;
476 } 507 } else if (n == -EAGAIN)
477 else if(n == -EAGAIN) 508 printk(UM_KERN_CONT "No, enabling workaround\n");
478 printk("No, enabling workaround\n"); 509 else
479 else panic("tty_output : read failed, err = %d\n", n); 510 printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
480} 511}
481 512
482static void tty_close(int master, int slave) 513static void tty_close(int master, int slave)
483{ 514{
484 printk("Checking that host ptys support SIGIO on close..."); 515 printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
516 "close...");
485 517
486 close(slave); 518 close(slave);
487 if(got_sigio){ 519 if (got_sigio) {
488 printk("Yes\n"); 520 printk(UM_KERN_CONT "Yes\n");
489 pty_close_sigio = 1; 521 pty_close_sigio = 1;
490 } 522 } else
491 else printk("No, enabling workaround\n"); 523 printk(UM_KERN_CONT "No, enabling workaround\n");
492} 524}
493 525
494void __init check_sigio(void) 526void __init check_sigio(void)
495{ 527{
496 if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && 528 if ((access("/dev/ptmx", R_OK) < 0) &&
497 (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ 529 (access("/dev/ptyp0", R_OK) < 0)) {
498 printk("No pseudo-terminals available - skipping pty SIGIO " 530 printk(UM_KERN_WARNING "No pseudo-terminals available - "
499 "check\n"); 531 "skipping pty SIGIO check\n");
500 return; 532 return;
501 } 533 }
502 check_one_sigio(tty_output); 534 check_one_sigio(tty_output);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index e9800b0b5689..0fb0cc8d4757 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -9,11 +9,47 @@
9#include <errno.h> 9#include <errno.h>
10#include <signal.h> 10#include <signal.h>
11#include <strings.h> 11#include <strings.h>
12#include "as-layout.h"
13#include "kern_util.h"
12#include "os.h" 14#include "os.h"
13#include "sysdep/barrier.h" 15#include "sysdep/barrier.h"
14#include "sysdep/sigcontext.h" 16#include "sysdep/sigcontext.h"
15#include "user.h" 17#include "user.h"
16 18
19/* Copied from linux/compiler-gcc.h since we can't include it directly */
20#define barrier() __asm__ __volatile__("": : :"memory")
21
22void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
23 [SIGTRAP] = relay_signal,
24 [SIGFPE] = relay_signal,
25 [SIGILL] = relay_signal,
26 [SIGWINCH] = winch,
27 [SIGBUS] = bus_handler,
28 [SIGSEGV] = segv_handler,
29 [SIGIO] = sigio_handler,
30 [SIGVTALRM] = timer_handler };
31
32static void sig_handler_common(int sig, struct sigcontext *sc)
33{
34 struct uml_pt_regs r;
35 int save_errno = errno;
36
37 r.is_user = 0;
38 if (sig == SIGSEGV) {
39 /* For segfaults, we want the data from the sigcontext. */
40 copy_sc(&r, sc);
41 GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
42 }
43
44 /* enable signals if sig isn't IRQ signal */
45 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
46 unblock_signals();
47
48 (*sig_info[sig])(sig, &r);
49
50 errno = save_errno;
51}
52
17/* 53/*
18 * These are the asynchronous signals. SIGPROF is excluded because we want to 54 * These are the asynchronous signals. SIGPROF is excluded because we want to
19 * be able to profile all of UML, not just the non-critical sections. If 55 * be able to profile all of UML, not just the non-critical sections. If
@@ -26,13 +62,8 @@
26#define SIGVTALRM_BIT 1 62#define SIGVTALRM_BIT 1
27#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) 63#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
28 64
29/* 65static int signals_enabled;
30 * These are used by both the signal handlers and 66static unsigned int signals_pending;
31 * block/unblock_signals. I don't want modifications cached in a
32 * register - they must go straight to memory.
33 */
34static volatile int signals_enabled = 1;
35static volatile int pending = 0;
36 67
37void sig_handler(int sig, struct sigcontext *sc) 68void sig_handler(int sig, struct sigcontext *sc)
38{ 69{
@@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc)
40 71
41 enabled = signals_enabled; 72 enabled = signals_enabled;
42 if (!enabled && (sig == SIGIO)) { 73 if (!enabled && (sig == SIGIO)) {
43 pending |= SIGIO_MASK; 74 signals_pending |= SIGIO_MASK;
44 return; 75 return;
45 } 76 }
46 77
47 block_signals(); 78 block_signals();
48 79
49 sig_handler_common_skas(sig, sc); 80 sig_handler_common(sig, sc);
50 81
51 set_signals(enabled); 82 set_signals(enabled);
52} 83}
@@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc)
68 99
69 enabled = signals_enabled; 100 enabled = signals_enabled;
70 if (!signals_enabled) { 101 if (!signals_enabled) {
71 pending |= SIGVTALRM_MASK; 102 signals_pending |= SIGVTALRM_MASK;
72 return; 103 return;
73 } 104 }
74 105
@@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size)
94 panic("enabling signal stack failed, errno = %d\n", errno); 125 panic("enabling signal stack failed, errno = %d\n", errno);
95} 126}
96 127
97void remove_sigstack(void)
98{
99 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
100 .ss_sp = NULL,
101 .ss_size = 0 });
102
103 if (sigaltstack(&stack, NULL) != 0)
104 panic("disabling signal stack failed, errno = %d\n", errno);
105}
106
107void (*handlers[_NSIG])(int sig, struct sigcontext *sc); 128void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
108 129
109void handle_signal(int sig, struct sigcontext *sc) 130void handle_signal(int sig, struct sigcontext *sc)
@@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
166 sigaddset(&action.sa_mask, mask); 187 sigaddset(&action.sa_mask, mask);
167 va_end(ap); 188 va_end(ap);
168 189
190 if (sig == SIGSEGV)
191 flags |= SA_NODEFER;
192
169 action.sa_flags = flags; 193 action.sa_flags = flags;
170 action.sa_restorer = NULL; 194 action.sa_restorer = NULL;
171 if (sigaction(sig, &action, NULL) < 0) 195 if (sigaction(sig, &action, NULL) < 0)
@@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
179 203
180int change_sig(int signal, int on) 204int change_sig(int signal, int on)
181{ 205{
182 sigset_t sigset, old; 206 sigset_t sigset;
183 207
184 sigemptyset(&sigset); 208 sigemptyset(&sigset);
185 sigaddset(&sigset, signal); 209 sigaddset(&sigset, signal);
186 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); 210 if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
187 return !sigismember(&old, signal); 211 return -errno;
212
213 return 0;
188} 214}
189 215
190void block_signals(void) 216void block_signals(void)
@@ -196,7 +222,7 @@ void block_signals(void)
196 * This might matter if gcc figures out how to inline this and 222 * This might matter if gcc figures out how to inline this and
197 * decides to shuffle this code into the caller. 223 * decides to shuffle this code into the caller.
198 */ 224 */
199 mb(); 225 barrier();
200} 226}
201 227
202void unblock_signals(void) 228void unblock_signals(void)
@@ -209,36 +235,26 @@ void unblock_signals(void)
209 /* 235 /*
210 * We loop because the IRQ handler returns with interrupts off. So, 236 * We loop because the IRQ handler returns with interrupts off. So,
211 * interrupts may have arrived and we need to re-enable them and 237 * interrupts may have arrived and we need to re-enable them and
212 * recheck pending. 238 * recheck signals_pending.
213 */ 239 */
214 while(1) { 240 while(1) {
215 /* 241 /*
216 * Save and reset save_pending after enabling signals. This 242 * Save and reset save_pending after enabling signals. This
217 * way, pending won't be changed while we're reading it. 243 * way, signals_pending won't be changed while we're reading it.
218 */ 244 */
219 signals_enabled = 1; 245 signals_enabled = 1;
220 246
221 /* 247 /*
222 * Setting signals_enabled and reading pending must 248 * Setting signals_enabled and reading signals_pending must
223 * happen in this order. 249 * happen in this order.
224 */ 250 */
225 mb(); 251 barrier();
226 252
227 save_pending = pending; 253 save_pending = signals_pending;
228 if (save_pending == 0) { 254 if (save_pending == 0)
229 /*
230 * This must return with signals enabled, so
231 * this barrier ensures that writes are
232 * flushed out before the return. This might
233 * matter if gcc figures out how to inline
234 * this (unlikely, given its size) and decides
235 * to shuffle this code into the caller.
236 */
237 mb();
238 return; 255 return;
239 }
240 256
241 pending = 0; 257 signals_pending = 0;
242 258
243 /* 259 /*
244 * We have pending interrupts, so disable signals, as the 260 * We have pending interrupts, so disable signals, as the
@@ -254,7 +270,7 @@ void unblock_signals(void)
254 * back here. 270 * back here.
255 */ 271 */
256 if (save_pending & SIGIO_MASK) 272 if (save_pending & SIGIO_MASK)
257 sig_handler_common_skas(SIGIO, NULL); 273 sig_handler_common(SIGIO, NULL);
258 274
259 if (save_pending & SIGVTALRM_MASK) 275 if (save_pending & SIGVTALRM_MASK)
260 real_alarm_handler(NULL); 276 real_alarm_handler(NULL);
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index 5fd8d4dad66a..d2ea3409e072 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -1,10 +1,10 @@
1# 1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) 2# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := mem.o process.o trap.o 6obj-y := mem.o process.o
7 7
8USER_OBJS := mem.o process.o trap.o 8USER_OBJS := $(obj-y)
9 9
10include arch/um/scripts/Makefile.rules 10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index e8b7a97e83d3..d36c89c24a45 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -15,6 +15,7 @@
15#include "as-layout.h" 15#include "as-layout.h"
16#include "chan_user.h" 16#include "chan_user.h"
17#include "kern_constants.h" 17#include "kern_constants.h"
18#include "kern_util.h"
18#include "mem.h" 19#include "mem.h"
19#include "os.h" 20#include "os.h"
20#include "process.h" 21#include "process.h"
@@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data)
37 38
38static int ptrace_dump_regs(int pid) 39static int ptrace_dump_regs(int pid)
39{ 40{
40 unsigned long regs[MAX_REG_NR]; 41 unsigned long regs[MAX_REG_NR];
41 int i; 42 int i;
42 43
43 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 44 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
44 return -errno; 45 return -errno;
45 46
46 printk(UM_KERN_ERR "Stub registers -\n"); 47 printk(UM_KERN_ERR "Stub registers -\n");
47 for (i = 0; i < ARRAY_SIZE(regs); i++) 48 for (i = 0; i < ARRAY_SIZE(regs); i++)
48 printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); 49 printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
49 50
50 return 0; 51 return 0;
51} 52}
52 53
53/* 54/*
54 * Signals that are OK to receive in the stub - we'll just continue it. 55 * Signals that are OK to receive in the stub - we'll just continue it.
55 * SIGWINCH will happen when UML is inside a detached screen. 56 * SIGWINCH will happen when UML is inside a detached screen.
56 */ 57 */
57#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH)) 58#define STUB_SIG_MASK (1 << SIGVTALRM)
58 59
59/* Signals that the stub will finish with - anything else is an error */ 60/* Signals that the stub will finish with - anything else is an error */
60#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP)) 61#define STUB_DONE_MASK (1 << SIGTRAP)
61 62
62void wait_stub_done(int pid) 63void wait_stub_done(int pid)
63{ 64{
@@ -72,9 +73,11 @@ void wait_stub_done(int pid)
72 break; 73 break;
73 74
74 err = ptrace(PTRACE_CONT, pid, 0, 0); 75 err = ptrace(PTRACE_CONT, pid, 0, 0);
75 if (err) 76 if (err) {
76 panic("wait_stub_done : continue failed, errno = %d\n", 77 printk(UM_KERN_ERR "wait_stub_done : continue failed, "
77 errno); 78 "errno = %d\n", errno);
79 fatal_sigsegv();
80 }
78 } 81 }
79 82
80 if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) 83 if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
@@ -85,8 +88,10 @@ bad_wait:
85 if (err) 88 if (err)
86 printk(UM_KERN_ERR "Failed to get registers from stub, " 89 printk(UM_KERN_ERR "Failed to get registers from stub, "
87 "errno = %d\n", -err); 90 "errno = %d\n", -err);
88 panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " 91 printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
89 "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); 92 "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
93 status);
94 fatal_sigsegv();
90} 95}
91 96
92extern unsigned long current_stub_stack(void); 97extern unsigned long current_stub_stack(void);
@@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
97 102
98 if (ptrace_faultinfo) { 103 if (ptrace_faultinfo) {
99 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 104 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
100 if (err) 105 if (err) {
101 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " 106 printk(UM_KERN_ERR "get_skas_faultinfo - "
102 "errno = %d\n", errno); 107 "PTRACE_FAULTINFO failed, errno = %d\n", errno);
108 fatal_sigsegv();
109 }
103 110
104 /* Special handling for i386, which has different structs */ 111 /* Special handling for i386, which has different structs */
105 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 112 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
@@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
109 } 116 }
110 else { 117 else {
111 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); 118 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
112 if (err) 119 if (err) {
113 panic("Failed to continue stub, pid = %d, errno = %d\n", 120 printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
114 pid, errno); 121 "errno = %d\n", pid, errno);
122 fatal_sigsegv();
123 }
115 wait_stub_done(pid); 124 wait_stub_done(pid);
116 125
117 /* 126 /*
@@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
137{ 146{
138 int err, status; 147 int err, status;
139 148
149 if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
150 fatal_sigsegv();
151
140 /* Mark this as a syscall */ 152 /* Mark this as a syscall */
141 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); 153 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
142 154
@@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
144 { 156 {
145 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, 157 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
146 __NR_getpid); 158 __NR_getpid);
147 if (err < 0) 159 if (err < 0) {
148 panic("handle_trap - nullifying syscall failed, " 160 printk(UM_KERN_ERR "handle_trap - nullifying syscall "
149 "errno = %d\n", errno); 161 "failed, errno = %d\n", errno);
162 fatal_sigsegv();
163 }
150 164
151 err = ptrace(PTRACE_SYSCALL, pid, 0, 0); 165 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
152 if (err < 0) 166 if (err < 0) {
153 panic("handle_trap - continuing to end of syscall " 167 printk(UM_KERN_ERR "handle_trap - continuing to end of "
154 "failed, errno = %d\n", errno); 168 "syscall failed, errno = %d\n", errno);
169 fatal_sigsegv();
170 }
155 171
156 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); 172 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
157 if ((err < 0) || !WIFSTOPPED(status) || 173 if ((err < 0) || !WIFSTOPPED(status) ||
158 (WSTOPSIG(status) != SIGTRAP + 0x80)) { 174 (WSTOPSIG(status) != SIGTRAP + 0x80)) {
159 err = ptrace_dump_regs(pid); 175 err = ptrace_dump_regs(pid);
160 if (err) 176 if (err)
161 printk(UM_KERN_ERR "Failed to get registers " 177 printk(UM_KERN_ERR "Failed to get registers "
162 "from process, errno = %d\n", -err); 178 "from process, errno = %d\n", -err);
163 panic("handle_trap - failed to wait at end of syscall, " 179 printk(UM_KERN_ERR "handle_trap - failed to wait at "
164 "errno = %d, status = %d\n", errno, status); 180 "end of syscall, errno = %d, status = %d\n",
165 } 181 errno, status);
182 fatal_sigsegv();
183 }
166 } 184 }
167 185
168 handle_syscall(regs); 186 handle_syscall(regs);
@@ -178,10 +196,13 @@ static int userspace_tramp(void *stack)
178 ptrace(PTRACE_TRACEME, 0, 0, 0); 196 ptrace(PTRACE_TRACEME, 0, 0, 0);
179 197
180 signal(SIGTERM, SIG_DFL); 198 signal(SIGTERM, SIG_DFL);
199 signal(SIGWINCH, SIG_IGN);
181 err = set_interval(); 200 err = set_interval();
182 if (err) 201 if (err) {
183 panic("userspace_tramp - setting timer failed, errno = %d\n", 202 printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
184 err); 203 "errno = %d\n", err);
204 exit(1);
205 }
185 206
186 if (!proc_mm) { 207 if (!proc_mm) {
187 /* 208 /*
@@ -221,16 +242,14 @@ static int userspace_tramp(void *stack)
221 242
222 set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); 243 set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
223 sigemptyset(&sa.sa_mask); 244 sigemptyset(&sa.sa_mask);
224 sigaddset(&sa.sa_mask, SIGIO); 245 sa.sa_flags = SA_ONSTACK | SA_NODEFER;
225 sigaddset(&sa.sa_mask, SIGWINCH);
226 sigaddset(&sa.sa_mask, SIGVTALRM);
227 sigaddset(&sa.sa_mask, SIGUSR1);
228 sa.sa_flags = SA_ONSTACK;
229 sa.sa_handler = (void *) v; 246 sa.sa_handler = (void *) v;
230 sa.sa_restorer = NULL; 247 sa.sa_restorer = NULL;
231 if (sigaction(SIGSEGV, &sa, NULL) < 0) 248 if (sigaction(SIGSEGV, &sa, NULL) < 0) {
232 panic("userspace_tramp - setting SIGSEGV handler " 249 printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
233 "failed - errno = %d\n", errno); 250 "handler failed - errno = %d\n", errno);
251 exit(1);
252 }
234 } 253 }
235 254
236 kill(os_getpid(), SIGSTOP); 255 kill(os_getpid(), SIGSTOP);
@@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack)
246{ 265{
247 void *stack; 266 void *stack;
248 unsigned long sp; 267 unsigned long sp;
249 int pid, status, n, flags; 268 int pid, status, n, flags, err;
250 269
251 stack = mmap(NULL, UM_KERN_PAGE_SIZE, 270 stack = mmap(NULL, UM_KERN_PAGE_SIZE,
252 PROT_READ | PROT_WRITE | PROT_EXEC, 271 PROT_READ | PROT_WRITE | PROT_EXEC,
253 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 272 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
254 if (stack == MAP_FAILED) 273 if (stack == MAP_FAILED) {
255 panic("start_userspace : mmap failed, errno = %d", errno); 274 err = -errno;
275 printk(UM_KERN_ERR "start_userspace : mmap failed, "
276 "errno = %d\n", errno);
277 return err;
278 }
279
256 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); 280 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
257 281
258 flags = CLONE_FILES; 282 flags = CLONE_FILES;
@@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack)
262 flags |= SIGCHLD; 286 flags |= SIGCHLD;
263 287
264 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 288 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
265 if (pid < 0) 289 if (pid < 0) {
266 panic("start_userspace : clone failed, errno = %d", errno); 290 err = -errno;
291 printk(UM_KERN_ERR "start_userspace : clone failed, "
292 "errno = %d\n", errno);
293 return err;
294 }
267 295
268 do { 296 do {
269 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); 297 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
270 if (n < 0) 298 if (n < 0) {
271 panic("start_userspace : wait failed, errno = %d", 299 err = -errno;
272 errno); 300 printk(UM_KERN_ERR "start_userspace : wait failed, "
301 "errno = %d\n", errno);
302 goto out_kill;
303 }
273 } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); 304 } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
274 305
275 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 306 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
276 panic("start_userspace : expected SIGSTOP, got status = %d", 307 err = -EINVAL;
277 status); 308 printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
309 "status = %d\n", status);
310 goto out_kill;
311 }
278 312
279 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, 313 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
280 (void *) PTRACE_O_TRACESYSGOOD) < 0) 314 (void *) PTRACE_O_TRACESYSGOOD) < 0) {
281 panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " 315 err = -errno;
282 "errno = %d\n", errno); 316 printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
317 "failed, errno = %d\n", errno);
318 goto out_kill;
319 }
283 320
284 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) 321 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
285 panic("start_userspace : munmap failed, errno = %d\n", errno); 322 err = -errno;
323 printk(UM_KERN_ERR "start_userspace : munmap failed, "
324 "errno = %d\n", errno);
325 goto out_kill;
326 }
286 327
287 return pid; 328 return pid;
329
330 out_kill:
331 os_kill_ptraced_process(pid, 1);
332 return err;
288} 333}
289 334
290void userspace(struct uml_pt_regs *regs) 335void userspace(struct uml_pt_regs *regs)
@@ -302,7 +347,16 @@ void userspace(struct uml_pt_regs *regs)
302 nsecs += os_nsecs(); 347 nsecs += os_nsecs();
303 348
304 while (1) { 349 while (1) {
305 restore_registers(pid, regs); 350 /*
351 * This can legitimately fail if the process loads a
352 * bogus value into a segment register. It will
353 * segfault and PTRACE_GETREGS will read that value
354 * out of the process. However, PTRACE_SETREGS will
355 * fail. In this case, there is nothing to do but
356 * just kill the process.
357 */
358 if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
359 fatal_sigsegv();
306 360
307 /* Now we set local_using_sysemu to be used for one loop */ 361 /* Now we set local_using_sysemu to be used for one loop */
308 local_using_sysemu = get_using_sysemu(); 362 local_using_sysemu = get_using_sysemu();
@@ -310,19 +364,26 @@ void userspace(struct uml_pt_regs *regs)
310 op = SELECT_PTRACE_OPERATION(local_using_sysemu, 364 op = SELECT_PTRACE_OPERATION(local_using_sysemu,
311 singlestepping(NULL)); 365 singlestepping(NULL));
312 366
313 err = ptrace(op, pid, 0, 0); 367 if (ptrace(op, pid, 0, 0)) {
314 if (err) 368 printk(UM_KERN_ERR "userspace - ptrace continue "
315 panic("userspace - could not resume userspace process, " 369 "failed, op = %d, errno = %d\n", op, errno);
316 "pid=%d, ptrace operation = %d, errno = %d\n", 370 fatal_sigsegv();
317 pid, op, errno); 371 }
318 372
319 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); 373 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
320 if (err < 0) 374 if (err < 0) {
321 panic("userspace - waitpid failed, errno = %d\n", 375 printk(UM_KERN_ERR "userspace - wait failed, "
322 errno); 376 "errno = %d\n", errno);
377 fatal_sigsegv();
378 }
323 379
324 regs->is_user = 1; 380 regs->is_user = 1;
325 save_registers(pid, regs); 381 if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
382 printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
383 "errno = %d\n", errno);
384 fatal_sigsegv();
385 }
386
326 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 387 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
327 388
328 if (WIFSTOPPED(status)) { 389 if (WIFSTOPPED(status)) {
@@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs)
345 break; 406 break;
346 case SIGVTALRM: 407 case SIGVTALRM:
347 now = os_nsecs(); 408 now = os_nsecs();
348 if(now < nsecs) 409 if (now < nsecs)
349 break; 410 break;
350 block_signals(); 411 block_signals();
351 (*sig_info[sig])(sig, regs); 412 (*sig_info[sig])(sig, regs);
@@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs)
368 default: 429 default:
369 printk(UM_KERN_ERR "userspace - child stopped " 430 printk(UM_KERN_ERR "userspace - child stopped "
370 "with signal %d\n", sig); 431 "with signal %d\n", sig);
432 fatal_sigsegv();
371 } 433 }
372 pid = userspace_pid[0]; 434 pid = userspace_pid[0];
373 interrupt_end(); 435 interrupt_end();
@@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
419 .it_interval = tv }) }); 481 .it_interval = tv }) });
420 482
421 err = ptrace_setregs(pid, thread_regs); 483 err = ptrace_setregs(pid, thread_regs);
422 if (err < 0) 484 if (err < 0) {
423 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 485 err = -errno;
424 "pid = %d, errno = %d\n", pid, -err); 486 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
487 "failed, pid = %d, errno = %d\n", pid, -err);
488 return err;
489 }
425 490
426 /* set a well known return code for detection of child write failure */ 491 /* set a well known return code for detection of child write failure */
427 child_data->err = 12345678; 492 child_data->err = 12345678;
@@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
431 * parent's stack, and check, if bad result. 496 * parent's stack, and check, if bad result.
432 */ 497 */
433 err = ptrace(PTRACE_CONT, pid, 0, 0); 498 err = ptrace(PTRACE_CONT, pid, 0, 0);
434 if (err) 499 if (err) {
435 panic("Failed to continue new process, pid = %d, " 500 err = -errno;
436 "errno = %d\n", pid, errno); 501 printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
502 "errno = %d\n", pid, errno);
503 return err;
504 }
505
437 wait_stub_done(pid); 506 wait_stub_done(pid);
438 507
439 pid = data->err; 508 pid = data->err;
440 if (pid < 0) 509 if (pid < 0) {
441 panic("copy_context_skas0 - stub-parent reports error %d\n", 510 printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
442 -pid); 511 "error %d\n", -pid);
512 return pid;
513 }
443 514
444 /* 515 /*
445 * Wait, until child has finished too: read child's result from 516 * Wait, until child has finished too: read child's result from
446 * child's stack and check it. 517 * child's stack and check it.
447 */ 518 */
448 wait_stub_done(pid); 519 wait_stub_done(pid);
449 if (child_data->err != STUB_DATA) 520 if (child_data->err != STUB_DATA) {
450 panic("copy_context_skas0 - stub-child reports error %ld\n", 521 printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
451 child_data->err); 522 "error %ld\n", child_data->err);
523 err = child_data->err;
524 goto out_kill;
525 }
452 526
453 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, 527 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
454 (void *)PTRACE_O_TRACESYSGOOD) < 0) 528 (void *)PTRACE_O_TRACESYSGOOD) < 0) {
455 panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " 529 err = -errno;
456 "errno = %d\n", errno); 530 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
531 "failed, errno = %d\n", errno);
532 goto out_kill;
533 }
457 534
458 return pid; 535 return pid;
536
537 out_kill:
538 os_kill_ptraced_process(pid, 1);
539 return err;
459} 540}
460 541
461/* 542/*
@@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
463 * available. Opening /proc/mm creates a new mm_context, which lacks 544 * available. Opening /proc/mm creates a new mm_context, which lacks
464 * the stub-pages. Thus, we map them using /proc/mm-fd 545 * the stub-pages. Thus, we map them using /proc/mm-fd
465 */ 546 */
466void map_stub_pages(int fd, unsigned long code, 547int map_stub_pages(int fd, unsigned long code, unsigned long data,
467 unsigned long data, unsigned long stack) 548 unsigned long stack)
468{ 549{
469 struct proc_mm_op mmop; 550 struct proc_mm_op mmop;
470 int n; 551 int n;
@@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code,
488 printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " 569 printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
489 "offset = %llx\n", code, code_fd, 570 "offset = %llx\n", code, code_fd,
490 (unsigned long long) code_offset); 571 (unsigned long long) code_offset);
491 panic("map_stub_pages : /proc/mm map for code failed, " 572 printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
492 "err = %d\n", n); 573 "failed, err = %d\n", n);
574 return -n;
493 } 575 }
494 576
495 if (stack) { 577 if (stack) {
@@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code,
507 .offset = map_offset 589 .offset = map_offset
508 } } }); 590 } } });
509 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); 591 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
510 if (n != sizeof(mmop)) 592 if (n != sizeof(mmop)) {
511 panic("map_stub_pages : /proc/mm map for data failed, " 593 n = errno;
512 "err = %d\n", errno); 594 printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
595 "data failed, err = %d\n", n);
596 return -n;
597 }
513 } 598 }
599
600 return 0;
514} 601}
515 602
516void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 603void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
@@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
571 kmalloc_ok = 0; 658 kmalloc_ok = 0;
572 return 1; 659 return 1;
573 default: 660 default:
574 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 661 printk(UM_KERN_ERR "Bad sigsetjmp return in "
662 "start_idle_thread - %d\n", n);
663 fatal_sigsegv();
575 } 664 }
576 longjmp(*switch_buf, 1); 665 longjmp(*switch_buf, 1);
577} 666}
@@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp)
614 if (proc_mm) { 703 if (proc_mm) {
615 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, 704 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
616 mm_idp->u.mm_fd); 705 mm_idp->u.mm_fd);
617 if (err) 706 if (err) {
618 panic("__switch_mm - PTRACE_SWITCH_MM failed, " 707 printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
619 "errno = %d\n", errno); 708 "failed, errno = %d\n", errno);
709 fatal_sigsegv();
710 }
620 } 711 }
621 else userspace_pid[0] = mm_idp->u.pid; 712 else userspace_pid[0] = mm_idp->u.pid;
622} 713}
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
deleted file mode 100644
index 3b1b9244f468..000000000000
--- a/arch/um/os-Linux/skas/trap.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#if 0
7#include "kern_util.h"
8#include "skas.h"
9#include "ptrace_user.h"
10#include "sysdep/ptrace_user.h"
11#endif
12
13#include <errno.h>
14#include <signal.h>
15#include "sysdep/ptrace.h"
16#include "kern_constants.h"
17#include "as-layout.h"
18#include "os.h"
19#include "sigcontext.h"
20#include "task.h"
21
22static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
23
24void sig_handler_common_skas(int sig, void *sc_ptr)
25{
26 struct sigcontext *sc = sc_ptr;
27 struct uml_pt_regs *r;
28 void (*handler)(int, struct uml_pt_regs *);
29 int save_user, save_errno = errno;
30
31 /*
32 * This is done because to allow SIGSEGV to be delivered inside a SEGV
33 * handler. This can happen in copy_user, and if SEGV is disabled,
34 * the process will die.
35 * XXX Figure out why this is better than SA_NODEFER
36 */
37 if (sig == SIGSEGV) {
38 change_sig(SIGSEGV, 1);
39 /*
40 * For segfaults, we want the data from the
41 * sigcontext. In this case, we don't want to mangle
42 * the process registers, so use a static set of
43 * registers. For other signals, the process
44 * registers are OK.
45 */
46 r = &ksig_regs[cpu()];
47 copy_sc(r, sc_ptr);
48 }
49 else r = TASK_REGS(get_current());
50
51 save_user = r->is_user;
52 r->is_user = 0;
53 if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
54 (sig == SIGILL) || (sig == SIGTRAP))
55 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
56
57 change_sig(SIGUSR1, 1);
58
59 handler = sig_info[sig];
60
61 /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
62 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
63 unblock_signals();
64
65 handler(sig, r);
66
67 errno = save_errno;
68 r->is_user = save_user;
69}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7b81f6c08a5e..b616e15638fb 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)
60 * the UML code itself. 60 * the UML code itself.
61 */ 61 */
62 ret = 2; 62 ret = 2;
63 _exit(ret); 63
64 exit(ret);
64} 65}
65 66
66static void fatal_perror(char *str) 67static void fatal_perror(const char *str)
67{ 68{
68 perror(str); 69 perror(str);
69 exit(1); 70 exit(1);
@@ -341,6 +342,8 @@ static void __init check_coredump_limit(void)
341 342
342void __init os_early_checks(void) 343void __init os_early_checks(void)
343{ 344{
345 int pid;
346
344 /* Print out the core dump limits early */ 347 /* Print out the core dump limits early */
345 check_coredump_limit(); 348 check_coredump_limit();
346 349
@@ -350,6 +353,11 @@ void __init os_early_checks(void)
350 * kernel is running. 353 * kernel is running.
351 */ 354 */
352 check_tmpexec(); 355 check_tmpexec();
356
357 pid = start_ptraced_child();
358 if (init_registers(pid))
359 fatal("Failed to initialize default registers");
360 stop_ptraced_child(pid, 1, 1);
353} 361}
354 362
355static int __init noprocmm_cmd_param(char *str, int* add) 363static int __init noprocmm_cmd_param(char *str, int* add)
@@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void)
411 non_fatal("found\n"); 419 non_fatal("found\n");
412 } 420 }
413 421
414 init_registers(pid);
415 stop_ptraced_child(pid, 1, 1); 422 stop_ptraced_child(pid, 1, 1);
416} 423}
417 424
@@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void)
466 else non_fatal("found\n"); 473 else non_fatal("found\n");
467} 474}
468 475
469int can_do_skas(void) 476void can_do_skas(void)
470{ 477{
471 non_fatal("Checking for the skas3 patch in the host:\n"); 478 non_fatal("Checking for the skas3 patch in the host:\n");
472 479
@@ -476,8 +483,6 @@ int can_do_skas(void)
476 483
477 if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) 484 if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
478 skas_needs_stub = 1; 485 skas_needs_stub = 1;
479
480 return 1;
481} 486}
482 487
483int __init parse_iomem(char *str, int *add) 488int __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 2a1c9843e32e..000000000000
--- a/arch/um/os-Linux/trap.c
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include "os.h"
8#include "sysdep/ptrace.h"
9
10/* Initialized from linux_main() */
11void (*sig_info[NSIG])(int, struct uml_pt_regs *);
12
13void os_fill_handlinfo(struct kern_handlers h)
14{
15 sig_info[SIGTRAP] = h.relay_signal;
16 sig_info[SIGFPE] = h.relay_signal;
17 sig_info[SIGILL] = h.relay_signal;
18 sig_info[SIGWINCH] = h.winch;
19 sig_info[SIGBUS] = h.bus_handler;
20 sig_info[SIGSEGV] = h.page_fault;
21 sig_info[SIGIO] = h.sigio_handler;
22 sig_info[SIGVTALRM] = h.timer_handler;
23}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 4cfdd18ea1ef..b09ff66a77ee 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -1,13 +1,16 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <unistd.h>
7#include <errno.h> 8#include <errno.h>
9#include <fcntl.h>
10#include "kern_constants.h"
11#include "kern_util.h"
8#include "os.h" 12#include "os.h"
9#include "user.h" 13#include "user.h"
10#include "kern_util.h"
11 14
12struct grantpt_info { 15struct grantpt_info {
13 int fd; 16 int fd;
@@ -26,36 +29,34 @@ static void grantpt_cb(void *arg)
26int get_pty(void) 29int get_pty(void)
27{ 30{
28 struct grantpt_info info; 31 struct grantpt_info info;
29 int fd; 32 int fd, err;
30 33
31 fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); 34 fd = open("/dev/ptmx", O_RDWR);
32 if(fd < 0){ 35 if (fd < 0) {
33 printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); 36 err = -errno;
34 return(fd); 37 printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - "
38 "err = %d\n", errno);
39 return err;
35 } 40 }
36 41
37 info.fd = fd; 42 info.fd = fd;
38 initial_thread_cb(grantpt_cb, &info); 43 initial_thread_cb(grantpt_cb, &info);
39 44
40 if(info.res < 0){ 45 if (info.res < 0) {
41 printk("get_pty : Couldn't grant pty - errno = %d\n", 46 err = -info.err;
42 -info.err); 47 printk(UM_KERN_ERR "get_pty : Couldn't grant pty - "
43 return(-1); 48 "errno = %d\n", -info.err);
49 goto out;
44 } 50 }
45 if(unlockpt(fd) < 0){ 51
46 printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); 52 if (unlockpt(fd) < 0) {
47 return(-1); 53 err = -errno;
54 printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - "
55 "errno = %d\n", errno);
56 goto out;
48 } 57 }
49 return(fd); 58 return fd;
59out:
60 close(fd);
61 return err;
50} 62}
51
52/*
53 * Overrides for Emacs so that we follow Linus's tabbing style.
54 * Emacs will notice this stuff at the end of the file and automatically
55 * adjust the settings for this buffer only. This must remain at the end
56 * of the file.
57 * ---------------------------------------------------------------------------
58 * Local variables:
59 * c-file-style: "linux"
60 * End:
61 */
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
index d11a55baa6bd..cc648e6fd3a2 100644
--- a/arch/um/os-Linux/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -12,7 +12,6 @@
12#include <sys/time.h> 12#include <sys/time.h>
13#include "init.h" 13#include "init.h"
14#include "user.h" 14#include "user.h"
15#include "kern_util.h"
16#include "os.h" 15#include "os.h"
17 16
18#define TTY_LOG_DIR "./" 17#define TTY_LOG_DIR "./"
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 3e058ce9ffb6..a6f31d476993 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)
88 host.release, host.version, host.machine); 88 host.release, host.version, host.machine);
89} 89}
90 90
91int setjmp_wrapper(void (*proc)(void *, void *), ...)
92{
93 va_list args;
94 jmp_buf buf;
95 int n;
96
97 n = UML_SETJMP(&buf);
98 if(n == 0){
99 va_start(args, proc);
100 (*proc)(&buf, &args);
101 }
102 va_end(args);
103 return n;
104}
105
106void os_dump_core(void) 91void os_dump_core(void)
107{ 92{
108 int pid; 93 int pid;
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
index a4360b5207db..8d4f273f1219 100644
--- a/arch/um/sys-i386/bug.c
+++ b/arch/um/sys-i386/bug.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <linux/uaccess.h> 6#include <linux/uaccess.h>
7#include <asm/errno.h>
7 8
8/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because 9/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
9 * that's not relevant in skas mode. 10 * that's not relevant in skas mode.
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 806895d73bcc..a74442d13762 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -3,171 +3,47 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <errno.h>
7#include <signal.h> 6#include <signal.h>
8#include <string.h>
9#include "kern_constants.h" 7#include "kern_constants.h"
10#include "os.h" 8#include "kern_util.h"
9#include "longjmp.h"
11#include "task.h" 10#include "task.h"
12#include "user.h" 11#include "user.h"
13 12#include "sysdep/ptrace.h"
14#define MAXTOKEN 64
15 13
16/* Set during early boot */ 14/* Set during early boot */
17int host_has_cmov = 1; 15int host_has_cmov = 1;
18int host_has_xmm = 0; 16static jmp_buf cmov_test_return;
19 17
20static char token(int fd, char *buf, int len, char stop) 18static void cmov_sigill_test_handler(int sig)
21{ 19{
22 int n; 20 host_has_cmov = 0;
23 char *ptr, *end, c; 21 longjmp(cmov_test_return, 1);
24
25 ptr = buf;
26 end = &buf[len];
27 do {
28 n = os_read_file(fd, ptr, sizeof(*ptr));
29 c = *ptr++;
30 if (n != sizeof(*ptr)) {
31 if (n == 0)
32 return 0;
33 printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
34 "err = %d\n", -n);
35 if (n < 0)
36 return n;
37 else return -EIO;
38 }
39 } while ((c != '\n') && (c != stop) && (ptr < end));
40
41 if (ptr == end) {
42 printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
43 stop);
44 return -1;
45 }
46 *(ptr - 1) = '\0';
47 return c;
48}
49
50static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
51{
52 int n;
53 char c;
54
55 scratch[len - 1] = '\0';
56 while (1) {
57 c = token(fd, scratch, len - 1, ':');
58 if (c <= 0)
59 return 0;
60 else if (c != ':') {
61 printk(UM_KERN_ERR "Failed to find ':' in "
62 "/proc/cpuinfo\n");
63 return 0;
64 }
65
66 if (!strncmp(scratch, key, strlen(key)))
67 return 1;
68
69 do {
70 n = os_read_file(fd, &c, sizeof(c));
71 if (n != sizeof(c)) {
72 printk(UM_KERN_ERR "Failed to find newline in "
73 "/proc/cpuinfo, err = %d\n", -n);
74 return 0;
75 }
76 } while (c != '\n');
77 }
78 return 0;
79} 22}
80 23
81static int check_cpu_flag(char *feature, int *have_it) 24void arch_check_bugs(void)
82{
83 char buf[MAXTOKEN], c;
84 int fd, len = ARRAY_SIZE(buf);
85
86 printk(UM_KERN_INFO "Checking for host processor %s support...",
87 feature);
88 fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
89 if (fd < 0) {
90 printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
91 -fd);
92 return 0;
93 }
94
95 *have_it = 0;
96 if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
97 goto out;
98
99 c = token(fd, buf, len - 1, ' ');
100 if (c < 0)
101 goto out;
102 else if (c != ' ') {
103 printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
104 goto out;
105 }
106
107 while (1) {
108 c = token(fd, buf, len - 1, ' ');
109 if (c < 0)
110 goto out;
111 else if (c == '\n')
112 break;
113
114 if (!strcmp(buf, feature)) {
115 *have_it = 1;
116 goto out;
117 }
118 }
119 out:
120 if (*have_it == 0)
121 printk("No\n");
122 else if (*have_it == 1)
123 printk("Yes\n");
124 os_close_file(fd);
125 return 1;
126}
127
128#if 0 /*
129 * This doesn't work in tt mode, plus it's causing compilation problems
130 * for some people.
131 */
132static void disable_lcall(void)
133{ 25{
134 struct modify_ldt_ldt_s ldt; 26 struct sigaction old, new;
135 int err;
136 27
137 bzero(&ldt, sizeof(ldt)); 28 printk(UM_KERN_INFO "Checking for host processor cmov support...");
138 ldt.entry_number = 7; 29 new.sa_handler = cmov_sigill_test_handler;
139 ldt.base_addr = 0;
140 ldt.limit = 0;
141 err = modify_ldt(1, &ldt, sizeof(ldt));
142 if (err)
143 printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
144 errno);
145}
146#endif
147 30
148void arch_init_thread(void) 31 /* Make sure that SIGILL is enabled after the handler longjmps back */
149{ 32 new.sa_flags = SA_NODEFER;
150#if 0 33 sigemptyset(&new.sa_mask);
151 disable_lcall(); 34 sigaction(SIGILL, &new, &old);
152#endif
153}
154 35
155void arch_check_bugs(void) 36 if (setjmp(cmov_test_return) == 0) {
156{ 37 unsigned long foo = 0;
157 int have_it; 38 __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
39 printk(UM_KERN_CONT "Yes\n");
40 } else
41 printk(UM_KERN_CONT "No\n");
158 42
159 if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) { 43 sigaction(SIGILL, &old, &new);
160 printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
161 "capability checks\n");
162 return;
163 }
164 if (check_cpu_flag("cmov", &have_it))
165 host_has_cmov = have_it;
166 if (check_cpu_flag("xmm", &have_it))
167 host_has_xmm = have_it;
168} 44}
169 45
170int arch_handle_signal(int sig, struct uml_pt_regs *regs) 46void arch_examine_signal(int sig, struct uml_pt_regs *regs)
171{ 47{
172 unsigned char tmp[2]; 48 unsigned char tmp[2];
173 49
@@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
176 * SIGILL in init. 52 * SIGILL in init.
177 */ 53 */
178 if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) 54 if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
179 return 0; 55 return;
56
57 if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
58 printk(UM_KERN_ERR "SIGILL in init, could not read "
59 "instructions!\n");
60 return;
61 }
180 62
181 if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
182 panic("SIGILL in init, could not read instructions!\n");
183 if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) 63 if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
184 return 0; 64 return;
185 65
186 if (host_has_cmov == 0) 66 if (host_has_cmov == 0)
187 panic("SIGILL caused by cmov, which this processor doesn't " 67 printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
188 "implement, boot a filesystem compiled for older " 68 "processor doesn't implement. Boot a filesystem "
189 "processors"); 69 "compiled for older processors");
190 else if (host_has_cmov == 1) 70 else if (host_has_cmov == 1)
191 panic("SIGILL caused by cmov, which this processor claims to " 71 printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
192 "implement"); 72 "processor claims to implement");
193 else if (host_has_cmov == -1) 73 else
194 panic("SIGILL caused by cmov, couldn't tell if this processor " 74 printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
195 "implements it, boot a filesystem compiled for older " 75 host_has_cmov);
196 "processors");
197 else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
198 return 0;
199} 76}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 67c0958eb984..a34263e6b08d 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,8 +3,9 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/mm.h" 6#include <linux/mm.h>
7#include "asm/unistd.h" 7#include <linux/sched.h>
8#include <asm/unistd.h>
8#include "os.h" 9#include "os.h"
9#include "proc_mm.h" 10#include "proc_mm.h"
10#include "skas.h" 11#include "skas.h"
@@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
146 if (ptrace_ldt) 147 if (ptrace_ldt)
147 return read_ldt_from_host(ptr, bytecount); 148 return read_ldt_from_host(ptr, bytecount);
148 149
149 down(&ldt->semaphore); 150 mutex_lock(&ldt->lock);
150 if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { 151 if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
151 size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; 152 size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
152 if (size > bytecount) 153 if (size > bytecount)
@@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
170 ptr += size; 171 ptr += size;
171 } 172 }
172 } 173 }
173 up(&ldt->semaphore); 174 mutex_unlock(&ldt->lock);
174 175
175 if (bytecount == 0 || err == -EFAULT) 176 if (bytecount == 0 || err == -EFAULT)
176 goto out; 177 goto out;
@@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
228 } 229 }
229 230
230 if (!ptrace_ldt) 231 if (!ptrace_ldt)
231 down(&ldt->semaphore); 232 mutex_lock(&ldt->lock);
232 233
233 err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); 234 err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
234 if (err) 235 if (err)
@@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
288 err = 0; 289 err = 0;
289 290
290out_unlock: 291out_unlock:
291 up(&ldt->semaphore); 292 mutex_unlock(&ldt->lock);
292out: 293out:
293 return err; 294 return err;
294} 295}
@@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
395 396
396 397
397 if (!ptrace_ldt) 398 if (!ptrace_ldt)
398 init_MUTEX(&new_mm->ldt.semaphore); 399 mutex_init(&new_mm->ldt.lock);
399 400
400 if (!from_mm) { 401 if (!from_mm) {
401 memset(&desc, 0, sizeof(desc)); 402 memset(&desc, 0, sizeof(desc));
@@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
455 * i.e., we have to use the stub for modify_ldt, which 456 * i.e., we have to use the stub for modify_ldt, which
456 * can't handle the big read buffer of up to 64kB. 457 * can't handle the big read buffer of up to 64kB.
457 */ 458 */
458 down(&from_mm->ldt.semaphore); 459 mutex_lock(&from_mm->ldt.lock);
459 if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) 460 if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
460 memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, 461 memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
461 sizeof(new_mm->ldt.u.entries)); 462 sizeof(new_mm->ldt.u.entries));
@@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
474 } 475 }
475 } 476 }
476 new_mm->ldt.entry_count = from_mm->ldt.entry_count; 477 new_mm->ldt.entry_count = from_mm->ldt.entry_count;
477 up(&from_mm->ldt.semaphore); 478 mutex_unlock(&from_mm->ldt.lock);
478 } 479 }
479 480
480 out: 481 out:
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index bd3da8a61f64..6b4499906a6c 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -8,11 +8,11 @@
8#include "asm/uaccess.h" 8#include "asm/uaccess.h"
9#include "skas.h" 9#include "skas.h"
10 10
11extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); 11extern int arch_switch_tls(struct task_struct *to);
12 12
13void arch_switch_to(struct task_struct *from, struct task_struct *to) 13void arch_switch_to(struct task_struct *to)
14{ 14{
15 int err = arch_switch_tls(from, to); 15 int err = arch_switch_tls(to);
16 if (!err) 16 if (!err)
17 return; 17 return;
18 18
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 5cf97bc229b9..0b10c3e74028 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)
19 return -errno; 19 return -errno;
20 return 0; 20 return 0;
21} 21}
22
23int ptrace_getfpregs(long pid, unsigned long *regs)
24{
25 if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
26 return -errno;
27 return 0;
28}
29
30int ptrace_setfpregs(long pid, unsigned long *regs)
31{
32 if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
33 return -errno;
34 return 0;
35}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 19053d46cb60..fd0c25ad6af3 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,
168 struct sigcontext __user *from) 168 struct sigcontext __user *from)
169{ 169{
170 struct sigcontext sc; 170 struct sigcontext sc;
171 int err; 171 int err, pid;
172 172
173 err = copy_from_user(&sc, from, sizeof(sc)); 173 err = copy_from_user(&sc, from, sizeof(sc));
174 if (err) 174 if (err)
175 return err; 175 return err;
176 176
177 pid = userspace_pid[current_thread_info()->cpu];
177 copy_sc(&regs->regs, &sc); 178 copy_sc(&regs->regs, &sc);
178 if (have_fpx_regs) { 179 if (have_fpx_regs) {
179 struct user_fxsr_struct fpx; 180 struct user_fxsr_struct fpx;
@@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
187 if (err) 188 if (err)
188 return 1; 189 return 1;
189 190
190 err = restore_fpx_registers(userspace_pid[current_thread->cpu], 191 err = restore_fpx_registers(pid, (unsigned long *) &fpx);
191 (unsigned long *) &fpx);
192 if (err < 0) { 192 if (err < 0) {
193 printk(KERN_ERR "copy_sc_from_user - " 193 printk(KERN_ERR "copy_sc_from_user - "
194 "restore_fpx_registers failed, errno = %d\n", 194 "restore_fpx_registers failed, errno = %d\n",
@@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
204 if (err) 204 if (err)
205 return 1; 205 return 1;
206 206
207 err = restore_fp_registers(userspace_pid[current_thread->cpu], 207 err = restore_fp_registers(pid, (unsigned long *) &fp);
208 (unsigned long *) &fp);
209 if (err < 0) { 208 if (err < 0) {
210 printk(KERN_ERR "copy_sc_from_user - " 209 printk(KERN_ERR "copy_sc_from_user - "
211 "restore_fp_registers failed, errno = %d\n", 210 "restore_fp_registers failed, errno = %d\n",
@@ -223,7 +222,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
223{ 222{
224 struct sigcontext sc; 223 struct sigcontext sc;
225 struct faultinfo * fi = &current->thread.arch.faultinfo; 224 struct faultinfo * fi = &current->thread.arch.faultinfo;
226 int err; 225 int err, pid;
227 226
228 sc.gs = REGS_GS(regs->regs.gp); 227 sc.gs = REGS_GS(regs->regs.gp);
229 sc.fs = REGS_FS(regs->regs.gp); 228 sc.fs = REGS_FS(regs->regs.gp);
@@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to,
249 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); 248 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
250 sc.fpstate = to_fp; 249 sc.fpstate = to_fp;
251 250
251 pid = userspace_pid[current_thread_info()->cpu];
252 if (have_fpx_regs) { 252 if (have_fpx_regs) {
253 struct user_fxsr_struct fpx; 253 struct user_fxsr_struct fpx;
254 254
255 err = save_fpx_registers(userspace_pid[current_thread->cpu], 255 err = save_fpx_registers(pid, (unsigned long *) &fpx);
256 (unsigned long *) &fpx);
257 if (err < 0){ 256 if (err < 0){
258 printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " 257 printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
259 "failed, errno = %d\n", err); 258 "failed, errno = %d\n", err);
@@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
276 else { 275 else {
277 struct user_i387_struct fp; 276 struct user_i387_struct fp;
278 277
279 err = save_fp_registers(userspace_pid[current_thread->cpu], 278 err = save_fp_registers(pid, (unsigned long *) &fp);
280 (unsigned long *) &fp);
281 if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) 279 if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
282 return 1; 280 return 1;
283 } 281 }
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index e730772c401b..7699e89f660f 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -7,7 +7,7 @@
7 .globl batch_syscall_stub 7 .globl batch_syscall_stub
8batch_syscall_stub: 8batch_syscall_stub:
9 /* load pointer to first operation */ 9 /* load pointer to first operation */
10 mov $(ASM_STUB_DATA+8), %esp 10 mov $(STUB_DATA+8), %esp
11 11
12again: 12again:
13 /* load length of additional data */ 13 /* load length of additional data */
@@ -15,12 +15,12 @@ again:
15 15
16 /* if(length == 0) : end of list */ 16 /* if(length == 0) : end of list */
17 /* write possible 0 to header */ 17 /* write possible 0 to header */
18 mov %eax, ASM_STUB_DATA+4 18 mov %eax, STUB_DATA+4
19 cmpl $0, %eax 19 cmpl $0, %eax
20 jz done 20 jz done
21 21
22 /* save current pointer */ 22 /* save current pointer */
23 mov %esp, ASM_STUB_DATA+4 23 mov %esp, STUB_DATA+4
24 24
25 /* skip additional data */ 25 /* skip additional data */
26 add %eax, %esp 26 add %eax, %esp
@@ -46,7 +46,7 @@ again:
46 46
47done: 47done:
48 /* save return value */ 48 /* save return value */
49 mov %eax, ASM_STUB_DATA 49 mov %eax, STUB_DATA
50 50
51 /* stop */ 51 /* stop */
52 int3 52 int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index b3999cb76bfd..28ccf737a79f 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -1,32 +1,17 @@
1/* 1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h>
7#include <sys/select.h> /* The only way I can see to get sigset_t */
8#include <asm/unistd.h>
9#include "as-layout.h"
10#include "uml-config.h"
11#include "sysdep/stub.h" 6#include "sysdep/stub.h"
12#include "sysdep/sigcontext.h" 7#include "sysdep/sigcontext.h"
13#include "sysdep/faultinfo.h"
14 8
15void __attribute__ ((__section__ (".__syscall_stub"))) 9void __attribute__ ((__section__ (".__syscall_stub")))
16stub_segv_handler(int sig) 10stub_segv_handler(int sig)
17{ 11{
18 struct sigcontext *sc = (struct sigcontext *) (&sig + 1); 12 struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
19 int pid;
20 13
21 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); 14 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
22 15
23 pid = stub_syscall0(__NR_getpid); 16 trap_myself();
24 stub_syscall2(__NR_kill, pid, SIGUSR1);
25
26 /* Load pointer to sigcontext into esp, since we need to leave
27 * the stack in its original form when we do the sigreturn here, by
28 * hand.
29 */
30 __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
31 "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
32} 17}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index 12d4148dba39..00e5f5203eea 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -9,4 +9,9 @@
9 9
10#define old_mmap old_mmap_i386 10#define old_mmap old_mmap_i386
11 11
12.section .rodata,"a"
13
12#include "../../x86/kernel/syscall_table_32.S" 14#include "../../x86/kernel/syscall_table_32.S"
15
16ENTRY(syscall_table_size)
17.long .-sys_call_table
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index fcaff86b000c..c6c7131e563b 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)
26 cpu = get_cpu(); 26 cpu = get_cpu();
27 ret = os_set_thread_area(info, userspace_pid[cpu]); 27 ret = os_set_thread_area(info, userspace_pid[cpu]);
28 put_cpu(); 28 put_cpu();
29
30 if (ret)
31 printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
32 "index = %d\n", ret, info->entry_number);
33
29 return ret; 34 return ret;
30} 35}
31 36
@@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info)
37 cpu = get_cpu(); 42 cpu = get_cpu();
38 ret = os_get_thread_area(info, userspace_pid[cpu]); 43 ret = os_get_thread_area(info, userspace_pid[cpu]);
39 put_cpu(); 44 put_cpu();
45
46 if (ret)
47 printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
48 "index = %d\n", ret, info->entry_number);
49
40 return ret; 50 return ret;
41} 51}
42 52
@@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task)
172 * SKAS patch. 182 * SKAS patch.
173 */ 183 */
174 184
175int arch_switch_tls(struct task_struct *from, struct task_struct *to) 185int arch_switch_tls(struct task_struct *to)
176{ 186{
177 if (!host_supports_tls) 187 if (!host_supports_tls)
178 return 0; 188 return 0;
@@ -225,7 +235,8 @@ out:
225} 235}
226 236
227/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */ 237/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
228static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx) 238static int get_tls_entry(struct task_struct *task, struct user_desc *info,
239 int idx)
229{ 240{
230 struct thread_struct *t = &task->thread; 241 struct thread_struct *t = &task->thread;
231 242
@@ -263,7 +274,7 @@ clear:
263 goto out; 274 goto out;
264} 275}
265 276
266asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) 277int sys_set_thread_area(struct user_desc __user *user_desc)
267{ 278{
268 struct user_desc info; 279 struct user_desc info;
269 int idx, ret; 280 int idx, ret;
@@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
298 * i386. However the only possible error are caused by bugs. 309 * i386. However the only possible error are caused by bugs.
299 */ 310 */
300int ptrace_set_thread_area(struct task_struct *child, int idx, 311int ptrace_set_thread_area(struct task_struct *child, int idx,
301 struct user_desc __user *user_desc) 312 struct user_desc __user *user_desc)
302{ 313{
303 struct user_desc info; 314 struct user_desc info;
304 315
@@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
311 return set_tls_entry(child, &info, idx, 0); 322 return set_tls_entry(child, &info, idx, 0);
312} 323}
313 324
314asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc) 325int sys_get_thread_area(struct user_desc __user *user_desc)
315{ 326{
316 struct user_desc info; 327 struct user_desc info;
317 int idx, ret; 328 int idx, ret;
@@ -355,10 +366,9 @@ out:
355 return ret; 366 return ret;
356} 367}
357 368
358
359/* 369/*
360 * XXX: This part is probably common to i386 and x86-64. Don't create a common 370 * This code is really i386-only, but it detects and logs x86_64 GDT indexes
361 * file for now, do that when implementing x86-64 support. 371 * if a 32-bit UML is running on a 64-bit host.
362 */ 372 */
363static int __init __setup_host_supports_tls(void) 373static int __init __setup_host_supports_tls(void)
364{ 374{
@@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void)
367 printk(KERN_INFO "Host TLS support detected\n"); 377 printk(KERN_INFO "Host TLS support detected\n");
368 printk(KERN_INFO "Detected host type: "); 378 printk(KERN_INFO "Detected host type: ");
369 switch (host_gdt_entry_tls_min) { 379 switch (host_gdt_entry_tls_min) {
370 case GDT_ENTRY_TLS_MIN_I386: 380 case GDT_ENTRY_TLS_MIN_I386:
371 printk("i386\n"); 381 printk(KERN_CONT "i386");
372 break; 382 break;
373 case GDT_ENTRY_TLS_MIN_X86_64: 383 case GDT_ENTRY_TLS_MIN_X86_64:
374 printk("x86_64\n"); 384 printk(KERN_CONT "x86_64");
375 break; 385 break;
376 } 386 }
387 printk(KERN_CONT " (GDT indexes %d to %d)\n",
388 host_gdt_entry_tls_min,
389 host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
377 } else 390 } else
378 printk(KERN_ERR " Host TLS support NOT detected! " 391 printk(KERN_ERR " Host TLS support NOT detected! "
379 "TLS support inside UML will not work\n"); 392 "TLS support inside UML will not work\n");
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index a9814a7ae60e..08901526e893 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
6OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ 6OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
7 ptrace_user.o sysrq.o 7 ptrace_user.o sysrq.o
8 8
9EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel 9EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
10 10
11all: $(OBJ) 11all: $(OBJ)
12 12
@@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c
22 22
23semaphore.c: 23semaphore.c:
24 rm -f $@ 24 rm -f $@
25 ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ 25 ln -s $(srctree)/arch/ppc/kernel/$@ $@
26 26
27checksum.S: 27checksum.S:
28 rm -f $@ 28 rm -f $@
29 ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ 29 ln -s $(srctree)/arch/ppc/lib/$@ $@
30 30
31mk_defs.c: 31mk_defs.c:
32 rm -f $@ 32 rm -f $@
33 ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ 33 ln -s $(srctree)/arch/ppc/kernel/$@ $@
34 34
35ppc_defs.head: 35ppc_defs.head:
36 rm -f $@ 36 rm -f $@
37 ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ 37 ln -s $(srctree)/arch/ppc/kernel/$@ $@
38 38
39ppc_defs.h: mk_defs.c ppc_defs.head \ 39ppc_defs.h: mk_defs.c ppc_defs.head \
40 $(TOPDIR)/include/asm-ppc/mmu.h \ 40 $(srctree)/include/asm-ppc/mmu.h \
41 $(TOPDIR)/include/asm-ppc/processor.h \ 41 $(srctree)/include/asm-ppc/processor.h \
42 $(TOPDIR)/include/asm-ppc/pgtable.h \ 42 $(srctree)/include/asm-ppc/pgtable.h \
43 $(TOPDIR)/include/asm-ppc/ptrace.h 43 $(srctree)/include/asm-ppc/ptrace.h
44# $(CC) $(CFLAGS) -S mk_defs.c 44# $(CC) $(CFLAGS) -S mk_defs.c
45 cp ppc_defs.head ppc_defs.h 45 cp ppc_defs.head ppc_defs.h
46# for bk, this way we can write to the file even if it's not checked out 46# 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 \
56 56
57checksum.o: checksum.S 57checksum.o: checksum.S
58 rm -f asm 58 rm -f asm
59 ln -s $(TOPDIR)/include/asm-ppc asm 59 ln -s $(srctree)/include/asm-ppc asm
60 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o 60 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
61 rm -f asm 61 rm -f asm
62 62
63misc.o: misc.S ppc_defs.h 63misc.o: misc.S ppc_defs.h
64 rm -f asm 64 rm -f asm
65 ln -s $(TOPDIR)/include/asm-ppc asm 65 ln -s $(srctree)/include/asm-ppc asm
66 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o 66 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
67 rm -f asm 67 rm -f asm
68 68
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
index a4360b5207db..e8034e363d83 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/um/sys-x86_64/bug.c
@@ -5,7 +5,8 @@
5 5
6#include <linux/uaccess.h> 6#include <linux/uaccess.h>
7 7
8/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because 8/*
9 * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
9 * that's not relevant in skas mode. 10 * that's not relevant in skas mode.
10 */ 11 */
11 12
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index 506b6765bbcb..44e02ba2a265 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -6,15 +6,10 @@
6 6
7#include "sysdep/ptrace.h" 7#include "sysdep/ptrace.h"
8 8
9void arch_init_thread(void)
10{
11}
12
13void arch_check_bugs(void) 9void arch_check_bugs(void)
14{ 10{
15} 11}
16 12
17int arch_handle_signal(int sig, struct uml_pt_regs *regs) 13void arch_examine_signal(int sig, struct uml_pt_regs *regs)
18{ 14{
19 return 0;
20} 15}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b7631b0e9ddc..f3458d7d1c5a 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,13 +5,12 @@
5 * Licensed under the GPL 5 * Licensed under the GPL
6 */ 6 */
7 7
8#define __FRAME_OFFSETS 8#include <linux/mm.h>
9#include <asm/ptrace.h>
10#include <linux/sched.h> 9#include <linux/sched.h>
11#include <linux/errno.h> 10#include <linux/errno.h>
12#include <linux/mm.h> 11#define __FRAME_OFFSETS
12#include <asm/ptrace.h>
13#include <asm/uaccess.h> 13#include <asm/uaccess.h>
14#include <asm/elf.h>
15 14
16/* 15/*
17 * determines which flags the user has access to. 16 * determines which flags the user has access to.
@@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
24 unsigned long tmp; 23 unsigned long tmp;
25 24
26#ifdef TIF_IA32 25#ifdef TIF_IA32
27 /* Some code in the 64bit emulation may not be 64bit clean. 26 /*
28 Don't take any chances. */ 27 * Some code in the 64bit emulation may not be 64bit clean.
28 * Don't take any chances.
29 */
29 if (test_tsk_thread_flag(child, TIF_IA32)) 30 if (test_tsk_thread_flag(child, TIF_IA32))
30 value &= 0xffffffff; 31 value &= 0xffffffff;
31#endif 32#endif
32 switch (regno){ 33 switch (regno) {
33 case FS: 34 case FS:
34 case GS: 35 case GS:
35 case DS: 36 case DS:
@@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data)
66 if (addr < MAX_REG_OFFSET) 67 if (addr < MAX_REG_OFFSET)
67 return putreg(child, addr, data); 68 return putreg(child, addr, data);
68 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 69 else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
69 (addr <= offsetof(struct user, u_debugreg[7]))){ 70 (addr <= offsetof(struct user, u_debugreg[7]))) {
70 addr -= offsetof(struct user, u_debugreg[0]); 71 addr -= offsetof(struct user, u_debugreg[0]);
71 addr = addr >> 2; 72 addr = addr >> 2;
72 if ((addr == 4) || (addr == 5)) 73 if ((addr == 4) || (addr == 5))
@@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data)
108 return -EIO; 109 return -EIO;
109 110
110 tmp = 0; /* Default return condition */ 111 tmp = 0; /* Default return condition */
111 if (addr < MAX_REG_OFFSET){ 112 if (addr < MAX_REG_OFFSET)
112 tmp = getreg(child, addr); 113 tmp = getreg(child, addr);
113 }
114 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 114 else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
115 (addr <= offsetof(struct user, u_debugreg[7]))){ 115 (addr <= offsetof(struct user, u_debugreg[7]))) {
116 addr -= offsetof(struct user, u_debugreg[0]); 116 addr -= offsetof(struct user, u_debugreg[0]);
117 addr = addr >> 2; 117 addr = addr >> 2;
118 tmp = child->thread.arch.debugregs[addr]; 118 tmp = child->thread.arch.debugregs[addr];
@@ -127,8 +127,9 @@ int is_syscall(unsigned long addr)
127 int n; 127 int n;
128 128
129 n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); 129 n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
130 if (n){ 130 if (n) {
131 /* access_process_vm() grants access to vsyscall and stub, 131 /*
132 * access_process_vm() grants access to vsyscall and stub,
132 * while copy_from_user doesn't. Maybe access_process_vm is 133 * while copy_from_user doesn't. Maybe access_process_vm is
133 * slow, but that doesn't matter, since it will be called only 134 * slow, but that doesn't matter, since it will be called only
134 * in case of singlestepping, if copy_from_user failed. 135 * 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)
155 return err; 156 return err;
156 157
157 n = copy_to_user(buf, fpregs, sizeof(fpregs)); 158 n = copy_to_user(buf, fpregs, sizeof(fpregs));
158 if(n > 0) 159 if (n > 0)
159 return -EFAULT; 160 return -EFAULT;
160 161
161 return n; 162 return n;
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index b5f9c33e311e..c57a496d3f5b 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -4,55 +4,19 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include <stddef.h>
8#include <errno.h> 7#include <errno.h>
9#include "ptrace_user.h" 8#include "ptrace_user.h"
10#include "user.h"
11#include "kern_constants.h"
12 9
13int ptrace_getregs(long pid, unsigned long *regs_out) 10int ptrace_getregs(long pid, unsigned long *regs_out)
14{ 11{
15 if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) 12 if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
16 return(-errno); 13 return -errno;
17 return(0);
18}
19
20int ptrace_setregs(long pid, unsigned long *regs)
21{
22 if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
23 return(-errno);
24 return(0); 14 return(0);
25} 15}
26 16
27int ptrace_setfpregs(long pid, unsigned long *regs) 17int ptrace_setregs(long pid, unsigned long *regs_out)
28{ 18{
29 if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) 19 if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
30 return -errno; 20 return -errno;
31 return 0; 21 return(0);
32}
33
34void ptrace_pokeuser(unsigned long addr, unsigned long data)
35{
36 panic("ptrace_pokeuser");
37}
38
39#define DS 184
40#define ES 192
41#define __USER_DS 0x2b
42
43void arch_enter_kernel(void *task, int pid)
44{
45}
46
47void arch_leave_kernel(void *task, int pid)
48{
49#ifdef UM_USER_CS
50 if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
51 printk("POKEUSR CS failed");
52#endif
53
54 if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
55 printk("POKEUSR DS failed");
56 if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
57 printk("POKEUSR ES failed");
58} 22}
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 14070181407b..1a899a7ed7a6 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,
81 if (err) 81 if (err)
82 return 1; 82 return 1;
83 83
84 err = restore_fp_registers(userspace_pid[current_thread->cpu], 84 err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
85 (unsigned long *) &fp); 85 (unsigned long *) &fp);
86 if (err < 0) { 86 if (err < 0) {
87 printk(KERN_ERR "copy_sc_from_user - " 87 printk(KERN_ERR "copy_sc_from_user - "
@@ -143,7 +143,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
143 if (err) 143 if (err)
144 return 1; 144 return 1;
145 145
146 err = save_fp_registers(userspace_pid[current_thread->cpu], 146 err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
147 (unsigned long *) &fp); 147 (unsigned long *) &fp);
148 if (err < 0) { 148 if (err < 0) {
149 printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " 149 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 4afe204a6af7..568768763155 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -8,18 +8,18 @@ syscall_stub:
8 /* We don't have 64-bit constants, so this constructs the address 8 /* We don't have 64-bit constants, so this constructs the address
9 * we need. 9 * we need.
10 */ 10 */
11 movq $(ASM_STUB_DATA >> 32), %rbx 11 movq $(STUB_DATA >> 32), %rbx
12 salq $32, %rbx 12 salq $32, %rbx
13 movq $(ASM_STUB_DATA & 0xffffffff), %rcx 13 movq $(STUB_DATA & 0xffffffff), %rcx
14 or %rcx, %rbx 14 or %rcx, %rbx
15 movq %rax, (%rbx) 15 movq %rax, (%rbx)
16 int3 16 int3
17 17
18 .globl batch_syscall_stub 18 .globl batch_syscall_stub
19batch_syscall_stub: 19batch_syscall_stub:
20 mov $(ASM_STUB_DATA >> 32), %rbx 20 mov $(STUB_DATA >> 32), %rbx
21 sal $32, %rbx 21 sal $32, %rbx
22 mov $(ASM_STUB_DATA & 0xffffffff), %rax 22 mov $(STUB_DATA & 0xffffffff), %rax
23 or %rax, %rbx 23 or %rax, %rbx
24 /* load pointer to first operation */ 24 /* load pointer to first operation */
25 mov %rbx, %rsp 25 mov %rbx, %rsp
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 3afb590f0072..ced051afc705 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -1,51 +1,22 @@
1/* 1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stddef.h>
7#include <signal.h> 6#include <signal.h>
8#include <asm/unistd.h>
9#include "as-layout.h" 7#include "as-layout.h"
10#include "uml-config.h"
11#include "sysdep/sigcontext.h"
12#include "sysdep/faultinfo.h"
13#include "sysdep/stub.h" 8#include "sysdep/stub.h"
14 9#include "sysdep/faultinfo.h"
15/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition 10#include "sysdep/sigcontext.h"
16 * in the libc headers anywhere.
17 */
18struct rt_sigframe
19{
20 char *pretcode;
21 struct ucontext uc;
22 struct siginfo info;
23};
24
25/* Copied here from <linux/kernel.h> - we're userspace. */
26#define container_of(ptr, type, member) ({ \
27 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
28 (type *)( (char *)__mptr - offsetof(type,member) );})
29 11
30void __attribute__ ((__section__ (".__syscall_stub"))) 12void __attribute__ ((__section__ (".__syscall_stub")))
31stub_segv_handler(int sig) 13stub_segv_handler(int sig)
32{ 14{
33 struct ucontext *uc; 15 struct ucontext *uc;
34 int pid;
35 16
36 __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); 17 __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
37 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), 18 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
38 &uc->uc_mcontext); 19 &uc->uc_mcontext);
39 20 trap_myself();
40 pid = stub_syscall0(__NR_getpid);
41 stub_syscall2(__NR_kill, pid, SIGUSR1);
42
43 /* sys_sigreturn expects that the stack pointer will be 8 bytes into
44 * the signal frame. So, we use the ucontext pointer, which we know
45 * already, to get the signal frame pointer, and add 8 to that.
46 */
47 __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
48 "g" ((unsigned long)
49 container_of(uc, struct rt_sigframe, uc) + 8),
50 "g" (__NR_rt_sigreturn));
51} 21}
22
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index 71b2ae4ad5de..c128eb897008 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -1,5 +1,7 @@
1/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c 1/*
2 * with some changes for UML. */ 2 * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
3 * with some changes for UML.
4 */
3 5
4#include <linux/linkage.h> 6#include <linux/linkage.h>
5#include <linux/sys.h> 7#include <linux/sys.h>
@@ -8,22 +10,26 @@
8 10
9#define __NO_STUBS 11#define __NO_STUBS
10 12
11/* Below you can see, in terms of #define's, the differences between the x86-64 13/*
12 * and the UML syscall table. */ 14 * Below you can see, in terms of #define's, the differences between the x86-64
15 * and the UML syscall table.
16 */
13 17
14/* Not going to be implemented by UML, since we have no hardware. */ 18/* Not going to be implemented by UML, since we have no hardware. */
15#define stub_iopl sys_ni_syscall 19#define stub_iopl sys_ni_syscall
16#define sys_ioperm sys_ni_syscall 20#define sys_ioperm sys_ni_syscall
17 21
18/* The UML TLS problem. Note that x86_64 does not implement this, so the below 22/*
19 * is needed only for the ia32 compatibility. */ 23 * The UML TLS problem. Note that x86_64 does not implement this, so the below
20/*#define sys_set_thread_area sys_ni_syscall 24 * is needed only for the ia32 compatibility.
21#define sys_get_thread_area sys_ni_syscall*/ 25 */
22 26
23/* On UML we call it this way ("old" means it's not mmap2) */ 27/* On UML we call it this way ("old" means it's not mmap2) */
24#define sys_mmap old_mmap 28#define sys_mmap old_mmap
25/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick. 29/*
26 * See arch/x86_64/kernel/sys_x86_64.c */ 30 * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
31 * See arch/x86_64/kernel/sys_x86_64.c
32 */
27#define sys_uname sys_uname64 33#define sys_uname sys_uname64
28 34
29#define stub_clone sys_clone 35#define stub_clone sys_clone
@@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void);
46 52
47extern void sys_ni_syscall(void); 53extern void sys_ni_syscall(void);
48 54
49sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = { 55/*
50 /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */ 56 * We used to have a trick here which made sure that holes in the
51 [0 ... UM_NR_syscall_max] = &sys_ni_syscall, 57 * x86_64 table were filled in with sys_ni_syscall, but a comment in
58 * unistd_64.h says that holes aren't allowed, so the trick was
59 * removed.
60 * The trick looked like this
61 * [0 ... UM_NR_syscall_max] = &sys_ni_syscall
62 * before including unistd_64.h - the later initializations overwrote
63 * the sys_ni_syscall filler.
64 */
65
66sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
52#include <asm-x86/unistd_64.h> 67#include <asm-x86/unistd_64.h>
53}; 68};
69
70int 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 86f6b18410ee..f1199fd34d38 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)
48 switch (code) { 48 switch (code) {
49 case ARCH_SET_FS: 49 case ARCH_SET_FS:
50 case ARCH_SET_GS: 50 case ARCH_SET_GS:
51 restore_registers(pid, &current->thread.regs.regs); 51 ret = restore_registers(pid, &current->thread.regs.regs);
52 if (ret)
53 return ret;
52 break; 54 break;
53 case ARCH_GET_FS: 55 case ARCH_GET_FS:
54 case ARCH_GET_GS: 56 case ARCH_GET_GS:
@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
70 switch (code) { 72 switch (code) {
71 case ARCH_SET_FS: 73 case ARCH_SET_FS:
72 current->thread.arch.fs = (unsigned long) ptr; 74 current->thread.arch.fs = (unsigned long) ptr;
73 save_registers(pid, &current->thread.regs.regs); 75 ret = save_registers(pid, &current->thread.regs.regs);
74 break; 76 break;
75 case ARCH_SET_GS: 77 case ARCH_SET_GS:
76 save_registers(pid, &current->thread.regs.regs); 78 ret = save_registers(pid, &current->thread.regs.regs);
77 break; 79 break;
78 case ARCH_GET_FS: 80 case ARCH_GET_FS:
79 ret = put_user(tmp, addr); 81 ret = put_user(tmp, addr);
@@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
105 return ret; 107 return ret;
106} 108}
107 109
108void arch_switch_to(struct task_struct *from, struct task_struct *to) 110void arch_switch_to(struct task_struct *to)
109{ 111{
110 if ((to->thread.arch.fs == 0) || (to->mm == NULL)) 112 if ((to->thread.arch.fs == 0) || (to->mm == NULL))
111 return; 113 return;
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index 765444031819..f4f82beb3508 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -4,32 +4,33 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/kernel.h" 7#include <linux/kernel.h>
8#include "linux/utsname.h" 8#include <linux/module.h>
9#include "linux/module.h" 9#include <linux/sched.h>
10#include "asm/current.h" 10#include <linux/utsname.h>
11#include "asm/ptrace.h" 11#include <asm/current.h>
12#include <asm/ptrace.h>
12#include "sysrq.h" 13#include "sysrq.h"
13 14
14void __show_regs(struct pt_regs * regs) 15void __show_regs(struct pt_regs *regs)
15{ 16{
16 printk("\n"); 17 printk("\n");
17 print_modules(); 18 print_modules();
18 printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), 19 printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
19 current->comm, print_tainted(), init_utsname()->release); 20 current->comm, print_tainted(), init_utsname()->release);
20 printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff, 21 printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
21 PT_REGS_RIP(regs)); 22 PT_REGS_RIP(regs));
22 printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), 23 printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
23 PT_REGS_EFLAGS(regs)); 24 PT_REGS_EFLAGS(regs));
24 printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", 25 printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
25 PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); 26 PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
26 printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", 27 printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
27 PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); 28 PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
28 printk("RBP: %016lx R08: %016lx R09: %016lx\n", 29 printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
29 PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); 30 PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
30 printk("R10: %016lx R11: %016lx R12: %016lx\n", 31 printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
31 PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); 32 PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
32 printk("R13: %016lx R14: %016lx R15: %016lx\n", 33 printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
33 PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); 34 PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
34} 35}
35 36
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
index 8b8eff1bd977..3dead392a415 100644
--- a/arch/um/sys-x86_64/um_module.c
+++ b/arch/um/sys-x86_64/um_module.c
@@ -1,7 +1,7 @@
1#include <linux/vmalloc.h> 1#include <linux/vmalloc.h>
2#include <linux/moduleloader.h> 2#include <linux/moduleloader.h>
3 3
4/*Copied from i386 arch/i386/kernel/module.c */ 4/* Copied from i386 arch/i386/kernel/module.c */
5void *module_alloc(unsigned long size) 5void *module_alloc(unsigned long size)
6{ 6{
7 if (size == 0) 7 if (size == 0)
@@ -13,7 +13,9 @@ void *module_alloc(unsigned long size)
13void module_free(struct module *mod, void *module_region) 13void module_free(struct module *mod, void *module_region)
14{ 14{
15 vfree(module_region); 15 vfree(module_region);
16 /* FIXME: If module_region == mod->init_region, trim exception 16 /*
17 table entries. */ 17 * FIXME: If module_region == mod->init_region, trim exception
18 * table entries.
19 */
18} 20}
19 21
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 59eef1c7fdaa..434821187cfc 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -465,6 +465,9 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
465 Calgary anyway, pass 'iommu=calgary' on the kernel command line. 465 Calgary anyway, pass 'iommu=calgary' on the kernel command line.
466 If unsure, say Y. 466 If unsure, say Y.
467 467
468config IOMMU_HELPER
469 def_bool (CALGARY_IOMMU || GART_IOMMU)
470
468# need this always selected by IOMMU for the VIA workaround 471# need this always selected by IOMMU for the VIA workaround
469config SWIOTLB 472config SWIOTLB
470 bool 473 bool
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 0db0a6291bbd..8022d3c695c0 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -722,7 +722,9 @@ ia32_sys_call_table:
722 .quad sys_epoll_pwait 722 .quad sys_epoll_pwait
723 .quad compat_sys_utimensat /* 320 */ 723 .quad compat_sys_utimensat /* 320 */
724 .quad compat_sys_signalfd 724 .quad compat_sys_signalfd
725 .quad compat_sys_timerfd 725 .quad sys_timerfd_create
726 .quad sys_eventfd 726 .quad sys_eventfd
727 .quad sys32_fallocate 727 .quad sys32_fallocate
728 .quad compat_sys_timerfd_settime /* 325 */
729 .quad compat_sys_timerfd_gettime
728ia32_syscall_end: 730ia32_syscall_end:
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 1fe7f043ebde..1b5464c2434f 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,6 +35,7 @@
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/scatterlist.h> 37#include <linux/scatterlist.h>
38#include <linux/iommu-helper.h>
38#include <asm/gart.h> 39#include <asm/gart.h>
39#include <asm/calgary.h> 40#include <asm/calgary.h>
40#include <asm/tce.h> 41#include <asm/tce.h>
@@ -260,22 +261,28 @@ static void iommu_range_reserve(struct iommu_table *tbl,
260 spin_unlock_irqrestore(&tbl->it_lock, flags); 261 spin_unlock_irqrestore(&tbl->it_lock, flags);
261} 262}
262 263
263static unsigned long iommu_range_alloc(struct iommu_table *tbl, 264static unsigned long iommu_range_alloc(struct device *dev,
264 unsigned int npages) 265 struct iommu_table *tbl,
266 unsigned int npages)
265{ 267{
266 unsigned long flags; 268 unsigned long flags;
267 unsigned long offset; 269 unsigned long offset;
270 unsigned long boundary_size;
271
272 boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
273 PAGE_SIZE) >> PAGE_SHIFT;
268 274
269 BUG_ON(npages == 0); 275 BUG_ON(npages == 0);
270 276
271 spin_lock_irqsave(&tbl->it_lock, flags); 277 spin_lock_irqsave(&tbl->it_lock, flags);
272 278
273 offset = find_next_zero_string(tbl->it_map, tbl->it_hint, 279 offset = iommu_area_alloc(tbl->it_map, tbl->it_size, tbl->it_hint,
274 tbl->it_size, npages); 280 npages, 0, boundary_size, 0);
275 if (offset == ~0UL) { 281 if (offset == ~0UL) {
276 tbl->chip_ops->tce_cache_blast(tbl); 282 tbl->chip_ops->tce_cache_blast(tbl);
277 offset = find_next_zero_string(tbl->it_map, 0, 283
278 tbl->it_size, npages); 284 offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
285 npages, 0, boundary_size, 0);
279 if (offset == ~0UL) { 286 if (offset == ~0UL) {
280 printk(KERN_WARNING "Calgary: IOMMU full.\n"); 287 printk(KERN_WARNING "Calgary: IOMMU full.\n");
281 spin_unlock_irqrestore(&tbl->it_lock, flags); 288 spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -286,7 +293,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
286 } 293 }
287 } 294 }
288 295
289 set_bit_string(tbl->it_map, offset, npages);
290 tbl->it_hint = offset + npages; 296 tbl->it_hint = offset + npages;
291 BUG_ON(tbl->it_hint > tbl->it_size); 297 BUG_ON(tbl->it_hint > tbl->it_size);
292 298
@@ -295,13 +301,13 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
295 return offset; 301 return offset;
296} 302}
297 303
298static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr, 304static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
299 unsigned int npages, int direction) 305 void *vaddr, unsigned int npages, int direction)
300{ 306{
301 unsigned long entry; 307 unsigned long entry;
302 dma_addr_t ret = bad_dma_address; 308 dma_addr_t ret = bad_dma_address;
303 309
304 entry = iommu_range_alloc(tbl, npages); 310 entry = iommu_range_alloc(dev, tbl, npages);
305 311
306 if (unlikely(entry == bad_dma_address)) 312 if (unlikely(entry == bad_dma_address))
307 goto error; 313 goto error;
@@ -354,7 +360,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
354 badbit, tbl, dma_addr, entry, npages); 360 badbit, tbl, dma_addr, entry, npages);
355 } 361 }
356 362
357 __clear_bit_string(tbl->it_map, entry, npages); 363 iommu_area_free(tbl->it_map, entry, npages);
358 364
359 spin_unlock_irqrestore(&tbl->it_lock, flags); 365 spin_unlock_irqrestore(&tbl->it_lock, flags);
360} 366}
@@ -438,7 +444,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
438 vaddr = (unsigned long) sg_virt(s); 444 vaddr = (unsigned long) sg_virt(s);
439 npages = num_dma_pages(vaddr, s->length); 445 npages = num_dma_pages(vaddr, s->length);
440 446
441 entry = iommu_range_alloc(tbl, npages); 447 entry = iommu_range_alloc(dev, tbl, npages);
442 if (entry == bad_dma_address) { 448 if (entry == bad_dma_address) {
443 /* makes sure unmap knows to stop */ 449 /* makes sure unmap knows to stop */
444 s->dma_length = 0; 450 s->dma_length = 0;
@@ -476,7 +482,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
476 npages = num_dma_pages(uaddr, size); 482 npages = num_dma_pages(uaddr, size);
477 483
478 if (translation_enabled(tbl)) 484 if (translation_enabled(tbl))
479 dma_handle = iommu_alloc(tbl, vaddr, npages, direction); 485 dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
480 else 486 else
481 dma_handle = virt_to_bus(vaddr); 487 dma_handle = virt_to_bus(vaddr);
482 488
@@ -516,7 +522,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
516 522
517 if (translation_enabled(tbl)) { 523 if (translation_enabled(tbl)) {
518 /* set up tces to cover the allocated range */ 524 /* set up tces to cover the allocated range */
519 mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL); 525 mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
520 if (mapping == bad_dma_address) 526 if (mapping == bad_dma_address)
521 goto free; 527 goto free;
522 528
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 845cbecd68e9..65f6acb025c8 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/kdebug.h> 26#include <linux/kdebug.h>
27#include <linux/scatterlist.h> 27#include <linux/scatterlist.h>
28#include <linux/iommu-helper.h>
28#include <asm/atomic.h> 29#include <asm/atomic.h>
29#include <asm/io.h> 30#include <asm/io.h>
30#include <asm/mtrr.h> 31#include <asm/mtrr.h>
@@ -82,17 +83,24 @@ AGPEXTERN __u32 *agp_gatt_table;
82static unsigned long next_bit; /* protected by iommu_bitmap_lock */ 83static unsigned long next_bit; /* protected by iommu_bitmap_lock */
83static int need_flush; /* global flush state. set for each gart wrap */ 84static int need_flush; /* global flush state. set for each gart wrap */
84 85
85static unsigned long alloc_iommu(int size) 86static unsigned long alloc_iommu(struct device *dev, int size)
86{ 87{
87 unsigned long offset, flags; 88 unsigned long offset, flags;
89 unsigned long boundary_size;
90 unsigned long base_index;
91
92 base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
93 PAGE_SIZE) >> PAGE_SHIFT;
94 boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
95 PAGE_SIZE) >> PAGE_SHIFT;
88 96
89 spin_lock_irqsave(&iommu_bitmap_lock, flags); 97 spin_lock_irqsave(&iommu_bitmap_lock, flags);
90 offset = find_next_zero_string(iommu_gart_bitmap, next_bit, 98 offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
91 iommu_pages, size); 99 size, base_index, boundary_size, 0);
92 if (offset == -1) { 100 if (offset == -1) {
93 need_flush = 1; 101 need_flush = 1;
94 offset = find_next_zero_string(iommu_gart_bitmap, 0, 102 offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
95 iommu_pages, size); 103 size, base_index, boundary_size, 0);
96 } 104 }
97 if (offset != -1) { 105 if (offset != -1) {
98 set_bit_string(iommu_gart_bitmap, offset, size); 106 set_bit_string(iommu_gart_bitmap, offset, size);
@@ -114,7 +122,7 @@ static void free_iommu(unsigned long offset, int size)
114 unsigned long flags; 122 unsigned long flags;
115 123
116 spin_lock_irqsave(&iommu_bitmap_lock, flags); 124 spin_lock_irqsave(&iommu_bitmap_lock, flags);
117 __clear_bit_string(iommu_gart_bitmap, offset, size); 125 iommu_area_free(iommu_gart_bitmap, offset, size);
118 spin_unlock_irqrestore(&iommu_bitmap_lock, flags); 126 spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
119} 127}
120 128
@@ -235,7 +243,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
235 size_t size, int dir) 243 size_t size, int dir)
236{ 244{
237 unsigned long npages = to_pages(phys_mem, size); 245 unsigned long npages = to_pages(phys_mem, size);
238 unsigned long iommu_page = alloc_iommu(npages); 246 unsigned long iommu_page = alloc_iommu(dev, npages);
239 int i; 247 int i;
240 248
241 if (iommu_page == -1) { 249 if (iommu_page == -1) {
@@ -355,10 +363,11 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
355} 363}
356 364
357/* Map multiple scatterlist entries continuous into the first. */ 365/* Map multiple scatterlist entries continuous into the first. */
358static int __dma_map_cont(struct scatterlist *start, int nelems, 366static int __dma_map_cont(struct device *dev, struct scatterlist *start,
359 struct scatterlist *sout, unsigned long pages) 367 int nelems, struct scatterlist *sout,
368 unsigned long pages)
360{ 369{
361 unsigned long iommu_start = alloc_iommu(pages); 370 unsigned long iommu_start = alloc_iommu(dev, pages);
362 unsigned long iommu_page = iommu_start; 371 unsigned long iommu_page = iommu_start;
363 struct scatterlist *s; 372 struct scatterlist *s;
364 int i; 373 int i;
@@ -394,8 +403,8 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
394} 403}
395 404
396static inline int 405static inline int
397dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout, 406dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
398 unsigned long pages, int need) 407 struct scatterlist *sout, unsigned long pages, int need)
399{ 408{
400 if (!need) { 409 if (!need) {
401 BUG_ON(nelems != 1); 410 BUG_ON(nelems != 1);
@@ -403,7 +412,7 @@ dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
403 sout->dma_length = start->length; 412 sout->dma_length = start->length;
404 return 0; 413 return 0;
405 } 414 }
406 return __dma_map_cont(start, nelems, sout, pages); 415 return __dma_map_cont(dev, start, nelems, sout, pages);
407} 416}
408 417
409/* 418/*
@@ -416,6 +425,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
416 struct scatterlist *s, *ps, *start_sg, *sgmap; 425 struct scatterlist *s, *ps, *start_sg, *sgmap;
417 int need = 0, nextneed, i, out, start; 426 int need = 0, nextneed, i, out, start;
418 unsigned long pages = 0; 427 unsigned long pages = 0;
428 unsigned int seg_size;
429 unsigned int max_seg_size;
419 430
420 if (nents == 0) 431 if (nents == 0)
421 return 0; 432 return 0;
@@ -426,6 +437,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
426 out = 0; 437 out = 0;
427 start = 0; 438 start = 0;
428 start_sg = sgmap = sg; 439 start_sg = sgmap = sg;
440 seg_size = 0;
441 max_seg_size = dma_get_max_seg_size(dev);
429 ps = NULL; /* shut up gcc */ 442 ps = NULL; /* shut up gcc */
430 for_each_sg(sg, s, nents, i) { 443 for_each_sg(sg, s, nents, i) {
431 dma_addr_t addr = sg_phys(s); 444 dma_addr_t addr = sg_phys(s);
@@ -443,11 +456,13 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
443 * offset. 456 * offset.
444 */ 457 */
445 if (!iommu_merge || !nextneed || !need || s->offset || 458 if (!iommu_merge || !nextneed || !need || s->offset ||
459 (s->length + seg_size > max_seg_size) ||
446 (ps->offset + ps->length) % PAGE_SIZE) { 460 (ps->offset + ps->length) % PAGE_SIZE) {
447 if (dma_map_cont(start_sg, i - start, sgmap, 461 if (dma_map_cont(dev, start_sg, i - start,
448 pages, need) < 0) 462 sgmap, pages, need) < 0)
449 goto error; 463 goto error;
450 out++; 464 out++;
465 seg_size = 0;
451 sgmap = sg_next(sgmap); 466 sgmap = sg_next(sgmap);
452 pages = 0; 467 pages = 0;
453 start = i; 468 start = i;
@@ -455,11 +470,12 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
455 } 470 }
456 } 471 }
457 472
473 seg_size += s->length;
458 need = nextneed; 474 need = nextneed;
459 pages += to_pages(s->offset, s->length); 475 pages += to_pages(s->offset, s->length);
460 ps = s; 476 ps = s;
461 } 477 }
462 if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0) 478 if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
463 goto error; 479 goto error;
464 out++; 480 out++;
465 flush_gart(); 481 flush_gart();
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 8344c70adf61..adff5562f5fd 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)
321 .long sys_epoll_pwait 321 .long sys_epoll_pwait
322 .long sys_utimensat /* 320 */ 322 .long sys_utimensat /* 320 */
323 .long sys_signalfd 323 .long sys_signalfd
324 .long sys_timerfd 324 .long sys_timerfd_create
325 .long sys_eventfd 325 .long sys_eventfd
326 .long sys_fallocate 326 .long sys_fallocate
327 .long sys_timerfd_settime /* 325 */
328 .long sys_timerfd_gettime
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8f94a0b89dff..cf5308148689 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,
1739 if (bytes == 8) { 1739 if (bytes == 8) {
1740 gpa_t gpa; 1740 gpa_t gpa;
1741 struct page *page; 1741 struct page *page;
1742 char *addr; 1742 char *kaddr;
1743 u64 val; 1743 u64 val;
1744 1744
1745 down_read(&current->mm->mmap_sem); 1745 down_read(&current->mm->mmap_sem);
@@ -1754,9 +1754,9 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
1754 1754
1755 val = *(u64 *)new; 1755 val = *(u64 *)new;
1756 page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT); 1756 page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
1757 addr = kmap_atomic(page, KM_USER0); 1757 kaddr = kmap_atomic(page, KM_USER0);
1758 set_64bit((u64 *)(addr + offset_in_page(gpa)), val); 1758 set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
1759 kunmap_atomic(addr, KM_USER0); 1759 kunmap_atomic(kaddr, KM_USER0);
1760 kvm_release_page_dirty(page); 1760 kvm_release_page_dirty(page);
1761 emul_write: 1761 emul_write:
1762 up_read(&current->mm->mmap_sem); 1762 up_read(&current->mm->mmap_sem);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 4876182daf8a..25df1c1989fe 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -21,7 +21,7 @@ else
21 21
22 lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o 22 lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
23 lib-y += thunk_64.o clear_page_64.o copy_page_64.o 23 lib-y += thunk_64.o clear_page_64.o copy_page_64.o
24 lib-y += bitstr_64.o bitops_64.o 24 lib-y += bitops_64.o
25 lib-y += memmove_64.o memset_64.o 25 lib-y += memmove_64.o memset_64.o
26 lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o 26 lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
27endif 27endif
diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
deleted file mode 100644
index 7445caf1b5de..000000000000
--- a/arch/x86/lib/bitstr_64.c
+++ /dev/null
@@ -1,28 +0,0 @@
1#include <linux/module.h>
2#include <linux/bitops.h>
3
4/* Find string of zero bits in a bitmap */
5unsigned long
6find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
7{
8 unsigned long n, end, i;
9
10 again:
11 n = find_next_zero_bit(bitmap, nbits, start);
12 if (n == -1)
13 return -1;
14
15 /* could test bitsliced, but it's hardly worth it */
16 end = n+len;
17 if (end > nbits)
18 return -1;
19 for (i = n+1; i < end; i++) {
20 if (test_bit(i, bitmap)) {
21 start = i+1;
22 goto again;
23 }
24 }
25 return n;
26}
27
28EXPORT_SYMBOL(find_next_zero_string);
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index c7db504be1ea..6c1914622a88 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)
272 * preallocate which never got a corresponding vma will need to be 272 * preallocate which never got a corresponding vma will need to be
273 * freed manually. 273 * freed manually.
274 */ 274 */
275static void pgd_mop_up_pmds(pgd_t *pgdp) 275static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
276{ 276{
277 int i; 277 int i;
278 278
@@ -285,7 +285,7 @@ static void pgd_mop_up_pmds(pgd_t *pgdp)
285 pgdp[i] = native_make_pgd(0); 285 pgdp[i] = native_make_pgd(0);
286 286
287 paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT); 287 paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
288 pmd_free(pmd); 288 pmd_free(mm, pmd);
289 } 289 }
290 } 290 }
291} 291}
@@ -313,7 +313,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
313 pmd_t *pmd = pmd_alloc_one(mm, addr); 313 pmd_t *pmd = pmd_alloc_one(mm, addr);
314 314
315 if (!pmd) { 315 if (!pmd) {
316 pgd_mop_up_pmds(pgd); 316 pgd_mop_up_pmds(mm, pgd);
317 return 0; 317 return 0;
318 } 318 }
319 319
@@ -333,7 +333,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
333 return 1; 333 return 1;
334} 334}
335 335
336static void pgd_mop_up_pmds(pgd_t *pgd) 336static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
337{ 337{
338} 338}
339#endif /* CONFIG_X86_PAE */ 339#endif /* CONFIG_X86_PAE */
@@ -352,9 +352,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
352 return pgd; 352 return pgd;
353} 353}
354 354
355void pgd_free(pgd_t *pgd) 355void pgd_free(struct mm_struct *mm, pgd_t *pgd)
356{ 356{
357 pgd_mop_up_pmds(pgd); 357 pgd_mop_up_pmds(mm, pgd);
358 quicklist_free(0, pgd_dtor, pgd); 358 quicklist_free(0, pgd_dtor, pgd);
359} 359}
360 360
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42ba0e2da1a0..103b9dff1213 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,
72 } 72 }
73 } 73 }
74} 74}
75 75EXPORT_SYMBOL(pcibios_align_resource);
76 76
77/* 77/*
78 * Handle resources of PCI devices. If the world were perfect, we could 78 * Handle resources of PCI devices. If the world were perfect, we could