aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/amd.c9
-rw-r--r--arch/i386/kernel/cpu/common.c5
-rw-r--r--arch/i386/kernel/smpboot.c1
-rw-r--r--arch/i386/mm/ioremap.c10
-rw-r--r--arch/ppc/kernel/head_44x.S15
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/ppc/lib/string.S7
-rw-r--r--arch/ppc/mm/init.c1
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c1
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c1
-rw-r--r--arch/ppc/syslib/open_pic.c2
-rw-r--r--arch/ppc64/kernel/prom_init.c44
-rw-r--r--arch/sparc64/kernel/pci_iommu.c167
-rw-r--r--arch/sparc64/kernel/sbus.c31
-rw-r--r--arch/um/Kconfig_x86_644
-rw-r--r--arch/um/drivers/chan_kern.c22
-rw-r--r--arch/um/drivers/mcast_kern.c4
-rw-r--r--arch/um/drivers/mcast_user.c47
-rw-r--r--arch/um/drivers/ubd_kern.c296
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h2
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h26
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h62
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/checksum.c0
-rw-r--r--arch/um/kernel/initrd.c78
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/mem.c40
-rw-r--r--arch/um/kernel/ptrace.c6
-rw-r--r--arch/um/kernel/trap_kern.c36
-rw-r--r--arch/um/kernel/tt/ksyms.c1
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/sys-i386/Makefile4
-rw-r--r--arch/um/sys-i386/delay.c16
-rw-r--r--arch/um/sys-x86_64/Makefile6
-rw-r--r--arch/um/sys-x86_64/delay.c33
-rw-r--r--arch/um/sys-x86_64/ksyms.c3
-rw-r--r--arch/um/sys-x86_64/ptrace.c9
-rw-r--r--arch/um/sys-x86_64/syscalls.c1
-rw-r--r--arch/um/sys-x86_64/user-offsets.c8
-rw-r--r--arch/x86_64/kernel/io_apic.c11
-rw-r--r--arch/x86_64/kernel/ptrace.c4
-rw-r--r--arch/x86_64/kernel/setup.c25
-rw-r--r--arch/x86_64/kernel/signal.c4
-rw-r--r--arch/x86_64/kernel/smpboot.c1
-rw-r--r--arch/x86_64/mm/ioremap.c29
45 files changed, 443 insertions, 636 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index fa34a06..73aeaf5 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -195,7 +195,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
c->x86_num_cores = 1;
}
-#ifdef CONFIG_X86_SMP
+#ifdef CONFIG_X86_HT
/*
* On a AMD dual core setup the lower bits of the APIC id
* distingush the cores. Assumes number of cores is a power
@@ -203,8 +203,11 @@ static void __init init_amd(struct cpuinfo_x86 *c)
*/
if (c->x86_num_cores > 1) {
int cpu = smp_processor_id();
- /* Fix up the APIC ID following AMD specifications. */
- cpu_core_id[cpu] >>= hweight32(c->x86_num_cores - 1);
+ unsigned bits = 0;
+ while ((1 << bits) < c->x86_num_cores)
+ bits++;
+ cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
+ phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 11e6e6f..d199e52 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -244,11 +244,8 @@ static void __init early_cpu_detect(void)
early_intel_workaround(c);
-#ifdef CONFIG_SMP
#ifdef CONFIG_X86_HT
- phys_proc_id[smp_processor_id()] =
-#endif
- cpu_core_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+ phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
#endif
}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index cbea7ac..35bfe13 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -888,6 +888,7 @@ void *xquad_portio;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
static void __init smp_boot_cpus(unsigned int max_cpus)
{
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index db06f73..ab54279 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -238,19 +238,21 @@ void iounmap(volatile void __iomem *addr)
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+ write_lock(&vmlist_lock);
+ p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- return;
+ printk("iounmap: bad address %p\n", addr);
+ goto out_unlock;
}
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
- /* p->size includes the guard page, but cpa doesn't like that */
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
}
+out_unlock:
+ write_unlock(&vmlist_lock);
kfree(p);
}
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 9b6a8e5..6c7ae60 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -330,8 +330,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -464,8 +465,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -533,8 +535,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 309797d..5c20266 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -499,7 +499,7 @@ static int __init set_preferred_console(void)
{
struct device_node *prom_stdout;
char *name;
- int offset;
+ int offset = 0;
if (of_stdout_device == NULL)
return -ENODEV;
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 8d08a2e..36c9b97 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -446,6 +446,7 @@ _GLOBAL(__copy_tofrom_user)
#ifdef CONFIG_8xx
/* Don't use prefetch on 8xx */
mtctr r0
+ li r0,0
53: COPY_16_BYTES_WITHEX(0)
bdnz 53b
@@ -564,7 +565,9 @@ _GLOBAL(__copy_tofrom_user)
/* or write fault in cacheline loop */
105: li r9,1
92: li r3,LG_CACHELINE_BYTES
- b 99f
+ mfctr r8
+ add r0,r0,r8
+ b 106f
/* read fault in final word loop */
108: li r9,0
b 93f
@@ -585,7 +588,7 @@ _GLOBAL(__copy_tofrom_user)
* r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
*/
99: mfctr r0
- slw r3,r0,r3
+106: slw r3,r0,r3
add. r3,r3,r5
beq 120f /* shouldn't happen */
cmpwi 0,r9,0
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index be02a7f..363c157 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -179,6 +179,7 @@ void free_initmem(void)
if (!have_of)
FREESEC(openfirmware);
printk("\n");
+ ppc_md.progress = NULL;
#undef FREESEC
}
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 5c1a919e..75c8e98 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
+ { },
};
struct platform_device ppc_sys_platform_devices[] = {
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index a231795..1e658ef 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
},
+ { },
};
struct platform_device ppc_sys_platform_devices[] = {
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 7619e16..9d4ed68 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -557,12 +557,10 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
*/
void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
{
- cpumask_t phys;
DECL_THIS_CPU;
CHECK_THIS_CPU;
check_arg_ipi(ipi);
- phys = physmask(cpumask);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
cpus_addr(physmask(cpumask))[0]);
}
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 35ec42d..6f79b7b 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1750,7 +1750,44 @@ static void __init flatten_device_tree(void)
prom_printf("Device tree struct 0x%x -> 0x%x\n",
RELOC(dt_struct_start), RELOC(dt_struct_end));
- }
+}
+
+
+static void __init fixup_device_tree(void)
+{
+ unsigned long offset = reloc_offset();
+ phandle u3, i2c, mpic;
+ u32 u3_rev;
+ u32 interrupts[2];
+ u32 parent;
+
+ /* Some G5s have a missing interrupt definition, fix it up here */
+ u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
+ if ((long)u3 <= 0)
+ return;
+ i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
+ if ((long)i2c <= 0)
+ return;
+ mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
+ if ((long)mpic <= 0)
+ return;
+
+ /* check if proper rev of u3 */
+ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+ return;
+ if (u3_rev != 0x35)
+ return;
+ /* does it need fixup ? */
+ if (prom_getproplen(i2c, "interrupts") > 0)
+ return;
+ /* interrupt on this revision of u3 is number 0 and level */
+ interrupts[0] = 0;
+ interrupts[1] = 1;
+ prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+ parent = (u32)mpic;
+ prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
static void __init prom_find_boot_cpu(void)
{
@@ -1920,6 +1957,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
}
/*
+ * Fixup any known bugs in the device-tree
+ */
+ fixup_device_tree();
+
+ /*
* Now finally create the flattened device-tree
*/
prom_printf("copying OF device tree ...\n");
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 2929834..33ca56c 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/delay.h>
#include <asm/pbm.h>
@@ -379,6 +380,56 @@ bad:
return PCI_DMA_ERROR_CODE;
}
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages)
+{
+ int limit;
+
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (strbuf->strbuf_ctxflush &&
+ iommu->iommu_ctxflush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+
+ limit = 100000;
+ pci_iommu_write(flushreg, ctx);
+ for(;;) {
+ if (((long)pci_iommu_read(matchreg)) >= 0L)
+ break;
+ limit--;
+ if (!limit)
+ break;
+ udelay(1);
+ }
+ if (!limit)
+ printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
+ "timeout vaddr[%08x] ctx[%lx]\n",
+ vaddr, ctx);
+ } else {
+ unsigned long i;
+
+ for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+
+ limit = 100000;
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
+ limit--;
+ if (!limit)
+ break;
+ udelay(1);
+ membar("#LoadLoad");
+ }
+ if (!limit)
+ printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
+ "vaddr[%08x] ctx[%lx] npages[%ld]\n",
+ vaddr, ctx, npages);
+}
+
/* Unmap a single streaming mode DMA translation. */
void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
@@ -386,7 +437,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
- unsigned long flags, npages, i, ctx;
+ unsigned long flags, npages, ctx;
if (direction == PCI_DMA_NONE)
BUG();
@@ -414,29 +465,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled) {
- u32 vaddr = bus_addr;
-
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (strbuf->strbuf_ctxflush &&
- iommu->iommu_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, vaddr);
- }
-
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
- }
+ if (strbuf->strbuf_enabled)
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -647,29 +677,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled) {
- u32 vaddr = (u32) bus_addr;
-
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (strbuf->strbuf_ctxflush &&
- iommu->iommu_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, vaddr);
- }
-
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
- }
+ if (strbuf->strbuf_enabled)
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -715,28 +724,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
}
/* Step 2: Kick data out of streaming buffers. */
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (iommu->iommu_ctxflush &&
- strbuf->strbuf_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- unsigned long i;
-
- for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
- }
-
- /* Step 3: Perform flush synchronization sequence. */
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -749,7 +737,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
- unsigned long flags, ctx;
+ unsigned long flags, ctx, npages, i;
+ u32 bus_addr;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
@@ -772,36 +761,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
}
/* Step 2: Kick data out of streaming buffers. */
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (iommu->iommu_ctxflush &&
- strbuf->strbuf_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while (((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- unsigned long i, npages;
- u32 bus_addr;
-
- bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
-
- for(i = 1; i < nelems; i++)
- if (!sglist[i].dma_length)
- break;
- i--;
- npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
- for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
- }
-
- /* Step 3: Perform flush synchronization sequence. */
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
+ bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
+ for(i = 1; i < nelems; i++)
+ if (!sglist[i].dma_length)
+ break;
+ i--;
+ npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
+ - bus_addr) >> IO_PAGE_SHIFT;
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 14d9c3a..76ea645 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -117,19 +117,34 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
#define STRBUF_TAG_VALID 0x02UL
-static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
{
+ unsigned long n;
+ int limit;
+
iommu->strbuf_flushflag = 0UL;
- while (npages--)
- upa_writeq(base + (npages << IO_PAGE_SHIFT),
+ n = npages;
+ while (n--)
+ upa_writeq(base + (n << IO_PAGE_SHIFT),
iommu->strbuf_regs + STRBUF_PFLUSH);
/* Whoopee cushion! */
upa_writeq(__pa(&iommu->strbuf_flushflag),
iommu->strbuf_regs + STRBUF_FSYNC);
upa_readq(iommu->sbus_control_reg);
- while (iommu->strbuf_flushflag == 0UL)
+
+ limit = 100000;
+ while (iommu->strbuf_flushflag == 0UL) {
+ limit--;
+ if (!limit)
+ break;
+ udelay(1);
membar("#LoadLoad");
+ }
+ if (!limit)
+ printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
+ "vaddr[%08x] npages[%ld]\n",
+ base, npages);
}
static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -406,7 +421,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
spin_lock_irqsave(&iommu->lock, flags);
free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
- strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -569,7 +584,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
iommu = sdev->bus->iommu;
spin_lock_irqsave(&iommu->lock, flags);
free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
- strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -581,7 +596,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
spin_lock_irqsave(&iommu->lock, flags);
- strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -605,7 +620,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
spin_lock_irqsave(&iommu->lock, flags);
- strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index fd8d7e8..f162f50 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -6,6 +6,10 @@ config 64BIT
bool
default y
+config TOP_ADDR
+ hex
+ default 0x80000000
+
config 3_LEVEL_PGTABLES
bool
default y
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 0150038..14a12d6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -20,9 +20,17 @@
#include "os.h"
#ifdef CONFIG_NOCONFIG_CHAN
+
+/* The printk's here are wrong because we are complaining that there is no
+ * output device, but printk is printing to that output device. The user will
+ * never see the error. printf would be better, except it can't run on a
+ * kernel stack because it will overflow it.
+ * Use printk for now since that will avoid crashing.
+ */
+
static void *not_configged_init(char *str, int device, struct chan_opts *opts)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(NULL);
}
@@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
static int not_configged_open(int input, int output, int primary, void *data,
char **dev_out)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
static void not_configged_close(int fd, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
}
static int not_configged_read(int fd, char *c_out, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
static int not_configged_write(int fd, const char *buf, int len, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
static int not_configged_console_write(int fd, const char *buf, int len,
void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
static int not_configged_window_size(int fd, void *data, unsigned short *rows,
unsigned short *cols)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index faf714e..217438c 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data)
struct mcast_init *init = data;
char *port_str = NULL, *ttl_str = NULL, *remain;
char *last;
- int n;
*init = ((struct mcast_init)
{ .addr = "239.192.168.1",
@@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data)
}
if(port_str != NULL){
- n = simple_strtoul(port_str, &last, 10);
+ init->port = simple_strtoul(port_str, &last, 10);
if((*last != '\0') || (last == port_str)){
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
return(0);
}
- init->port = htons(n);
}
if(ttl_str != NULL){
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 0fe1d9f..7a0d115 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
}
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in_aton(addr);
- sin->sin_port = port;
+ sin->sin_port = htons(port);
return(sin);
}
@@ -55,28 +55,25 @@ static int mcast_open(void *data)
struct mcast_data *pri = data;
struct sockaddr_in *sin = pri->mcast_addr;
struct ip_mreq mreq;
- int fd, yes = 1;
+ int fd = -EINVAL, yes = 1, err = -EINVAL;;
- if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
- fd = -EINVAL;
+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
goto out;
- }
fd = socket(AF_INET, SOCK_DGRAM, 0);
+
if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
- fd = -ENOMEM;
+ fd = -errno;
goto out;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* set ttl according to config */
@@ -84,26 +81,20 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* set LOOP, so data does get fed back to local sockets */
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* subscribe to the multicast group */
@@ -117,12 +108,15 @@ static int mcast_open(void *data)
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
- os_close_file(fd);
- fd = -EINVAL;
+ goto out_close;
}
out:
- return(fd);
+ return fd;
+
+ out_close:
+ os_close_file(fd);
+ return err;
}
static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = {
.delete_address = NULL,
.max_packet = MAX_PACKET - ETH_HEADER_OTHER
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9a56ff9..88f956c 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -55,7 +55,7 @@
#include "mem_kern.h"
#include "cow.h"
-enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
+enum ubd_req { UBD_READ, UBD_WRITE };
struct io_thread_req {
enum ubd_req op;
@@ -68,8 +68,6 @@ struct io_thread_req {
unsigned long sector_mask;
unsigned long long cow_offset;
unsigned long bitmap_words[2];
- int map_fd;
- unsigned long long map_offset;
int error;
};
@@ -122,10 +120,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
#define MAX_DEV (8)
-/* Changed in early boot */
-static int ubd_do_mmap = 0;
-#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
-
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
.open = ubd_open,
@@ -175,12 +169,6 @@ struct ubd {
int no_cow;
struct cow cow;
struct platform_device pdev;
-
- int map_writes;
- int map_reads;
- int nomap_writes;
- int nomap_reads;
- int write_maps;
};
#define DEFAULT_COW { \
@@ -200,11 +188,6 @@ struct ubd {
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
.cow = DEFAULT_COW, \
- .map_writes = 0, \
- .map_reads = 0, \
- .nomap_writes = 0, \
- .nomap_reads = 0, \
- .write_maps = 0, \
}
struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +297,6 @@ static int ubd_setup_common(char *str, int *index_out)
int major;
str++;
- if(!strcmp(str, "mmap")){
- CHOOSE_MODE(printk("mmap not supported by the ubd "
- "driver in tt mode\n"),
- ubd_do_mmap = 1);
- return(0);
- }
-
if(!strcmp(str, "sync")){
global_openflags = of_sync(global_openflags);
return(0);
@@ -524,7 +500,7 @@ static void ubd_handler(void)
{
struct io_thread_req req;
struct request *rq = elv_next_request(ubd_queue);
- int n, err;
+ int n;
do_ubd = NULL;
intr_count++;
@@ -538,19 +514,6 @@ static void ubd_handler(void)
return;
}
- if((req.op != UBD_MMAP) &&
- ((req.offset != ((__u64) (rq->sector)) << 9) ||
- (req.length != (rq->current_nr_sectors) << 9)))
- panic("I/O op mismatch");
-
- if(req.map_fd != -1){
- err = physmem_subst_mapping(req.buffer, req.map_fd,
- req.map_offset, 1);
- if(err)
- printk("ubd_handler - physmem_subst_mapping failed, "
- "err = %d\n", -err);
- }
-
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -583,14 +546,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
static void ubd_close(struct ubd *dev)
{
- if(ubd_do_mmap)
- physmem_forget_descriptor(dev->fd);
os_close_file(dev->fd);
if(dev->cow.file == NULL)
return;
- if(ubd_do_mmap)
- physmem_forget_descriptor(dev->cow.fd);
os_close_file(dev->cow.fd);
vfree(dev->cow.bitmap);
dev->cow.bitmap = NULL;
@@ -1010,94 +969,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
req->bitmap_words, bitmap_len);
}
-static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
-{
- __u64 sector;
- unsigned char *bitmap;
- int bit, i;
-
- /* mmap must have been requested on the command line */
- if(!ubd_do_mmap)
- return(-1);
-
- /* The buffer must be page aligned */
- if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
- return(-1);
-
- /* The request must be a page long */
- if((req->current_nr_sectors << 9) != PAGE_SIZE)
- return(-1);
-
- if(dev->cow.file == NULL)
- return(dev->fd);
-
- sector = offset >> 9;
- bitmap = (unsigned char *) dev->cow.bitmap;
- bit = ubd_test_bit(sector, bitmap);
-
- for(i = 1; i < req->current_nr_sectors; i++){
- if(ubd_test_bit(sector + i, bitmap) != bit)
- return(-1);
- }
-
- if(bit || (rq_data_dir(req) == WRITE))
- offset += dev->cow.data_offset;
-
- /* The data on disk must be page aligned */
- if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
- return(-1);
-
- return(bit ? dev->fd : dev->cow.fd);
-}
-
-static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
- struct request *req,
- struct io_thread_req *io_req)
-{
- int err;
-
- if(rq_data_dir(req) == WRITE){
- /* Writes are almost no-ops since the new data is already in the
- * host page cache
- */
- dev->map_writes++;
- if(dev->cow.file != NULL)
- cowify_bitmap(io_req->offset, io_req->length,
- &io_req->sector_mask, &io_req->cow_offset,
- dev->cow.bitmap, dev->cow.bitmap_offset,
- io_req->bitmap_words,
- dev->cow.bitmap_len);
- }
- else {
- int w;
-
- if((dev->cow.file != NULL) && (fd == dev->cow.fd))
- w = 0;
- else w = dev->openflags.w;
-
- if((dev->cow.file != NULL) && (fd == dev->fd))
- offset += dev->cow.data_offset;
-
- err = physmem_subst_mapping(req->buffer, fd, offset, w);
- if(err){
- printk("physmem_subst_mapping failed, err = %d\n",
- -err);
- return(1);
- }
- dev->map_reads++;
- }
- io_req->op = UBD_MMAP;
- io_req->buffer = req->buffer;
- return(0);
-}
-
/* Called with ubd_io_lock held */
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
struct gendisk *disk = req->rq_disk;
struct ubd *dev = disk->private_data;
__u64 offset;
- int len, fd;
+ int len;
if(req->rq_status == RQ_INACTIVE) return(1);
@@ -1114,34 +992,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
io_req->fds[1] = dev->fd;
- io_req->map_fd = -1;
io_req->cow_offset = -1;
io_req->offset = offset;
io_req->length = len;
io_req->error = 0;
io_req->sector_mask = 0;
- fd = mmap_fd(req, dev, io_req->offset);
- if(fd > 0){
- /* If mmapping is otherwise OK, but the first access to the
- * page is a write, then it's not mapped in yet. So we have
- * to write the data to disk first, then we can map the disk
- * page in and continue normally from there.
- */
- if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
- io_req->map_fd = dev->fd;
- io_req->map_offset = io_req->offset +
- dev->cow.data_offset;
- dev->write_maps++;
- }
- else return(prepare_mmap_request(dev, fd, io_req->offset, req,
- io_req));
- }
-
- if(rq_data_dir(req) == READ)
- dev->nomap_reads++;
- else dev->nomap_writes++;
-
io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1085,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
-static int ubd_check_remapped(int fd, unsigned long address, int is_write,
- __u64 offset)
-{
- __u64 bitmap_offset;
- unsigned long new_bitmap[2];
- int i, err, n;
-
- /* If it's not a write access, we can't do anything about it */
- if(!is_write)
- return(0);
-
- /* We have a write */
- for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
- struct ubd *dev = &ubd_dev[i];
-
- if((dev->fd != fd) && (dev->cow.fd != fd))
- continue;
-
- /* It's a write to a ubd device */
-
- /* This should be impossible now */
- if(!dev->openflags.w){
- /* It's a write access on a read-only device - probably
- * shouldn't happen. If the kernel is trying to change
- * something with no intention of writing it back out,
- * then this message will clue us in that this needs
- * fixing
- */
- printk("Write access to mapped page from readonly ubd "
- "device %d\n", i);
- return(0);
- }
-
- /* It's a write to a writeable ubd device - it must be COWed
- * because, otherwise, the page would have been mapped in
- * writeable
- */
-
- if(!dev->cow.file)
- panic("Write fault on writeable non-COW ubd device %d",
- i);
-
- /* It should also be an access to the backing file since the
- * COW pages should be mapped in read-write
- */
-
- if(fd == dev->fd)
- panic("Write fault on a backing page of ubd "
- "device %d\n", i);
-
- /* So, we do the write, copying the backing data to the COW
- * file...
- */
-
- err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of ubd "
- "device %d, err = %d",
- offset + dev->cow.data_offset, i, -err);
-
- n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
- if(n != PAGE_SIZE)
- panic("Couldn't copy data to COW file of ubd "
- "device %d, err = %d", i, -n);
-
- /* ... updating the COW bitmap... */
-
- cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
- dev->cow.bitmap, dev->cow.bitmap_offset,
- new_bitmap, dev->cow.bitmap_len);
-
- err = os_seek_file(dev->fd, bitmap_offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of ubd "
- "device %d, err = %d", bitmap_offset, i, -err);
-
- n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
- if(n != sizeof(new_bitmap))
- panic("Couldn't update bitmap of ubd device %d, "
- "err = %d", i, -n);
-
- /* Maybe we can map the COW page in, and maybe we can't. If
- * it is a pre-V3 COW file, we can't, since the alignment will
- * be wrong. If it is a V3 or later COW file which has been
- * moved to a system with a larger page size, then maybe we
- * can't, depending on the exact location of the page.
- */
-
- offset += dev->cow.data_offset;
-
- /* Remove the remapping, putting the original anonymous page
- * back. If the COW file can be mapped in, that is done.
- * Otherwise, the COW page is read in.
- */
-
- if(!physmem_remove_mapping((void *) address))
- panic("Address 0x%lx not remapped by ubd device %d",
- address, i);
- if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
- physmem_subst_mapping((void *) address, dev->fd,
- offset, 1);
- else {
- err = os_seek_file(dev->fd, offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of "
- "ubd device %d, err = %d", offset, i,
- -err);
-
- n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
- if(n != PAGE_SIZE)
- panic("Failed to read page from offset %llx of "
- "COW file of ubd device %d, err = %d",
- offset, i, -n);
- }
-
- return(1);
- }
-
- /* It's not a write on a ubd device */
- return(0);
-}
-
-static struct remapper ubd_remapper = {
- .list = LIST_HEAD_INIT(ubd_remapper.list),
- .proc = ubd_check_remapped,
-};
-
-static int ubd_remapper_setup(void)
-{
- if(ubd_do_mmap)
- register_remapper(&ubd_remapper);
-
- return(0);
-}
-
-__initcall(ubd_remapper_setup);
-
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
{
struct uml_stat buf1, buf2;
@@ -1568,15 +1287,6 @@ void do_io(struct io_thread_req *req)
int err;
__u64 off;
- if(req->op == UBD_MMAP){
- /* Touch the page to force the host to do any necessary IO to
- * get it into memory
- */
- n = *((volatile int *) req->buffer);
- req->error = update_bitmap(req);
- return;
- }
-
nsectors = req->length / req->sectorsize;
start = 0;
do {
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 84ec7ff..6eaeb99 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -31,7 +31,6 @@ extern int sysemu_supported;
#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
-#include "sysdep/faultinfo.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
@@ -59,6 +58,7 @@ extern int sysemu_supported;
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
+#include "sysdep/faultinfo.h"
#include "choose-mode.h"
union uml_pt_regs {
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index 572c6c1..ea97005 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,8 +9,6 @@
#include "linux/in6.h"
#include "asm/uaccess.h"
-extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
- int sum, int *err_ptr);
extern unsigned csum_partial(const unsigned char *buff, unsigned len,
unsigned sum);
@@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
}
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
- int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char *src,
+ unsigned char *dst, int len, int sum,
+ int *err_ptr)
{
- return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+ if(copy_from_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
+ return csum_partial(dst, len, sum);
}
/**
@@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
return a;
}
-#endif
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 348e8fc..be8acd5 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -135,6 +135,7 @@ extern int mode_tt;
__CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_SC(r) ((r)->tt.sc)
#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
extern int user_context(unsigned long sp);
@@ -196,32 +197,32 @@ struct syscall_args {
#define UPT_SET(regs, reg, val) \
- ({ unsigned long val; \
+ ({ unsigned long __upt_val = val; \
switch(reg){ \
- case R8: UPT_R8(regs) = val; break; \
- case R9: UPT_R9(regs) = val; break; \
- case R10: UPT_R10(regs) = val; break; \
- case R11: UPT_R11(regs) = val; break; \
- case R12: UPT_R12(regs) = val; break; \
- case R13: UPT_R13(regs) = val; break; \
- case R14: UPT_R14(regs) = val; break; \
- case R15: UPT_R15(regs) = val; break; \
- case RIP: UPT_IP(regs) = val; break; \
- case RSP: UPT_SP(regs) = val; break; \
- case RAX: UPT_RAX(regs) = val; break; \
- case RBX: UPT_RBX(regs) = val; break; \
- case RCX: UPT_RCX(regs) = val; break; \
- case RDX: UPT_RDX(regs) = val; break; \
- case RSI: UPT_RSI(regs) = val; break; \
- case RDI: UPT_RDI(regs) = val; break; \
- case RBP: UPT_RBP(regs) = val; break; \
- case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
- case CS: UPT_CS(regs) = val; break; \
- case DS: UPT_DS(regs) = val; break; \
- case ES: UPT_ES(regs) = val; break; \
- case FS: UPT_FS(regs) = val; break; \
- case GS: UPT_GS(regs) = val; break; \
- case EFLAGS: UPT_EFLAGS(regs) = val; break; \
+ case R8: UPT_R8(regs) = __upt_val; break; \
+ case R9: UPT_R9(regs) = __upt_val; break; \
+ case R10: UPT_R10(regs) = __upt_val; break; \
+ case R11: UPT_R11(regs) = __upt_val; break; \
+ case R12: UPT_R12(regs) = __upt_val; break; \
+ case R13: UPT_R13(regs) = __upt_val; break; \
+ case R14: UPT_R14(regs) = __upt_val; break; \
+ case R15: UPT_R15(regs) = __upt_val; break; \
+ case RIP: UPT_IP(regs) = __upt_val; break; \
+ case RSP: UPT_SP(regs) = __upt_val; break; \
+ case RAX: UPT_RAX(regs) = __upt_val; break; \
+ case RBX: UPT_RBX(regs) = __upt_val; break; \
+ case RCX: UPT_RCX(regs) = __upt_val; break; \
+ case RDX: UPT_RDX(regs) = __upt_val; break; \
+ case RSI: UPT_RSI(regs) = __upt_val; break; \
+ case RDI: UPT_RDI(regs) = __upt_val; break; \
+ case RBP: UPT_RBP(regs) = __upt_val; break; \
+ case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
+ case CS: UPT_CS(regs) = __upt_val; break; \
+ case DS: UPT_DS(regs) = __upt_val; break; \
+ case ES: UPT_ES(regs) = __upt_val; break; \
+ case FS: UPT_FS(regs) = __upt_val; break; \
+ case GS: UPT_GS(regs) = __upt_val; break; \
+ case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
default : \
panic("Bad register in UPT_SET : %d\n", reg); \
break; \
@@ -245,14 +246,3 @@ struct syscall_args {
CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 9736ca2..a8918e80 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \
tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
user_util.o
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69de29..0000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
new file mode 100644
index 0000000..82ecf90
--- /dev/null
+++ b/arch/um/kernel/initrd.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/bootmem.h"
+#include "linux/initrd.h"
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "initrd.h"
+#include "init.h"
+#include "os.h"
+
+/* Changed by uml_initrd_setup, which is a setup */
+static char *initrd __initdata = NULL;
+
+static int __init read_initrd(void)
+{
+ void *area;
+ long long size;
+ int err;
+
+ if(initrd == NULL) return 0;
+ err = os_file_size(initrd, &size);
+ if(err) return 0;
+ area = alloc_bootmem(size);
+ if(area == NULL) return 0;
+ if(load_initrd(initrd, area, size) == -1) return 0;
+ initrd_start = (unsigned long) area;
+ initrd_end = initrd_start + size;
+ return 0;
+}
+
+__uml_postsetup(read_initrd);
+
+static int __init uml_initrd_setup(char *line, int *add)
+{
+ initrd = line;
+ return 0;
+}
+
+__uml_setup("initrd=", uml_initrd_setup,
+"initrd=<initrd image>\n"
+" This is used to boot UML from an initrd image. The argument is the\n"
+" name of the file containing the image.\n\n"
+);
+
+int load_initrd(char *filename, void *buf, int size)
+{
+ int fd, n;
+
+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ return(-1);
+ }
+ n = os_read_file(fd, buf, size);
+ if(n != size){
+ printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ filename, -n);
+ return(-1);
+ }
+
+ os_close_file(fd);
+ return(0);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 78d69dc..99439fa 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
EXPORT_SYMBOL(strncpy_from_user_skas);
EXPORT_SYMBOL(copy_to_user_skas);
EXPORT_SYMBOL(copy_from_user_skas);
+EXPORT_SYMBOL(clear_user_skas);
#endif
EXPORT_SYMBOL(uml_strdup);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index f156661..c22825f 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -100,12 +100,37 @@ void mem_init(void)
#endif
}
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+ if (pmd_none(*pmd)) {
+ pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ (unsigned long) __pa(pte)));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+ if (pmd_table != pmd_offset(pud, 0))
+ BUG();
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
int i, j;
unsigned long vaddr;
@@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
- pmd = (pmd_t *)pgd;
+ pud = pud_offset(pgd, vaddr);
+ if (pud_none(*pud))
+ one_md_table_init(pud);
+ pmd = pmd_offset(pud, vaddr);
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- if (pmd_none(*pmd)) {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE +
- (unsigned long) __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
+ one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
j = 0;
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 2b75d8d..2925e15 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on)
child->thread.singlestep_syscall = 0;
#ifdef SUBARCH_SET_SINGLESTEPPING
- SUBARCH_SET_SINGLESTEPPING(child, on)
+ SUBARCH_SET_SINGLESTEPPING(child, on);
#endif
- }
+}
/*
* Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
}
#ifdef SUBACH_PTRACE_SPECIAL
- SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
+ SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
#endif
ret = ptrace_check_attach(child, request == PTRACE_KILL);
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 5fca2c6..1de22d8 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -57,10 +57,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_ACCERR;
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
+
+ if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto out;
+
page = address & PAGE_MASK;
- pgd = pgd_offset(mm, page);
- pud = pud_offset(pgd, page);
- pmd = pmd_offset(pud, page);
do {
survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,33 +107,6 @@ out_of_memory:
goto out;
}
-LIST_HEAD(physmem_remappers);
-
-void register_remapper(struct remapper *info)
-{
- list_add(&info->list, &physmem_remappers);
-}
-
-static int check_remapped_addr(unsigned long address, int is_write)
-{
- struct remapper *remapper;
- struct list_head *ele;
- __u64 offset;
- int fd;
-
- fd = phys_mapping(__pa(address), &offset);
- if(fd == -1)
- return(0);
-
- list_for_each(ele, &physmem_remappers){
- remapper = list_entry(ele, struct remapper, list);
- if((*remapper->proc)(fd, address, is_write, offset))
- return(1);
- }
-
- return(0);
-}
-
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -151,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
flush_tlb_kernel_vm();
return(0);
}
- else if(check_remapped_addr(address & PAGE_MASK, is_write))
- return(0);
else if(current->mm == NULL)
panic("Segfault with no mm");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
index 92ec85d..84a9385 100644
--- a/arch/um/kernel/tt/ksyms.c
+++ b/arch/um/kernel/tt/ksyms.c
@@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user);
EXPORT_SYMBOL(__do_strncpy_from_user);
EXPORT_SYMBOL(__do_strnlen_user);
EXPORT_SYMBOL(__do_clear_user);
+EXPORT_SYMBOL(clear_user_tt);
EXPORT_SYMBOL(tracing_pid);
EXPORT_SYMBOL(honeypot);
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 76eadb3..dd53555 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -73,6 +73,8 @@ SECTIONS
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index fcd67c3..4351e56 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -9,11 +9,11 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
SYMLINKS = bitops.c semaphore.c highmem.c module.c
+include arch/um/scripts/Makefile.rules
+
bitops.c-dir = lib
semaphore.c-dir = kernel
highmem.c-dir = mm
module.c-dir = kernel
subdir- := util
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index e9892ee..2c11b97 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,5 +1,7 @@
-#include "linux/delay.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
void __delay(unsigned long time)
{
@@ -20,13 +22,19 @@ void __udelay(unsigned long usecs)
int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+EXPORT_SYMBOL(__udelay);
+
void __const_udelay(unsigned long usecs)
{
int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+
+EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 3d7da91..608466a 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
USER_OBJS := ptrace_user.o sigcontext.o
-include arch/um/scripts/Makefile.rules
-
SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
semaphore.c thunk.S module.c
+include arch/um/scripts/Makefile.rules
+
bitops.c-dir = lib
csum-copy.S-dir = lib
csum-partial.c-dir = lib
@@ -28,6 +28,4 @@ semaphore.c-dir = kernel
thunk.S-dir = lib
module.c-dir = kernel
-CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
-
subdir- := util
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index 651332a..137f444 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -5,40 +5,37 @@
* Licensed under the GPL
*/
-#include "linux/delay.h"
-#include "asm/processor.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/param.h>
void __delay(unsigned long loops)
{
unsigned long i;
- for(i = 0; i < loops; i++) ;
+ for(i = 0; i < loops; i++)
+ cpu_relax();
}
void __udelay(unsigned long usecs)
{
- int i, n;
+ unsigned long i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+EXPORT_SYMBOL(__udelay);
+
void __const_udelay(unsigned long usecs)
{
- int i, n;
+ unsigned long i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
index a27f0ee..8592738 100644
--- a/arch/um/sys-x86_64/ksyms.c
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -16,5 +16,4 @@ EXPORT_SYMBOL(__up_wakeup);
EXPORT_SYMBOL(__memcpy);
/* Networking helper routines. */
-/*EXPORT_SYMBOL(csum_partial_copy_from);
-EXPORT_SYMBOL(csum_partial_copy_to);*/
+EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b593bb2..74eee5c 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,10 +5,11 @@
*/
#define __FRAME_OFFSETS
-#include "asm/ptrace.h"
-#include "linux/sched.h"
-#include "linux/errno.h"
-#include "asm/elf.h"
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/elf.h>
/* XXX x86_64 */
unsigned long not_ss;
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index dd99146..d4a5965 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -15,6 +15,7 @@
#include "asm/unistd.h"
#include "asm/prctl.h" /* XXX This should get the constants from libc */
#include "choose-mode.h"
+#include "kern.h"
asmlinkage long sys_uname64(struct new_utsname __user * name)
{
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 5e14792..513d17c 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -3,6 +3,14 @@
#include <signal.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
+#include <asm/types.h>
+/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
+ * refuse to include here, even though they're used throughout the headers.
+ * These are used in asm/user.h, and that include can't be avoided because of
+ * the sizeof(struct user_regs_struct) below.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
#include <asm/user.h>
#define DEFINE(sym, val) \
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index ac76843..80e9b49 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -42,6 +42,8 @@
int sis_apic_bug; /* not actually supported, dummy for compile */
+static int no_timer_check;
+
static DEFINE_SPINLOCK(ioapic_lock);
/*
@@ -1601,7 +1603,7 @@ static inline void check_timer(void)
* Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(0);
- if (timer_irq_works()) {
+ if (!no_timer_check && timer_irq_works()) {
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0);
@@ -1671,6 +1673,13 @@ static inline void check_timer(void)
panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
}
+static int __init notimercheck(char *s)
+{
+ no_timer_check = 1;
+ return 1;
+}
+__setup("no_timer_check", notimercheck);
+
/*
*
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 60dc9b9..525f6a1 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -380,7 +380,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct):
+ case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
tmp = getreg(child, addr);
break;
case offsetof(struct user, u_debugreg[0]):
@@ -425,7 +425,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct):
+ case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
ret = putreg(child, addr, data);
break;
/* Disallows to set a breakpoint into the vsyscall */
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index b9fd025..99f038e 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -719,7 +719,6 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
}
}
-#ifdef CONFIG_SMP
/*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
@@ -729,16 +728,24 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
#ifdef CONFIG_SMP
int cpu = smp_processor_id();
int node = 0;
+ unsigned bits;
if (c->x86_num_cores == 1)
return;
- /* Fix up the APIC ID following the AMD specification. */
- cpu_core_id[cpu] >>= hweight32(c->x86_num_cores - 1);
+
+ bits = 0;
+ while ((1 << bits) < c->x86_num_cores)
+ bits++;
+
+ /* Low order bits define the core id (index of core in socket) */
+ cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+ /* Convert the APIC ID into the socket ID */
+ phys_proc_id[cpu] >>= bits;
#ifdef CONFIG_NUMA
/* When an ACPI SRAT table is available use the mappings from SRAT
instead. */
if (acpi_numa <= 0) {
- node = cpu_core_id[cpu];
+ node = phys_proc_id[cpu];
if (!node_online(node))
node = first_node(node_online_map);
cpu_to_node[cpu] = node;
@@ -746,18 +753,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
node = cpu_to_node[cpu];
}
#endif
- /* For now: - better than BAD_APIC_ID at least*/
- phys_proc_id[cpu] = cpu_core_id[cpu];
printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
#endif
}
-#else
-static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
-{
-}
-#endif
static int __init init_amd(struct cpuinfo_x86 *c)
{
@@ -963,8 +963,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
}
#ifdef CONFIG_SMP
- phys_proc_id[smp_processor_id()] =
- cpu_core_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+ phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
#endif
}
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index d439ced..3fdcdba 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -452,7 +452,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->rip -= 2;
}
if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
- regs->rax = __NR_restart_syscall;
+ regs->rax = test_thread_flag(TIF_IA32) ?
+ __NR_ia32_restart_syscall :
+ __NR_restart_syscall;
regs->rip -= 2;
}
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 5abdee1..f1ec0f3 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -94,6 +94,7 @@ int smp_threads_ready;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
/*
* Trampoline 80x86 program as an array.
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index c6fb0cb..58aac23 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -133,7 +133,7 @@ ioremap_change_attr(unsigned long phys_addr, unsigned long size,
unsigned long flags)
{
int err = 0;
- if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
+ if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long vaddr = (unsigned long) __va(phys_addr);
@@ -214,7 +214,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
return NULL;
}
- if (ioremap_change_attr(phys_addr, size, flags) < 0) {
+ if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) {
area->flags &= 0xffffff;
vunmap(addr);
return NULL;
@@ -251,7 +251,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
void iounmap(volatile void __iomem *addr)
{
- struct vm_struct *p, **pprev;
+ struct vm_struct *p;
if (addr <= high_memory)
return;
@@ -260,24 +260,11 @@ void iounmap(volatile void __iomem *addr)
return;
write_lock(&vmlist_lock);
- for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev)
- if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr))
- break;
- if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- goto out_unlock;
- }
- *pprev = p->next;
- unmap_vm_area(p);
- if ((p->flags >> 20) &&
- p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
- /* p->size includes the guard page, but cpa doesn't like that */
- change_page_attr_addr((unsigned long)__va(p->phys_addr),
- p->size >> PAGE_SHIFT,
- PAGE_KERNEL);
- global_flush_tlb();
- }
-out_unlock:
+ p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
+ if (!p)
+ printk("iounmap: bad address %p\n", addr);
+ else if (p->flags >> 20)
+ ioremap_change_attr(p->phys_addr, p->size, 0);
write_unlock(&vmlist_lock);
kfree(p);
}