diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-11 18:08:53 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-11 18:08:53 -0800 |
commit | f95e6dae6522e0c403bef92405a3577ebd8baee9 (patch) | |
tree | 40c9f91e77cba0fddd1c019ae317f5768c267740 /arch | |
parent | f741676a0eea898c7fd2169df9cfcf65a3f76bd1 (diff) | |
parent | aae7d141676c5d83dbc97732f1cf48839f404774 (diff) | |
download | history-f95e6dae6522e0c403bef92405a3577ebd8baee9.tar.gz |
Merge http://lia64.bkbits.net/linux-ia64-release-2.6.11
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'arch')
181 files changed, 4383 insertions, 1560 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index cae9d38b5c9f18..674791c81502fe 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -519,7 +519,7 @@ config PREEMPT config PREEMPT_BKL bool "Preempt The Big Kernel Lock" - depends on PREEMPT || SMP + depends on PREEMPT default y help This option reduces the latency of the kernel by making the diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index df8900b1f1670a..406f5a93d01b8c 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -877,23 +877,18 @@ static unsigned int __init get_8254_timer_count(void) /* next tick in 8254 can be caught by catching timer wraparound */ static void __init wait_8254_wraparound(void) { - unsigned int curr_count, prev_count=~0; - int delta; + unsigned int curr_count, prev_count; curr_count = get_8254_timer_count(); - do { prev_count = curr_count; curr_count = get_8254_timer_count(); - delta = curr_count-prev_count; - /* - * This limit for delta seems arbitrary, but it isn't, it's - * slightly above the level of error a buggy Mercury/Neptune - * chipset timer can cause. - */ + /* workaround for broken Mercury/Neptune */ + if (prev_count >= curr_count + 0x100) + curr_count = get_8254_timer_count(); - } while (delta < 300); + } while (prev_count >= curr_count); } /* diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 091b98ae93b672..ae94585d044513 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -188,6 +188,23 @@ static void __init init_amd(struct cpuinfo_x86 *c) } display_cacheinfo(c); + detect_ht(c); + +#ifdef CONFIG_X86_HT + /* AMD dual core looks like HT but isn't really. Hide it from the + scheduler. This works around problems with the domain scheduler. + Also probably gives slightly better scheduling and disables + SMT nice which is harmful on dual core. + TBD tune the domain scheduler for dual core. */ + if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) + smp_num_siblings = 1; +#endif + + if (cpuid_eax(0x80000000) >= 0x80000008) { + c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; + if (c->x86_num_cores & (c->x86_num_cores - 1)) + c->x86_num_cores = 1; + } } static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index aef962cac86202..b619be984d5a88 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -10,6 +10,11 @@ #include <asm/msr.h> #include <asm/io.h> #include <asm/mmu_context.h> +#ifdef CONFIG_X86_LOCAL_APIC +#include <asm/mpspec.h> +#include <asm/apic.h> +#include <mach_apic.h> +#endif #include "cpu.h" @@ -274,8 +279,10 @@ void __init generic_identify(struct cpuinfo_x86 * c) /* AMD-defined flags: level 0x80000001 */ xlvl = cpuid_eax(0x80000000); if ( (xlvl & 0xffff0000) == 0x80000000 ) { - if ( xlvl >= 0x80000001 ) + if ( xlvl >= 0x80000001 ) { c->x86_capability[1] = cpuid_edx(0x80000001); + c->x86_capability[6] = cpuid_ecx(0x80000001); + } if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } @@ -321,6 +328,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) c->x86_model = c->x86_mask = 0; /* So far unknown... */ c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ + c->x86_num_cores = 1; memset(&c->x86_capability, 0, sizeof c->x86_capability); if (!have_cpuid_p()) { @@ -429,6 +437,50 @@ void __init dodgy_tsc(void) cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); } +#ifdef CONFIG_X86_HT +void __init detect_ht(struct cpuinfo_x86 *c) +{ + u32 eax, ebx, ecx, edx; + int index_lsb, index_msb, tmp; + int cpu = smp_processor_id(); + + if (!cpu_has(c, X86_FEATURE_HT)) + return; + + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; + + if (smp_num_siblings == 1) { + printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + } else if (smp_num_siblings > 1 ) { + index_lsb = 0; + index_msb = 31; + + if (smp_num_siblings > NR_CPUS) { + printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); + smp_num_siblings = 1; + return; + } + tmp = smp_num_siblings; + while ((tmp & 1) == 0) { + tmp >>=1 ; + index_lsb++; + } + tmp = smp_num_siblings; + while ((tmp & 0x80000000 ) == 0) { + tmp <<=1 ; + index_msb--; + } + if (index_lsb != index_msb ) + index_msb++; + phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + phys_proc_id[cpu]); + } +} +#endif + void __init print_cpu_info(struct cpuinfo_x86 *c) { char *vendor = NULL; diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index eb145ed88d6a55..b8d847b850dc66 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -139,50 +139,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) if ( p ) strcpy(c->x86_model_id, p); -#ifdef CONFIG_X86_HT - if (cpu_has(c, X86_FEATURE_HT)) { - extern int phys_proc_id[NR_CPUS]; - - u32 eax, ebx, ecx, edx; - int index_lsb, index_msb, tmp; - int cpu = smp_processor_id(); - - cpuid(1, &eax, &ebx, &ecx, &edx); - smp_num_siblings = (ebx & 0xff0000) >> 16; - - if (smp_num_siblings == 1) { - printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); - } else if (smp_num_siblings > 1 ) { - index_lsb = 0; - index_msb = 31; - - if (smp_num_siblings > NR_CPUS) { - printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); - smp_num_siblings = 1; - goto too_many_siblings; - } - tmp = smp_num_siblings; - while ((tmp & 1) == 0) { - tmp >>=1 ; - index_lsb++; - } - tmp = smp_num_siblings; - while ((tmp & 0x80000000 ) == 0) { - tmp <<=1 ; - index_msb--; - } - if (index_lsb != index_msb ) - index_msb++; - phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); - - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - phys_proc_id[cpu]); - } - - } -too_many_siblings: - -#endif + detect_ht(c); /* Work around errata */ Intel_errata_workarounds(c); diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 4ba834c44ea523..c8d83fdc237a35 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -28,7 +28,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, - NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -45,7 +45,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", - "tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL, + "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -54,6 +54,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* AMD-defined (#2) */ + "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; struct cpuinfo_x86 *c = v; int i, n = c - cpu_data; @@ -88,11 +94,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_X86_HT - if (smp_num_siblings > 1) { - extern int phys_proc_id[NR_CPUS]; - seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); - seq_printf(m, "siblings\t: %d\n", smp_num_siblings); - } + seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); + seq_printf(m, "siblings\t: %d\n", c->x86_num_cores * smp_num_siblings); #endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index b9eb1a95bb53d9..1879a89d00acaf 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -86,15 +86,28 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled thorough out this function. */ -static inline int kprobe_handler(struct pt_regs *regs) +static int kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; - u8 *addr = (u8 *) (regs->eip - 1); + kprobe_opcode_t *addr = NULL; + unsigned long *lp; /* We're in an interrupt, but this is clear and BUG()-safe. */ preempt_disable(); - + /* Check if the application is using LDT entry for its code segment and + * calculate the address by reading the base address from the LDT entry. + */ + if ((regs->xcs & 4) && (current->mm)) { + lp = (unsigned long *) ((unsigned long)((regs->xcs >> 3) * 8) + + (char *) current->mm->context.ldt); + addr = (kprobe_opcode_t *) ((((*lp) >> 16 & 0x0000ffff) + | (*(lp +1) & 0xff000000) + | ((*(lp +1) << 16) & 0x00ff0000)) + + regs->eip - sizeof(kprobe_opcode_t)); + } else { + addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); + } /* Check we're not actually recursing */ if (kprobe_running()) { /* We *are* holding lock here, so this is safe. diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 51c4bfc53c938e..f98146004f5e1d 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -190,6 +190,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; err |= restore_i387(buf); + } else { + struct task_struct *me = current; + if (me->used_math) { + clear_fpu(me); + me->used_math = 0; + } } } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index caa3d1315a7479..d1ced13320d002 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -61,6 +61,7 @@ static int __initdata smp_b_stepping; /* Number of siblings per CPU package */ int smp_num_siblings = 1; int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ +EXPORT_SYMBOL(phys_proc_id); /* bitmap of online cpus */ cpumask_t cpu_online_map; diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index 1aa488b7f99917..58ff04eeb9dbc0 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c @@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr) if (!p) { printk("__iounmap: bad address %p\n", addr); return; - } + } - if (p->flags && p->phys_addr < virt_to_phys(high_memory) - 1) { + if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, PAGE_KERNEL); diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 7647cde233a798..46c86395fe40d9 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -120,27 +120,35 @@ __change_page_attr(struct page *page, pgprot_t prot) kpte_page = virt_to_page(kpte); if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { if ((pte_val(*kpte) & _PAGE_PSE) == 0) { - pte_t old = *kpte; - pte_t standard = mk_pte(page, PAGE_KERNEL); set_pte_atomic(kpte, mk_pte(page, prot)); - if (pte_same(old,standard)) - get_page(kpte_page); } else { struct page *split = split_large_page(address, prot); if (!split) return -ENOMEM; - get_page(kpte_page); set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL)); + kpte_page = split; } + get_page(kpte_page); } else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL)); __put_page(kpte_page); - } + } else + BUG(); - if (cpu_has_pse && (page_count(kpte_page) == 1)) { - list_add(&kpte_page->lru, &df_list); - revert_page(kpte_page, address); - } + /* + * If the pte was reserved, it means it was created at boot + * time (not via split_large_page) and in turn we must not + * replace it with a largepage. + */ + if (!PageReserved(kpte_page)) { + /* memleak and potential failed 2M page regeneration */ + BUG_ON(!page_count(kpte_page)); + + if (cpu_has_pse && (page_count(kpte_page) == 1)) { + list_add(&kpte_page->lru, &df_list); + revert_page(kpte_page, address); + } + } return 0; } diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 27cf192061c2e2..af18331b3fb294 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -227,10 +227,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_ */ static void __init pci_fixup_nforce2(struct pci_dev *dev) { - u32 val, fixed_val; - u8 rev; - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + u32 val; /* * Chip Old value New value @@ -240,17 +237,14 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) * Northbridge chip version may be determined by * reading the PCI revision ID (0xC1 or greater is C18D). */ - fixed_val = rev < 0xC1 ? 0x1F01FF01 : 0x9F01FF01; - pci_read_config_dword(dev, 0x6c, &val); /* - * Apply fixup only if C1 Halt Disconnect is enabled - * (bit28) because it is not supported on some boards. + * Apply fixup if needed, but don't touch disconnect state */ - if ((val & (1 << 28)) && val != fixed_val) { + if ((val & 0x00FF0000) != 0x00010000) { printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n"); - pci_write_config_dword(dev, 0x6c, fixed_val); + pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000); } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 42800941f17cf5..52951437d9d3b5 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -377,6 +377,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, region->start = res->start - offset; region->end = res->end - offset; } +EXPORT_SYMBOL(pcibios_resource_to_bus); void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, struct pci_bus_region *region) diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index 736c8d86f64b93..ec968e453f79a1 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -9,8 +9,6 @@ * Copyright (C) 1995 Linus Torvalds */ -/* $Id$ */ - #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -19,6 +17,7 @@ #include <linux/swap.h> #include <linux/highmem.h> #include <linux/bitops.h> +#include <linux/nodemask.h> #include <asm/types.h> #include <asm/processor.h> #include <asm/page.h> diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index aee1f399e15b95..43c254299e4a73 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -127,7 +127,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } @@ -375,7 +377,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, /* Map the last of the bss segment */ if (last_bss > len) { + down_write(¤t->mm->mmap_sem); do_brk(len, (last_bss - len)); + up_write(¤t->mm->mmap_sem); } kfree(elf_phdata); @@ -562,7 +566,9 @@ void irix_map_prda_page (void) unsigned long v; struct prda *pp; + down_write(¤t->mm->mmap_sem); v = do_brk (PRDA_ADDRESS, PAGE_SIZE); + up_write(¤t->mm->mmap_sem); if (v < 0) return; @@ -852,8 +858,11 @@ static int load_irix_library(struct file *file) len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; - if (bss > len) + if (bss > len) { + down_write(¤t->mm->mmap_sem); do_brk(len, bss-len); + up_write(¤t->mm->mmap_sem); + } kfree(elf_phdata); return 0; } diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c index 4486a745b0ef25..6fd07e90aad76b 100644 --- a/arch/parisc/kernel/binfmt_elf32.c +++ b/arch/parisc/kernel/binfmt_elf32.c @@ -92,10 +92,12 @@ struct elf_prpsinfo32 current->thread.map_base = DEFAULT_MAP_BASE32; \ current->thread.task_size = DEFAULT_TASK_SIZE32 \ -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 53547b6de45bd4..ddad50b0129841 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -41,14 +41,17 @@ void default_idle(void) if (!need_resched()) { if (powersave != NULL) powersave(); -#ifdef CONFIG_SMP else { +#ifdef CONFIG_SMP set_thread_flag(TIF_POLLING_NRFLAG); + local_irq_enable(); while (!need_resched()) barrier(); clear_thread_flag(TIF_POLLING_NRFLAG); - } +#else + local_irq_enable(); #endif + } } if (need_resched()) schedule(); diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c index 88452272cc9361..cbb29e6f490202 100644 --- a/arch/ppc/kernel/perfmon.c +++ b/arch/ppc/kernel/perfmon.c @@ -47,7 +47,6 @@ static void dummy_perf(struct pt_regs *regs) #else /* Ensure exceptions are disabled */ -#define MMCR0_PMXE (1UL << (31 - 5)) static void dummy_perf(struct pt_regs *regs) { diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index e69bc4e94297a1..6e31db0fe4b468 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -31,6 +31,7 @@ #include <linux/bootmem.h> #include <linux/highmem.h> #include <linux/initrd.h> +#include <linux/pagemap.h> #include <asm/pgalloc.h> #include <asm/prom.h> diff --git a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c index 478e5fce6be174..fadc699a0497c8 100644 --- a/arch/ppc64/kernel/binfmt_elf32.c +++ b/arch/ppc64/kernel/binfmt_elf32.c @@ -60,10 +60,12 @@ struct elf_prpsinfo32 #include <linux/time.h> -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index f136d3d8a9479e..677f6272fc2941 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -99,6 +99,7 @@ static inline int kprobe_handler(struct pt_regs *regs) p = get_kprobe(addr); if (!p) { unlock_kprobes(); +#if 0 if (*addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right @@ -109,6 +110,7 @@ static inline int kprobe_handler(struct pt_regs *regs) */ ret = 1; } +#endif /* Not one of ours: let kernel handle it */ goto no_kprobe; } diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c index f8cd5b495d6b0b..53993999b265ac 100644 --- a/arch/ppc64/kernel/maple_pci.c +++ b/arch/ppc64/kernel/maple_pci.c @@ -382,9 +382,6 @@ void __init maple_pcibios_fixup(void) /* Do the mapping of the IO space */ phbs_remap_io(); - /* Fixup the pci_bus sysdata pointers */ - pci_fix_bus_sysdata(); - DBG(" <- maple_pcibios_fixup\n"); } diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index a795ae320b371a..1502b814a55895 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -167,27 +167,7 @@ _GLOBAL(call_with_mmu_off) xori r0,r0,MSR_IR|MSR_DR mtspr SPRN_SRR1,r0 rfid - -/* - * Flush instruction cache. - */ -_GLOBAL(flush_instruction_cache) -/* - * This is called by kgdb code - * and should probably go away - * to be replaced by invalidating - * the cache lines that are actually - * modified - */ - /* use invalidate-all bit in HID0 - * - is this consistent across all 64-bit cpus? -- paulus */ - mfspr r3,HID0 - ori r3,r3,HID0_ICFI - mtspr HID0,r3 - sync - isync - blr .section ".toc","aw" PPC64_CACHES: diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index 2b9a00951f2070..8953e94889bab4 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -552,7 +552,6 @@ void __init pSeries_final_fixup(void) phbs_remap_io(); pSeries_request_regions(); - pci_fix_bus_sysdata(); pci_addr_cache_build(); } diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index d03c4716400171..f8f2007b888505 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c @@ -19,9 +19,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/interrupt.h> -#include <linux/kernel_stat.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/spinlock.h> @@ -40,7 +38,6 @@ #include <asm/smp.h> #include <asm/paca.h> #include <asm/time.h> -#include <asm/ppcdebug.h> #include <asm/machdep.h> #include <asm/xics.h> #include <asm/cputable.h> @@ -87,11 +84,8 @@ static int query_cpu_stopped(unsigned int pcpu) #ifdef CONFIG_HOTPLUG_CPU -int __cpu_disable(void) +int pSeries_cpu_disable(void) { - /* FIXME: go put this in a header somewhere */ - extern void xics_migrate_irqs_away(void); - systemcfg->processorCount--; /*fix boot_cpuid here*/ @@ -103,7 +97,7 @@ int __cpu_disable(void) return 0; } -void __cpu_die(unsigned int cpu) +void pSeries_cpu_die(unsigned int cpu) { int tries; int cpu_status; @@ -250,8 +244,6 @@ static void smp_xics_message_pass(int target, int msg) } } -extern void xics_request_IPIs(void); - static int __init smp_xics_probe(void) { xics_request_IPIs(); @@ -263,6 +255,19 @@ static void __devinit smp_xics_setup_cpu(int cpu) { if (cpu != boot_cpuid) xics_setup_cpu(); + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) + vpa_init(cpu); + +#ifdef CONFIG_IRQ_ALL_CPUS + /* + * Put the calling processor into the GIQ. This is really only + * necessary from a secondary thread as the OF start-cpu interface + * performs this function for us on primary threads. + */ + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); +#endif } static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; @@ -290,26 +295,7 @@ static void __devinit pSeries_take_timebase(void) spin_unlock(&timebase_lock); } -static void __devinit pSeries_late_setup_cpu(int cpu) -{ - extern unsigned int default_distrib_server; - - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - vpa_init(cpu); - } - -#ifdef CONFIG_IRQ_ALL_CPUS - /* Put the calling processor into the GIQ. This is really only - * necessary from a secondary thread as the OF start-cpu interface - * performs this function for us on primary threads. - */ - /* TODO: 9005 is #defined in rtas-proc.c -- move to a header */ - rtas_set_indicator(9005, default_distrib_server, 1); -#endif -} - - -void __devinit smp_pSeries_kick_cpu(int nr) +static void __devinit smp_pSeries_kick_cpu(int nr) { BUG_ON(nr < 0 || nr >= NR_CPUS); @@ -329,7 +315,6 @@ static struct smp_ops_t pSeries_mpic_smp_ops = { .probe = smp_mpic_probe, .kick_cpu = smp_pSeries_kick_cpu, .setup_cpu = smp_mpic_setup_cpu, - .late_setup_cpu = pSeries_late_setup_cpu, }; static struct smp_ops_t pSeries_xics_smp_ops = { @@ -337,7 +322,6 @@ static struct smp_ops_t pSeries_xics_smp_ops = { .probe = smp_xics_probe, .kick_cpu = smp_pSeries_kick_cpu, .setup_cpu = smp_xics_setup_cpu, - .late_setup_cpu = pSeries_late_setup_cpu, }; /* This is called very early */ @@ -352,6 +336,11 @@ void __init smp_init_pSeries(void) else smp_ops = &pSeries_xics_smp_ops; +#ifdef CONFIG_HOTPLUG_CPU + smp_ops->cpu_disable = pSeries_cpu_disable; + smp_ops->cpu_die = pSeries_cpu_die; +#endif + /* Start secondary threads on SMT systems; primary threads * are already in the running state. */ @@ -367,9 +356,6 @@ void __init smp_init_pSeries(void) } } - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) - vpa_init(boot_cpuid); - /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { smp_ops->give_timebase = pSeries_give_timebase; diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 206c52d8ca66f7..0b18d17b94d4c5 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -78,13 +78,16 @@ struct paca_struct paca[] = { #else PACAINITDATA( 0, 1, NULL, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR), #endif +#if NR_CPUS > 1 PACAINITDATA( 1, 0, NULL, 0, 0), PACAINITDATA( 2, 0, NULL, 0, 0), PACAINITDATA( 3, 0, NULL, 0, 0), +#if NR_CPUS > 4 PACAINITDATA( 4, 0, NULL, 0, 0), PACAINITDATA( 5, 0, NULL, 0, 0), PACAINITDATA( 6, 0, NULL, 0, 0), PACAINITDATA( 7, 0, NULL, 0, 0), +#if NR_CPUS > 8 PACAINITDATA( 8, 0, NULL, 0, 0), PACAINITDATA( 9, 0, NULL, 0, 0), PACAINITDATA(10, 0, NULL, 0, 0), @@ -209,4 +212,7 @@ struct paca_struct paca[] = { PACAINITDATA(127, 0, NULL, 0, 0), #endif #endif +#endif +#endif +#endif }; diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 25822272542e30..a7bf62655601b8 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -91,7 +91,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region struct resource *res) { unsigned long offset = 0; - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); if (!hose) return; @@ -127,7 +127,7 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { struct pci_dev *dev = data; - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); unsigned long start = res->start; unsigned long alignto; @@ -292,7 +292,7 @@ int pci_domain_nr(struct pci_bus *bus) #ifdef CONFIG_PPC_ISERIES return 0; #else - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); return hose->global_number; #endif @@ -304,7 +304,7 @@ EXPORT_SYMBOL(pci_domain_nr); int pci_name_bus(char *name, struct pci_bus *bus) { #ifndef CONFIG_PPC_ISERIES - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); if (hose->buid) sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); @@ -336,7 +336,7 @@ static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long io_offset = 0; int i, res_bit; @@ -643,7 +643,7 @@ void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose) static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, unsigned long *start_virt, unsigned long *size) { - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); struct pci_bus_region region; struct resource *res; @@ -728,23 +728,6 @@ void phbs_remap_io(void) remap_bus_range(hose->bus); } - -/* - * This function finds the PHB that matching device_node in the - * OpenFirmware by scanning all the pci_controllers. - */ -struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node) -{ - while (node) { - struct pci_controller *hose, *tmp; - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) - if (hose->arch_data == node) - return hose; - node=node->parent; - } - return NULL; -} - /* * ppc64 can have multifunction devices that do not respond to function 0. * In this case we must scan all functions. @@ -778,7 +761,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) { /* Update device resources. */ - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -814,7 +797,7 @@ EXPORT_SYMBOL(pcibios_fixup_device_resources); void __devinit pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); struct pci_dev *dev = bus->self; struct resource *res; int i; diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index 2ed6b674bbca21..28517c14015b92 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -17,7 +17,6 @@ extern unsigned long isa_io_base; extern void pci_setup_pci_controller(struct pci_controller *hose); extern void pci_setup_phb_io(struct pci_controller *hose, int primary); -extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); extern void pci_setup_phb_io_dynamic(struct pci_controller *hose); @@ -36,11 +35,8 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); -void pci_fix_bus_sysdata(void); struct device_node *fetch_dev_dn(struct pci_dev *dev); -#define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb) - /* PCI address cache management routines */ void pci_addr_cache_insert_device(struct pci_dev *dev); void pci_addr_cache_remove_device(struct pci_dev *dev); diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 962394708ece6e..280b744fe64e3a 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -21,19 +21,12 @@ */ #include <linux/kernel.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/string.h> #include <linux/init.h> -#include <linux/bootmem.h> #include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/irq.h> #include <asm/prom.h> -#include <asm/machdep.h> #include <asm/pci-bridge.h> -#include <asm/ppcdebug.h> -#include <asm/iommu.h> #include "pci.h" @@ -178,29 +171,3 @@ void __init pci_devs_phb_init(void) list_for_each_entry_safe(phb, tmp, &hose_list, list_node) pci_devs_phb_init_dynamic(phb); } - - -static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list) -{ - struct pci_bus *bus; - - list_for_each_entry(bus, bus_list, node) { - if (bus->self) - bus->sysdata = bus->self->sysdata; - pci_fixup_bus_sysdata_list(&bus->children); - } -} - -/* - * Fixup the bus->sysdata ptrs to point to the bus' device_node. - * This is done late in pcibios_init(). We do this mostly for - * sanity, but pci_dma.c uses these at DMA time so they must be - * correct. - * To do this we recurse down the bus hierarchy. Note that PHB's - * have bus->self == NULL, but fortunately bus->sysdata is already - * correct in this case. - */ -void __init pci_fix_bus_sysdata(void) -{ - pci_fixup_bus_sysdata_list(&pci_root_buses); -} diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c index 32634216ad78f6..00a831df6d9f10 100644 --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -664,8 +664,6 @@ void __init pmac_pcibios_fixup(void) for_each_pci_dev(dev) pci_read_irq_line(dev); - - pci_fix_bus_sysdata(); } static void __init pmac_fixup_phb_resources(void) diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index 7efdaabf5b7b8e..38c0398d823cc8 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -114,7 +114,6 @@ EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(flush_instruction_cache); EXPORT_SYMBOL(giveup_fpu); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(giveup_altivec); diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index e647e7bc95c18f..d90a50e456696f 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c @@ -214,23 +214,57 @@ struct task_struct *__switch_to(struct task_struct *prev, return last; } +static int instructions_to_print = 16; + +static void show_instructions(struct pt_regs *regs) +{ + int i; + unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 * + sizeof(int)); + + printk("Instruction dump:"); + + for (i = 0; i < instructions_to_print; i++) { + int instr; + + if (!(i % 8)) + printk("\n"); + + if (((REGION_ID(pc) != KERNEL_REGION_ID) && + (REGION_ID(pc) != VMALLOC_REGION_ID)) || + __get_user(instr, (unsigned int *)pc)) { + printk("XXXXXXXX "); + } else { + if (regs->nip == pc) + printk("<%08x> ", instr); + else + printk("%08x ", instr); + } + + pc += sizeof(int); + } + + printk("\n"); +} + void show_regs(struct pt_regs * regs) { int i; unsigned long trap; - printk("NIP: %016lX XER: %016lX LR: %016lX\n", - regs->nip, regs->xer, regs->link); + printk("NIP: %016lX XER: %08X LR: %016lX CTR: %016lX\n", + regs->nip, (unsigned int)regs->xer, regs->link, regs->ctr); printk("REGS: %p TRAP: %04lx %s (%s)\n", regs, regs->trap, print_tainted(), UTS_RELEASE); - printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", + printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x " + "IR/DR: %01x%01x CR: %08X\n", regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); + regs->msr&MSR_DR ? 1 : 0, + (unsigned int)regs->ccr); trap = TRAP(regs); - if (trap == 0x300 || trap == 0x380 || trap == 0x600) - printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr); + printk("DAR: %016lx DSISR: %016lx\n", regs->dar, regs->dsisr); printk("TASK: %p[%d] '%s' THREAD: %p", current, current->pid, current->comm, current->thread_info); @@ -257,6 +291,8 @@ void show_regs(struct pt_regs * regs) printk("LR [%016lx] ", regs->link); print_symbol("%s\n", regs->link); show_stack(current, (unsigned long *)regs->gpr[1]); + if (!user_mode(regs)) + show_instructions(regs); } void exit_thread(void) diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c index ed07210b9917df..28b1f1521f2165 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/ppc64/kernel/rtas-proc.c @@ -52,7 +52,6 @@ #define IBM_VOLTAGE 0x232a /* 9002 */ #define IBM_DRCONNECTOR 0x232b /* 9003 */ #define IBM_POWERSUPPLY 0x232c /* 9004 */ -#define IBM_INTQUEUE 0x232d /* 9005 */ /* Status return values */ #define SENSOR_CRITICAL_HIGH 13 @@ -107,7 +106,6 @@ #define DR_ACTION 0x2329 /* 9001 */ #define DR_INDICATOR 0x232a /* 9002 */ /* 9003 - 9004: Vendor specific */ -#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */ /* 9006 - 9999: Vendor specific */ /* other */ @@ -553,7 +551,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m, "No current flow" }; const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", "Exchange" }; - const char * ibm_intqueue[] = { "Disabled", "Enabled" }; int have_strings = 0; int num_states = 0; @@ -665,15 +662,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m, case IBM_POWERSUPPLY: seq_printf(m, "Powersupply:\t"); break; - case IBM_INTQUEUE: - seq_printf(m, "Interrupt queue:\t"); - num_states = sizeof(ibm_intqueue) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - ibm_intqueue[state]); - have_strings = 1; - } - break; default: seq_printf(m, "Unknown sensor (type %d), ignoring it\n", s->token); diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c index ade32f6a6d30a8..b5a96ec9f3bcd3 100644 --- a/arch/ppc64/kernel/rtasd.c +++ b/arch/ppc64/kernel/rtasd.c @@ -486,7 +486,7 @@ static int __init rtas_init(void) /* No RTAS, only warn if we are on a pSeries box */ if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { - if (systemcfg->platform & PLATFORM_PSERIES); + if (systemcfg->platform & PLATFORM_PSERIES) printk(KERN_ERR "rtasd: no event-scan on system\n"); return 1; } diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index db78b2f03884de..f5b4a8f295815d 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -22,9 +22,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/interrupt.h> -#include <linux/kernel_stat.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/spinlock.h> @@ -38,12 +36,10 @@ #include <asm/irq.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/io.h> #include <asm/prom.h> #include <asm/smp.h> #include <asm/paca.h> #include <asm/time.h> -#include <asm/ppcdebug.h> #include <asm/machdep.h> #include <asm/cputable.h> #include <asm/system.h> @@ -58,7 +54,6 @@ #endif int smp_threads_ready; -unsigned long cache_decay_ticks; cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; @@ -77,10 +72,6 @@ void smp_call_function_interrupt(void); int smt_enabled_at_boot = 1; -/* Low level assembly function used to backup CPU 0 state */ -extern void __save_cpu_setup(void); - - #ifdef CONFIG_PPC_MULTIPLATFORM void smp_mpic_message_pass(int target, int msg) { @@ -507,9 +498,6 @@ int __devinit start_secondary(void *unused) if (smp_ops->take_timebase) smp_ops->take_timebase(); - if (smp_ops->late_setup_cpu) - smp_ops->late_setup_cpu(cpu); - spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); spin_unlock(&call_lock); @@ -551,3 +539,19 @@ void __init smp_cpus_done(unsigned int max_cpus) */ cpu_present_map = cpu_possible_map; } + +#ifdef CONFIG_HOTPLUG_CPU +int __cpu_disable(void) +{ + if (smp_ops->cpu_disable) + return smp_ops->cpu_disable(); + + return -ENOSYS; +} + +void __cpu_die(unsigned int cpu) +{ + if (smp_ops->cpu_die) + smp_ops->cpu_die(cpu); +} +#endif diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 1a6493196f2dfe..01b21095b76cd2 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -142,16 +142,54 @@ static __inline__ void timer_check_rtc(void) } } +/* + * This version of gettimeofday has microsecond resolution. + */ +static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val) +{ + unsigned long sec, usec, tb_ticks; + unsigned long xsec, tb_xsec; + struct gettimeofday_vars * temp_varp; + unsigned long temp_tb_to_xs, temp_stamp_xsec; + + /* + * These calculations are faster (gets rid of divides) + * if done in units of 1/2^20 rather than microseconds. + * The conversion to microseconds at the end is done + * without a divide (and in fact, without a multiply) + */ + tb_ticks = tb_val - do_gtod.tb_orig_stamp; + temp_varp = do_gtod.varp; + temp_tb_to_xs = temp_varp->tb_to_xs; + temp_stamp_xsec = temp_varp->stamp_xsec; + tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs ); + xsec = temp_stamp_xsec + tb_xsec; + sec = xsec / XSEC_PER_SEC; + xsec -= sec * XSEC_PER_SEC; + usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC; + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void do_gettimeofday(struct timeval *tv) +{ + __do_gettimeofday(tv, get_tb()); +} + +EXPORT_SYMBOL(do_gettimeofday); + /* Synchronize xtime with do_gettimeofday */ -static __inline__ void timer_sync_xtime( unsigned long cur_tb ) +static inline void timer_sync_xtime(unsigned long cur_tb) { struct timeval my_tv; - if ( cur_tb > next_xtime_sync_tb ) { + if (cur_tb > next_xtime_sync_tb) { next_xtime_sync_tb = cur_tb + xtime_sync_interval; - do_gettimeofday( &my_tv ); - if ( xtime.tv_sec <= my_tv.tv_sec ) { + __do_gettimeofday(&my_tv, cur_tb); + + if (xtime.tv_sec <= my_tv.tv_sec) { xtime.tv_sec = my_tv.tv_sec; xtime.tv_nsec = my_tv.tv_usec * 1000; } @@ -274,7 +312,7 @@ int timer_interrupt(struct pt_regs * regs) write_seqlock(&xtime_lock); tb_last_stamp = lpaca->next_jiffy_update_tb; do_timer(regs); - timer_sync_xtime( cur_tb ); + timer_sync_xtime(lpaca->next_jiffy_update_tb); timer_check_rtc(); write_sequnlock(&xtime_lock); if ( adjusting_time && (time_adjust == 0) ) @@ -313,36 +351,6 @@ unsigned long long sched_clock(void) return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; } -/* - * This version of gettimeofday has microsecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long sec, usec, tb_ticks; - unsigned long xsec, tb_xsec; - struct gettimeofday_vars * temp_varp; - unsigned long temp_tb_to_xs, temp_stamp_xsec; - - /* These calculations are faster (gets rid of divides) - * if done in units of 1/2^20 rather than microseconds. - * The conversion to microseconds at the end is done - * without a divide (and in fact, without a multiply) */ - tb_ticks = get_tb() - do_gtod.tb_orig_stamp; - temp_varp = do_gtod.varp; - temp_tb_to_xs = temp_varp->tb_to_xs; - temp_stamp_xsec = temp_varp->stamp_xsec; - tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs ); - xsec = temp_stamp_xsec + tb_xsec; - sec = xsec / XSEC_PER_SEC; - xsec -= sec * XSEC_PER_SEC; - usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC; - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - int do_settimeofday(struct timespec *tv) { time_t wtm_sec, new_sec = tv->tv_sec; diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index 44f04fc727fd5a..418aff49933ed1 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -127,6 +127,7 @@ int die(const char *str, struct pt_regs *regs, long err) } if (nl) printk("\n"); + print_modules(); show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -343,7 +344,7 @@ extern struct bug_entry __start___bug_table[], __stop___bug_table[]; #define module_find_bug(x) NULL #endif -static struct bug_entry *find_bug(unsigned long bugaddr) +struct bug_entry *find_bug(unsigned long bugaddr) { struct bug_entry *bug; @@ -353,7 +354,7 @@ static struct bug_entry *find_bug(unsigned long bugaddr) return module_find_bug(bugaddr); } -int +static int check_bug_trap(struct pt_regs *regs) { struct bug_entry *bug; diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index b9fdcc60d6e8e0..eca025abe0987b 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -91,6 +91,7 @@ static int xics_irq_8259_cascade_real = 0; static unsigned int default_server = 0xFF; /* also referenced in smp.c... */ unsigned int default_distrib_server = 0; +unsigned int interrupt_server_size = 8; /* * XICS only has a single IPI, so encode the messages per CPU @@ -511,6 +512,10 @@ nextnode: default_server = ireg[0]; default_distrib_server = ireg[i-1]; /* take last element */ } + ireg = (uint *)get_property(np, + "ibm,interrupt-server#-size", NULL); + if (ireg) + interrupt_server_size = *ireg; break; } } @@ -643,20 +648,16 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) /* Interrupts are disabled. */ void xics_migrate_irqs_away(void) { - int set_indicator = rtas_token("set-indicator"); - const unsigned int giqs = 9005UL; /* Global Interrupt Queue Server */ - int status = 0; + int status; unsigned int irq, virq, cpu = smp_processor_id(); - BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE); - /* Reject any interrupt that was queued to us... */ ops->cppr_info(cpu, 0); iosync(); - /* Refuse any new interrupts... */ - rtas_call(set_indicator, 3, 1, &status, giqs, - hard_smp_processor_id(), 0); + /* remove ourselves from the global interrupt queue */ + status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); WARN_ON(status != 0); /* Allow IPIs again... */ diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index 056db88671b4d9..723a3dc77db6d3 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c @@ -37,6 +37,7 @@ #include <linux/bootmem.h> #include <linux/highmem.h> #include <linux/idr.h> +#include <linux/nodemask.h> #include <asm/pgalloc.h> #include <asm/page.h> diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c index ad07e3d0d3445e..83d7ec3b7c104e 100644 --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -345,8 +345,6 @@ new_range: numa_domain = 0; } - node_set_online(numa_domain); - if (max_domain < numa_domain) max_domain = numa_domain; @@ -361,14 +359,19 @@ new_range: init_node_data[numa_domain].node_start_pfn + init_node_data[numa_domain].node_spanned_pages; if (shouldstart != (start / PAGE_SIZE)) { - printk(KERN_ERR "WARNING: Hole in node, " - "disabling region start %lx " - "length %lx\n", start, size); - continue; + /* Revert to non-numa for now */ + printk(KERN_ERR + "WARNING: Unexpected node layout: " + "region start %lx length %lx\n", + start, size); + printk(KERN_ERR "NUMA is disabled\n"); + goto err; } init_node_data[numa_domain].node_spanned_pages += size / PAGE_SIZE; } else { + node_set_online(numa_domain); + init_node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; init_node_data[numa_domain].node_spanned_pages = @@ -388,6 +391,14 @@ new_range: node_set_online(i); return 0; +err: + /* Something has gone wrong; revert any setup we've done */ + for_each_node(i) { + node_set_offline(i); + init_node_data[i].node_start_pfn = 0; + init_node_data[i].node_spanned_pages = 0; + } + return -1; } static void __init setup_nonnuma(void) diff --git a/arch/ppc64/xmon/setjmp.S b/arch/ppc64/xmon/setjmp.S new file mode 100644 index 00000000000000..30ee643d557cd8 --- /dev/null +++ b/arch/ppc64/xmon/setjmp.S @@ -0,0 +1,73 @@ +/* + * Copyright (C) 1996 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * NOTE: assert(sizeof(buf) > 184) + */ +#include <asm/processor.h> +#include <asm/ppc_asm.h> + +_GLOBAL(xmon_setjmp) + mflr r0 + std r0,0(r3) + std r1,8(r3) + std r2,16(r3) + mfcr r0 + std r0,24(r3) + std r13,32(r3) + std r14,40(r3) + std r15,48(r3) + std r16,56(r3) + std r17,64(r3) + std r18,72(r3) + std r19,80(r3) + std r20,88(r3) + std r21,96(r3) + std r22,104(r3) + std r23,112(r3) + std r24,120(r3) + std r25,128(r3) + std r26,136(r3) + std r27,144(r3) + std r28,152(r3) + std r29,160(r3) + std r30,168(r3) + std r31,176(r3) + li r3,0 + blr + +_GLOBAL(xmon_longjmp) + cmpdi r4,0 + bne 1f + li r4,1 +1: ld r13,32(r3) + ld r14,40(r3) + ld r15,48(r3) + ld r16,56(r3) + ld r17,64(r3) + ld r18,72(r3) + ld r19,80(r3) + ld r20,88(r3) + ld r21,96(r3) + ld r22,104(r3) + ld r23,112(r3) + ld r24,120(r3) + ld r25,128(r3) + ld r26,136(r3) + ld r27,144(r3) + ld r28,152(r3) + ld r29,160(r3) + ld r30,168(r3) + ld r31,176(r3) + ld r0,24(r3) + mtcrf 56,r0 + ld r0,0(r3) + ld r1,8(r3) + ld r2,16(r3) + mtlr r0 + mr r3,r4 + blr diff --git a/arch/ppc64/xmon/setjmp.c b/arch/ppc64/xmon/setjmp.c deleted file mode 100644 index a3f6135c5669b5..00000000000000 --- a/arch/ppc64/xmon/setjmp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 1996 Paul Mackerras. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * NB this file must be compiled with -O2. - */ - -int -xmon_setjmp(long *buf) /* NOTE: assert(sizeof(buf) > 184) */ -{ - /* XXX should save fp regs as well */ - asm volatile ( - "mflr 0; std 0,0(%0)\n\ - std 1,8(%0)\n\ - std 2,16(%0)\n\ - mfcr 0; std 0,24(%0)\n\ - std 13,32(%0)\n\ - std 14,40(%0)\n\ - std 15,48(%0)\n\ - std 16,56(%0)\n\ - std 17,64(%0)\n\ - std 18,72(%0)\n\ - std 19,80(%0)\n\ - std 20,88(%0)\n\ - std 21,96(%0)\n\ - std 22,104(%0)\n\ - std 23,112(%0)\n\ - std 24,120(%0)\n\ - std 25,128(%0)\n\ - std 26,136(%0)\n\ - std 27,144(%0)\n\ - std 28,152(%0)\n\ - std 29,160(%0)\n\ - std 30,168(%0)\n\ - std 31,176(%0)\n\ - " : : "r" (buf)); - return 0; -} - -void -xmon_longjmp(long *buf, int val) -{ - if (val == 0) - val = 1; - asm volatile ( - "ld 13,32(%0)\n\ - ld 14,40(%0)\n\ - ld 15,48(%0)\n\ - ld 16,56(%0)\n\ - ld 17,64(%0)\n\ - ld 18,72(%0)\n\ - ld 19,80(%0)\n\ - ld 20,88(%0)\n\ - ld 21,96(%0)\n\ - ld 22,104(%0)\n\ - ld 23,112(%0)\n\ - ld 24,120(%0)\n\ - ld 25,128(%0)\n\ - ld 26,136(%0)\n\ - ld 27,144(%0)\n\ - ld 28,152(%0)\n\ - ld 29,160(%0)\n\ - ld 30,168(%0)\n\ - ld 31,176(%0)\n\ - ld 0,24(%0)\n\ - mtcrf 0x38,0\n\ - ld 0,0(%0)\n\ - ld 1,8(%0)\n\ - ld 2,16(%0)\n\ - mtlr 0\n\ - mr 3,%1\n\ - " : : "r" (buf), "r" (val)); -} diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index c53046d52e6c1b..2be270592fb399 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -31,6 +31,7 @@ #include <asm/cputable.h> #include <asm/rtas.h> #include <asm/sstep.h> +#include <asm/bug.h> #include "nonstdio.h" #include "privinst.h" @@ -1319,6 +1320,26 @@ static void backtrace(struct pt_regs *excp) scannl(); } +static void print_bug_trap(struct pt_regs *regs) +{ + struct bug_entry *bug; + unsigned long addr; + + if (regs->msr & MSR_PR) + return; /* not in kernel */ + addr = regs->nip; /* address of trap instruction */ + if (addr < PAGE_OFFSET) + return; + bug = find_bug(regs->nip); + if (bug == NULL) + return; + if (bug->line & BUG_WARNING_TRAP) + return; + + printf("kernel BUG in %s at %s:%d!\n", + bug->function, bug->file, (unsigned int)bug->line); +} + void excprint(struct pt_regs *fp) { unsigned long trap; @@ -1350,6 +1371,9 @@ void excprint(struct pt_regs *fp) printf(" pid = %ld, comm = %s\n", current->pid, current->comm); } + + if (trap == 0x700) + print_bug_trap(fp); } void prregs(struct pt_regs *fp) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 85ecab32be8915..8394c4e5107332 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -367,6 +367,13 @@ config VIRT_TIMER This provides a kernel interface for virtual CPU timers. Default is disabled. +config VIRT_CPU_ACCOUNTING + bool "Base user process accounting on virtual cpu timer" + depends on VIRT_TIMER + help + Select this option to use CPU timer deltas to do user + process accounting. + config APPLDATA_BASE bool "Linux - VM Monitor Stream, base infrastructure" depends on PROC_FS && VIRT_TIMER=y diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 1100c409b5bb7e..03ba5893f17b7f 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -197,12 +197,13 @@ MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>"); #undef MODULE_DESCRIPTION #undef MODULE_AUTHOR -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { - value->tv_usec = (jiffies % HZ) * (1000000L / HZ); - value->tv_sec = jiffies / HZ; + value->tv_usec = cputime % 1000000; + value->tv_sec = cputime / 1000000; } #include "../../../fs/binfmt_elf.c" diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index f72f9ec9be55a5..c0e09b33febe6f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -66,6 +66,27 @@ STACK_SIZE = 1 << STACK_SHIFT * R15 - kernel stack pointer */ + .macro STORE_TIMER lc_offset +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + stpt \lc_offset +#endif + .endm + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .macro UPDATE_VTIME lc_from,lc_to,lc_sum + lm %r10,%r11,\lc_from + sl %r10,\lc_to + sl %r11,\lc_to+4 + bc 3,BASED(0f) + sl %r10,BASED(.Lc_1) +0: al %r10,\lc_sum + al %r11,\lc_sum+4 + bc 12,BASED(1f) + al %r10,BASED(.Lc_1) +1: stm %r10,%r11,\lc_sum + .endm +#endif + .macro SAVE_ALL_BASE savearea stm %r12,%r15,\savearea l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 @@ -118,6 +139,7 @@ STACK_SIZE = 1 << STACK_SHIFT ni __LC_RETURN_PSW+1,0xfd # clear wait state bit .endif lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user + STORE_TIMER __LC_EXIT_TIMER lpsw __LC_RETURN_PSW # back to caller .endm @@ -159,9 +181,21 @@ __critical_start: .globl system_call system_call: + STORE_TIMER __LC_SYNC_ENTER_TIMER +sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 lh %r7,0x8a # get svc number from lowcore +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +sysc_vtime: + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(sysc_do_svc) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +sysc_stime: + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +sysc_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +#endif sysc_do_svc: l %r9,__LC_THREAD_INFO # load pointer to thread_info struct sla %r7,2 # *4 and test for svc 0 @@ -391,10 +425,19 @@ pgm_check_handler: * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ + STORE_TIMER __LC_SYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception bnz BASED(pgm_per) # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f @@ -425,6 +468,14 @@ pgm_per: # pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime2) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime2: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID @@ -442,6 +493,14 @@ pgm_per_std: # pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime3) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime3: +#endif lh %r7,0x8a # get svc number from lowcore l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,__TI_task(%r9) @@ -458,9 +517,18 @@ pgm_svcper: .globl io_int_handler io_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(io_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +io_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area @@ -549,9 +617,18 @@ io_sigpending: .globl ext_int_handler ext_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(ext_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +ext_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # get interruption code @@ -565,8 +642,17 @@ ext_int_handler: .globl mcck_int_handler mcck_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(mcck_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +mcck_no_vtime: +#endif l %r1,BASED(.Ls390_mcck) basr %r14,%r1 # call machine check handler mcck_return: @@ -661,17 +747,47 @@ cleanup_critical: br %r14 cleanup_system_call: - mvc __LC_RETURN_PSW(4),0(%r12) - clc 4(4,%r12),BASED(cleanup_table_system_call) - bne BASED(0f) + mvc __LC_RETURN_PSW(8),0(%r12) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) + bh BASED(0f) + mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) + bhe BASED(cleanup_vtime) +#endif + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) + bh BASED(0f) mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 0: st %r13,__LC_SAVE_AREA+20 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 st %r15,__LC_SAVE_AREA+28 lh %r7,0x8a +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +cleanup_vtime: + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) + bhe BASED(cleanup_stime) + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(cleanup_novtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +cleanup_stime: + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) + bh BASED(cleanup_update) + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +cleanup_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +cleanup_novtime: +#endif mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) la %r12,__LC_RETURN_PSW br %r14 +cleanup_system_call_insn: + .long sysc_saveall + 0x80000000 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .long system_call + 0x80000000 + .long sysc_vtime + 0x80000000 + .long sysc_stime + 0x80000000 + .long sysc_update + 0x80000000 +#endif cleanup_sysc_return: mvc __LC_RETURN_PSW(4),0(%r12) @@ -680,15 +796,23 @@ cleanup_sysc_return: br %r14 cleanup_sysc_leave: - clc 4(4,%r12),BASED(cleanup_sysc_leave_lpsw) + clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) + be BASED(0f) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) be BASED(0f) +#endif mvc __LC_RETURN_PSW(8),SP_PSW(%r15) mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) lm %r0,%r11,SP_R0(%r15) l %r15,SP_R15(%r15) 0: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_lpsw: +cleanup_sysc_leave_insn: +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .long sysc_leave + 14 + 0x80000000 +#endif .long sysc_leave + 10 + 0x80000000 /* @@ -704,6 +828,7 @@ cleanup_sysc_leave_lpsw: .L0x028: .short 0x028 .L0x030: .short 0x030 .L0x038: .short 0x038 +.Lc_1: .long 1 /* * Symbol constants diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index adbe2a5f5f72b0..51527ab8c8f974 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -58,6 +58,21 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) #define BASED(name) name-system_call(%r13) + .macro STORE_TIMER lc_offset +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + stpt \lc_offset +#endif + .endm + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .macro UPDATE_VTIME lc_from,lc_to,lc_sum + lg %r10,\lc_from + slg %r10,\lc_to + alg %r10,\lc_sum + stg %r10,\lc_sum + .endm +#endif + /* * Register usage in interrupt handlers: * R9 - pointer to current task structure @@ -117,6 +132,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) ni __LC_RETURN_PSW+1,0xfd # clear wait state bit .endif lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user + STORE_TIMER __LC_EXIT_TIMER lpswe __LC_RETURN_PSW # back to caller .endm @@ -156,9 +172,21 @@ __critical_start: .globl system_call system_call: + STORE_TIMER __LC_SYNC_ENTER_TIMER +sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +sysc_vtime: + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz sysc_do_svc + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +sysc_stime: + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +sysc_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +#endif sysc_do_svc: lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct slag %r7,%r7,2 # *4 and test for svc 0 @@ -441,10 +469,19 @@ pgm_check_handler: * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ + STORE_TIMER __LC_SYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception jnz pgm_per # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f @@ -475,6 +512,14 @@ pgm_per: # pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime2 + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime2: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID @@ -492,6 +537,14 @@ pgm_per_std: # pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime3 + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime3: +#endif llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) @@ -507,9 +560,18 @@ pgm_svcper: */ .globl io_int_handler io_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz io_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +io_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler @@ -595,9 +657,18 @@ io_sigpending: */ .globl ext_int_handler ext_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz ext_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +ext_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code @@ -609,8 +680,17 @@ ext_int_handler: */ .globl mcck_int_handler mcck_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA+64 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz mcck_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +mcck_no_vtime: +#endif brasl %r14,s390_do_machine_check mcck_return: RESTORE_ALL 0 @@ -700,17 +780,47 @@ cleanup_critical: br %r14 cleanup_system_call: - mvc __LC_RETURN_PSW(8),0(%r12) - clc 8(8,%r12),BASED(cleanup_table_system_call) - jne 0f + mvc __LC_RETURN_PSW(16),0(%r12) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) + jh 0f + mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) + jhe cleanup_vtime +#endif + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) + jh 0f mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 0: stg %r13,__LC_SAVE_AREA+40 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 stg %r15,__LC_SAVE_AREA+56 llgh %r7,__LC_SVC_INT_CODE +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +cleanup_vtime: + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) + jhe cleanup_stime + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz cleanup_novtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +cleanup_stime: + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32) + jh cleanup_update + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +cleanup_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +cleanup_novtime: +#endif mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) la %r12,__LC_RETURN_PSW br %r14 +cleanup_system_call_insn: + .quad sysc_saveall +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .quad system_call + .quad sysc_vtime + .quad sysc_stime + .quad sysc_update +#endif cleanup_sysc_return: mvc __LC_RETURN_PSW(8),0(%r12) @@ -719,15 +829,23 @@ cleanup_sysc_return: br %r14 cleanup_sysc_leave: - clc 8(8,%r12),BASED(cleanup_sysc_leave_lpsw) + clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) + je 0f +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) je 0f +#endif mvc __LC_RETURN_PSW(16),SP_PSW(%r15) mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) lmg %r0,%r11,SP_R0(%r15) lg %r15,SP_R15(%r15) 0: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_lpsw: +cleanup_sysc_leave_insn: +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .quad sysc_leave + 16 +#endif .quad sysc_leave + 12 /* diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 75275fe905b134..59bfceabaebebe 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -71,6 +71,10 @@ asmlinkage void do_softirq(void) local_irq_save(flags); + account_system_vtime(current); + + local_bh_disable(); + if (local_softirq_pending()) { /* Get current stack pointer. */ asm volatile("la %0,0(15)" : "=a" (old)); @@ -93,6 +97,10 @@ asmlinkage void do_softirq(void) __do_softirq(); } + account_system_vtime(current); + + __local_bh_enable(); + local_irq_restore(flags); } diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 2fea300f4b479c..995e2cd38e773f 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -150,28 +150,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); -#ifndef CONFIG_ARCH_S390X - -static inline __u32 -__calculate_ticks(__u64 elapsed) -{ - register_pair rp; - - rp.pair = elapsed >> 1; - asm ("dr %0,%1" : "+d" (rp) : "d" (CLK_TICKS_PER_JIFFY >> 1)); - return rp.subreg.odd; -} - -#else /* CONFIG_ARCH_S390X */ - -static inline __u32 -__calculate_ticks(__u64 elapsed) -{ - return elapsed / CLK_TICKS_PER_JIFFY; -} - -#endif /* CONFIG_ARCH_S390X */ - #ifdef CONFIG_PROFILING #define s390_do_profile(regs) profile_tick(CPU_PROFILING, regs) @@ -187,14 +165,14 @@ __calculate_ticks(__u64 elapsed) void account_ticks(struct pt_regs *regs) { __u64 tmp; - __u32 ticks; + __u32 ticks, xticks; /* Calculate how many ticks have passed. */ if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) return; tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */ - ticks = __calculate_ticks(tmp) + 1; + ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1; S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY * (__u64) ticks; } else if (tmp >= CLK_TICKS_PER_JIFFY) { @@ -216,11 +194,9 @@ void account_ticks(struct pt_regs *regs) */ write_seqlock(&xtime_lock); if (S390_lowcore.jiffy_timer > xtime_cc) { - __u32 xticks; - tmp = S390_lowcore.jiffy_timer - xtime_cc; if (tmp >= 2*CLK_TICKS_PER_JIFFY) { - xticks = __calculate_ticks(tmp); + xticks = __div(tmp, CLK_TICKS_PER_JIFFY); xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY; } else { xticks = 1; @@ -230,14 +206,18 @@ void account_ticks(struct pt_regs *regs) do_timer(regs); } write_sequnlock(&xtime_lock); - while (ticks--) - update_process_times(user_mode(regs)); #else - while (ticks--) { + for (xticks = ticks; xticks > 0; xticks--) do_timer(regs); +#endif + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + account_user_vtime(current); +#else + while (ticks--) update_process_times(user_mode(regs)); - } #endif + s390_do_profile(regs); } diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 02d2179e40828a..63cdfec3ba99b7 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -17,6 +17,8 @@ #include <linux/types.h> #include <linux/timex.h> #include <linux/notifier.h> +#include <linux/kernel_stat.h> +#include <linux/rcupdate.h> #include <asm/s390_ext.h> #include <asm/timer.h> @@ -25,7 +27,95 @@ static ext_int_info_t ext_int_info_timer; DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); -void start_cpu_timer(void) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +/* + * Update process times based on virtual cpu times stored by entry.S + * to the lowcore fields user_timer, system_timer & steal_clock. + */ +void account_user_vtime(struct task_struct *tsk) +{ + cputime_t cputime; + __u64 timer, clock; + int rcu_user_flag; + + timer = S390_lowcore.last_update_timer; + clock = S390_lowcore.last_update_clock; + asm volatile (" STPT %0\n" /* Store current cpu timer value */ + " STCK %1" /* Store current tod clock value */ + : "=m" (S390_lowcore.last_update_timer), + "=m" (S390_lowcore.last_update_clock) ); + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; + S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock; + + cputime = S390_lowcore.user_timer >> 12; + rcu_user_flag = cputime != 0; + S390_lowcore.user_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_user_time(tsk, cputime); + + cputime = S390_lowcore.system_timer >> 12; + S390_lowcore.system_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_system_time(tsk, HARDIRQ_OFFSET, cputime); + + cputime = S390_lowcore.steal_clock; + if ((__s64) cputime > 0) { + cputime >>= 12; + S390_lowcore.steal_clock -= cputime << 12; + account_steal_time(tsk, cputime); + } + + run_local_timers(); + if (rcu_pending(smp_processor_id())) + rcu_check_callbacks(smp_processor_id(), rcu_user_flag); + scheduler_tick(); +} + +/* + * Update process times based on virtual cpu times stored by entry.S + * to the lowcore fields user_timer, system_timer & steal_clock. + */ +void account_system_vtime(struct task_struct *tsk) +{ + cputime_t cputime; + __u64 timer; + + timer = S390_lowcore.last_update_timer; + asm volatile (" STPT %0" /* Store current cpu timer value */ + : "=m" (S390_lowcore.last_update_timer) ); + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; + + cputime = S390_lowcore.system_timer >> 12; + S390_lowcore.system_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_system_time(tsk, 0, cputime); +} + +static inline void set_vtimer(__u64 expires) +{ + __u64 timer; + + asm volatile (" STPT %0\n" /* Store current cpu timer value */ + " SPT %1" /* Set new value immediatly afterwards */ + : "=m" (timer) : "m" (expires) ); + S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; + S390_lowcore.last_update_timer = expires; + + /* store expire time for this CPU timer */ + per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; +} +#else +static inline void set_vtimer(__u64 expires) +{ + S390_lowcore.last_update_timer = expires; + asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); + + /* store expire time for this CPU timer */ + per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; +} +#endif + +static void start_cpu_timer(void) { struct vtimer_queue *vt_list; @@ -33,7 +123,7 @@ void start_cpu_timer(void) set_vtimer(vt_list->idle); } -void stop_cpu_timer(void) +static void stop_cpu_timer(void) { __u64 done; struct vtimer_queue *vt_list; @@ -71,19 +161,11 @@ void stop_cpu_timer(void) set_vtimer(VTIMER_MAX_SLICE); } -void set_vtimer(__u64 expires) -{ - asm volatile ("SPT %0" : : "m" (expires)); - - /* store expire time for this CPU timer */ - per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; -} - /* * Sorted add to a list. List is linear searched until first bigger * element is found. */ -void list_add_sorted(struct vtimer_list *timer, struct list_head *head) +static void list_add_sorted(struct vtimer_list *timer, struct list_head *head) { struct vtimer_list *event; @@ -429,11 +511,12 @@ void init_cpu_vtimer(void) { struct vtimer_queue *vt_list; unsigned long cr0; - __u64 timer; /* kick the virtual timer */ - timer = VTIMER_MAX_SLICE; - asm volatile ("SPT %0" : : "m" (timer)); + S390_lowcore.exit_timer = VTIMER_MAX_SLICE; + S390_lowcore.last_update_timer = VTIMER_MAX_SLICE; + asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); + asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); __ctl_store(cr0, 0, 0); cr0 |= 0x400; __ctl_load(cr0, 0, 0); diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index 64d547853b48c0..1afe88f6abc082 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -49,7 +49,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } /* @@ -95,7 +97,7 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file) set_fs(KERNEL_DS); has_dumped = 1; current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(current->comm)); + strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm)); dump.signal = signr; dump_thread(regs, &dump); @@ -246,10 +248,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* Fuck me plenty... */ + down_write(¤t->mm->mmap_sem); error = do_brk(N_TXTADDR(ex), ex.a_text); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text, &pos); + down_write(¤t->mm->mmap_sem); error = do_brk(N_DATADDR(ex), ex.a_data); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -257,8 +263,10 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (N_MAGIC(ex) == OMAGIC) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); } else { @@ -272,7 +280,9 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(0, ex.a_text+ex.a_data); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -389,7 +399,9 @@ static int load_aout32_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { + down_write(¤t->mm->mmap_sem); error = do_brk(start_addr + len, bss - len); + up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr + len) goto out; diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index c13eaf0307588f..a1a12d2aa3530e 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -132,10 +132,12 @@ struct elf_prpsinfo32 #include <linux/time.h> -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 06ba2aca73a54c..f399b64a137c4f 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -68,6 +68,8 @@ config MODE_SKAS to CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this option will shrink the UML binary slightly. +source "arch/um/Kconfig_arch" + config NET bool "Networking support" help @@ -283,7 +285,10 @@ if BROKEN endif config INPUT - bool + bool "Dummy option" + depends BROKEN default n + help + This is a dummy option to get rid of warnings. source "arch/um/Kconfig.debug" diff --git a/arch/um/Kconfig_arch b/arch/um/Kconfig_arch new file mode 100644 index 00000000000000..2f5f053bc46195 --- /dev/null +++ b/arch/um/Kconfig_arch @@ -0,0 +1,16 @@ +config 64_BIT + bool + default n + +config TOP_ADDR + hex + default 0xc0000000 if !HOST_2G_2G + default 0x80000000 if HOST_2G_2G + +config 3_LEVEL_PGTABLES + bool "Three-level pagetables" + default n + help + Three-level pagetables will let UML have more than 4G of physical + memory. All the memory that can't be mapped directly will be treated + as high memory. diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char index 7a933d1b5d5bd2..fa34a9698586a1 100644 --- a/arch/um/Kconfig_char +++ b/arch/um/Kconfig_char @@ -23,15 +23,6 @@ config SSL Unless you have a specific reason for disabling this, say Y. -config FD_CHAN - bool "file descriptor channel support" - help - This option enables support for attaching UML consoles and serial - lines to already set up file descriptors. Generally, the main - console is attached to file descriptors 0 and 1 (stdin and stdout), - so it would be wise to leave this enabled unless you intend to - attach it to some other host device. - config NULL_CHAN bool "null channel support" help @@ -80,7 +71,7 @@ config XTERM_CHAN config NOCONFIG_CHAN bool - default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && FD_CHAN && NULL_CHAN) + default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && NULL_CHAN) config CON_ZERO_CHAN string "Default main console channel initialization" diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386 new file mode 100644 index 00000000000000..e3d956db3daad5 --- /dev/null +++ b/arch/um/Kconfig_i386 @@ -0,0 +1,20 @@ +config 64_BIT + bool + default n + +config TOP_ADDR + hex + default 0xc0000000 if !HOST_2G_2G + default 0x80000000 if HOST_2G_2G + +config 3_LEVEL_PGTABLES + bool "Three-level pagetables" + default n + help + Three-level pagetables will let UML have more than 4G of physical + memory. All the memory that can't be mapped directly will be treated + as high memory. + +config ARCH_HAS_SC_SIGNALS + bool + default y diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64 new file mode 100644 index 00000000000000..0d3d05cab5b7d7 --- /dev/null +++ b/arch/um/Kconfig_x86_64 @@ -0,0 +1,11 @@ +config 64_BIT + bool + default y + +config 3_LEVEL_PGTABLES + bool + default y + +config ARCH_HAS_SC_SIGNALS + bool + default n diff --git a/arch/um/Makefile b/arch/um/Makefile index b8371a95849a05..a21b5d1da07fa9 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -12,14 +12,17 @@ SHELL := /bin/bash filechk_gen_header = $< core-y += $(ARCH_DIR)/kernel/ \ - $(ARCH_DIR)/drivers/ \ - $(ARCH_DIR)/sys-$(SUBARCH)/ + $(ARCH_DIR)/drivers/ + +clean-dirs := sys-$(SUBARCH) # Have to precede the include because the included Makefiles reference them. SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ - arch-signal.h module.h + arch-signal.h module.h vm-flags.h SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) +CLEAN_FILES += $(ARCH_SYMLINKS) + ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h @@ -38,6 +41,9 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) +core-y += $(SUBARCH_CORE) +libs-y += $(SUBARCH_LIBS) + # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common # in CFLAGS. Otherwise, it would cause ld to complain about the two different @@ -77,6 +83,11 @@ define archhelp echo ' find in the kernel root.' endef +$(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch) + +CLEAN_FILES += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h \ + $(TOPDIR)/$(ARCH_DIR)/os + prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \ $(ARCH_DIR)/kernel/vmlinux.lds.S @@ -137,7 +148,8 @@ USER_CFLAGS += -D_GNU_SOURCE #When cleaning we don't include .config, so we don't include #TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ - $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h + $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \ + $(ARCH_DIR)/util/mk_constants $(ARCH_DIR)/util/mk_task MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \ $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 7c7d008478b691..97b223bfa78e57 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -1,8 +1,6 @@ -ifeq ($(CONFIG_HOST_2G_2G), y) -TOP_ADDR := 0x80000000 -else -TOP_ADDR := 0xc0000000 -endif +SUBARCH_CORE := arch/um/sys-i386/ + +TOP_ADDR := $(CONFIG_TOP_ADDR) ifeq ($(CONFIG_MODE_SKAS),y) ifneq ($(CONFIG_MODE_TT),y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 705df73454c821..9638cac9316509 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -1 +1,36 @@ +# Copyright 2003 - 2004 Pathscale, Inc +# Released under the GPL + +SUBARCH_LIBS := arch/um/sys-x86_64/ +START := 0x60000000 + +CFLAGS += -U__$(SUBARCH)__ -fno-builtin ARCH_USER_CFLAGS := -D__x86_64__ + +ELF_ARCH := i386:x86-64 +ELF_FORMAT := elf64-x86-64 + +SYS_UTIL_DIR := $(ARCH_DIR)/sys-x86_64/util +SYS_DIR := $(ARCH_DIR)/include/sysdep-x86_64 + +SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h + +prepare: $(SYS_HEADERS) + +$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc + $(call filechk,gen_header) + +$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread + $(call filechk,gen_header) + +$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +CLEAN_FILES += $(SYS_HEADERS) + +LIBC_DIR := /usr/lib64 + +export LIBC_DIR diff --git a/arch/um/defconfig b/arch/um/defconfig index 708878e397a918..66f902a9907b10 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -17,6 +17,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_MODE_TT=y CONFIG_MODE_SKAS=y +# CONFIG_3_LEVEL_PGTABLES is not set CONFIG_NET=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m @@ -91,13 +92,12 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_STDERR_CONSOLE=y CONFIG_STDIO_CONSOLE=y CONFIG_SSL=y -CONFIG_FD_CHAN=y CONFIG_NULL_CHAN=y CONFIG_PORT_CHAN=y CONFIG_PTY_CHAN=y CONFIG_TTY_CHAN=y CONFIG_XTERM_CHAN=y -# CONFIG_NOCONFIG_CHAN is not set +CONFIG_NOCONFIG_CHAN=y CONFIG_CON_ZERO_CHAN="fd:0,fd:1" CONFIG_CON_CHAN="xterm" CONFIG_SSL_CHAN="pty" diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 3a3ac38017f4fc..e94da95ffdcfa8 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -20,7 +20,7 @@ ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o harddog-objs := harddog_kern.o harddog_user.o -obj-y := stdio_console.o $(CHAN_OBJS) +obj-y := stdio_console.o fd.o $(CHAN_OBJS) obj-$(CONFIG_SSL) += ssl.o obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o @@ -34,7 +34,6 @@ obj-$(CONFIG_MCONSOLE) += mconsole.o obj-$(CONFIG_MMAPPER) += mmapper_kern.o obj-$(CONFIG_BLK_DEV_UBD) += ubd.o obj-$(CONFIG_HOSTAUDIO) += hostaudio.o -obj-$(CONFIG_FD_CHAN) += fd.o obj-$(CONFIG_NULL_CHAN) += null.o obj-$(CONFIG_PORT_CHAN) += port.o obj-$(CONFIG_PTY_CHAN) += pty.o diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index bf4bb736e6afac..f30ae1b0bcc04b 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -399,11 +399,7 @@ struct chan_type { }; struct chan_type chan_table[] = { -#ifdef CONFIG_FD_CHAN { "fd", &fd_ops }, -#else - { "fd", ¬_configged_ops }, -#endif #ifdef CONFIG_NULL_CHAN { "null", &null_ops }, diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 19517312aa863d..4fcbe8b1b77e11 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -21,11 +21,12 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg); extern int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, __u32 *version_out, char **backing_file_out, time_t *mtime_out, - __u64 *size_out, int *sectorsize_out, + unsigned long long *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out); extern int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, int alignment, long long *size); + int sectorsize, int alignment, + unsigned long long *size); extern void cow_sizes(int version, __u64 size, int sectorsize, int align, int bitmap_offset, unsigned long *bitmap_len_out, diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index ce251f08305fe6..c83fc5d68936d1 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h @@ -23,12 +23,12 @@ static inline char *cow_strdup(char *str) return(uml_strdup(str)); } -static inline int cow_seek_file(int fd, __u64 offset) +static inline int cow_seek_file(int fd, unsigned long long offset) { return(os_seek_file(fd, offset)); } -static inline int cow_file_size(char *file, __u64 *size_out) +static inline int cow_file_size(char *file, unsigned long long *size_out) { return(os_file_size(file, size_out)); } diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 122664b6b16ada..c43425c1ee1f25 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -159,7 +159,7 @@ static int absolutize(char *to, int size, char *from) } int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, int alignment, long long *size) + int sectorsize, int alignment, unsigned long long *size) { struct cow_header_v3 *header; unsigned long modtime; @@ -236,7 +236,7 @@ int file_reader(__u64 offset, char *buf, int len, void *arg) int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, __u32 *version_out, char **backing_file_out, - time_t *mtime_out, __u64 *size_out, + time_t *mtime_out, unsigned long long *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out) { @@ -329,7 +329,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out) { - __u64 size, offset; + unsigned long long size, offset; char zero = 0; int err; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 73d6e3e0af51d8..baa9f7f46bc30a 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -198,6 +198,37 @@ int line_ioctl(struct tty_struct *tty, struct file * file, ret = 0; switch(cmd) { +#ifdef TIOCGETP + case TIOCGETP: + case TIOCSETP: + case TIOCSETN: +#endif +#ifdef TIOCGETC + case TIOCGETC: + case TIOCSETC: +#endif +#ifdef TIOCGLTC + case TIOCGLTC: + case TIOCSLTC: +#endif + case TCGETS: + case TCSETSF: + case TCSETSW: + case TCSETS: + case TCGETA: + case TCSETAF: + case TCSETAW: + case TCSETA: + case TCXONC: + case TCFLSH: + case TIOCOUTQ: + case TIOCINQ: + case TIOCGLCKTRMIOS: + case TIOCSLCKTRMIOS: + case TIOCPKT: + case TIOCGSOFTCAR: + case TIOCSSOFTCAR: + return -ENOIOCTLCMD; #if 0 case TCwhatever: /* do something */ diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 0c87589c078134..ecbabd351c6d3f 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -73,11 +73,12 @@ DECLARE_WORK(mconsole_work, mc_work_proc, NULL); static irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - int fd; + /* long to avoid size mismatch warnings from gcc */ + long fd; struct mconsole_entry *new; struct mc_request req; - fd = (int) dev_id; + fd = (long) dev_id; while (mconsole_get_request(fd, &req)){ if(req.cmd->context == MCONSOLE_INTR) (*req.cmd->handler)(&req); @@ -457,7 +458,9 @@ static char *notify_socket = NULL; int mconsole_init(void) { - int err, sock; + /* long to avoid size mismatch warnings from gcc */ + long sock; + int err; char file[256]; if(umid_file_name("mconsole", file, sizeof(file))) return(-1); @@ -496,7 +499,7 @@ int mconsole_init(void) __initcall(mconsole_init); -static int write_proc_mconsole(struct file *file, const char *buffer, +static int write_proc_mconsole(struct file *file, const char __user *buffer, unsigned long count, void *data) { char *buf; diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 1546b0429ce22e..a63231dffe058e 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -8,6 +8,8 @@ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com * */ + +#include <linux/types.h> #include <linux/kdev_t.h> #include <linux/time.h> #include <linux/devfs_fs_kernel.h> diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index f05c2b7514f212..17d85730086b81 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -172,7 +172,7 @@ static struct proc_dir_entry *proc_ide = NULL; static void make_proc_ide(void) { - proc_ide_root = proc_mkdir("ide", 0); + proc_ide_root = proc_mkdir("ide", NULL); proc_ide = proc_mkdir("ide0", proc_ide_root); } @@ -1087,7 +1087,7 @@ static void do_ubd_request(request_queue_t *q) static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct hd_geometry *loc = (struct hd_geometry *) arg; + struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; struct ubd *dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, @@ -1108,19 +1108,19 @@ static int ubd_ioctl(struct inode * inode, struct file * file, case HDIO_GET_IDENTITY: ubd_id.cyls = dev->size / (128 * 32 * 512); - if(copy_to_user((char *) arg, (char *) &ubd_id, + if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); return(0); case CDROMVOLREAD: - if(copy_from_user(&volume, (char *) arg, sizeof(volume))) + if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) return(-EFAULT); volume.channel0 = 255; volume.channel1 = 255; volume.channel2 = 255; volume.channel3 = 255; - if(copy_to_user((char *) arg, &volume, sizeof(volume))) + if(copy_to_user((char __user *) arg, &volume, sizeof(volume))) return(-EFAULT); return(0); } diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index 882d2f7c1ee72a..c6d8ffa5641b52 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -107,7 +107,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int *create_cow_out) { time_t mtime; - __u64 size; + unsigned long long size; __u32 version, align; char *backing_file; int fd, err, sectorsize, same, mode = 0644; diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 07af218574fdf3..5af9157ff54fb0 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -6,7 +6,7 @@ #ifndef __PROCESS_H__ #define __PROCESS_H__ -#include <asm/sigcontext.h> +#include <signal.h> extern void sig_handler(int sig, struct sigcontext sc); extern void alarm_handler(int sig, struct sigcontext sc); diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h new file mode 100644 index 00000000000000..87899df0072f81 --- /dev/null +++ b/arch/um/include/registers.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Licensed under the GPL + */ + +#ifndef __REGISTERS_H +#define __REGISTERS_H + +#include "sysdep/ptrace.h" + +extern void init_thread_registers(union uml_pt_regs *to); +extern void save_registers(int pid, union uml_pt_regs *regs); +extern void restore_registers(int pid, union uml_pt_regs *regs); +extern void init_registers(int pid); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h index fc8e4f314ca6f1..dc126e5e25ac50 100644 --- a/arch/um/include/sysdep-i386/ptrace.h +++ b/arch/um/include/sysdep-i386/ptrace.h @@ -9,11 +9,52 @@ #include "uml-config.h" #ifdef UML_CONFIG_MODE_TT -#include "ptrace-tt.h" +#include "sysdep/sc.h" #endif #ifdef UML_CONFIG_MODE_SKAS -#include "ptrace-skas.h" + +/* syscall emulation path in ptrace */ + +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif + +void set_using_sysemu(int value); +int get_using_sysemu(void); +extern int sysemu_supported; + +#include "skas_ptregs.h" + +#define HOST_FRAME_SIZE 17 + +#define REGS_IP(r) ((r)[HOST_IP]) +#define REGS_SP(r) ((r)[HOST_SP]) +#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) +#define REGS_EAX(r) ((r)[HOST_EAX]) +#define REGS_EBX(r) ((r)[HOST_EBX]) +#define REGS_ECX(r) ((r)[HOST_ECX]) +#define REGS_EDX(r) ((r)[HOST_EDX]) +#define REGS_ESI(r) ((r)[HOST_ESI]) +#define REGS_EDI(r) ((r)[HOST_EDI]) +#define REGS_EBP(r) ((r)[HOST_EBP]) +#define REGS_CS(r) ((r)[HOST_CS]) +#define REGS_SS(r) ((r)[HOST_SS]) +#define REGS_DS(r) ((r)[HOST_DS]) +#define REGS_ES(r) ((r)[HOST_ES]) +#define REGS_FS(r) ((r)[HOST_FS]) +#define REGS_GS(r) ((r)[HOST_GS]) + +#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) + +#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) + +#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) + +#define REGS_FAULT_ADDR(r) ((r)->fault_addr) + +#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) + #endif #ifndef PTRACE_SYSEMU_SINGLESTEP #define PTRACE_SYSEMU_SINGLESTEP 32 diff --git a/arch/um/kernel/tt/include/ptrace-tt.h b/arch/um/include/sysdep-i386/signal.h index 3084c1db867863..b1e1f7a7749992 100644 --- a/arch/um/kernel/tt/include/ptrace-tt.h +++ b/arch/um/include/sysdep-i386/signal.h @@ -1,16 +1,15 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2004 PathScale, Inc * Licensed under the GPL */ -#ifndef __PTRACE_TT_H -#define __PTRACE_TT_H +#ifndef __I386_SIGNAL_H_ +#define __I386_SIGNAL_H_ -#include "uml-config.h" +#include <signal.h> -#ifdef UML_CONFIG_MODE_TT -#include "sysdep/sc.h" -#endif +#define ARCH_GET_SIGCONTEXT(sc, sig) \ + do sc = (struct sigcontext *) (&sig + 1); while(0) #endif diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h index 47687dcf2b51be..36d9beec431b8b 100644 --- a/arch/um/include/sysdep-i386/syscalls.h +++ b/arch/um/include/sysdep-i386/syscalls.h @@ -8,11 +8,70 @@ typedef long syscall_handler_t(struct pt_regs); +/* Not declared on x86, incompatible declarations on x86_64, so these have + * to go here rather than in sys_call_table.c + */ +extern syscall_handler_t sys_ptrace; +extern syscall_handler_t sys_rt_sigaction; + +extern syscall_handler_t old_mmap_i386; + #define EXECUTE_SYSCALL(syscall, regs) \ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) +extern long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); + #define ARCH_SYSCALLS \ + [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \ + [ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_oldstat ] = (syscall_handler_t *) sys_stat, \ + [ __NR_umount ] = (syscall_handler_t *) sys_oldumount, \ + [ __NR_stime ] = um_stime, \ + [ __NR_oldfstat ] = (syscall_handler_t *) sys_fstat, \ + [ __NR_stty ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_gtty ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_nice ] = (syscall_handler_t *) sys_nice, \ + [ __NR_ftime ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_prof ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_signal ] = (syscall_handler_t *) sys_signal, \ + [ __NR_lock ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_mpx ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_ulimit ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_oldolduname ] = (syscall_handler_t *) sys_olduname, \ + [ __NR_sigaction ] = (syscall_handler_t *) sys_sigaction, \ + [ __NR_sgetmask ] = (syscall_handler_t *) sys_sgetmask, \ + [ __NR_ssetmask ] = (syscall_handler_t *) sys_ssetmask, \ + [ __NR_sigsuspend ] = (syscall_handler_t *) sys_sigsuspend, \ + [ __NR_sigpending ] = (syscall_handler_t *) sys_sigpending, \ + [ __NR_oldlstat ] = (syscall_handler_t *) sys_lstat, \ + [ __NR_readdir ] = old_readdir, \ + [ __NR_profil ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_socketcall ] = (syscall_handler_t *) sys_socketcall, \ + [ __NR_olduname ] = (syscall_handler_t *) sys_uname, \ + [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_idle ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_ipc ] = (syscall_handler_t *) sys_ipc, \ + [ __NR_sigreturn ] = (syscall_handler_t *) sys_sigreturn, \ + [ __NR_sigprocmask ] = (syscall_handler_t *) sys_sigprocmask, \ + [ __NR_bdflush ] = (syscall_handler_t *) sys_bdflush, \ + [ __NR__llseek ] = (syscall_handler_t *) sys_llseek, \ + [ __NR__newselect ] = (syscall_handler_t *) sys_select, \ + [ __NR_vm86 ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \ + [ __NR_ugetrlimit ] = (syscall_handler_t *) sys_getrlimit, \ + [ __NR_mmap2 ] = (syscall_handler_t *) sys_mmap2, \ + [ __NR_truncate64 ] = (syscall_handler_t *) sys_truncate64, \ + [ __NR_ftruncate64 ] = (syscall_handler_t *) sys_ftruncate64, \ + [ __NR_stat64 ] = (syscall_handler_t *) sys_stat64, \ + [ __NR_lstat64 ] = (syscall_handler_t *) sys_lstat64, \ + [ __NR_fstat64 ] = (syscall_handler_t *) sys_fstat64, \ + [ __NR_fcntl64 ] = (syscall_handler_t *) sys_fcntl64, \ + [ __NR_sendfile64 ] = (syscall_handler_t *) sys_sendfile64, \ + [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, \ + [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, \ + [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \ [ __NR_select ] = (syscall_handler_t *) old_select, \ [ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \ @@ -38,11 +97,19 @@ typedef long syscall_handler_t(struct pt_regs); [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \ [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \ [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \ - [ 222 ] = (syscall_handler_t *) sys_ni_syscall, + [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \ + [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \ + [ 251 ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \ + [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \ + [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, /* 222 doesn't yet have a name in include/asm-i386/unistd.h */ -#define LAST_ARCH_SYSCALL 222 +#define LAST_ARCH_SYSCALL __NR_vserver /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/arch/um/include/sysdep-ppc/syscalls.h b/arch/um/include/sysdep-ppc/syscalls.h index d703d0d12c7e24..679df351e19b6b 100644 --- a/arch/um/include/sysdep-ppc/syscalls.h +++ b/arch/um/include/sysdep-ppc/syscalls.h @@ -34,9 +34,12 @@ int old_mmap(unsigned long addr, unsigned long len, [ __NR_multiplexer ] = sys_ni_syscall, \ [ __NR_mmap ] = old_mmap, \ [ __NR_madvise ] = sys_madvise, \ - [ __NR_mincore ] = sys_mincore, + [ __NR_mincore ] = sys_mincore, \ + [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \ + [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, -#define LAST_ARCH_SYSCALL __NR_mincore +#define LAST_ARCH_SYSCALL __NR_fadvise64 /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h new file mode 100644 index 00000000000000..d57aa7f3130ea6 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/checksum.h @@ -0,0 +1,151 @@ +/* + * Licensed under the GPL + */ + +#ifndef __UM_SYSDEP_CHECKSUM_H +#define __UM_SYSDEP_CHECKSUM_H + +#include "linux/string.h" +#include "linux/in6.h" +#include "asm/uaccess.h" + +extern unsigned int csum_partial_copy_from(const char *src, char *dst, int len, + int sum, int *err_ptr); +extern unsigned csum_partial(const unsigned char *buff, unsigned len, + unsigned sum); + +/* + * Note: when you get a NULL pointer exception here this means someone + * passed in an incorrect kernel address to one of these functions. + * + * If you use these functions directly please don't forget the + * verify_area(). + */ + +static __inline__ +unsigned int csum_partial_copy_nocheck(const char *src, char *dst, + int len, int sum) +{ + memcpy(dst, src, len); + return(csum_partial(dst, len, sum)); +} + +static __inline__ +unsigned int csum_partial_copy_from_user(const char *src, char *dst, + int len, int sum, int *err_ptr) +{ + return csum_partial_copy_from(src, dst, len, sum, err_ptr); +} + +/** + * csum_fold - Fold and invert a 32bit checksum. + * sum: 32bit unfolded sum + * + * Fold a 32bit running checksum to 16bit and invert it. This is usually + * the last step before putting a checksum into a packet. + * Make sure not to mix with 64bit checksums. + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + __asm__( + " addl %1,%0\n" + " adcl $0xffff,%0" + : "=r" (sum) + : "r" (sum << 16), "0" (sum & 0xffff0000) + ); + return (~sum) >> 16; +} + +/** + * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum. + * @saddr: source address + * @daddr: destination address + * @len: length of packet + * @proto: ip protocol of packet + * @sum: initial sum to be added in (32bit unfolded) + * + * Returns the pseudo header checksum the input data. Result is + * 32bit unfolded. + */ +static inline unsigned long +csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len, + unsigned short proto, unsigned int sum) +{ + asm(" addl %1, %0\n" + " adcl %2, %0\n" + " adcl %3, %0\n" + " adcl $0, %0\n" + : "=r" (sum) + : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum)); + return sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/** + * ip_fast_csum - Compute the IPv4 header checksum efficiently. + * iph: ipv4 header + * ihl: length of header / 4 + */ +static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) +{ + unsigned int sum; + + asm( " movl (%1), %0\n" + " subl $4, %2\n" + " jbe 2f\n" + " addl 4(%1), %0\n" + " adcl 8(%1), %0\n" + " adcl 12(%1), %0\n" + "1: adcl 16(%1), %0\n" + " lea 4(%1), %1\n" + " decl %2\n" + " jne 1b\n" + " adcl $0, %0\n" + " movl %0, %2\n" + " shrl $16, %0\n" + " addw %w2, %w0\n" + " adcl $0, %0\n" + " notl %0\n" + "2:" + /* Since the input registers which are loaded with iph and ipl + are modified, we must also specify them as outputs, or gcc + will assume they contain their original values. */ + : "=r" (sum), "=r" (iph), "=r" (ihl) + : "1" (iph), "2" (ihl) + : "memory"); + return(sum); +} + +static inline unsigned add32_with_carry(unsigned a, unsigned b) +{ + asm("addl %2,%0\n\t" + "adcl $0,%0" + : "=r" (a) + : "0" (a), "r" (b)); + return a; +} + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h new file mode 100644 index 00000000000000..64b1cc16752df5 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -0,0 +1,260 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_PTRACE_H +#define __SYSDEP_X86_64_PTRACE_H + +#include "uml-config.h" + +#ifdef UML_CONFIG_MODE_TT +#include "sysdep/sc.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS +#include "skas_ptregs.h" + +#define REGS_IP(r) ((r)[HOST_IP]) +#define REGS_SP(r) ((r)[HOST_SP]) + +#define REGS_RBX(r) ((r)[HOST_RBX]) +#define REGS_RCX(r) ((r)[HOST_RCX]) +#define REGS_RDX(r) ((r)[HOST_RDX]) +#define REGS_RSI(r) ((r)[HOST_RSI]) +#define REGS_RDI(r) ((r)[HOST_RDI]) +#define REGS_RBP(r) ((r)[HOST_RBP]) +#define REGS_RAX(r) ((r)[HOST_RAX]) +#define REGS_R8(r) ((r)[HOST_R8]) +#define REGS_R9(r) ((r)[HOST_R9]) +#define REGS_R10(r) ((r)[HOST_R10]) +#define REGS_R11(r) ((r)[HOST_R11]) +#define REGS_R12(r) ((r)[HOST_R12]) +#define REGS_R13(r) ((r)[HOST_R13]) +#define REGS_R14(r) ((r)[HOST_R14]) +#define REGS_R15(r) ((r)[HOST_R15]) +#define REGS_CS(r) ((r)[HOST_CS]) +#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) +#define REGS_SS(r) ((r)[HOST_SS]) + +#define HOST_FS_BASE 21 +#define HOST_GS_BASE 22 +#define HOST_DS 23 +#define HOST_ES 24 +#define HOST_FS 25 +#define HOST_GS 26 + +#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE]) +#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE]) +#define REGS_DS(r) ((r)[HOST_DS]) +#define REGS_ES(r) ((r)[HOST_ES]) +#define REGS_FS(r) ((r)[HOST_FS]) +#define REGS_GS(r) ((r)[HOST_GS]) + +#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX]) + +#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res) + +#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) + +#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) + +#define REGS_FAULT_ADDR(r) ((r)->fault_addr) + +#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) + +#define REGS_TRAP(r) ((r)->trap_type) + +#define REGS_ERR(r) ((r)->fault_type) + +#endif + +#include "choose-mode.h" + +/* XXX */ +union uml_pt_regs { +#ifdef UML_CONFIG_MODE_TT + struct tt_regs { + long syscall; + unsigned long orig_rax; + void *sc; + } tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { + /* XXX */ + unsigned long regs[27]; + unsigned long fp[65]; + unsigned long fault_addr; + unsigned long fault_type; + unsigned long trap_type; + long syscall; + int is_user; + } skas; +#endif +}; + +#define EMPTY_UML_PT_REGS { } + +/* XXX */ +extern int mode_tt; + +#define UPT_RBX(r) CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs)) +#define UPT_RCX(r) CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs)) +#define UPT_RDX(r) CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs)) +#define UPT_RSI(r) CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs)) +#define UPT_RDI(r) CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs)) +#define UPT_RBP(r) CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs)) +#define UPT_RAX(r) CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs)) +#define UPT_R8(r) CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs)) +#define UPT_R9(r) CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs)) +#define UPT_R10(r) CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs)) +#define UPT_R11(r) CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs)) +#define UPT_R12(r) CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs)) +#define UPT_R13(r) CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs)) +#define UPT_R14(r) CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) +#define UPT_R15(r) CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) +#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_FS(r) CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) +#define UPT_GS(r) CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) +#define UPT_DS(r) CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) +#define UPT_ES(r) CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) +#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_ORIG_RAX(r) \ + CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) + +#define UPT_IP(r) CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) +#define UPT_SP(r) CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) + +#define UPT_EFLAGS(r) \ + 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) + +extern int user_context(unsigned long sp); + +#define UPT_IS_USER(r) \ + CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) + +#define UPT_SYSCALL_ARG1(r) UPT_RDI(r) +#define UPT_SYSCALL_ARG2(r) UPT_RSI(r) +#define UPT_SYSCALL_ARG3(r) UPT_RDX(r) +#define UPT_SYSCALL_ARG4(r) UPT_R10(r) +#define UPT_SYSCALL_ARG5(r) UPT_R8(r) +#define UPT_SYSCALL_ARG6(r) UPT_R9(r) + +struct syscall_args { + unsigned long args[6]; +}; + +#define SYSCALL_ARGS(r) ((struct syscall_args) \ + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) + +#define UPT_REG(regs, reg) \ + ({ unsigned long val; \ + switch(reg){ \ + case R8: val = UPT_R8(regs); break; \ + case R9: val = UPT_R9(regs); break; \ + case R10: val = UPT_R10(regs); break; \ + case R11: val = UPT_R11(regs); break; \ + case R12: val = UPT_R12(regs); break; \ + case R13: val = UPT_R13(regs); break; \ + case R14: val = UPT_R14(regs); break; \ + case R15: val = UPT_R15(regs); break; \ + case RIP: val = UPT_IP(regs); break; \ + case RSP: val = UPT_SP(regs); break; \ + case RAX: val = UPT_RAX(regs); break; \ + case RBX: val = UPT_RBX(regs); break; \ + case RCX: val = UPT_RCX(regs); break; \ + case RDX: val = UPT_RDX(regs); break; \ + case RSI: val = UPT_RSI(regs); break; \ + case RDI: val = UPT_RDI(regs); break; \ + case RBP: val = UPT_RBP(regs); break; \ + case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ + case CS: val = UPT_CS(regs); break; \ + case DS: val = UPT_DS(regs); break; \ + case ES: val = UPT_ES(regs); break; \ + case FS: val = UPT_FS(regs); break; \ + case GS: val = UPT_GS(regs); break; \ + case EFLAGS: val = UPT_EFLAGS(regs); break; \ + default : \ + panic("Bad register in UPT_REG : %d\n", reg); \ + val = -1; \ + } \ + val; \ + }) + + +#define UPT_SET(regs, reg, val) \ + ({ unsigned long 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; \ + default : \ + panic("Bad register in UPT_SET : %d\n", reg); \ + break; \ + } \ + val; \ + }) + +#define UPT_SET_SYSCALL_RETURN(r, res) \ + CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ + REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) + +#define UPT_RESTART_SYSCALL(r) \ + CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ + REGS_RESTART_SYSCALL((r)->skas.regs)) + +#define UPT_SEGV_IS_FIXABLE(r) \ + CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ + REGS_SEGV_IS_FIXABLE(&r->skas)) + +#define UPT_FAULT_ADDR(r) \ + CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) + +#define UPT_FAULT_WRITE(r) \ + CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas)) + +#define UPT_TRAP(r) CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas)) +#define UPT_ERR(r) CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas)) + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h new file mode 100644 index 00000000000000..a7bb52bbe6240a --- /dev/null +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -0,0 +1,69 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_PTRACE_USER_H__ +#define __SYSDEP_X86_64_PTRACE_USER_H__ + +#define __FRAME_OFFSETS +#include <asm/ptrace.h> +#undef __FRAME_OFFSETS + +#define PT_INDEX(off) ((off) / sizeof(unsigned long)) + +#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)]) +#define PT_SYSCALL_NR_OFFSET (ORIG_RAX) + +#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)]) +#define PT_SYSCALL_ARG1_OFFSET (RDI) + +#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)]) +#define PT_SYSCALL_ARG2_OFFSET (RSI) + +#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)]) +#define PT_SYSCALL_ARG3_OFFSET (RDX) + +#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)]) +#define PT_SYSCALL_ARG4_OFFSET (RCX) + +#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)]) +#define PT_SYSCALL_ARG5_OFFSET (R8) + +#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)]) +#define PT_SYSCALL_ARG6_OFFSET (R9) + +#define PT_SYSCALL_RET_OFFSET (RAX) + +#define PT_IP_OFFSET (RIP) +#define PT_IP(regs) ((regs)[PT_INDEX(RIP)]) + +#define PT_SP_OFFSET (RSP) +#define PT_SP(regs) ((regs)[PT_INDEX(RSP)]) + +#define PT_ORIG_RAX_OFFSET (ORIG_RAX) +#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)]) + +#define MAX_REG_OFFSET (FRAME_SIZE) +#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) + +/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though + * it's defined in the kernel's include/linux/ptrace.h + */ +#ifndef PTRACE_SETOPTIONS +#define PTRACE_SETOPTIONS 0x4200 +#endif + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h new file mode 100644 index 00000000000000..6a0c346b640408 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/sigcontext.h @@ -0,0 +1,49 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_SIGCONTEXT_H +#define __SYSDEP_X86_64_SIGCONTEXT_H + +#include "sc.h" + +#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) + +#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) +#define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result) + +#define SC_FAULT_ADDR(sc) SC_CR2(sc) +#define SC_FAULT_TYPE(sc) SC_ERR(sc) + +#define FAULT_WRITE(err) ((err) & 2) + +#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc)) + +#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) + +/* ptrace expects that, at the start of a system call, %eax contains + * -ENOSYS, so this makes it so. + */ + +#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) + +#define SEGV_IS_FIXABLE(trap) ((trap) == 14) +#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc)) + +extern unsigned long *sc_sigmask(void *sc_ptr); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ + diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h new file mode 100644 index 00000000000000..e5e52756fab4fb --- /dev/null +++ b/arch/um/include/sysdep-x86_64/signal.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Licensed under the GPL + */ + +#ifndef __X86_64_SIGNAL_H_ +#define __X86_64_SIGNAL_H_ + +#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \ + do { \ + struct ucontext *__uc; \ + asm("movq %%rdx, %0" : "=r" (__uc)); \ + sc = (struct sigcontext *) &__uc->uc_mcontext; \ + } while(0) + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h new file mode 100644 index 00000000000000..65fd494420f990 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/syscalls.h @@ -0,0 +1,96 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_SYSCALLS_H__ +#define __SYSDEP_X86_64_SYSCALLS_H__ + +#include <linux/msg.h> +#include <linux/shm.h> + +typedef long syscall_handler_t(void); + +extern syscall_handler_t *ia32_sys_call_table[]; + +#define EXECUTE_SYSCALL(syscall, regs) \ + (((long (*)(long, long, long, long, long, long)) \ + (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(®s->regs), \ + UPT_SYSCALL_ARG2(®s->regs), \ + UPT_SYSCALL_ARG3(®s->regs), \ + UPT_SYSCALL_ARG4(®s->regs), \ + UPT_SYSCALL_ARG5(®s->regs), \ + UPT_SYSCALL_ARG6(®s->regs))) + +extern long old_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); +extern syscall_handler_t wrap_sys_shmat; +extern syscall_handler_t sys_modify_ldt; +extern syscall_handler_t sys_arch_prctl; + +#define ARCH_SYSCALLS \ + [ __NR_mmap ] = (syscall_handler_t *) old_mmap, \ + [ __NR_select ] = (syscall_handler_t *) sys_select, \ + [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \ + [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \ + [ __NR_shmget ] = (syscall_handler_t *) sys_shmget, \ + [ __NR_shmat ] = (syscall_handler_t *) wrap_sys_shmat, \ + [ __NR_shmctl ] = (syscall_handler_t *) sys_shmctl, \ + [ __NR_semop ] = (syscall_handler_t *) sys_semop, \ + [ __NR_semget ] = (syscall_handler_t *) sys_semget, \ + [ __NR_semctl ] = (syscall_handler_t *) sys_semctl, \ + [ __NR_shmdt ] = (syscall_handler_t *) sys_shmdt, \ + [ __NR_msgget ] = (syscall_handler_t *) sys_msgget, \ + [ __NR_msgsnd ] = (syscall_handler_t *) sys_msgsnd, \ + [ __NR_msgrcv ] = (syscall_handler_t *) sys_msgrcv, \ + [ __NR_msgctl ] = (syscall_handler_t *) sys_msgctl, \ + [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \ + [ __NR_tuxcall ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_security ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_epoll_ctl_old ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_epoll_wait_old ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \ + [ __NR_arch_prctl ] = (syscall_handler_t *) sys_arch_prctl, \ + [ __NR_socket ] = (syscall_handler_t *) sys_socket, \ + [ __NR_connect ] = (syscall_handler_t *) sys_connect, \ + [ __NR_accept ] = (syscall_handler_t *) sys_accept, \ + [ __NR_recvfrom ] = (syscall_handler_t *) sys_recvfrom, \ + [ __NR_recvmsg ] = (syscall_handler_t *) sys_recvmsg, \ + [ __NR_sendmsg ] = (syscall_handler_t *) sys_sendmsg, \ + [ __NR_bind ] = (syscall_handler_t *) sys_bind, \ + [ __NR_listen ] = (syscall_handler_t *) sys_listen, \ + [ __NR_getsockname ] = (syscall_handler_t *) sys_getsockname, \ + [ __NR_getpeername ] = (syscall_handler_t *) sys_getpeername, \ + [ __NR_socketpair ] = (syscall_handler_t *) sys_socketpair, \ + [ __NR_sendto ] = (syscall_handler_t *) sys_sendto, \ + [ __NR_shutdown ] = (syscall_handler_t *) sys_shutdown, \ + [ __NR_setsockopt ] = (syscall_handler_t *) sys_setsockopt, \ + [ __NR_getsockopt ] = (syscall_handler_t *) sys_getsockopt, \ + [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \ + [ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \ + [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \ + [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \ + [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \ + [ 251 ] = (syscall_handler_t *) sys_ni_syscall, + +#define LAST_ARCH_SYSCALL 251 +#define NR_syscalls 1024 + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 0924fcc95f1cf1..4eb302cbf8650d 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -20,19 +20,19 @@ #define access_ok(type, addr, size) \ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) -static inline int verify_area(int type, const void * addr, unsigned long size) +static inline int verify_area(int type, const void __user *addr, unsigned long size) { - return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, + return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, size)); } -static inline int copy_from_user(void *to, const void *from, int n) +static inline int copy_from_user(void *to, const void __user *from, int n) { return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, from, n)); } -static inline int copy_to_user(void *to, const void *from, int n) +static inline int copy_to_user(void __user *to, const void *from, int n) { return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, from, n)); @@ -57,7 +57,7 @@ static inline int copy_to_user(void *to, const void *from, int n) * and returns @count. */ -static inline int strncpy_from_user(char *dst, const char *src, int count) +static inline int strncpy_from_user(char *dst, const char __user *src, int count) { return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, dst, src, count)); @@ -89,7 +89,7 @@ static inline int __clear_user(void *mem, int len) * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -static inline int clear_user(void *mem, int len) +static inline int clear_user(void __user *mem, int len) { return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); } @@ -105,7 +105,7 @@ static inline int clear_user(void *mem, int len) * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -static inline int strnlen_user(const void *str, int len) +static inline int strnlen_user(const void __user *str, long len) { return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); } diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h index 785ccd51bbf526..f77eb642845385 100644 --- a/arch/um/include/uml_uaccess.h +++ b/arch/um/include/uml_uaccess.h @@ -7,7 +7,7 @@ #define __UML_UACCESS_H__ extern int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher); + void **fault_addr, void **fault_catcher); extern unsigned long __do_user_copy(void *to, const void *from, int n, void **fault_addr, void **fault_catcher, void (*op)(void *to, const void *from, diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c index fa50a9b81ca204..669783580fe51c 100644 --- a/arch/um/kernel/checksum.c +++ b/arch/um/kernel/checksum.c @@ -2,16 +2,16 @@ #include "linux/errno.h" #include "linux/module.h" -extern unsigned int arch_csum_partial(const char *buff, int len, int sum); +unsigned int arch_csum_partial(const char *buff, int len, int sum); -extern unsigned int csum_partial(char *buff, int len, int sum) +unsigned int csum_partial(char *buff, int len, int sum) { - return(arch_csum_partial(buff, len, sum)); + return arch_csum_partial(buff, len, sum); } EXPORT_SYMBOL(csum_partial); -unsigned int csum_partial_copy_to(const char *src, char *dst, int len, +unsigned int csum_partial_copy_to(const char *src, char __user *dst, int len, int sum, int *err_ptr) { if(copy_to_user(dst, src, len)){ @@ -22,7 +22,7 @@ unsigned int csum_partial_copy_to(const char *src, char *dst, int len, return(arch_csum_partial(src, len, sum)); } -unsigned int csum_partial_copy_from(const char *src, char *dst, int len, +unsigned int csum_partial_copy_from(const char __user *src, char *dst, int len, int sum, int *err_ptr) { if(copy_from_user(dst, src, len)){ @@ -30,7 +30,7 @@ unsigned int csum_partial_copy_from(const char *src, char *dst, int len, return(-1); } - return(arch_csum_partial(dst, len, sum)); + return arch_csum_partial(dst, len, sum); } /* diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 4336240c179a4c..49ddabe69be74e 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -34,7 +34,8 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) extern void log_exec(char **argv, void *tty); -static long execve1(char *file, char **argv, char **env) +static long execve1(char *file, char __user * __user *argv, + char *__user __user *env) { long error; @@ -51,7 +52,7 @@ static long execve1(char *file, char **argv, char **env) return(error); } -long um_execve(char *file, char **argv, char **env) +long um_execve(char *file, char __user *__user *argv, char __user *__user *env) { long err; @@ -61,13 +62,14 @@ long um_execve(char *file, char **argv, char **env) return(err); } -long sys_execve(char *file, char **argv, char **env) +long sys_execve(char *file, char __user *__user *argv, + char __user *__user *env) { long error; char *filename; lock_kernel(); - filename = getname((char *) file); + filename = getname((char __user *) file); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = execve1(filename, argv, env); diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 14a748e2e25a25..0ea87f24b36fde 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -27,7 +27,7 @@ static int read_proc_exitcode(char *page, char **start, off_t off, return(len); } -static int write_proc_exitcode(struct file *file, const char *buffer, +static int write_proc_exitcode(struct file *file, const char __user *buffer, unsigned long count, void *data) { char *end, buf[sizeof("nnnnn\0")]; diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 9d572b6ffd1dbb..ab7417b78c87b8 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -45,9 +45,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; j<NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "CPU%d ",j); + for_each_cpu(j) + seq_printf(p, "CPU%d ",j); seq_putc(p, '\n'); } @@ -60,9 +59,8 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + for_each_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); seq_printf(p, " %s", action->name); @@ -154,13 +152,13 @@ void __init init_IRQ(void) int i; irq_desc[TIMER_IRQ].status = IRQ_DISABLED; - irq_desc[TIMER_IRQ].action = 0; + irq_desc[TIMER_IRQ].action = NULL; irq_desc[TIMER_IRQ].depth = 1; irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; enable_irq(TIMER_IRQ); for(i=1;i<NR_IRQS;i++){ irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; + irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &SIGIO_irq_type; enable_irq(i); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 4279161c884905..b138eca53d0698 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -25,7 +25,7 @@ extern char __binary_start; /* Changed during early boot */ unsigned long *empty_zero_page = NULL; unsigned long *empty_bad_page = NULL; -pgd_t swapper_pg_dir[1024]; +pgd_t swapper_pg_dir[PTRS_PER_PGD]; unsigned long highmem; int kmalloc_ok = 0; @@ -130,12 +130,13 @@ static void __init fixrange_init(unsigned long start, unsigned long end, } } -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM pte_t *kmap_pte; pgprot_t kmap_prot; #define kmap_get_fixmap_pte(vaddr) \ - pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ + (vaddr)), (vaddr)) void __init kmap_init(void) { @@ -172,6 +173,7 @@ static void init_highmem(void) static void __init fixaddr_user_init( void) { +#if FIXADDR_USER_START != 0 long size = FIXADDR_USER_END - FIXADDR_USER_START; pgd_t *pgd; pmd_t *pmd; @@ -191,6 +193,7 @@ static void __init fixaddr_user_init( void) pte = pte_offset_kernel(pmd, vaddr); pte_set_val( (*pte), paddr, PAGE_READONLY); } +#endif } void paging_init(void) @@ -232,7 +235,7 @@ struct page *arch_validate(struct page *page, int mask, int order) addr = (unsigned long) page_address(page); for(i = 0; i < (1 << order); i++){ current->thread.fault_addr = (void *) addr; - if(__do_copy_to_user((void *) addr, &zero, + if(__do_copy_to_user((void __user *) addr, &zero, sizeof(zero), ¤t->thread.fault_addr, ¤t->thread.fault_catcher)){ @@ -241,6 +244,7 @@ struct page *arch_validate(struct page *page, int mask, int order) } addr += PAGE_SIZE; } + if(i == (1 << order)) return(page); page = alloc_pages(mask, order); goto again; @@ -335,7 +339,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *pte; - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); + pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c index 33f71e76495177..4a663fd434bbaf 100644 --- a/arch/um/kernel/mem_user.c +++ b/arch/um/kernel/mem_user.c @@ -48,8 +48,6 @@ #include "tempfile.h" #include "kern_constants.h" -extern struct mem_region physmem_region; - #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" static int create_tmp_file(unsigned long len) @@ -135,7 +133,7 @@ static int create_anon_file(unsigned long len) addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if(addr == MAP_FAILED){ - os_print_error((int) addr, "mapping physmem file"); + perror("mapping physmem file"); exit(1); } munmap(addr, len); diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 3253bc0e3a5cad..2853028657b36b 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -309,7 +309,7 @@ struct page *__virt_to_page(const unsigned long virt) return(&mem_map[__pa(virt) >> PAGE_SHIFT]); } -unsigned long page_to_phys(struct page *page) +phys_t page_to_phys(struct page *page) { return((page - mem_map) << PAGE_SHIFT); } @@ -318,8 +318,9 @@ pte_t mk_pte(struct page *page, pgprot_t pgprot) { pte_t pte; - pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot); - if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte)); + pte_set_val(pte, page_to_phys(page), pgprot); + if(pte_present(pte)) + pte_mknewprot(pte_mknewpage(pte)); return(pte); } diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 7460bd36e534e1..1e638b8131996f 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -13,14 +13,10 @@ #include <setjmp.h> #include <sys/time.h> #include <sys/ptrace.h> -#include <linux/ptrace.h> #include <sys/wait.h> #include <sys/mman.h> -#include <asm/ptrace.h> -#include <asm/sigcontext.h> #include <asm/unistd.h> #include <asm/page.h> -#include <asm/user.h> #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -28,6 +24,7 @@ #include "signal_kern.h" #include "signal_user.h" #include "sysdep/ptrace.h" +#include "sysdep/ptrace_user.h" #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" @@ -40,6 +37,7 @@ #ifdef UML_CONFIG_MODE_SKAS #include "skas.h" #include "skas_ptrace.h" +#include "registers.h" #endif void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) @@ -330,7 +328,7 @@ void __init check_ptrace(void) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80))) + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP + 0x80)) panic("check_ptrace : expected SIGTRAP + 0x80, " "got status = %d", status); diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 2af5a343cf1c2b..8d003f351eb38f 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; if(task->mm == NULL) return(ERR_PTR(-EINVAL)); pgd = pgd_offset(task->mm, addr); - pmd = pmd_offset(pgd, addr); + if(!pgd_present(*pgd)) + return(ERR_PTR(-EINVAL)); + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)) + return(ERR_PTR(-EINVAL)); + + pmd = pmd_offset(pud, addr); if(!pmd_present(*pmd)) return(ERR_PTR(-EINVAL)); + pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte)) return(ERR_PTR(-EINVAL)); + if(pte_out != NULL) *pte_out = *pte; return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); @@ -358,22 +368,22 @@ void *get_init_task(void) return(&init_thread_union.thread_info.task); } -int copy_to_user_proc(void *to, void *from, int size) +int copy_to_user_proc(void __user *to, void *from, int size) { return(copy_to_user(to, from, size)); } -int copy_from_user_proc(void *to, void *from, int size) +int copy_from_user_proc(void *to, void __user *from, int size) { return(copy_from_user(to, from, size)); } -int clear_user_proc(void *buf, int size) +int clear_user_proc(void __user *buf, int size) { return(clear_user(buf, size)); } -int strlen_user_proc(char *str) +int strlen_user_proc(char __user *str) { return(strlen_user(str)); } diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index daf1cb54d023bf..0d8e7696960039 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -16,6 +16,7 @@ #include "asm/uaccess.h" #include "kern_util.h" #include "ptrace_user.h" +#include "skas_ptrace.h" /* * Called by kernel/ptrace.c when detaching.. @@ -80,7 +81,7 @@ long sys_ptrace(long request, long pid, long addr, long data) copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp, (unsigned long __user *) data); break; } @@ -102,7 +103,7 @@ long sys_ptrace(long request, long pid, long addr, long data) addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; } - ret = put_user(tmp, (unsigned long *) data); + ret = put_user(tmp, (unsigned long __user *) data); break; } @@ -200,7 +201,8 @@ long sys_ptrace(long request, long pid, long addr, long data) break; } for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { - __put_user(getreg(child, i), (unsigned long *) data); + __put_user(getreg(child, i), + (unsigned long __user *) data); data += sizeof(long); } ret = 0; @@ -216,7 +218,7 @@ long sys_ptrace(long request, long pid, long addr, long data) break; } for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { - __get_user(tmp, (unsigned long *) data); + __get_user(tmp, (unsigned long __user *) data); putreg(child, i, tmp); data += sizeof(long); } @@ -250,14 +252,14 @@ long sys_ptrace(long request, long pid, long addr, long data) fault = ((struct ptrace_faultinfo) { .is_write = child->thread.err, .addr = child->thread.cr2 }); - ret = copy_to_user((unsigned long *) data, &fault, + ret = copy_to_user((unsigned long __user *) data, &fault, sizeof(fault)); if(ret) break; break; } case PTRACE_SIGPENDING: - ret = copy_to_user((unsigned long *) data, + ret = copy_to_user((unsigned long __user *) data, &child->pending.signal, sizeof(child->pending.signal)); break; @@ -265,7 +267,7 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_LDT: { struct ptrace_ldt ldt; - if(copy_from_user(&ldt, (unsigned long *) data, + if(copy_from_user(&ldt, (unsigned long __user *) data, sizeof(ldt))){ ret = -EIO; break; @@ -306,6 +308,25 @@ long sys_ptrace(long request, long pid, long addr, long data) return ret; } +void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, + int error_code) +{ + struct siginfo info; + + memset(&info, 0, sizeof(info)); + info.si_signo = SIGTRAP; + info.si_code = TRAP_BRKPT; + + /* User-mode eip? */ + info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL; + + /* Send us the fakey SIGTRAP */ + force_sig_info(SIGTRAP, &info, tsk); +} + +/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and + * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check + */ void syscall_trace(union uml_pt_regs *regs, int entryexit) { int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; @@ -320,14 +341,19 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) audit_syscall_exit(current, regs->eax); } - if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep) + /* Fake a debug trap */ + if (is_singlestep) + send_sigtrap(current, regs, 0); + + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; + if (!(current->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep; + tracesysgood = (current->ptrace & PT_TRACESYSGOOD); ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); if (entryexit) /* force do_signal() --> is_syscall() */ diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 2a5b9b8ef3f8ba..7807a3e8c426e3 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -74,10 +74,12 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; - if(ka->sa.sa_flags & SA_SIGINFO) - err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); - else +#ifdef CONFIG_ARCH_HAS_SC_SIGNALS + if(!(ka->sa.sa_flags & SA_SIGINFO)) err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); + else +#endif + err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); if(err){ spin_lock_irq(¤t->sighand->siglock); @@ -194,38 +196,7 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) } } -int sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -long sys_sigaltstack(const stack_t *uss, stack_t *uoss) +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c index 2468cd6a625d54..62f457835fb1dc 100644 --- a/arch/um/kernel/signal_user.c +++ b/arch/um/kernel/signal_user.c @@ -41,6 +41,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) while((mask = va_arg(ap, int)) != -1){ sigaddset(&action.sa_mask, mask); } + va_end(ap); action.sa_flags = flags; action.sa_restorer = NULL; if(sigaction(sig, &action, NULL) < 0) diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index d7b61cba94487b..c340c9cbf19b8e 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -6,8 +6,6 @@ obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \ -subdir-y := util - USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h deleted file mode 100644 index f5c5268cc4925a..00000000000000 --- a/arch/um/kernel/skas/include/ptrace-skas.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __PTRACE_SKAS_H -#define __PTRACE_SKAS_H - -#include "uml-config.h" - -#ifdef UML_CONFIG_MODE_SKAS - -#include "skas_ptregs.h" - -#define HOST_FRAME_SIZE 17 - -#define REGS_IP(r) ((r)[HOST_IP]) -#define REGS_SP(r) ((r)[HOST_SP]) -#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -#define REGS_EAX(r) ((r)[HOST_EAX]) -#define REGS_EBX(r) ((r)[HOST_EBX]) -#define REGS_ECX(r) ((r)[HOST_ECX]) -#define REGS_EDX(r) ((r)[HOST_EDX]) -#define REGS_ESI(r) ((r)[HOST_ESI]) -#define REGS_EDI(r) ((r)[HOST_EDI]) -#define REGS_EBP(r) ((r)[HOST_EBP]) -#define REGS_CS(r) ((r)[HOST_CS]) -#define REGS_SS(r) ((r)[HOST_SS]) -#define REGS_DS(r) ((r)[HOST_DS]) -#define REGS_ES(r) ((r)[HOST_ES]) -#define REGS_FS(r) ((r)[HOST_FS]) -#define REGS_GS(r) ((r)[HOST_GS]) - -#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) - -#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) - -#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) - -#define REGS_FAULT_ADDR(r) ((r)->fault_addr) - -#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) - -#endif - -#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/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index 2f6eaa37455d79..1c7fcd3effc204 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -29,10 +29,7 @@ extern int protect(int fd, unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern void user_signal(int sig, union uml_pt_regs *regs); extern int new_mm(int from); -extern void save_registers(union uml_pt_regs *regs); -extern void restore_registers(union uml_pt_regs *regs); extern void start_userspace(int cpu); -extern void init_registers(int pid); #endif diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index ec169a86cdbe2e..438db2f43456b4 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -13,8 +13,13 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, /* Round up to the nearest 4M */ unsigned long top = ROUND_4M((unsigned long) &arg); +#ifdef CONFIG_HOST_TASK_SIZE + *host_size_out = CONFIG_HOST_TASK_SIZE; + *task_size_out = CONFIG_HOST_TASK_SIZE; +#else *host_size_out = top; *task_size_out = top; +#endif return(((unsigned long) set_task_sizes_skas) & ~0xffffff); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 247b06d09c59f9..6b1acc66ff949e 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -28,6 +28,7 @@ #include "skas_ptrace.h" #include "chan_user.h" #include "signal_user.h" +#include "registers.h" int is_skas_winch(int pid, int fd, void *data) { @@ -38,13 +39,6 @@ int is_skas_winch(int pid, int fd, void *data) return(1); } -/* These are set once at boot time and not changed thereafter */ - -unsigned long exec_regs[FRAME_SIZE]; -unsigned long exec_fp_regs[HOST_FP_SIZE]; -unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -int have_fpx_regs = 1; - static void handle_segv(int pid) { struct ptrace_faultinfo fault; @@ -79,7 +73,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu "errno = %d\n", errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80))) + if((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)) panic("handle_trap - failed to wait at end of syscall, " "errno = %d, status = %d\n", errno, status); } @@ -97,6 +92,7 @@ static int userspace_tramp(void *arg) } /* Each element set once, and only accessed by a single processor anyway */ +#undef NR_CPUS #define NR_CPUS 1 int userspace_pid[NR_CPUS]; @@ -143,7 +139,7 @@ void userspace(union uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ - restore_registers(regs); + restore_registers(pid, regs); local_using_sysemu = get_using_sysemu(); @@ -160,7 +156,7 @@ void userspace(union uml_pt_regs *regs) errno); regs->skas.is_user = 1; - save_registers(regs); + save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if(WIFSTOPPED(status)){ @@ -192,7 +188,7 @@ void userspace(union uml_pt_regs *regs) PT_SYSCALL_NR(regs->skas.regs) = -1; } - restore_registers(regs); + restore_registers(pid, regs); /*Now we ended the syscall, so re-read local_using_sysemu.*/ local_using_sysemu = get_using_sysemu(); @@ -243,58 +239,6 @@ void thread_wait(void *sw, void *fb) siglongjmp(*fork_buf, 1); } -static int move_registers(int pid, int int_op, int fp_op, - union uml_pt_regs *regs, unsigned long *fp_regs) -{ - if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return(-errno); - if(ptrace(fp_op, pid, 0, fp_regs) < 0) - return(-errno); - return(0); -} - -void save_registers(union uml_pt_regs *regs) -{ - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_GETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_GETFPREGS; - fp_regs = regs->skas.fp; - } - - err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs, - fp_regs); - if(err) - panic("save_registers - saving registers failed, errno = %d\n", - -err); -} - -void restore_registers(union uml_pt_regs *regs) -{ - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_SETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_SETFPREGS; - fp_regs = regs->skas.fp; - } - - err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs, - fp_regs); - if(err) - panic("restore_registers - saving registers failed, " - "errno = %d\n", -err); -} - void switch_threads(void *me, void *next) { sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; @@ -394,29 +338,6 @@ void kill_off_processes_skas(void) os_kill_ptraced_process(userspace_pid[0], 1); } -void init_registers(int pid) -{ - int err; - - if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); - - err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); - if(!err) - return; - - have_fpx_regs = 0; - if(errno != EIO) - panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", - errno); - - err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); - if(err) - panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", - errno); -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 648955b0476ff9..5d096ea63b97a6 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -22,6 +22,7 @@ #include "kern.h" #include "mode.h" #include "proc_mm.h" +#include "registers.h" void *switch_to_skas(void *prev, void *next) { @@ -118,12 +119,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, handler = fork_handler; } else { - memcpy(p->thread.regs.regs.skas.regs, exec_regs, - sizeof(p->thread.regs.regs.skas.regs)); - memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, - sizeof(p->thread.regs.regs.skas.fp)); - memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, - sizeof(p->thread.regs.regs.skas.xfp)); + init_thread_registers(&p->thread.regs.regs); p->thread.request.u.thread = current->thread.request.u.thread; handler = new_thread_handler; } diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 02e3e06bb03313..956fb0102a1ee4 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -18,52 +19,86 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { pgd_t *npgd; + pud_t *npud; pmd_t *npmd; pte_t *npte; - unsigned long addr; + unsigned long addr, end; int r, w, x, err, fd; if(mm == NULL) return; fd = mm->context.skas.mm_fd; for(addr = start_addr; addr < end_addr;){ npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); - if(pmd_present(*npmd)){ - npte = pte_offset_kernel(npmd, addr); - r = pte_read(*npte); - w = pte_write(*npte); - x = pte_exec(*npte); - if(!pte_dirty(*npte)) w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } - if(force || pte_newpage(*npte)){ - err = unmap(fd, (void *) addr, PAGE_SIZE); + if(!pgd_present(*npgd)){ + if(force || pgd_newpage(*npgd)){ + end = addr + PGDIR_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*npte)) - map(fd, addr, - pte_val(*npte) & PAGE_MASK, - PAGE_SIZE, r, w, x); + pgd_mkuptodate(*npgd); } - else if(pte_newprot(*npte)){ - protect(fd, addr, PAGE_SIZE, r, w, x, 1); + addr += PGDIR_SIZE; + continue; + } + + npud = pud_offset(npgd, addr); + if(!pud_present(*npud)){ + if(force || pud_newpage(*npud)){ + end = addr + PUD_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + pud_mkuptodate(*npud); } - *npte = pte_mkuptodate(*npte); - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + npmd = pmd_offset(npud, addr); + if(!pmd_present(*npmd)){ if(force || pmd_newpage(*npmd)){ - err = unmap(fd, (void *) addr, PMD_SIZE); + end = addr + PMD_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); pmd_mkuptodate(*npmd); } addr += PMD_SIZE; + continue; + } + + npte = pte_offset_kernel(npmd, addr); + r = pte_read(*npte); + w = pte_write(*npte); + x = pte_exec(*npte); + if(!pte_dirty(*npte)) + w = 0; + if(!pte_young(*npte)){ + r = 0; + w = 0; + } + if(force || pte_newpage(*npte)){ + err = unmap(fd, (void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*npte)) + map(fd, addr, pte_val(*npte) & PAGE_MASK, + PAGE_SIZE, r, w, x); } + else if(pte_newprot(*npte)) + protect(fd, addr, PAGE_SIZE, r, w, x, 1); + + *npte = pte_mkuptodate(*npte); + addr += PAGE_SIZE; } } @@ -71,45 +106,82 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned long addr; + unsigned long addr, last; int updated = 0, err; mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); - if(pmd_present(*pmd)){ - pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte) || pte_newpage(*pte)){ + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + if(!pgd_present(*pgd)){ + if(pgd_newpage(*pgd)){ updated = 1; + last = addr + PGDIR_SIZE; + if(last > end) + last = end; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*pte)) - map_memory(addr, - pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, 1, 1, 1); } - else if(pte_newprot(*pte)){ + addr += PGDIR_SIZE; + continue; + } + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)){ + if(pud_newpage(*pud)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + last = addr + PUD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); } - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + pmd = pmd_offset(pud, addr); + if(!pmd_present(*pmd)){ if(pmd_newpage(*pmd)){ updated = 1; - err = os_unmap_memory((void *) addr, PMD_SIZE); + last = addr + PMD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } addr += PMD_SIZE; + continue; + } + + pte = pte_offset_kernel(pmd, addr); + if(!pte_present(*pte) || pte_newpage(*pte)){ + updated = 1; + err = os_unmap_memory((void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*pte)) + map_memory(addr, pte_val(*pte) & PAGE_MASK, + PAGE_SIZE, 1, 1, 1); } + else if(pte_newprot(*pte)){ + updated = 1; + protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + } + addr += PAGE_SIZE; } } diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c index 96593709a6e169..09248772de6059 100644 --- a/arch/um/kernel/skas/trap_user.c +++ b/arch/um/kernel/skas/trap_user.c @@ -5,7 +5,6 @@ #include <signal.h> #include <errno.h> -#include <asm/sigcontext.h> #include "sysdep/ptrace.h" #include "signal_user.h" #include "user_util.h" diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 77048cd6775cb7..c8e5fe49583aee 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -54,15 +54,23 @@ static int do_op(unsigned long addr, int len, int is_write, static void do_buffer_op(void *jmpbuf, void *arg_ptr) { - va_list args = *((va_list *) arg_ptr); - unsigned long addr = va_arg(args, unsigned long); - int len = va_arg(args, int); - int is_write = va_arg(args, int); - int (*op)(unsigned long, int, void *) = va_arg(args, void *); - void *arg = va_arg(args, void *); - int *res = va_arg(args, int *); - int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); - int remain = len, n; + va_list args; + unsigned long addr; + int len, is_write, size, remain, n; + int (*op)(unsigned long, int, void *); + void *arg; + int *res; + + va_copy(args, *(va_list *)arg_ptr); + addr = va_arg(args, unsigned long); + len = va_arg(args, int); + is_write = va_arg(args, int); + op = va_arg(args, void *); + arg = va_arg(args, void *); + res = va_arg(args, int *); + va_end(args); + size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); + remain = len; current->thread.fault_catcher = jmpbuf; n = do_op(addr, size, is_write, op, arg); @@ -124,10 +132,10 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) return(0); } -int copy_from_user_skas(void *to, const void *from, int n) +int copy_from_user_skas(void *to, const void __user *from, int n) { if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); + memcpy(to, (__force void*)from, n); return(0); } @@ -145,10 +153,10 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) return(0); } -int copy_to_user_skas(void *to, const void *from, int n) +int copy_to_user_skas(void __user *to, const void *from, int n) { if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); + memcpy((__force void*)to, from, n); return(0); } @@ -171,13 +179,13 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) return(0); } -int strncpy_from_user_skas(char *dst, const char *src, int count) +int strncpy_from_user_skas(char *dst, const char __user *src, int count) { int n; char *ptr = dst; if(segment_eq(get_fs(), KERNEL_DS)){ - strncpy(dst, src, count); + strncpy(dst, (__force void*)src, count); return(strnlen(dst, count)); } @@ -197,15 +205,15 @@ static int clear_chunk(unsigned long addr, int len, void *unused) return(0); } -int __clear_user_skas(void *mem, int len) +int __clear_user_skas(void __user *mem, int len) { return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); } -int clear_user_skas(void *mem, int len) +int clear_user_skas(void __user *mem, int len) { if(segment_eq(get_fs(), KERNEL_DS)){ - memset(mem, 0, len); + memset((__force void*)mem, 0, len); return(0); } @@ -225,12 +233,12 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) return(0); } -int strnlen_user_skas(const void *str, int len) +int strnlen_user_skas(const void __user *str, int len) { int count = 0, n; if(segment_eq(get_fs(), KERNEL_DS)) - return(strnlen(str, len) + 1); + return(strnlen((__force char*)str, len) + 1); n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); if(n == 0) diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile index a26e0c34a762bd..17f5909d60f7f4 100644 --- a/arch/um/kernel/skas/util/Makefile +++ b/arch/um/kernel/skas/util/Makefile @@ -1,2 +1,4 @@ hostprogs-y := mk_ptregs always := $(hostprogs-y) + +mk_ptregs-objs := mk_ptregs-$(SUBARCH).o diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c index 116f74d2c334f0..0788dd05bcacd5 100644 --- a/arch/um/kernel/skas/util/mk_ptregs.c +++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c @@ -13,9 +13,9 @@ int main(int argc, char **argv) printf("#define __SKAS_PT_REGS_\n"); printf("\n"); printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); - printf("#define HOST_FP_SIZE %d\n", + printf("#define HOST_FP_SIZE %d\n", sizeof(struct user_i387_struct) / sizeof(unsigned long)); - printf("#define HOST_XFP_SIZE %d\n", + printf("#define HOST_XFP_SIZE %d\n", sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); PRINT_REG("IP", EIP); diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c new file mode 100644 index 00000000000000..67aee92a70efa5 --- /dev/null +++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c @@ -0,0 +1,68 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include <stdio.h> +#define __FRAME_OFFSETS +#include <asm/ptrace.h> + +#define PRINT_REG(name, val) \ + printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val)) + +int main(int argc, char **argv) +{ + printf("/* Automatically generated by " + "arch/um/kernel/skas/util/mk_ptregs */\n"); + printf("\n"); + printf("#ifndef __SKAS_PT_REGS_\n"); + printf("#define __SKAS_PT_REGS_\n"); + printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n", + FRAME_SIZE); + PRINT_REG("RBX", RBX); + PRINT_REG("RCX", RCX); + PRINT_REG("RDI", RDI); + PRINT_REG("RSI", RSI); + PRINT_REG("RDX", RDX); + PRINT_REG("RBP", RBP); + PRINT_REG("RAX", RAX); + PRINT_REG("R8", R8); + PRINT_REG("R9", R9); + PRINT_REG("R10", R10); + PRINT_REG("R11", R11); + PRINT_REG("R12", R12); + PRINT_REG("R13", R13); + PRINT_REG("R14", R14); + PRINT_REG("R15", R15); + PRINT_REG("ORIG_RAX", ORIG_RAX); + PRINT_REG("CS", CS); + PRINT_REG("SS", SS); + PRINT_REG("EFLAGS", EFLAGS); +#if 0 + PRINT_REG("FS", FS); + PRINT_REG("GS", GS); + PRINT_REG("DS", DS); + PRINT_REG("ES", ES); +#endif + + PRINT_REG("IP", RIP); + PRINT_REG("SP", RSP); + printf("#define HOST_FP_SIZE 0\n"); + printf("#define HOST_XFP_SIZE 0\n"); + printf("\n"); + printf("\n"); + printf("#endif\n"); + 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/smp.c b/arch/um/kernel/smp.c index b5e66b291cc32f..abe892be6cfe4a 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -247,10 +247,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, func = _func; info = _info; - for (i=0;i<NR_CPUS;i++) - if((i != current_thread->cpu) && - cpu_isset(i, cpu_online_map)) - os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); + for_each_cpu(i) + os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); while (atomic_read(&scf_started) != cpus) barrier(); diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c index 314925365cf52b..b09266a012c152 100644 --- a/arch/um/kernel/sys_call_table.c +++ b/arch/um/kernel/sys_call_table.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -19,7 +20,7 @@ #define NFSSERVCTL sys_ni_syscall #endif -#define LAST_GENERIC_SYSCALL __NR_vserver +#define LAST_GENERIC_SYSCALL __NR_vperfctr_read #if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL #define LAST_SYSCALL LAST_GENERIC_SYSCALL @@ -32,7 +33,6 @@ extern syscall_handler_t sys_execve; extern syscall_handler_t um_time; extern syscall_handler_t um_mount; extern syscall_handler_t um_stime; -extern syscall_handler_t sys_ptrace; extern syscall_handler_t sys_pipe; extern syscall_handler_t sys_olduname; extern syscall_handler_t sys_sigaction; @@ -43,269 +43,249 @@ extern syscall_handler_t sys_ipc; extern syscall_handler_t sys_sigreturn; extern syscall_handler_t sys_clone; extern syscall_handler_t sys_rt_sigreturn; -extern syscall_handler_t sys_rt_sigaction; extern syscall_handler_t sys_sigaltstack; extern syscall_handler_t sys_vfork; -extern syscall_handler_t sys_mmap2; -extern syscall_handler_t old_mmap_i386; extern syscall_handler_t old_select; extern syscall_handler_t sys_modify_ldt; extern syscall_handler_t sys_rt_sigsuspend; +extern syscall_handler_t sys_vserver; +extern syscall_handler_t sys_mbind; +extern syscall_handler_t sys_get_mempolicy; +extern syscall_handler_t sys_set_mempolicy; +extern syscall_handler_t sys_sys_kexec_load; +extern syscall_handler_t sys_sys_setaltroot; +extern syscall_handler_t sys_vperfctr_open; +extern syscall_handler_t sys_vperfctr_control; +extern syscall_handler_t sys_vperfctr_unlink; +extern syscall_handler_t sys_vperfctr_iresume; +extern syscall_handler_t sys_vperfctr_read; syscall_handler_t *sys_call_table[] = { [ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall, - [ __NR_exit ] (syscall_handler_t *) sys_exit, - [ __NR_fork ] (syscall_handler_t *) sys_fork, + [ __NR_exit ] = (syscall_handler_t *) sys_exit, + [ __NR_fork ] = (syscall_handler_t *) sys_fork, [ __NR_read ] = (syscall_handler_t *) sys_read, [ __NR_write ] = (syscall_handler_t *) sys_write, /* These three are declared differently in asm/unistd.h */ [ __NR_open ] = (syscall_handler_t *) sys_open, [ __NR_close ] = (syscall_handler_t *) sys_close, - [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, - [ __NR_creat ] (syscall_handler_t *) sys_creat, - [ __NR_link ] (syscall_handler_t *) sys_link, - [ __NR_unlink ] (syscall_handler_t *) sys_unlink, + [ __NR_creat ] = (syscall_handler_t *) sys_creat, + [ __NR_link ] = (syscall_handler_t *) sys_link, + [ __NR_unlink ] = (syscall_handler_t *) sys_unlink, [ __NR_execve ] = (syscall_handler_t *) sys_execve, /* declared differently in kern_util.h */ - [ __NR_chdir ] (syscall_handler_t *) sys_chdir, + [ __NR_chdir ] = (syscall_handler_t *) sys_chdir, [ __NR_time ] = um_time, - [ __NR_mknod ] (syscall_handler_t *) sys_mknod, - [ __NR_chmod ] (syscall_handler_t *) sys_chmod, - [ __NR_lchown ] (syscall_handler_t *) sys_lchown16, - [ __NR_break ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_oldstat ] (syscall_handler_t *) sys_stat, + [ __NR_mknod ] = (syscall_handler_t *) sys_mknod, + [ __NR_chmod ] = (syscall_handler_t *) sys_chmod, + [ __NR_lchown ] = (syscall_handler_t *) sys_lchown16, [ __NR_lseek ] = (syscall_handler_t *) sys_lseek, - [ __NR_getpid ] (syscall_handler_t *) sys_getpid, + [ __NR_getpid ] = (syscall_handler_t *) sys_getpid, [ __NR_mount ] = um_mount, - [ __NR_umount ] (syscall_handler_t *) sys_oldumount, - [ __NR_setuid ] (syscall_handler_t *) sys_setuid16, - [ __NR_getuid ] (syscall_handler_t *) sys_getuid16, - [ __NR_stime ] = um_stime, - [ __NR_ptrace ] (syscall_handler_t *) sys_ptrace, - [ __NR_alarm ] (syscall_handler_t *) sys_alarm, - [ __NR_oldfstat ] (syscall_handler_t *) sys_fstat, - [ __NR_pause ] (syscall_handler_t *) sys_pause, - [ __NR_utime ] (syscall_handler_t *) sys_utime, - [ __NR_stty ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_access ] (syscall_handler_t *) sys_access, - [ __NR_nice ] (syscall_handler_t *) sys_nice, - [ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_sync ] (syscall_handler_t *) sys_sync, - [ __NR_kill ] (syscall_handler_t *) sys_kill, - [ __NR_rename ] (syscall_handler_t *) sys_rename, - [ __NR_mkdir ] (syscall_handler_t *) sys_mkdir, - [ __NR_rmdir ] (syscall_handler_t *) sys_rmdir, + [ __NR_setuid ] = (syscall_handler_t *) sys_setuid16, + [ __NR_getuid ] = (syscall_handler_t *) sys_getuid16, + [ __NR_ptrace ] = (syscall_handler_t *) sys_ptrace, + [ __NR_alarm ] = (syscall_handler_t *) sys_alarm, + [ __NR_pause ] = (syscall_handler_t *) sys_pause, + [ __NR_utime ] = (syscall_handler_t *) sys_utime, + [ __NR_access ] = (syscall_handler_t *) sys_access, + [ __NR_sync ] = (syscall_handler_t *) sys_sync, + [ __NR_kill ] = (syscall_handler_t *) sys_kill, + [ __NR_rename ] = (syscall_handler_t *) sys_rename, + [ __NR_mkdir ] = (syscall_handler_t *) sys_mkdir, + [ __NR_rmdir ] = (syscall_handler_t *) sys_rmdir, /* Declared differently in asm/unistd.h */ [ __NR_dup ] = (syscall_handler_t *) sys_dup, - [ __NR_pipe ] (syscall_handler_t *) sys_pipe, - [ __NR_times ] (syscall_handler_t *) sys_times, - [ __NR_prof ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_brk ] (syscall_handler_t *) sys_brk, - [ __NR_setgid ] (syscall_handler_t *) sys_setgid16, - [ __NR_getgid ] (syscall_handler_t *) sys_getgid16, - [ __NR_signal ] (syscall_handler_t *) sys_signal, - [ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16, - [ __NR_getegid ] (syscall_handler_t *) sys_getegid16, - [ __NR_acct ] (syscall_handler_t *) sys_acct, - [ __NR_umount2 ] (syscall_handler_t *) sys_umount, - [ __NR_lock ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_ioctl ] (syscall_handler_t *) sys_ioctl, - [ __NR_fcntl ] (syscall_handler_t *) sys_fcntl, - [ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_setpgid ] (syscall_handler_t *) sys_setpgid, - [ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_oldolduname ] (syscall_handler_t *) sys_olduname, - [ __NR_umask ] (syscall_handler_t *) sys_umask, - [ __NR_chroot ] (syscall_handler_t *) sys_chroot, - [ __NR_ustat ] (syscall_handler_t *) sys_ustat, - [ __NR_dup2 ] (syscall_handler_t *) sys_dup2, - [ __NR_getppid ] (syscall_handler_t *) sys_getppid, - [ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp, + [ __NR_pipe ] = (syscall_handler_t *) sys_pipe, + [ __NR_times ] = (syscall_handler_t *) sys_times, + [ __NR_brk ] = (syscall_handler_t *) sys_brk, + [ __NR_setgid ] = (syscall_handler_t *) sys_setgid16, + [ __NR_getgid ] = (syscall_handler_t *) sys_getgid16, + [ __NR_geteuid ] = (syscall_handler_t *) sys_geteuid16, + [ __NR_getegid ] = (syscall_handler_t *) sys_getegid16, + [ __NR_acct ] = (syscall_handler_t *) sys_acct, + [ __NR_umount2 ] = (syscall_handler_t *) sys_umount, + [ __NR_ioctl ] = (syscall_handler_t *) sys_ioctl, + [ __NR_fcntl ] = (syscall_handler_t *) sys_fcntl, + [ __NR_setpgid ] = (syscall_handler_t *) sys_setpgid, + [ __NR_umask ] = (syscall_handler_t *) sys_umask, + [ __NR_chroot ] = (syscall_handler_t *) sys_chroot, + [ __NR_ustat ] = (syscall_handler_t *) sys_ustat, + [ __NR_dup2 ] = (syscall_handler_t *) sys_dup2, + [ __NR_getppid ] = (syscall_handler_t *) sys_getppid, + [ __NR_getpgrp ] = (syscall_handler_t *) sys_getpgrp, [ __NR_setsid ] = (syscall_handler_t *) sys_setsid, - [ __NR_sigaction ] (syscall_handler_t *) sys_sigaction, - [ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask, - [ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask, - [ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16, - [ __NR_setregid ] (syscall_handler_t *) sys_setregid16, - [ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend, - [ __NR_sigpending ] (syscall_handler_t *) sys_sigpending, - [ __NR_sethostname ] (syscall_handler_t *) sys_sethostname, - [ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit, - [ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit, - [ __NR_getrusage ] (syscall_handler_t *) sys_getrusage, - [ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday, - [ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday, - [ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16, - [ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16, - [ __NR_symlink ] (syscall_handler_t *) sys_symlink, - [ __NR_oldlstat ] (syscall_handler_t *) sys_lstat, - [ __NR_readlink ] (syscall_handler_t *) sys_readlink, - [ __NR_uselib ] (syscall_handler_t *) sys_uselib, + [ __NR_setreuid ] = (syscall_handler_t *) sys_setreuid16, + [ __NR_setregid ] = (syscall_handler_t *) sys_setregid16, + [ __NR_sethostname ] = (syscall_handler_t *) sys_sethostname, + [ __NR_setrlimit ] = (syscall_handler_t *) sys_setrlimit, + [ __NR_getrlimit ] = (syscall_handler_t *) sys_old_getrlimit, + [ __NR_getrusage ] = (syscall_handler_t *) sys_getrusage, + [ __NR_gettimeofday ] = (syscall_handler_t *) sys_gettimeofday, + [ __NR_settimeofday ] = (syscall_handler_t *) sys_settimeofday, + [ __NR_getgroups ] = (syscall_handler_t *) sys_getgroups16, + [ __NR_setgroups ] = (syscall_handler_t *) sys_setgroups16, + [ __NR_symlink ] = (syscall_handler_t *) sys_symlink, + [ __NR_readlink ] = (syscall_handler_t *) sys_readlink, + [ __NR_uselib ] = (syscall_handler_t *) sys_uselib, [ __NR_swapon ] = (syscall_handler_t *) sys_swapon, - [ __NR_reboot ] (syscall_handler_t *) sys_reboot, - [ __NR_readdir ] = old_readdir, - [ __NR_munmap ] (syscall_handler_t *) sys_munmap, - [ __NR_truncate ] (syscall_handler_t *) sys_truncate, - [ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate, - [ __NR_fchmod ] (syscall_handler_t *) sys_fchmod, - [ __NR_fchown ] (syscall_handler_t *) sys_fchown16, - [ __NR_getpriority ] (syscall_handler_t *) sys_getpriority, - [ __NR_setpriority ] (syscall_handler_t *) sys_setpriority, - [ __NR_profil ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_statfs ] (syscall_handler_t *) sys_statfs, - [ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs, - [ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_socketcall ] (syscall_handler_t *) sys_socketcall, - [ __NR_syslog ] (syscall_handler_t *) sys_syslog, - [ __NR_setitimer ] (syscall_handler_t *) sys_setitimer, - [ __NR_getitimer ] (syscall_handler_t *) sys_getitimer, - [ __NR_stat ] (syscall_handler_t *) sys_newstat, - [ __NR_lstat ] (syscall_handler_t *) sys_newlstat, - [ __NR_fstat ] (syscall_handler_t *) sys_newfstat, - [ __NR_olduname ] (syscall_handler_t *) sys_uname, - [ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_vhangup ] (syscall_handler_t *) sys_vhangup, - [ __NR_idle ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_reboot ] = (syscall_handler_t *) sys_reboot, + [ __NR_munmap ] = (syscall_handler_t *) sys_munmap, + [ __NR_truncate ] = (syscall_handler_t *) sys_truncate, + [ __NR_ftruncate ] = (syscall_handler_t *) sys_ftruncate, + [ __NR_fchmod ] = (syscall_handler_t *) sys_fchmod, + [ __NR_fchown ] = (syscall_handler_t *) sys_fchown16, + [ __NR_getpriority ] = (syscall_handler_t *) sys_getpriority, + [ __NR_setpriority ] = (syscall_handler_t *) sys_setpriority, + [ __NR_statfs ] = (syscall_handler_t *) sys_statfs, + [ __NR_fstatfs ] = (syscall_handler_t *) sys_fstatfs, + [ __NR_ioperm ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_syslog ] = (syscall_handler_t *) sys_syslog, + [ __NR_setitimer ] = (syscall_handler_t *) sys_setitimer, + [ __NR_getitimer ] = (syscall_handler_t *) sys_getitimer, + [ __NR_stat ] = (syscall_handler_t *) sys_newstat, + [ __NR_lstat ] = (syscall_handler_t *) sys_newlstat, + [ __NR_fstat ] = (syscall_handler_t *) sys_newfstat, + [ __NR_vhangup ] = (syscall_handler_t *) sys_vhangup, [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4, [ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff, - [ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo, - [ __NR_ipc ] (syscall_handler_t *) sys_ipc, - [ __NR_fsync ] (syscall_handler_t *) sys_fsync, - [ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn, - [ __NR_clone ] (syscall_handler_t *) sys_clone, - [ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname, - [ __NR_uname ] (syscall_handler_t *) sys_newuname, - [ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex, - [ __NR_mprotect ] (syscall_handler_t *) sys_mprotect, - [ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask, - [ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_init_module ] (syscall_handler_t *) sys_init_module, - [ __NR_delete_module ] (syscall_handler_t *) sys_delete_module, - [ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_quotactl ] (syscall_handler_t *) sys_quotactl, - [ __NR_getpgid ] (syscall_handler_t *) sys_getpgid, - [ __NR_fchdir ] (syscall_handler_t *) sys_fchdir, - [ __NR_bdflush ] (syscall_handler_t *) sys_bdflush, - [ __NR_sysfs ] (syscall_handler_t *) sys_sysfs, - [ __NR_personality ] (syscall_handler_t *) sys_personality, - [ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16, - [ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16, - [ __NR__llseek ] (syscall_handler_t *) sys_llseek, - [ __NR_getdents ] (syscall_handler_t *) sys_getdents, - [ __NR__newselect ] = (syscall_handler_t *) sys_select, - [ __NR_flock ] (syscall_handler_t *) sys_flock, - [ __NR_msync ] (syscall_handler_t *) sys_msync, - [ __NR_readv ] (syscall_handler_t *) sys_readv, - [ __NR_writev ] (syscall_handler_t *) sys_writev, - [ __NR_getsid ] (syscall_handler_t *) sys_getsid, - [ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync, + [ __NR_sysinfo ] = (syscall_handler_t *) sys_sysinfo, + [ __NR_fsync ] = (syscall_handler_t *) sys_fsync, + [ __NR_clone ] = (syscall_handler_t *) sys_clone, + [ __NR_setdomainname ] = (syscall_handler_t *) sys_setdomainname, + [ __NR_uname ] = (syscall_handler_t *) sys_newuname, + [ __NR_adjtimex ] = (syscall_handler_t *) sys_adjtimex, + [ __NR_mprotect ] = (syscall_handler_t *) sys_mprotect, + [ __NR_create_module ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_init_module ] = (syscall_handler_t *) sys_init_module, + [ __NR_delete_module ] = (syscall_handler_t *) sys_delete_module, + [ __NR_get_kernel_syms ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_quotactl ] = (syscall_handler_t *) sys_quotactl, + [ __NR_getpgid ] = (syscall_handler_t *) sys_getpgid, + [ __NR_fchdir ] = (syscall_handler_t *) sys_fchdir, + [ __NR_sysfs ] = (syscall_handler_t *) sys_sysfs, + [ __NR_personality ] = (syscall_handler_t *) sys_personality, + [ __NR_afs_syscall ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_setfsuid ] = (syscall_handler_t *) sys_setfsuid16, + [ __NR_setfsgid ] = (syscall_handler_t *) sys_setfsgid16, + [ __NR_getdents ] = (syscall_handler_t *) sys_getdents, + [ __NR_flock ] = (syscall_handler_t *) sys_flock, + [ __NR_msync ] = (syscall_handler_t *) sys_msync, + [ __NR_readv ] = (syscall_handler_t *) sys_readv, + [ __NR_writev ] = (syscall_handler_t *) sys_writev, + [ __NR_getsid ] = (syscall_handler_t *) sys_getsid, + [ __NR_fdatasync ] = (syscall_handler_t *) sys_fdatasync, [ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl, - [ __NR_mlock ] (syscall_handler_t *) sys_mlock, - [ __NR_munlock ] (syscall_handler_t *) sys_munlock, - [ __NR_mlockall ] (syscall_handler_t *) sys_mlockall, - [ __NR_munlockall ] (syscall_handler_t *) sys_munlockall, - [ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam, - [ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam, - [ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler, - [ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler, + [ __NR_mlock ] = (syscall_handler_t *) sys_mlock, + [ __NR_munlock ] = (syscall_handler_t *) sys_munlock, + [ __NR_mlockall ] = (syscall_handler_t *) sys_mlockall, + [ __NR_munlockall ] = (syscall_handler_t *) sys_munlockall, + [ __NR_sched_setparam ] = (syscall_handler_t *) sys_sched_setparam, + [ __NR_sched_getparam ] = (syscall_handler_t *) sys_sched_getparam, + [ __NR_sched_setscheduler ] = (syscall_handler_t *) sys_sched_setscheduler, + [ __NR_sched_getscheduler ] = (syscall_handler_t *) sys_sched_getscheduler, [ __NR_sched_yield ] = (syscall_handler_t *) yield, - [ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max, - [ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min, - [ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval, - [ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep, - [ __NR_mremap ] (syscall_handler_t *) sys_mremap, - [ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16, - [ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16, - [ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_poll ] (syscall_handler_t *) sys_poll, + [ __NR_sched_get_priority_max ] = (syscall_handler_t *) sys_sched_get_priority_max, + [ __NR_sched_get_priority_min ] = (syscall_handler_t *) sys_sched_get_priority_min, + [ __NR_sched_rr_get_interval ] = (syscall_handler_t *) sys_sched_rr_get_interval, + [ __NR_nanosleep ] = (syscall_handler_t *) sys_nanosleep, + [ __NR_mremap ] = (syscall_handler_t *) sys_mremap, + [ __NR_setresuid ] = (syscall_handler_t *) sys_setresuid16, + [ __NR_getresuid ] = (syscall_handler_t *) sys_getresuid16, + [ __NR_query_module ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_poll ] = (syscall_handler_t *) sys_poll, [ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL, - [ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16, - [ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16, - [ __NR_prctl ] (syscall_handler_t *) sys_prctl, - [ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn, - [ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction, - [ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask, - [ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending, - [ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait, - [ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo, - [ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend, - [ __NR_pread64 ] (syscall_handler_t *) sys_pread64, - [ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64, - [ __NR_chown ] (syscall_handler_t *) sys_chown16, - [ __NR_getcwd ] (syscall_handler_t *) sys_getcwd, - [ __NR_capget ] (syscall_handler_t *) sys_capget, - [ __NR_capset ] (syscall_handler_t *) sys_capset, - [ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack, - [ __NR_sendfile ] (syscall_handler_t *) sys_sendfile, - [ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_vfork ] (syscall_handler_t *) sys_vfork, - [ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit, - [ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2, - [ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64, - [ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64, - [ __NR_stat64 ] (syscall_handler_t *) sys_stat64, - [ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64, - [ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64, - [ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64, - [ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64, - [ 223 ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_gettid ] (syscall_handler_t *) sys_gettid, - [ __NR_readahead ] (syscall_handler_t *) sys_readahead, - [ __NR_setxattr ] (syscall_handler_t *) sys_setxattr, - [ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr, - [ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr, - [ __NR_getxattr ] (syscall_handler_t *) sys_getxattr, - [ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr, - [ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr, - [ __NR_listxattr ] (syscall_handler_t *) sys_listxattr, - [ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr, - [ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr, - [ __NR_removexattr ] (syscall_handler_t *) sys_removexattr, - [ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr, - [ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr, - [ __NR_tkill ] (syscall_handler_t *) sys_tkill, - [ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64, - [ __NR_futex ] (syscall_handler_t *) sys_futex, - [ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity, - [ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity, - [ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_io_setup ] (syscall_handler_t *) sys_io_setup, - [ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy, - [ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents, - [ __NR_io_submit ] (syscall_handler_t *) sys_io_submit, - [ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel, - [ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64, - [ 251 ] (syscall_handler_t *) sys_ni_syscall, - [ __NR_exit_group ] (syscall_handler_t *) sys_exit_group, - [ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie, - [ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create, - [ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl, - [ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait, - [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages, - [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address, - [ __NR_timer_create ] (syscall_handler_t *) sys_timer_create, - [ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime, - [ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime, - [ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun, - [ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete, - [ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime, - [ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime, - [ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres, - [ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep, - [ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64, - [ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64, - [ __NR_tgkill ] (syscall_handler_t *) sys_tgkill, - [ __NR_utimes ] (syscall_handler_t *) sys_utimes, - [ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64, - [ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_setresgid ] = (syscall_handler_t *) sys_setresgid16, + [ __NR_getresgid ] = (syscall_handler_t *) sys_getresgid16, + [ __NR_prctl ] = (syscall_handler_t *) sys_prctl, + [ __NR_rt_sigreturn ] = (syscall_handler_t *) sys_rt_sigreturn, + [ __NR_rt_sigaction ] = (syscall_handler_t *) sys_rt_sigaction, + [ __NR_rt_sigprocmask ] = (syscall_handler_t *) sys_rt_sigprocmask, + [ __NR_rt_sigpending ] = (syscall_handler_t *) sys_rt_sigpending, + [ __NR_rt_sigtimedwait ] = (syscall_handler_t *) sys_rt_sigtimedwait, + [ __NR_rt_sigqueueinfo ] = (syscall_handler_t *) sys_rt_sigqueueinfo, + [ __NR_rt_sigsuspend ] = (syscall_handler_t *) sys_rt_sigsuspend, + [ __NR_pread64 ] = (syscall_handler_t *) sys_pread64, + [ __NR_pwrite64 ] = (syscall_handler_t *) sys_pwrite64, + [ __NR_chown ] = (syscall_handler_t *) sys_chown16, + [ __NR_getcwd ] = (syscall_handler_t *) sys_getcwd, + [ __NR_capget ] = (syscall_handler_t *) sys_capget, + [ __NR_capset ] = (syscall_handler_t *) sys_capset, + [ __NR_sigaltstack ] = (syscall_handler_t *) sys_sigaltstack, + [ __NR_sendfile ] = (syscall_handler_t *) sys_sendfile, + [ __NR_getpmsg ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_putpmsg ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_vfork ] = (syscall_handler_t *) sys_vfork, + [ __NR_getdents64 ] = (syscall_handler_t *) sys_getdents64, + [ __NR_gettid ] = (syscall_handler_t *) sys_gettid, + [ __NR_readahead ] = (syscall_handler_t *) sys_readahead, + [ __NR_setxattr ] = (syscall_handler_t *) sys_setxattr, + [ __NR_lsetxattr ] = (syscall_handler_t *) sys_lsetxattr, + [ __NR_fsetxattr ] = (syscall_handler_t *) sys_fsetxattr, + [ __NR_getxattr ] = (syscall_handler_t *) sys_getxattr, + [ __NR_lgetxattr ] = (syscall_handler_t *) sys_lgetxattr, + [ __NR_fgetxattr ] = (syscall_handler_t *) sys_fgetxattr, + [ __NR_listxattr ] = (syscall_handler_t *) sys_listxattr, + [ __NR_llistxattr ] = (syscall_handler_t *) sys_llistxattr, + [ __NR_flistxattr ] = (syscall_handler_t *) sys_flistxattr, + [ __NR_removexattr ] = (syscall_handler_t *) sys_removexattr, + [ __NR_lremovexattr ] = (syscall_handler_t *) sys_lremovexattr, + [ __NR_fremovexattr ] = (syscall_handler_t *) sys_fremovexattr, + [ __NR_tkill ] = (syscall_handler_t *) sys_tkill, + [ __NR_futex ] = (syscall_handler_t *) sys_futex, + [ __NR_sched_setaffinity ] = (syscall_handler_t *) sys_sched_setaffinity, + [ __NR_sched_getaffinity ] = (syscall_handler_t *) sys_sched_getaffinity, + [ __NR_io_setup ] = (syscall_handler_t *) sys_io_setup, + [ __NR_io_destroy ] = (syscall_handler_t *) sys_io_destroy, + [ __NR_io_getevents ] = (syscall_handler_t *) sys_io_getevents, + [ __NR_io_submit ] = (syscall_handler_t *) sys_io_submit, + [ __NR_io_cancel ] = (syscall_handler_t *) sys_io_cancel, + [ __NR_exit_group ] = (syscall_handler_t *) sys_exit_group, + [ __NR_lookup_dcookie ] = (syscall_handler_t *) sys_lookup_dcookie, + [ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create, + [ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl, + [ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait, + [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address, + [ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create, + [ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime, + [ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime, + [ __NR_timer_getoverrun ] = (syscall_handler_t *) sys_timer_getoverrun, + [ __NR_timer_delete ] = (syscall_handler_t *) sys_timer_delete, + [ __NR_clock_settime ] = (syscall_handler_t *) sys_clock_settime, + [ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime, + [ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres, + [ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep, + [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, + [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, + [ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill, + [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, + [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, + [ __NR_vserver ] = (syscall_handler_t *) sys_vserver, + [ __NR_mbind ] = (syscall_handler_t *) sys_mbind, + [ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy, + [ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy, + [ __NR_mq_open ] = (syscall_handler_t *) sys_mq_open, + [ __NR_mq_unlink ] = (syscall_handler_t *) sys_mq_unlink, + [ __NR_mq_timedsend ] = (syscall_handler_t *) sys_mq_timedsend, + [ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive, + [ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify, + [ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr, + [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_kexec_load, + [ __NR_waitid ] = (syscall_handler_t *) sys_waitid, +#if 0 + [ __NR_sys_setaltroot ] = (syscall_handler_t *) sys_sys_setaltroot, +#endif + [ __NR_add_key ] = (syscall_handler_t *) sys_add_key, + [ __NR_request_key ] = (syscall_handler_t *) sys_request_key, + [ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl, + [ __NR_vperfctr_open ] = (syscall_handler_t *) sys_vperfctr_open, + [ __NR_vperfctr_control ] = (syscall_handler_t *) sys_vperfctr_control, + [ __NR_vperfctr_unlink ] = (syscall_handler_t *) sys_vperfctr_unlink, + [ __NR_vperfctr_iresume ] = (syscall_handler_t *) sys_vperfctr_iresume, + [ __NR_vperfctr_read ] = (syscall_handler_t *) sys_vperfctr_read, ARCH_SYSCALLS [ LAST_SYSCALL + 1 ... NR_syscalls ] = diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c index a549b3b1410f2b..a294e5071fe8f2 100644 --- a/arch/um/kernel/syscall_kern.c +++ b/arch/um/kernel/syscall_kern.c @@ -27,10 +27,9 @@ /* Unlocked, I don't care if this is a bit off */ int nsyscalls = 0; -long um_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void * data) +long um_mount(char __user * dev_name, char __user * dir_name, + char __user * type, unsigned long new_flags, void __user * data) { - if(type == NULL) type = ""; return(sys_mount(dev_name, dir_name, type, new_flags, data)); } @@ -56,12 +55,11 @@ long sys_vfork(void) } /* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) +long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) { - int error = -EBADF; + long error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); @@ -81,38 +79,15 @@ static inline long do_mmap2( return error; } -long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - -/* - * Perform the select(nd, in, out, ex, tv) and mmap() system - * calls. Linux/i386 didn't use to be able to handle more than - * 4 system call parameters, so these system calls used a memory - * block for parameter passing.. - */ - -struct mmap_arg_struct { - unsigned long addr; - unsigned long len; - unsigned long prot; - unsigned long flags; - unsigned long fd; - unsigned long offset; -}; - long old_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long offset) + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset) { long err = -EINVAL; if (offset & ~PAGE_MASK) goto out; - err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); out: return err; } @@ -120,7 +95,7 @@ long old_mmap(unsigned long addr, unsigned long len, * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -long sys_pipe(unsigned long * fildes) +long sys_pipe(unsigned long __user * fildes) { int fd[2]; long error; @@ -133,90 +108,6 @@ long sys_pipe(unsigned long * fildes) return error; } -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - switch (call) { - case SEMOP: - return sys_semtimedop(first, (struct sembuf *) ptr, second, - NULL); - case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf *) ptr, second, - (const struct timespec *) fifth); - case SEMGET: - return sys_semget (first, second, third); - case SEMCTL: { - union semun fourth; - if (!ptr) - return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) - return -EFAULT; - return sys_semctl (first, second, third, fourth); - } - - case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - if (!ptr) - return -EINVAL; - - if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, - sizeof (tmp))) - return -EFAULT; - return sys_msgrcv (first, tmp.msgp, second, - tmp.msgtyp, third); - } - default: - panic("msgrcv with version != 0"); - return sys_msgrcv (first, - (struct msgbuf *) ptr, - second, fifth, third); - } - case MSGGET: - return sys_msgget ((key_t) first, second); - case MSGCTL: - return sys_msgctl (first, second, (struct msqid_ds *) ptr); - - case SHMAT: - switch (version) { - default: { - ulong raddr; - ret = do_shmat (first, (char *) ptr, second, &raddr); - if (ret) - return ret; - return put_user (raddr, (ulong *) third); - } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - return do_shmat (first, (char *) ptr, second, (ulong *) third); - } - case SHMDT: - return sys_shmdt ((char *)ptr); - case SHMGET: - return sys_shmget (first, second, third); - case SHMCTL: - return sys_shmctl (first, second, - (struct shmid_ds *) ptr); - default: - return -ENOSYS; - } -} long sys_uname(struct old_utsname * name) { diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 498344110eee03..df21b0529ae62a 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -111,19 +111,19 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) return(IRQ_HANDLED); } -long um_time(int * tloc) +long um_time(int __user *tloc) { struct timeval now; do_gettimeofday(&now); if (tloc) { - if (put_user(now.tv_sec,tloc)) + if (put_user(now.tv_sec, tloc)) now.tv_sec = -EFAULT; } return now.tv_sec; } -long um_stime(int * tptr) +long um_stime(int __user *tptr) { int value; struct timespec new; @@ -136,22 +136,7 @@ long um_stime(int * tptr) return 0; } -/* XXX Needs to be moved under sys-i386 */ -void __delay(um_udelay_t time) -{ - /* Stolen from the i386 __loop_delay */ - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (time)); -} - -void __udelay(um_udelay_t usecs) +void __udelay(unsigned long usecs) { int i, n; @@ -159,7 +144,7 @@ void __udelay(um_udelay_t usecs) for(i=0;i<n;i++) ; } -void __const_udelay(um_udelay_t usecs) +void __const_udelay(unsigned long usecs) { int i, n; diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index c42053140e2b91..26f5d12d81f340 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) return(pgd_offset(mm, address)); } -pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) +pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) { - return(pmd_offset(pgd, address)); + return(pud_offset(pgd, address)); +} + +pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) +{ + return(pmd_offset(pud, address)); } pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) @@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) pte_t *addr_pte(struct task_struct *task, unsigned long addr) { - return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr), - addr)); + pgd_t *pgd = pgd_offset(task->mm, addr); + pud_t *pud = pud_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); + + return(pte_offset_map(pmd, addr)); } /* diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index cba33ef6da5d8c..80d07fe6b97923 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -13,6 +13,7 @@ #include "linux/ptrace.h" #include "asm/semaphore.h" #include "asm/pgtable.h" +#include "asm/pgalloc.h" #include "asm/tlbflush.h" #include "asm/a.out.h" #include "asm/current.h" @@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long page; @@ -55,7 +57,8 @@ int handle_page_fault(unsigned long address, unsigned long ip, goto out; page = address & PAGE_MASK; pgd = pgd_offset(mm, page); - pmd = pmd_offset(pgd, page); + pud = pud_offset(pgd, page); + pmd = pmd_offset(pud, page); do { survive: switch (handle_mm_fault(mm, vma, address, is_write)){ @@ -74,6 +77,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, default: BUG(); } + pgd = pgd_offset(mm, page); + pud = pud_offset(pgd, page); + pmd = pmd_offset(pud, page); pte = pte_offset_kernel(pmd, page); } while(!pte_present(*pte)); err = 0; diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c index 73103c29aff715..0a3d279ce64f0c 100644 --- a/arch/um/kernel/trap_user.c +++ b/arch/um/kernel/trap_user.c @@ -102,28 +102,6 @@ struct signal_info sig_info[] = { .is_irq = 0 }, }; -void sig_handler(int sig, struct sigcontext sc) -{ - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, &sc); -} - -extern int timer_irq_inited; - -void alarm_handler(int sig, struct sigcontext sc) -{ - if(!timer_irq_inited) return; - - if(sig == SIGALRM) - switch_timers(0); - - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, &sc); - - if(sig == SIGALRM) - switch_timers(1); -} - void do_longjmp(void *b, int val) { sigjmp_buf *buf = b; diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile index 17f4594dc2314b..7c9eec5fded52c 100644 --- a/arch/um/kernel/tt/Makefile +++ b/arch/um/kernel/tt/Makefile @@ -24,6 +24,9 @@ $(USER_OBJS) : %.o: %.c $(obj)/unmap.o: $(src)/unmap.c $(CC) $(UNMAP_CFLAGS) -c -o $@ $< +LIBC_DIR ?= /usr/lib + $(obj)/unmap_fin.o : $(obj)/unmap.o - ld -r -o $(obj)/unmap_tmp.o $< -lc -L/usr/lib + ld -r -o $(obj)/unmap_tmp.o $< -lc -L$(LIBC_DIR) objcopy $(obj)/unmap_tmp.o $@ -G switcheroo + diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 10db6d6ab7ea65..22cbdbffbe3e65 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -162,7 +162,7 @@ int gdb_remove(char *unused) void signal_usr1(int sig) { if(debugger_pid != -1){ - printk(UM_KERN_ERR "The debugger is already running\n"); + printf("The debugger is already running\n"); return; } debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); @@ -228,19 +228,19 @@ int debugger_signal(int status, pid_t pid){ return(0); } void child_signal(pid_t pid, int status){ } int init_ptrace_proxy(int idle_pid, int startup, int stop) { - printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); + printf("debug requested when CONFIG_PT_PROXY is off\n"); kill_child_dead(idle_pid); exit(1); } void signal_usr1(int sig) { - printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); + printf("debug requested when CONFIG_PT_PROXY is off\n"); } int attach_debugger(int idle_pid, int pid, int stop) { - printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY " + printf("attach_debugger called when CONFIG_PT_PROXY " "is off\n"); return(-1); } diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c index 458ecf9a45f182..f41832c79f364d 100644 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ b/arch/um/kernel/tt/ptproxy/proxy.c @@ -94,7 +94,9 @@ int debugger_syscall(debugger_state *debugger, pid_t child) debugger->handle_trace = debugger_syscall; return(ret); +#ifdef __NR_waitpid case __NR_waitpid: +#endif case __NR_wait4: if(!debugger_wait(debugger, (int *) arg2, arg3, debugger_syscall, debugger_normal_return, @@ -153,7 +155,11 @@ static int parent_syscall(debugger_state *debugger, int pid) syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); - if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){ + if((syscall == __NR_wait4) +#ifdef __NR_waitpid + || (syscall == __NR_waitpid) +#endif + ){ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, parent_normal_return, parent_wait_return); } diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index c42855aeda6052..4545ea4f27e164 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -12,7 +12,6 @@ terms and conditions. #include <errno.h> #include <sys/types.h> #include <sys/ptrace.h> -#include <asm/ptrace.h> #include <linux/unistd.h> #include "ptrace_user.h" #include "user_util.h" diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c index 86ef67653e7261..fcb7ea50fc7e60 100644 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ b/arch/um/kernel/tt/ptproxy/wait.c @@ -10,7 +10,6 @@ terms and conditions. #include <signal.h> #include <sys/wait.h> #include <sys/ptrace.h> -#include <asm/ptrace.h> #include "ptproxy.h" #include "sysdep.h" diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 891045bb966a5c..c02e504e54c1b3 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c @@ -14,95 +14,6 @@ #include "sysdep/syscalls.h" #include "kern_util.h" -static inline int check_area(void *ptr, int size) -{ - return(verify_area(VERIFY_WRITE, ptr, size)); -} - -static int check_readlink(struct pt_regs *regs) -{ - return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), - UPT_SYSCALL_ARG2(®s->regs))); -} - -static int check_utime(struct pt_regs *regs) -{ - return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), - sizeof(struct utimbuf))); -} - -static int check_oldstat(struct pt_regs *regs) -{ - return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), - sizeof(struct __old_kernel_stat))); -} - -static int check_stat(struct pt_regs *regs) -{ - return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), - sizeof(struct stat))); -} - -static int check_stat64(struct pt_regs *regs) -{ - return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), - sizeof(struct stat64))); -} - -struct bogus { - int kernel_ds; - int (*check_params)(struct pt_regs *); -}; - -struct bogus this_is_bogus[256] = { - [ __NR_mknod ] = { 1, NULL }, - [ __NR_mkdir ] = { 1, NULL }, - [ __NR_rmdir ] = { 1, NULL }, - [ __NR_unlink ] = { 1, NULL }, - [ __NR_symlink ] = { 1, NULL }, - [ __NR_link ] = { 1, NULL }, - [ __NR_rename ] = { 1, NULL }, - [ __NR_umount ] = { 1, NULL }, - [ __NR_mount ] = { 1, NULL }, - [ __NR_pivot_root ] = { 1, NULL }, - [ __NR_chdir ] = { 1, NULL }, - [ __NR_chroot ] = { 1, NULL }, - [ __NR_open ] = { 1, NULL }, - [ __NR_quotactl ] = { 1, NULL }, - [ __NR_sysfs ] = { 1, NULL }, - [ __NR_readlink ] = { 1, check_readlink }, - [ __NR_acct ] = { 1, NULL }, - [ __NR_execve ] = { 1, NULL }, - [ __NR_uselib ] = { 1, NULL }, - [ __NR_statfs ] = { 1, NULL }, - [ __NR_truncate ] = { 1, NULL }, - [ __NR_access ] = { 1, NULL }, - [ __NR_chmod ] = { 1, NULL }, - [ __NR_chown ] = { 1, NULL }, - [ __NR_lchown ] = { 1, NULL }, - [ __NR_utime ] = { 1, check_utime }, - [ __NR_oldlstat ] = { 1, check_oldstat }, - [ __NR_oldstat ] = { 1, check_oldstat }, - [ __NR_stat ] = { 1, check_stat }, - [ __NR_lstat ] = { 1, check_stat }, - [ __NR_stat64 ] = { 1, check_stat64 }, - [ __NR_lstat64 ] = { 1, check_stat64 }, - [ __NR_chown32 ] = { 1, NULL }, -}; - -/* sys_utimes */ - -static int check_bogosity(struct pt_regs *regs) -{ - struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(®s->regs)]; - - if(!bogon->kernel_ds) return(0); - if(bogon->check_params && (*bogon->check_params)(regs)) - return(-EFAULT); - set_fs(KERNEL_DS); - return(0); -} - extern syscall_handler_t *sys_call_table[]; long execute_syscall_tt(void *r) @@ -117,12 +28,8 @@ long execute_syscall_tt(void *r) if((syscall >= NR_syscalls) || (syscall < 0)) res = -ENOSYS; - else if(honeypot && check_bogosity(regs)) - res = -EFAULT; else res = EXECUTE_SYSCALL(syscall, regs); - set_fs(USER_DS); - return(res); } diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index d8ad334cfac933..3bc35eea1da4ad 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -19,9 +20,10 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { pgd_t *npgd; + pud_t *npud; pmd_t *npmd; pte_t *npte; - unsigned long addr; + unsigned long addr, end; int r, w, x, err; if((current->thread.mode.tt.extern_pid != -1) && @@ -41,45 +43,81 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, addr = STACK_TOP - ABOVE_KMEM; continue; } + npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); - if(pmd_present(*npmd)){ - npte = pte_offset_kernel(npmd, addr); - r = pte_read(*npte); - w = pte_write(*npte); - x = pte_exec(*npte); - if(!pte_dirty(*npte)) w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } - if(force || pte_newpage(*npte)){ + if(!pgd_present(*npgd)){ + if(force || pgd_newpage(*npgd)){ + end = addr + PGDIR_SIZE; + if(end > end_addr) + end = end_addr; + err = os_unmap_memory((void *) addr, + end - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + pgd_mkuptodate(*npgd); + } + addr += PGDIR_SIZE; + continue; + } + + npud = pud_offset(npgd, addr); + if(!pud_present(*npud)){ + if(force || pud_newpage(*npud)){ + end = addr + PUD_SIZE; + if(end > end_addr) + end = end_addr; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*npte)) - map_memory(addr, - pte_val(*npte) & PAGE_MASK, - PAGE_SIZE, r, w, x); - } - else if(pte_newprot(*npte)){ - protect_memory(addr, PAGE_SIZE, r, w, x, 1); + pud_mkuptodate(*npud); } - *npte = pte_mkuptodate(*npte); - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + npmd = pmd_offset(npud, addr); + if(!pmd_present(*npmd)){ if(force || pmd_newpage(*npmd)){ - err = os_unmap_memory((void *) addr, PMD_SIZE); + end = addr + PMD_SIZE; + if(end > end_addr) + end = end_addr; + err = os_unmap_memory((void *) addr, + end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); pmd_mkuptodate(*npmd); } addr += PMD_SIZE; + continue; } + + npte = pte_offset_kernel(npmd, addr); + r = pte_read(*npte); + w = pte_write(*npte); + x = pte_exec(*npte); + if(!pte_dirty(*npte)) + w = 0; + if(!pte_young(*npte)){ + r = 0; + w = 0; + } + if(force || pte_newpage(*npte)){ + err = os_unmap_memory((void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*npte)) + map_memory(addr, pte_val(*npte) & PAGE_MASK, + PAGE_SIZE, r, w, x); + } + else if(pte_newprot(*npte)) + protect_memory(addr, PAGE_SIZE, r, w, x, 1); + + *npte = pte_mkuptodate(*npte); + addr += PAGE_SIZE; } } @@ -90,45 +128,83 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned long addr; + unsigned long addr, last; int updated = 0, err; mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); - if(pmd_present(*pmd)){ - pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte) || pte_newpage(*pte)){ + if(!pgd_present(*pgd)){ + if(pgd_newpage(*pgd)){ updated = 1; + last = addr + PGDIR_SIZE; + if(last > end) + last = end; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*pte)) - map_memory(addr, - pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, 1, 1, 1); } - else if(pte_newprot(*pte)){ + addr += PGDIR_SIZE; + continue; + } + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)){ + if(pud_newpage(*pud)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + last = addr + PUD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); } - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + pmd = pmd_offset(pud, addr); + if(!pmd_present(*pmd)){ if(pmd_newpage(*pmd)){ updated = 1; - err = os_unmap_memory((void *) addr, PMD_SIZE); + last = addr + PMD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } addr += PMD_SIZE; + continue; + } + + pte = pte_offset_kernel(pmd, addr); + if(!pte_present(*pte) || pte_newpage(*pte)){ + updated = 1; + err = os_unmap_memory((void *) addr, + PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + if(pte_present(*pte)) + map_memory(addr, + pte_val(*pte) & PAGE_MASK, + PAGE_SIZE, 1, 1, 1); + } + else if(pte_newprot(*pte)){ + updated = 1; + protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); } + addr += PAGE_SIZE; } if(updated && update_seq) atomic_inc(&vmchange_seq); } @@ -155,6 +231,7 @@ void mprotect_kernel_vm(int w) { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long addr; @@ -162,7 +239,8 @@ void mprotect_kernel_vm(int w) mm = &init_mm; for(addr = start_vm; addr < end_vm;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(pte_present(*pte)) protect_vm_page(addr, w, 0); diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index e1f3506e9d1d73..de5dcd2504256e 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -84,6 +84,7 @@ void tracer_panic(char *format, ...) va_start(ap, format); vprintf(format, ap); + va_end(ap); printf("\n"); while(1) pause(); } diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index 00bacacfcc3529..67fdef69d54eed 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -6,7 +6,6 @@ #include <stdlib.h> #include <errno.h> #include <signal.h> -#include <asm/sigcontext.h> #include "sysdep/ptrace.h" #include "signal_user.h" #include "user_util.h" diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index 0409718935f71e..a72aa632972f4e 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c @@ -6,7 +6,7 @@ #include "linux/sched.h" #include "asm/uaccess.h" -int copy_from_user_tt(void *to, const void *from, int n) +int copy_from_user_tt(void *to, const void __user *from, int n) { if(!access_ok_tt(VERIFY_READ, from, n)) return(n); @@ -15,7 +15,7 @@ int copy_from_user_tt(void *to, const void *from, int n) ¤t->thread.fault_catcher)); } -int copy_to_user_tt(void *to, const void *from, int n) +int copy_to_user_tt(void __user *to, const void *from, int n) { if(!access_ok_tt(VERIFY_WRITE, to, n)) return(n); @@ -24,7 +24,7 @@ int copy_to_user_tt(void *to, const void *from, int n) ¤t->thread.fault_catcher)); } -int strncpy_from_user_tt(char *dst, const char *src, int count) +int strncpy_from_user_tt(char *dst, const char __user *src, int count) { int n; @@ -38,14 +38,14 @@ int strncpy_from_user_tt(char *dst, const char *src, int count) return(n); } -int __clear_user_tt(void *mem, int len) +int __clear_user_tt(void __user *mem, int len) { return(__do_clear_user(mem, len, ¤t->thread.fault_addr, ¤t->thread.fault_catcher)); } -int clear_user_tt(void *mem, int len) +int clear_user_tt(void __user *mem, int len) { if(!access_ok_tt(VERIFY_WRITE, mem, len)) return(len); @@ -54,7 +54,7 @@ int clear_user_tt(void *mem, int len) ¤t->thread.fault_catcher)); } -int strnlen_user_tt(const void *str, int len) +int strnlen_user_tt(const void __user *str, int len) { return(__do_strnlen_user(str, len, ¤t->thread.fault_addr, diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 1ce25f89f8acf3..8096843e4d4cba 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -17,6 +17,7 @@ #include "linux/sysrq.h" #include "linux/seq_file.h" #include "linux/delay.h" +#include "linux/module.h" #include "asm/page.h" #include "asm/pgtable.h" #include "asm/ptrace.h" @@ -156,6 +157,8 @@ static int __init uml_version_setup(char *line, int *add) { printf("%s\n", system_utsname.release); exit(0); + + return 0; } __uml_setup("--version", uml_version_setup, @@ -256,6 +259,8 @@ static int __init Usage(char *line, int *add) p++; } exit(0); + + return 0; } __uml_setup("--help", Usage, diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 3521466db282a7..f8378124be1357 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,10 +3,13 @@ # Licensed under the GPL # -obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/ +obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \ + sys-$(SUBARCH)/ -USER_OBJS := elf_aux.o file.o process.o time.o tty.o +USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< + +CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 36575ff8bfac7e..9aee0b62ebca19 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -26,7 +26,6 @@ unsigned long vsyscall_end; unsigned long __kernel_vsyscall; - __init void scan_elf_aux( char **envp) { long page_size = 0; diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c new file mode 100644 index 00000000000000..7eac1baf597568 --- /dev/null +++ b/arch/um/os-Linux/signal.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Licensed under the GPL + */ + +#include <signal.h> +#include "time_user.h" +#include "mode.h" +#include "sysdep/signal.h" + +void sig_handler(int sig) +{ + struct sigcontext *sc; + + ARCH_GET_SIGCONTEXT(sc, sig); + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, + sig, sc); +} + +extern int timer_irq_inited; + +void alarm_handler(int sig) +{ + struct sigcontext *sc; + + ARCH_GET_SIGCONTEXT(sc, sig); + if(!timer_irq_inited) return; + + if(sig == SIGALRM) + switch_timers(0); + + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, + sig, sc); + + if(sig == SIGALRM) + switch_timers(1); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile new file mode 100644 index 00000000000000..bdfa841fca165d --- /dev/null +++ b/arch/um/os-Linux/sys-i386/Makefile @@ -0,0 +1,11 @@ +# +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +obj-$(CONFIG_MODE_SKAS) = registers.o + +USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file)) + +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c new file mode 100644 index 00000000000000..cbfbaf2ab78d81 --- /dev/null +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Licensed under the GPL + */ + +#include <errno.h> +#include <string.h> +#include <sys/ptrace.h> +#include "sysdep/ptrace.h" +#include "uml-config.h" +#include "skas_ptregs.h" +#include "registers.h" +#include "user.h" + +/* These are set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[HOST_FRAME_SIZE]; +static unsigned long exec_fp_regs[HOST_FP_SIZE]; +static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; +static int have_fpx_regs = 1; + +void init_thread_registers(union uml_pt_regs *to) +{ + memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); + memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); + if(have_fpx_regs) + memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); +} + +static int move_registers(int pid, int int_op, union uml_pt_regs *regs, + int fp_op, unsigned long *fp_regs) +{ + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) + return(-errno); + + if(ptrace(fp_op, pid, 0, fp_regs) < 0) + return(-errno); + + return(0); +} + +void save_registers(int pid, union uml_pt_regs *regs) +{ + unsigned long *fp_regs; + int err, fp_op; + + if(have_fpx_regs){ + fp_op = PTRACE_GETFPXREGS; + fp_regs = regs->skas.xfp; + } + else { + fp_op = PTRACE_GETFPREGS; + fp_regs = regs->skas.fp; + } + + err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); + if(err) + panic("save_registers - saving registers failed, errno = %d\n", + -err); +} + +void restore_registers(int pid, union uml_pt_regs *regs) +{ + unsigned long *fp_regs; + int err, fp_op; + + if(have_fpx_regs){ + fp_op = PTRACE_SETFPXREGS; + fp_regs = regs->skas.xfp; + } + else { + fp_op = PTRACE_SETFPREGS; + fp_regs = regs->skas.fp; + } + + err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); + if(err) + panic("restore_registers - saving registers failed, " + "errno = %d\n", -err); +} + +void init_registers(int pid) +{ + int err; + + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if(err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", + err); + + err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); + if(!err) + return; + + have_fpx_regs = 0; + if(err != EIO) + panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", + err); + + err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); + if(err) + panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", + err); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile new file mode 100644 index 00000000000000..bdfa841fca165d --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/Makefile @@ -0,0 +1,11 @@ +# +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +obj-$(CONFIG_MODE_SKAS) = registers.o + +USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file)) + +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c new file mode 100644 index 00000000000000..31b1f4fa67e0e0 --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Licensed under the GPL + */ + +#include <errno.h> +#include <string.h> +#include <sys/ptrace.h> +#include "sysdep/ptrace.h" +#include "uml-config.h" +#include "skas_ptregs.h" +#include "registers.h" +#include "user.h" + +/* These are set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[HOST_FRAME_SIZE]; +static unsigned long exec_fp_regs[HOST_FP_SIZE]; + +void init_thread_registers(union uml_pt_regs *to) +{ + memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); + memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); +} + +static int move_registers(int pid, int int_op, int fp_op, + union uml_pt_regs *regs) +{ + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) + return(-errno); + + if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) + return(-errno); + + return(0); +} + +void save_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); + if(err) + panic("save_registers - saving registers failed, errno = %d\n", + -err); +} + +void restore_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); + if(err) + panic("restore_registers - saving registers failed, " + "errno = %d\n", -err); +} + +void init_registers(int pid) +{ + int err; + + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if(err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", + err); + + err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); + if(err) + panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", + err); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 383ac7b52beb0a..75d7af9ae1d226 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -26,9 +26,6 @@ EXPORT_SYMBOL(printf); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(vsyscall_ehdr); -EXPORT_SYMBOL(vsyscall_end); - /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. * However, the modules will use the CRC defined *here*, no matter if it is * good; so the versions of these symbols will always match @@ -37,6 +34,11 @@ EXPORT_SYMBOL(vsyscall_end); int sym(void); \ EXPORT_SYMBOL(sym); +#ifdef SUBARCH_i386 +EXPORT_SYMBOL(vsyscall_ehdr); +EXPORT_SYMBOL(vsyscall_end); +#endif + EXPORT_SYMBOL_PROTO(__errno_location); EXPORT_SYMBOL_PROTO(access); diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 45cc75f63a756f..8a0994b696b00f 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,4 +1,4 @@ -obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \ +obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o obj-$(CONFIG_HIGHMEM) += highmem.o diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c new file mode 100644 index 00000000000000..20d37dbbaf08be --- /dev/null +++ b/arch/um/sys-i386/delay.c @@ -0,0 +1,14 @@ +void __delay(unsigned long time) +{ + /* Stolen from the i386 __loop_delay */ + int d0; + __asm__ __volatile__( + "\tjmp 1f\n" + ".align 16\n" + "1:\tjmp 2f\n" + ".align 16\n" + "2:\tdecl %0\n\tjns 2b" + :"=&a" (d0) + :"0" (time)); +} + diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index ba77ccaa836122..e97b98806af797 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -15,17 +15,21 @@ extern int modify_ldt(int func, void *ptr, unsigned long bytecount); /* XXX this needs copy_to_user and copy_from_user */ -int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) +int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount) { - if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); - return(modify_ldt(func, ptr, bytecount)); + if (verify_area(VERIFY_READ, ptr, bytecount)) + return -EFAULT; + + return modify_ldt(func, ptr, bytecount); } #endif #ifdef CONFIG_MODE_SKAS extern int userspace_pid; -int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) +#include "skas_ptrace.h" + +int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount) { struct ptrace_ldt ldt; void *buf; @@ -74,7 +78,7 @@ int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) } #endif -int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) +int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, ptr, bytecount)); diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 42322d88850349..c6a1bba337eacb 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -3,6 +3,8 @@ * Licensed under the GPL */ +#include <linux/config.h> +#include <linux/compiler.h> #include "linux/sched.h" #include "asm/elf.h" #include "asm/ptrace.h" @@ -22,7 +24,7 @@ int is_syscall(unsigned long addr) unsigned short instr; int n; - n = copy_from_user(&instr, (void *) addr, sizeof(instr)); + n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); if(n){ printk("is_syscall : failed to read instruction from 0x%lx\n", addr); @@ -175,12 +177,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave */ #ifdef CONFIG_MODE_TT -static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, +static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, struct pt_regs *regs) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; - struct _fpreg *to; + struct _fpreg __user *to; struct _fpxreg *from; int i; @@ -205,7 +207,7 @@ static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, } #endif -static inline int convert_fxsr_to_user(struct _fpstate *buf, +static inline int convert_fxsr_to_user(struct _fpstate __user *buf, struct pt_regs *regs) { return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); @@ -213,12 +215,12 @@ static inline int convert_fxsr_to_user(struct _fpstate *buf, #ifdef CONFIG_MODE_TT static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; struct _fpxreg *to; - struct _fpreg *from; + struct _fpreg __user *from; int i; if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) @@ -244,7 +246,7 @@ static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, #endif static inline int convert_fxsr_from_user(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); } @@ -253,7 +255,7 @@ int get_fpregs(unsigned long buf, struct task_struct *child) { int err; - err = convert_fxsr_to_user((struct _fpstate *) buf, + err = convert_fxsr_to_user((struct _fpstate __user *) buf, &child->thread.regs); if(err) return(-EFAULT); else return(0); @@ -264,7 +266,7 @@ int set_fpregs(unsigned long buf, struct task_struct *child) int err; err = convert_fxsr_from_user(&child->thread.regs, - (struct _fpstate *) buf); + (struct _fpstate __user *) buf); if(err) return(-EFAULT); else return(0); } @@ -276,7 +278,7 @@ int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_to_user((void *) buf, fxsave, + err = __copy_to_user((void __user *) buf, fxsave, sizeof(struct user_fxsr_struct)); if(err) return -EFAULT; else return 0; @@ -295,7 +297,7 @@ int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_from_user(fxsave, (void *) buf, + err = __copy_from_user(fxsave, (void __user *) buf, sizeof(struct user_fxsr_struct) ); if(err) return -EFAULT; else return 0; diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c index a30140331cf7f9..467d489c31cd00 100644 --- a/arch/um/sys-i386/sigcontext.c +++ b/arch/um/sys-i386/sigcontext.c @@ -22,8 +22,7 @@ void sc_to_sc(void *to_ptr, void *from_ptr) unsigned long *sc_sigmask(void *sc_ptr) { struct sigcontext *sc = sc_ptr; - - return(&sc->oldmask); + return &sc->oldmask; } int sc_get_fpregs(unsigned long buf, void *sc_ptr) diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 6794671be7a36b..0cb4c86b5c2b5b 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -146,7 +146,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, } #endif -static int copy_sc_from_user(struct pt_regs *to, void *from) +static int copy_sc_from_user(struct pt_regs *to, void __user *from) { int ret; diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index 6ad31749bfe721..dd58b5511e9b6e 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c @@ -1,9 +1,11 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/sched.h" +#include "linux/shm.h" +#include "asm/ipc.h" #include "asm/mman.h" #include "asm/uaccess.h" #include "asm/unistd.h" @@ -28,7 +30,7 @@ extern int old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset); -int old_mmap_i386(struct mmap_arg_struct *arg) +long old_mmap_i386(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int err = -EFAULT; @@ -43,11 +45,13 @@ int old_mmap_i386(struct mmap_arg_struct *arg) struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp; + fd_set __user *outp; + fd_set __user *exp; + struct timeval __user *tvp; }; -int old_select(struct sel_arg_struct *arg) +long old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -60,8 +64,8 @@ int old_select(struct sel_arg_struct *arg) /* The i386 version skips reading from %esi, the fourth argument. So we must do * this, too. */ -int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, - int unused, int *child_tid) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tid, int unused, int __user *child_tid) { long ret; @@ -79,6 +83,122 @@ int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, } /* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +long sys_ipc (uint call, int first, int second, + int third, void *__user ptr, long fifth) +{ + int version, ret; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + switch (call) { + case SEMOP: + return sys_semtimedop(first, (struct sembuf *) ptr, second, + NULL); + case SEMTIMEDOP: + return sys_semtimedop(first, (struct sembuf *) ptr, second, + (const struct timespec *) fifth); + case SEMGET: + return sys_semget (first, second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void **) ptr)) + return -EFAULT; + return sys_semctl (first, second, third, fourth); + } + + case MSGSND: + return sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + if (!ptr) + return -EINVAL; + + if (copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, second, + tmp.msgtyp, third); + } + default: + panic("msgrcv with version != 0"); + return sys_msgrcv (first, + (struct msgbuf *) ptr, + second, fifth, third); + } + case MSGGET: + return sys_msgget ((key_t) first, second); + case MSGCTL: + return sys_msgctl (first, second, (struct msqid_ds *) ptr); + + case SHMAT: + switch (version) { + default: { + ulong raddr; + ret = do_shmat (first, (char *) ptr, second, &raddr); + if (ret) + return ret; + return put_user (raddr, (ulong *) third); + } + case 1: /* iBCS2 emulator entry point */ + if (!segment_eq(get_fs(), get_ds())) + return -EINVAL; + return do_shmat (first, (char *) ptr, second, (ulong *) third); + } + case SHMDT: + return sys_shmdt ((char *)ptr); + case SHMGET: + return sys_shmget (first, second, third); + case SHMCTL: + return sys_shmctl (first, second, + (struct shmid_ds *) ptr); + default: + return -ENOSYS; + } +} + +long sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +/* * 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 diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile new file mode 100644 index 00000000000000..1ec504b7681091 --- /dev/null +++ b/arch/um/sys-x86_64/Makefile @@ -0,0 +1,39 @@ +# +# Copyright 2003 PathScale, Inc. +# +# Licensed under the GPL +# + +lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ + ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ + syscalls.o sysrq.o thunk.o + +USER_OBJS := ptrace_user.o sigcontext.o +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) + +SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ + semaphore.c thunk.S +SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f) + +clean-files := $(SYMLINKS) + +bitops.c-dir = lib +csum-copy.S-dir = lib +csum-partial.c-dir = lib +csum-wrappers.c-dir = lib +memcpy.S-dir = lib +semaphore.c-dir = kernel +thunk.S-dir = lib + +define make_link + -rm -f $1 + ln -sf $(TOPDIR)/arch/x86_64/$($(notdir $1)-dir)/$(notdir $1) $1 +endef + +$(SYMLINKS): + $(call make_link,$@) + +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< + +CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c new file mode 100644 index 00000000000000..fdce7ea98ca79c --- /dev/null +++ b/arch/um/sys-x86_64/bugs.c @@ -0,0 +1,122 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "linux/errno.h" +#include "asm/system.h" +#include "asm/pda.h" +#include "sysdep/ptrace.h" +#include "os.h" + +void arch_init_thread(void) +{ +} + +void arch_check_bugs(void) +{ +} + +int arch_handle_signal(int sig, union uml_pt_regs *regs) +{ + return(0); +} + +#define MAXTOKEN 64 + +/* Set during early boot */ +int host_has_cmov = 1; +int host_has_xmm = 0; + +static char token(int fd, char *buf, int len, char stop) +{ + int n; + char *ptr, *end, c; + + ptr = buf; + end = &buf[len]; + do { + n = os_read_file(fd, ptr, sizeof(*ptr)); + c = *ptr++; + if(n != sizeof(*ptr)){ + if(n == 0) return(0); + printk("Reading /proc/cpuinfo failed, err = %d\n", -n); + if(n < 0) + return(n); + else + return(-EIO); + } + } while((c != '\n') && (c != stop) && (ptr < end)); + + if(ptr == end){ + printk("Failed to find '%c' in /proc/cpuinfo\n", stop); + return(-1); + } + *(ptr - 1) = '\0'; + return(c); +} + +static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) +{ + int n; + char c; + + scratch[len - 1] = '\0'; + while(1){ + c = token(fd, scratch, len - 1, ':'); + if(c <= 0) + return(0); + else if(c != ':'){ + printk("Failed to find ':' in /proc/cpuinfo\n"); + return(0); + } + + if(!strncmp(scratch, key, strlen(key))) + return(1); + + do { + n = os_read_file(fd, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("Failed to find newline in " + "/proc/cpuinfo, err = %d\n", -n); + return(0); + } + } while(c != '\n'); + } + return(0); +} + +int cpu_feature(char *what, char *buf, int len) +{ + int fd, ret = 0; + + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + if(!find_cpuinfo_line(fd, what, buf, len)){ + printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); + goto out_close; + } + + token(fd, buf, len, '\n'); + ret = 1; + + out_close: + os_close_file(fd); + return(ret); +} + +/* 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/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c new file mode 100644 index 00000000000000..f3b5187942b4e6 --- /dev/null +++ b/arch/um/sys-x86_64/delay.c @@ -0,0 +1,26 @@ +/* + * Copyright 2003 PathScale, Inc. + * Copied from arch/x86_64 + * + * Licensed under the GPL + */ + +#include "asm/processor.h" + +void __delay(unsigned long loops) +{ + unsigned long i; + + for(i = 0; i < loops; i++) ; +} + +/* + * 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/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c new file mode 100644 index 00000000000000..cee1513c5c3163 --- /dev/null +++ b/arch/um/sys-x86_64/fault.c @@ -0,0 +1,23 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "user.h" + +int arch_fixup(unsigned long address, void *sc_ptr) +{ + /* XXX search_exception_tables() */ + 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/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c new file mode 100644 index 00000000000000..3f59a0a4f15604 --- /dev/null +++ b/arch/um/sys-x86_64/mem.c @@ -0,0 +1,25 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/mm.h" +#include "asm/page.h" +#include "asm/mman.h" + +unsigned long vm_stack_flags = __VM_STACK_FLAGS; +unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; +unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_force_exec32 = PROT_EXEC; + +/* 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/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c new file mode 100644 index 00000000000000..8c146b2a1e00ae --- /dev/null +++ b/arch/um/sys-x86_64/ptrace.c @@ -0,0 +1,138 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#define __FRAME_OFFSETS +#include "asm/ptrace.h" +#include "linux/sched.h" +#include "linux/errno.h" +#include "asm/elf.h" + +/* XXX x86_64 */ +unsigned long not_ss; +unsigned long not_ds; +unsigned long not_es; + +#define SC_SS(r) (not_ss) +#define SC_DS(r) (not_ds) +#define SC_ES(r) (not_es) + +/* determines which flags the user has access to. */ +/* 1 = access 0 = no access */ +#define FLAG_MASK 0x44dd5UL + +int putreg(struct task_struct *child, int regno, unsigned long value) +{ + unsigned long tmp; + +#ifdef TIF_IA32 + /* Some code in the 64bit emulation may not be 64bit clean. + Don't take any chances. */ + if (test_tsk_thread_flag(child, TIF_IA32)) + value &= 0xffffffff; +#endif + switch (regno){ + case FS: + case GS: + case DS: + case ES: + case SS: + case CS: + if (value && (value & 3) != 3) + return -EIO; + value &= 0xffff; + break; + + case FS_BASE: + case GS_BASE: + if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) + return -EIO; + break; + + case EFLAGS: + value &= FLAG_MASK; + tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK; + value |= tmp; + break; + } + + PT_REGS_SET(&child->thread.regs, regno, value); + return 0; +} + +unsigned long getreg(struct task_struct *child, int regno) +{ + unsigned long retval = ~0UL; + switch (regno) { + case FS: + case GS: + case DS: + case ES: + case SS: + case CS: + retval = 0xffff; + /* fall through */ + default: + retval &= PT_REG(&child->thread.regs, regno); +#ifdef TIF_IA32 + if (test_tsk_thread_flag(child, TIF_IA32)) + retval &= 0xffffffff; +#endif + } + return retval; +} + +void arch_switch(void) +{ +/* XXX + printk("arch_switch\n"); +*/ +} + +int is_syscall(unsigned long addr) +{ + panic("is_syscall"); +} + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) +{ + panic("dump_fpu"); + return(1); +} + +int get_fpregs(unsigned long buf, struct task_struct *child) +{ + panic("get_fpregs"); + return(0); +} + +int set_fpregs(unsigned long buf, struct task_struct *child) +{ + panic("set_fpregs"); + return(0); +} + +int get_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + panic("get_fpxregs"); + return(0); +} + +int set_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + panic("set_fxpregs"); + 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/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c new file mode 100644 index 00000000000000..e1f8bacc5f1ae6 --- /dev/null +++ b/arch/um/sys-x86_64/ptrace_user.c @@ -0,0 +1,64 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include <stddef.h> +#include <errno.h> +#define __FRAME_OFFSETS +#include <sys/ptrace.h> +#include <asm/ptrace.h> +#include "user.h" +#include "kern_constants.h" + +int ptrace_getregs(long pid, unsigned long *regs_out) +{ + if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) + return(-errno); + return(0); +} + +int ptrace_setregs(long pid, unsigned long *regs) +{ + if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) + return(-errno); + return(0); +} + +void ptrace_pokeuser(unsigned long addr, unsigned long data) +{ + panic("ptrace_pokeuser"); +} + +#define DS 184 +#define ES 192 +#define __USER_DS 0x2b + +void arch_enter_kernel(void *task, int pid) +{ +} + +void arch_leave_kernel(void *task, int pid) +{ +#ifdef UM_USER_CS + if(ptrace(PTRACE_POKEUSER, pid, CS, UM_USER_CS) < 0) + tracer_panic("POKEUSER CS failed"); +#endif + + if(ptrace(PTRACE_POKEUSER, pid, DS, __USER_DS) < 0) + tracer_panic("POKEUSER DS failed"); + if(ptrace(PTRACE_POKEUSER, pid, ES, __USER_DS) < 0) + tracer_panic("POKEUSER ES failed"); +} + +/* + * 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/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c new file mode 100644 index 00000000000000..c88e64def6f242 --- /dev/null +++ b/arch/um/sys-x86_64/sigcontext.c @@ -0,0 +1,39 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include "user.h" + +void sc_to_sc(void *to_ptr, void *from_ptr) +{ + struct sigcontext *to = to_ptr, *from = from_ptr; + int size = sizeof(*to); /* + sizeof(struct _fpstate); */ + + memcpy(to, from, size); + if(from->fpstate != NULL) + to->fpstate = (struct _fpstate *) (to + 1); + + to->fpstate = NULL; +} + +unsigned long *sc_sigmask(void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + + return(&sc->oldmask); +} + +/* 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/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c new file mode 100644 index 00000000000000..a5682f1d020ddc --- /dev/null +++ b/arch/um/sys-x86_64/signal.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2003 PathScale, Inc. + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/errno.h" +#include "linux/personality.h" +#include "linux/ptrace.h" +#include "asm/current.h" +#include "asm/uaccess.h" +#include "asm/sigcontext.h" +#include "asm/ptrace.h" +#include "asm/arch/ucontext.h" +#include "choose-mode.h" +#include "sysdep/ptrace.h" +#include "frame_kern.h" + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" + +static int copy_sc_from_user_skas(struct pt_regs *regs, + struct sigcontext *from) +{ + int err = 0; + +#define GETREG(regs, regno, sc, regname) \ + __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= GETREG(regs, R8, from, r8); + err |= GETREG(regs, R9, from, r9); + err |= GETREG(regs, R10, from, r10); + err |= GETREG(regs, R11, from, r11); + err |= GETREG(regs, R12, from, r12); + err |= GETREG(regs, R13, from, r13); + err |= GETREG(regs, R14, from, r14); + err |= GETREG(regs, R15, from, r15); + err |= GETREG(regs, RDI, from, rdi); + err |= GETREG(regs, RSI, from, rsi); + err |= GETREG(regs, RBP, from, rbp); + err |= GETREG(regs, RBX, from, rbx); + err |= GETREG(regs, RDX, from, rdx); + err |= GETREG(regs, RAX, from, rax); + err |= GETREG(regs, RCX, from, rcx); + err |= GETREG(regs, RSP, from, rsp); + err |= GETREG(regs, RIP, from, rip); + err |= GETREG(regs, EFLAGS, from, eflags); + err |= GETREG(regs, CS, from, cs); + +#undef GETREG + + return(err); +} + +int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, + struct pt_regs *regs, unsigned long mask) +{ + unsigned long eflags; + int err = 0; + + err |= __put_user(0, &to->gs); + err |= __put_user(0, &to->fs); + +#define PUTREG(regs, regno, sc, regname) \ + __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= PUTREG(regs, RDI, to, rdi); + err |= PUTREG(regs, RSI, to, rsi); + err |= PUTREG(regs, RBP, to, rbp); + err |= PUTREG(regs, RSP, to, rsp); + err |= PUTREG(regs, RBX, to, rbx); + err |= PUTREG(regs, RDX, to, rdx); + err |= PUTREG(regs, RCX, to, rcx); + err |= PUTREG(regs, RAX, to, rax); + err |= PUTREG(regs, R8, to, r8); + err |= PUTREG(regs, R9, to, r9); + err |= PUTREG(regs, R10, to, r10); + err |= PUTREG(regs, R11, to, r11); + err |= PUTREG(regs, R12, to, r12); + err |= PUTREG(regs, R13, to, r13); + err |= PUTREG(regs, R14, to, r14); + err |= PUTREG(regs, R15, to, r15); + err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ + err |= __put_user(current->thread.err, &to->err); + err |= __put_user(current->thread.trap_no, &to->trapno); + err |= PUTREG(regs, RIP, to, rip); + err |= PUTREG(regs, EFLAGS, to, eflags); +#undef PUTREG + + err |= __put_user(mask, &to->oldmask); + err |= __put_user(current->thread.cr2, &to->cr2); + + return(err); +} + +#endif + +#ifdef CONFIG_MODE_TT +int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, + int fpsize) +{ + struct _fpstate *to_fp, *from_fp; + unsigned long sigs; + int err; + + to_fp = to->fpstate; + from_fp = from->fpstate; + sigs = to->oldmask; + err = copy_from_user(to, from, sizeof(*to)); + to->oldmask = sigs; + return(err); +} + +int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, + struct sigcontext *from, int fpsize) +{ + struct _fpstate *to_fp, *from_fp; + int err; + + to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); + from_fp = from->fpstate; + err = copy_to_user(to, from, sizeof(*to)); + return(err); +} + +#endif + +static int copy_sc_from_user(struct pt_regs *to, void __user *from) +{ + int ret; + + ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, + sizeof(struct _fpstate)), + copy_sc_from_user_skas(to, from)); + return(ret); +} + +static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, + struct pt_regs *from, unsigned long mask) +{ + return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), + sizeof(*fp)), + copy_sc_to_user_skas(to, fp, from, mask))); +} + +struct rt_sigframe +{ + char *pretcode; + struct ucontext uc; + struct siginfo info; +}; + +#define round_down(m, n) (((m) / (n)) * (n)) + +int setup_signal_stack_si(unsigned long stack_top, int sig, + struct k_sigaction *ka, struct pt_regs * regs, + siginfo_t *info, sigset_t *set) +{ + struct rt_sigframe __user *frame; + struct _fpstate __user *fp = NULL; + int err = 0; + struct task_struct *me = current; + + frame = (struct rt_sigframe __user *) + round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; + frame -= 128; + + if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) + goto out; + +#if 0 /* XXX */ + if (save_i387(fp) < 0) + err |= -1; +#endif + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto out; + + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto out; + } + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); + err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); + if (sizeof(*set) == 16) { + __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); + __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + } + else + err |= __copy_to_user(&frame->uc.uc_sigmask, set, + sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + /* x86-64 should always use SA_RESTORER. */ + if (ka->sa.sa_flags & SA_RESTORER) + err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); + else + /* could use a vstub here */ + goto out; + + if (err) + goto out; + + /* Set up registers for signal handler */ + { + struct exec_domain *ed = current_thread_info()->exec_domain; + if (unlikely(ed && ed->signal_invmap && sig < 32)) + sig = ed->signal_invmap[sig]; + } + + PT_REGS_RDI(regs) = sig; + /* In case the signal handler was declared without prototypes */ + PT_REGS_RAX(regs) = 0; + + /* This also works for non SA_SIGINFO handlers because they expect the + next argument after the signal number on the stack. */ + PT_REGS_RSI(regs) = (unsigned long) &frame->info; + PT_REGS_RDX(regs) = (unsigned long) &frame->uc; + PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; + + PT_REGS_RSP(regs) = (unsigned long) frame; + out: + return(err); +} + +long sys_rt_sigreturn(struct pt_regs *regs) +{ + unsigned long __user sp = PT_REGS_SP(¤t->thread.regs); + struct rt_sigframe __user *frame = + (struct rt_sigframe __user *)(sp - 8); + struct ucontext __user *uc = &frame->uc; + sigset_t set; + + if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto segfault; + + sigdelsetmask(&set, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) + goto segfault; + + /* Avoid ERESTART handling */ + PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; + return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); + + segfault: + force_sig(SIGSEGV, current); + 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/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c new file mode 100644 index 00000000000000..4c61dcc0901ff9 --- /dev/null +++ b/arch/um/sys-x86_64/syscalls.c @@ -0,0 +1,191 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/linkage.h" +#include "linux/slab.h" +#include "linux/shm.h" +#include "asm/uaccess.h" +#define __FRAME_OFFSETS +#include "asm/ptrace.h" +#include "asm/unistd.h" +#include "asm/prctl.h" /* XXX This should get the constants from libc */ +#include "choose-mode.h" + +asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg) +{ + unsigned long raddr; + + return do_shmat(shmid, shmaddr, shmflg, &raddr) ?: (long) raddr; +} + +#ifdef CONFIG_MODE_TT +extern int modify_ldt(int func, void *ptr, unsigned long bytecount); + +long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) +{ + /* XXX This should check VERIFY_WRITE depending on func, check this + * in i386 as well. + */ + if(verify_area(VERIFY_READ, ptr, bytecount)) + return(-EFAULT); + return(modify_ldt(func, ptr, bytecount)); +} +#endif + +#ifdef CONFIG_MODE_SKAS +extern int userspace_pid; + +#ifndef __NR_mm_indirect +#define __NR_mm_indirect 241 +#endif + +long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) +{ + unsigned long args[6]; + void *buf; + int res, n; + + buf = kmalloc(bytecount, GFP_KERNEL); + if(buf == NULL) + return(-ENOMEM); + + res = 0; + + switch(func){ + case 1: + case 0x11: + res = copy_from_user(buf, ptr, bytecount); + break; + } + + if(res != 0){ + res = -EFAULT; + goto out; + } + + args[0] = func; + args[1] = (unsigned long) buf; + args[2] = bytecount; + res = syscall(__NR_mm_indirect, ¤t->mm->context.u, + __NR_modify_ldt, args); + + if(res < 0) + goto out; + + switch(func){ + case 0: + case 2: + n = res; + res = copy_to_user(ptr, buf, n); + if(res != 0) + res = -EFAULT; + else + res = n; + break; + } + + out: + kfree(buf); + return(res); +} +#endif + +long sys_modify_ldt(int func, void *ptr, unsigned long bytecount) +{ + return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, + ptr, bytecount)); +} + +#ifdef CONFIG_MODE_TT +extern long arch_prctl(int code, unsigned long addr); + +static long arch_prctl_tt(int code, unsigned long addr) +{ + unsigned long tmp; + long ret; + + switch(code){ + case ARCH_SET_GS: + case ARCH_SET_FS: + ret = arch_prctl(code, addr); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + ret = arch_prctl(code, (unsigned long) &tmp); + if(!ret) + ret = put_user(tmp, &addr); + break; + default: + ret = -EINVAL; + break; + } + + return(ret); +} +#endif + +#ifdef CONFIG_MODE_SKAS + +static long arch_prctl_skas(int code, unsigned long addr) +{ + long ret = 0; + + switch(code){ + case ARCH_SET_GS: + current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; + break; + case ARCH_SET_FS: + current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; + break; + case ARCH_GET_FS: + ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr); + break; + case ARCH_GET_GS: + ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \ +long)], &addr); + break; + default: + ret = -EINVAL; + break; + } + + return(ret); +} +#endif + +long sys_arch_prctl(int code, unsigned long addr) +{ + return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr)); +} + +long sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid) +{ + long ret; + + /* XXX: normal arch do here this pass, and also pass the regs to + * do_fork, instead of NULL. Currently the arch-independent code + * ignores these values, while the UML code (actually it's + * copy_thread) does the right thing. But this should change, + probably. */ + /*if (!newsp) + newsp = UPT_SP(current->thread.regs);*/ + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); + current->thread.forking = 0; + return(ret); +} + +/* + * 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/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c new file mode 100644 index 00000000000000..c33f85f9e8bb2c --- /dev/null +++ b/arch/um/sys-x86_64/sysrq.c @@ -0,0 +1,49 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/version.h" +#include "linux/module.h" +#include "asm/current.h" +#include "asm/ptrace.h" +#include "sysrq.h" + +void __show_regs(struct pt_regs * regs) +{ + printk("\n"); + print_modules(); + printk("Pid: %d, comm: %.20s %s %s\n", + current->pid, current->comm, print_tainted(), UTS_RELEASE); + printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff, + PT_REGS_RIP(regs)); + printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), + PT_REGS_EFLAGS(regs)); + printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); + printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); + printk("RBP: %016lx R08: %016lx R09: %016lx\n", + PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); + printk("R10: %016lx R11: %016lx R12: %016lx\n", + PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); + printk("R13: %016lx R14: %016lx R15: %016lx\n", + PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); +} + +void show_regs(struct pt_regs *regs) +{ + __show_regs(regs); + show_trace((unsigned long *) ®s); +} + +/* 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/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile new file mode 100644 index 00000000000000..002607980864c4 --- /dev/null +++ b/arch/um/sys-x86_64/util/Makefile @@ -0,0 +1,10 @@ +# Copyright 2003 - 2004 Pathscale, Inc +# Released under the GPL + +hostprogs-y := mk_sc mk_thread +always := $(hostprogs-y) + +mk_thread-objs := mk_thread_kern.o mk_thread_user.o + +HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS) diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c new file mode 100644 index 00000000000000..c236e213918db4 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_sc.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 - 2004 PathScale, Inc + * Released under the GPL + */ + +#include <stdio.h> +#include <signal.h> +#include <linux/stddef.h> + +#define SC_OFFSET(name, field) \ + printf("#define " name \ + "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\ + offsetof(struct sigcontext, field)) + +#define SC_FP_OFFSET(name, field) \ + printf("#define " name \ + "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\ + offsetof(struct _fpstate, field)) + +#define SC_FP_OFFSET_PTR(name, field, type) \ + printf("#define " name \ + "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ + offsetof(struct _fpstate, field)) + +int main(int argc, char **argv) +{ + SC_OFFSET("SC_RBX", rbx); + SC_OFFSET("SC_RCX", rcx); + SC_OFFSET("SC_RDX", rdx); + SC_OFFSET("SC_RSI", rsi); + SC_OFFSET("SC_RDI", rdi); + SC_OFFSET("SC_RBP", rbp); + SC_OFFSET("SC_RAX", rax); + SC_OFFSET("SC_R8", r8); + SC_OFFSET("SC_R9", r9); + SC_OFFSET("SC_R10", r10); + SC_OFFSET("SC_R11", r11); + SC_OFFSET("SC_R12", r12); + SC_OFFSET("SC_R13", r13); + SC_OFFSET("SC_R14", r14); + SC_OFFSET("SC_R15", r15); + SC_OFFSET("SC_IP", rip); + SC_OFFSET("SC_SP", rsp); + SC_OFFSET("SC_CR2", cr2); + SC_OFFSET("SC_ERR", err); + SC_OFFSET("SC_TRAPNO", trapno); + SC_OFFSET("SC_CS", cs); + SC_OFFSET("SC_FS", fs); + SC_OFFSET("SC_GS", gs); + SC_OFFSET("SC_EFLAGS", eflags); + SC_OFFSET("SC_SIGMASK", oldmask); +#if 0 + SC_OFFSET("SC_ORIG_RAX", orig_rax); + SC_OFFSET("SC_DS", ds); + SC_OFFSET("SC_ES", es); + SC_OFFSET("SC_SS", ss); +#endif + return(0); +} diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c new file mode 100644 index 00000000000000..a281673f02b240 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_kern.c @@ -0,0 +1,21 @@ +#include "linux/config.h" +#include "linux/stddef.h" +#include "linux/sched.h" + +extern void print_head(void); +extern void print_constant_ptr(char *name, int value); +extern void print_constant(char *name, char *type, int value); +extern void print_tail(void); + +#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) + +int main(int argc, char **argv) +{ + print_head(); +#ifdef CONFIG_MODE_TT + print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); +#endif + print_tail(); + return(0); +} + diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c new file mode 100644 index 00000000000000..7989725568b8df --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_user.c @@ -0,0 +1,30 @@ +#include <stdio.h> + +void print_head(void) +{ + printf("/*\n"); + printf(" * Generated by mk_thread\n"); + printf(" */\n"); + printf("\n"); + printf("#ifndef __UM_THREAD_H\n"); + printf("#define __UM_THREAD_H\n"); + printf("\n"); +} + +void print_constant_ptr(char *name, int value) +{ + printf("#define %s(task) ((unsigned long *) " + "&(((char *) (task))[%d]))\n", name, value); +} + +void print_constant(char *name, char *type, int value) +{ + printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, + value); +} + +void print_tail(void) +{ + printf("\n"); + printf("#endif\n"); +} diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 47339a83c9957f..5186d2a4c4e950 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -251,7 +251,7 @@ config PREEMPT config PREEMPT_BKL bool "Preempt The Big Kernel Lock" - depends on PREEMPT || SMP + depends on PREEMPT default y help This option reduces the latency of the kernel by making the diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index a69f7bcdfc2cdf..6f90c246c41899 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -59,6 +59,8 @@ endif # -funit-at-a-time shrinks the kernel .text considerably # unfortunately it makes reading oopses harder. CFLAGS += $(call cc-option,-funit-at-a-time) +# prevent gcc from generating any FP code by mistake +CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 06d778083feeaa..941e9b93008117 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc1-bk6 -# Thu Oct 28 00:07:32 2004 +# Linux kernel version: 2.6.10-bk7 +# Fri Jan 7 06:27:52 2005 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -45,6 +45,10 @@ CONFIG_FUTEX=y CONFIG_EPOLL=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set # @@ -88,6 +92,7 @@ CONFIG_NR_CPUS=8 CONFIG_GART_IOMMU=y CONFIG_SWIOTLB=y CONFIG_X86_MCE=y +CONFIG_X86_MCE_INTEL=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y @@ -110,10 +115,13 @@ CONFIG_ACPI_SLEEP_PROC_FS=y CONFIG_ACPI_AC=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y +# CONFIG_ACPI_VIDEO is not set CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_NUMA=y # CONFIG_ACPI_ASUS is not set +# CONFIG_ACPI_IBM is not set CONFIG_ACPI_TOSHIBA=y CONFIG_ACPI_BLACKLIST_YEAR=2001 CONFIG_ACPI_DEBUG=y @@ -122,11 +130,35 @@ CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_CONTAINER is not set # # CPU Frequency scaling # -# CONFIG_CPU_FREQ is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_PROC_INTF=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_24_API=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_TABLE=y + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +CONFIG_X86_ACPI_CPUFREQ=y + +# +# shared options +# +CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y # # Bus options (PCI etc.) @@ -174,6 +206,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # +# CONFIG_PNP is not set # # Block devices @@ -189,6 +222,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -292,6 +326,7 @@ CONFIG_BLK_DEV_SD=y # # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set # # SCSI low-level drivers @@ -337,14 +372,12 @@ CONFIG_SCSI_SATA_VIA=y # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set @@ -397,6 +430,8 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +CONFIG_IP_TCPDIAG_IPV6=y CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_INET6_AH is not set @@ -508,7 +543,9 @@ CONFIG_TIGON3=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_S2IO is not set +CONFIG_S2IO=m +# CONFIG_S2IO_NAPI is not set +# CONFIG_2BUFF_MODE is not set # # Token Ring devices @@ -743,6 +780,7 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_ROOT_HUB_TT is not set CONFIG_USB_OHCI_HCD=y CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set # # USB Device Class drivers @@ -752,6 +790,10 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_MIDI is not set # CONFIG_USB_ACM is not set CONFIG_USB_PRINTER=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_RW_DETECT is not set @@ -797,7 +839,7 @@ CONFIG_USB_HIDINPUT=y # # -# USB Network adaptors +# USB Network Adapters # # CONFIG_USB_CATC is not set # CONFIG_USB_KAWETH is not set @@ -840,6 +882,16 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# # Firmware Drivers # # CONFIG_EDD is not set @@ -870,6 +922,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set @@ -884,8 +937,11 @@ CONFIG_ISO9660_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -951,7 +1007,46 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=y +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y # # Profiling support @@ -972,6 +1067,7 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_INFO is not set CONFIG_INIT_DEBUG=y # CONFIG_IOMMU_DEBUG is not set +CONFIG_KPROBES=y # # Security options @@ -985,6 +1081,10 @@ CONFIG_INIT_DEBUG=y # CONFIG_CRYPTO is not set # +# Hardware crypto devices +# + +# # Library routines # # CONFIG_CRC_CCITT is not set diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 6ac57fcf1340b4..2014f2113cd8ac 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c @@ -115,7 +115,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } #if CORE_DUMP @@ -325,7 +327,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) pos = 32; map_size = ex.a_text+ex.a_data; + down_write(¤t->mm->mmap_sem); error = do_brk(text_addr & PAGE_MASK, map_size); + up_write(¤t->mm->mmap_sem); + if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -361,7 +366,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); flush_icache_range((unsigned long) N_TXTADDR(ex), @@ -469,8 +476,9 @@ static int load_aout_library(struct file *file) error_time = jiffies; } #endif - + down_write(¤t->mm->mmap_sem); do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); + up_write(¤t->mm->mmap_sem); file->f_op->read(file, (char *)start_addr, ex.a_text + ex.a_data, &pos); @@ -494,7 +502,9 @@ static int load_aout_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { + down_write(¤t->mm->mmap_sem); error = do_brk(start_addr + len, bss - len); + up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr + len) goto out; diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 16854c4faa64c7..7b78206dd90bc8 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -261,6 +261,12 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; err |= restore_i387_ia32(current, buf, 0); + } else { + struct task_struct *me = current; + if (me->used_math) { + clear_fpu(me); + me->used_math = 0; + } } } diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 4210fa0e6918d7..270f8ca873ae06 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -587,6 +587,10 @@ ia32_sys_call_table: .quad compat_sys_mq_getsetattr .quad quiet_ni_syscall /* reserved for kexec */ .quad sys32_waitid + .quad quiet_ni_syscall /* sys_altroot */ + .quad sys_add_key + .quad sys_request_key + .quad sys_keyctl /* don't forget to change IA32_NR_syscalls */ ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 1d8b3912c1d908..4baa99fe1e5c95 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -200,8 +200,8 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) void __init iommu_hole_init(void) { int fix, num; - u32 aper_size, aper_alloc = 0, aper_order; - u64 aper_base; + u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0; + u64 aper_base, last_aper_base = 0; int valid_agp = 0; if (iommu_aperture_disabled || !fix_aperture) @@ -230,7 +230,15 @@ void __init iommu_hole_init(void) if (!aperture_valid(name, aper_base, aper_size)) { fix = 1; break; - } + } + + if ((last_aper_order && aper_order != last_aper_order) || + (last_aper_base && aper_base != last_aper_base)) { + fix = 1; + break; + } + last_aper_order = aper_order; + last_aper_base = aper_base; } if (!fix && !fallback_aper_force) diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index cd37a0aa66f3e5..dbccec4894c0b1 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -225,6 +225,11 @@ int __init verify_local_APIC(void) void __init sync_Arb_IDs(void) { + /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ + unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + if (ver >= 0x14) /* P4 or higher */ + return; + /* * Wait for idle. */ diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c index 9aa5cb6af6602a..d2c42fb99cb345 100644 --- a/arch/x86_64/kernel/genapic.c +++ b/arch/x86_64/kernel/genapic.c @@ -41,6 +41,12 @@ void __init clustered_apic_check(void) u8 id; u8 cluster_cnt[NUM_APIC_CLUSTERS]; + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + /* AMD always uses flat mode right now */ + genapic = &apic_flat; + goto print; + } + memset(cluster_cnt, 0, sizeof(cluster_cnt)); for (i = 0; i < NR_CPUS; i++) { @@ -71,6 +77,7 @@ void __init clustered_apic_check(void) else genapic = &apic_cluster; +print: printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); } diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 766a7d6ef9b0bf..30e92ff8b3c073 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -355,7 +355,7 @@ ENTRY(cpu_gdt_table) .quad 0x008f9a000000ffff /* __KERNEL_COMPAT32_CS */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ - .quad 0x00cffe000000ffff /* __USER32_CS */ + .quad 0x00cffa000000ffff /* __USER32_CS */ .quad 0x00cff2000000ffff /* __USER_DS, __USER32_DS */ .quad 0x00affa000000ffff /* __USER_CS */ .quad 0x00cf9a000000ffff /* __KERNEL32_CS */ diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 5254e90a8113cd..6cad46c98a2340 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -61,16 +61,17 @@ static void __init copy_bootdata(char *real_mode_data) static void __init setup_boot_cpu_data(void) { - int dummy, eax; + unsigned int dummy, eax; /* get vendor info */ - cpuid(0, &boot_cpu_data.cpuid_level, - (int *)&boot_cpu_data.x86_vendor_id[0], - (int *)&boot_cpu_data.x86_vendor_id[8], - (int *)&boot_cpu_data.x86_vendor_id[4]); + cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level, + (unsigned int *)&boot_cpu_data.x86_vendor_id[0], + (unsigned int *)&boot_cpu_data.x86_vendor_id[8], + (unsigned int *)&boot_cpu_data.x86_vendor_id[4]); /* get cpu type */ - cpuid(1, &eax, &dummy, &dummy, (int *) &boot_cpu_data.x86_capability); + cpuid(1, &eax, &dummy, &dummy, + (unsigned int *) &boot_cpu_data.x86_capability); boot_cpu_data.x86 = (eax >> 8) & 0xf; boot_cpu_data.x86_model = (eax >> 4) & 0xf; boot_cpu_data.x86_mask = eax & 0xf; diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index c22a8f045ecf9e..7b568f14b5ecb9 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1160,13 +1160,6 @@ static void __init setup_ioapic_ids_from_mpc (void) old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= 0xf) { - apic_printk(APIC_QUIET,KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", - apic, mp_ioapics[apic].mpc_apicid); - apic_printk(APIC_QUIET,KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - reg_00.bits.ID); - mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; - } printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid); diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 6e717e4704602b..b05d3b19278d5e 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -31,6 +31,8 @@ static int mce_dont_init; static int tolerant = 1; static int banks; static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL }; +static unsigned long console_logged; +static int notify_user; /* * Lockless MCE logging infrastructure. @@ -68,6 +70,9 @@ void mce_log(struct mce *mce) smp_wmb(); mcelog.entry[entry].finished = 1; smp_wmb(); + + if (!test_and_set_bit(0, &console_logged)) + notify_user = 1; } static void print_mce(struct mce *m) @@ -252,6 +257,19 @@ static void mcheck_timer(void *data) { on_each_cpu(mcheck_check_cpu, NULL, 1, 1); schedule_delayed_work(&mcheck_work, check_interval * HZ); + + /* + * It's ok to read stale data here for notify_user and + * console_logged as we'll simply get the updated versions + * on the next mcheck_timer execution and atomic operations + * on console_logged act as synchronization for notify_user + * writes. + */ + if (notify_user && console_logged) { + notify_user = 0; + clear_bit(0, &console_logged); + printk(KERN_INFO "Machine check events logged\n"); + } } diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 1f415db882d188..7f5f57e5474012 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -576,7 +576,6 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) extern void __bad_mpf_size(void); unsigned int *bp = phys_to_virt(base); struct intel_mp_floating *mpf; - static int printed __initdata; Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); if (sizeof(*mpf) != 16) @@ -600,10 +599,6 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) bp += 4; length -= 16; } - if (!printed) { - printk(KERN_INFO "No mptable found.\n"); - printed = 1; - } return 0; } @@ -640,7 +635,11 @@ void __init find_intel_smp (void) address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; - smp_scan_config(address, 0x1000); + if (smp_scan_config(address, 0x1000)) + return; + + /* If we have come this far, we did not find an MP table */ + printk(KERN_INFO "No mptable found.\n"); } /* diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 1bf8d4e95e928d..407d42b2dc5582 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -493,7 +493,7 @@ void __init setup_arch(char **cmdline_p) check_efer(); - init_memory_mapping(); + init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); #ifdef CONFIG_ACPI_BOOT /* @@ -657,18 +657,18 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c) cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); - c->x86_cache_size=(ecx>>24)+(edx>>24); - /* DTLB and ITLB together, but only 4K */ - c->x86_tlbsize = ((ebx>>16)&0xff) + (ebx&0xff); + c->x86_cache_size=(ecx>>24)+(edx>>24); + /* On K8 L1 TLB is inclusive, so don't count it */ + c->x86_tlbsize = 0; } if (n >= 0x80000006) { cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); - ecx = cpuid_ecx(0x80000006); - c->x86_cache_size = ecx >> 16; + ecx = cpuid_ecx(0x80000006); + c->x86_cache_size = ecx >> 16; c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); - printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", + printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", c->x86_cache_size, ecx & 0xFF); } @@ -849,10 +849,10 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) memset(&c->x86_capability, 0, sizeof c->x86_capability); /* Get vendor name */ - cpuid(0x00000000, &c->cpuid_level, - (int *)&c->x86_vendor_id[0], - (int *)&c->x86_vendor_id[8], - (int *)&c->x86_vendor_id[4]); + cpuid(0x00000000, (unsigned int *)&c->cpuid_level, + (unsigned int *)&c->x86_vendor_id[0], + (unsigned int *)&c->x86_vendor_id[8], + (unsigned int *)&c->x86_vendor_id[4]); get_cpu_vendor(c); @@ -892,19 +892,19 @@ void __init identify_cpu(struct cpuinfo_x86 *c) /* AMD-defined flags: level 0x80000001 */ xlvl = cpuid_eax(0x80000000); - if ( (xlvl & 0xffff0000) == 0x80000000 ) { - if ( xlvl >= 0x80000001 ) { + if ((xlvl & 0xffff0000) == 0x80000000) { + if (xlvl >= 0x80000001) { c->x86_capability[1] = cpuid_edx(0x80000001); c->x86_capability[5] = cpuid_ecx(0x80000001); } - if ( xlvl >= 0x80000004 ) + if (xlvl >= 0x80000004) get_model_name(c); /* Default name */ } /* Transmeta-defined flags: level 0x80860001 */ xlvl = cpuid_eax(0x80860000); - if ( (xlvl & 0xffff0000) == 0x80860000 ) { - if ( xlvl >= 0x80860001 ) + if ((xlvl & 0xffff0000) == 0x80860000) { + if (xlvl >= 0x80860001) c->x86_capability[2] = cpuid_edx(0x80860001); } @@ -918,20 +918,19 @@ void __init identify_cpu(struct cpuinfo_x86 *c) * At the end of this section, c->x86_capability better * indicate the features this CPU genuinely supports! */ - switch ( c->x86_vendor ) { - - case X86_VENDOR_AMD: - init_amd(c); - break; + switch (c->x86_vendor) { + case X86_VENDOR_AMD: + init_amd(c); + break; - case X86_VENDOR_INTEL: - init_intel(c); - break; + case X86_VENDOR_INTEL: + init_intel(c); + break; - case X86_VENDOR_UNKNOWN: - default: - display_cacheinfo(c); - break; + case X86_VENDOR_UNKNOWN: + default: + display_cacheinfo(c); + break; } select_idle_routine(c); @@ -944,9 +943,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c) * common between the CPUs. The first time this routine gets * executed, c == &boot_cpu_data. */ - if ( c != &boot_cpu_data ) { + if (c != &boot_cpu_data) { /* AND the already accumulated flags with these */ - for ( i = 0 ; i < NCAPINTS ; i++ ) + for (i = 0 ; i < NCAPINTS ; i++) boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index e9aa2ca0b55dfe..ad3b240cdd9c77 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -125,6 +125,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; err |= restore_i387(buf); + } else { + struct task_struct *me = current; + if (me->used_math) { + clear_fpu(me); + me->used_math = 0; + } } } @@ -139,7 +145,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; - long eax; + unsigned long eax; frame = (struct rt_sigframe __user *)(regs->rsp - 8); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { diff --git a/arch/x86_64/lib/io.c b/arch/x86_64/lib/io.c index df68a2623736f6..87b4a4e1803912 100644 --- a/arch/x86_64/lib/io.c +++ b/arch/x86_64/lib/io.c @@ -13,3 +13,11 @@ void __memcpy_fromio(void *dst,unsigned long src,unsigned len) __inline_memcpy(dst,(const void *) src,len); } EXPORT_SYMBOL(__memcpy_fromio); + +void memset_io(volatile void __iomem *a, int b, size_t c) +{ + /* XXX: memset can mangle the IO patterns quite a bit. + perhaps it would be better to use a dumb one */ + memset((void *)a,b,c); +} +EXPORT_SYMBOL(memset_io); diff --git a/arch/x86_64/lib/old-checksum.c b/arch/x86_64/lib/old-checksum.c deleted file mode 100644 index 20d5b8f633d36b..00000000000000 --- a/arch/x86_64/lib/old-checksum.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Temporal C versions of the checksum functions until optimized assembler versions - * can go in. - */ - -#include <net/checksum.h> - -/* - * Copy from userspace and compute checksum. If we catch an exception - * then zero the rest of the buffer. - */ -unsigned int csum_partial_copy_from_user (const char *src, char *dst, - int len, unsigned int sum, - int *err_ptr) -{ - int missing; - - missing = copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *err_ptr = -EFAULT; - } - - return csum_partial(dst, len, sum); -} - -unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum) -{ - memcpy(dst,src,len); - return csum_partial(dst,len,sum); -} - -/* Fallback for csum_and_copy_to_user is currently in include/net/checksum.h */ diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index f47f0715e37f4e..e4c8d2dc190c7f 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -68,8 +68,8 @@ void show_mem(void) for_each_pgdat(pgdat) { for (i = 0; i < pgdat->node_spanned_pages; ++i) { - page = pgdat->node_mem_map + i; - total++; + page = pfn_to_page(pgdat->node_start_pfn + i); + total++; if (PageReserved(page)) reserved++; else if (PageSwapCache(page)) @@ -252,51 +252,55 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon __flush_tlb(); } +static void __init find_early_table_space(unsigned long end) +{ + unsigned long puds, pmds, tables; + + puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; + pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; + tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + + round_up(pmds * sizeof(pmd_t), PAGE_SIZE); + + table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables); + if (table_start == -1UL) + panic("Cannot find space for the kernel page tables"); + + table_start >>= PAGE_SHIFT; + table_end = table_start; +} + /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __init init_memory_mapping(void) +void __init init_memory_mapping(unsigned long start, unsigned long end) { - unsigned long adr; - unsigned long end; unsigned long next; - unsigned long puds, pmds, tables; Dprintk("init_memory_mapping\n"); - end = end_pfn_map << PAGE_SHIFT; - /* * Find space for the kernel direct mapping tables. * Later we should allocate these tables in the local node of the memory * mapped. Unfortunately this is done currently before the nodes are * discovered. */ + find_early_table_space(end); - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - tables = round_up(puds*8, PAGE_SIZE) + round_up(pmds * 8, PAGE_SIZE); - - table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables); - if (table_start == -1UL) - panic("Cannot find space for the kernel page tables"); + start = (unsigned long)__va(start); + end = (unsigned long)__va(end); - table_start >>= PAGE_SHIFT; - table_end = table_start; - - end += __PAGE_OFFSET; /* turn virtual */ - - for (adr = PAGE_OFFSET; adr < end; adr = next) { + for (; start < end; start = next) { int map; unsigned long pud_phys; pud_t *pud = alloc_low_page(&map, &pud_phys); - next = adr + PGDIR_SIZE; + next = start + PGDIR_SIZE; if (next > end) next = end; - phys_pud_init(pud, adr-PAGE_OFFSET, next-PAGE_OFFSET); - set_pgd(init_level4_pgt + pgd_index(adr), mk_kernel_pgd(pud_phys)); + phys_pud_init(pud, __pa(start), __pa(next)); + set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(map); } + asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); __flush_tlb_all(); early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, @@ -437,7 +441,7 @@ void __init mem_init(void) /* * Only count reserved RAM pages */ - if (page_is_ram(tmp) && PageReserved(mem_map+tmp)) + if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp))) reservedpages++; #endif diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index 1a166779eeba56..12363e69b0c31e 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l if (phys_addr >= 0xA0000 && last_addr < 0x100000) return (__force void __iomem *)phys_to_virt(phys_addr); +#ifndef CONFIG_DISCONTIGMEM /* * Don't allow anybody to remap normal RAM that we're using.. */ - if (phys_addr < virt_to_phys(high_memory)) { -#ifndef CONFIG_DISCONTIGMEM + if (last_addr < virt_to_phys(high_memory)) { char *t_addr, *t_end; struct page *page; @@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; -#endif } +#endif /* * Mappings have to be page-aligned @@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP | (flags << 24)); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr) } *pprev = p->next; unmap_vm_area(p); - if ((p->flags >> 24) && + if ((p->flags >> 20) && p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index b3acd04b3b30ed..55a2e67e32a68d 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -47,6 +47,10 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) int nodeid, i, nb; int found = 0; u32 reg; + unsigned numnodes; + nodemask_t nodes_parsed; + + nodes_clear(nodes_parsed); nb = find_northbridge(); if (nb < 0) @@ -55,10 +59,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb); reg = read_pci_config(0, nb, 0, 0x60); - for (i = 0; i <= ((reg >> 4) & 7); i++) - node_set_online(i); + numnodes = ((reg >> 4) & 7) + 1; - printk(KERN_INFO "Number of nodes %d (%x)\n", num_online_nodes(), reg); + printk(KERN_INFO "Number of nodes %d\n", numnodes); memset(&nodes,0,sizeof(nodes)); prevbase = 0; @@ -70,11 +73,11 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) nodeid = limit & 7; if ((base & 3) == 0) { - if (i < num_online_nodes()) + if (i < numnodes) printk("Skipping disabled node %d\n", i); continue; } - if (nodeid >= num_online_nodes()) { + if (nodeid >= numnodes) { printk("Ignoring excess node %d (%lx:%lx)\n", nodeid, base, limit); continue; @@ -90,7 +93,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) nodeid, (base>>8)&3, (limit>>8) & 3); return -1; } - if (node_online(nodeid)) { + if (node_isset(nodeid, nodes_parsed)) { printk(KERN_INFO "Node %d already present. Skipping\n", nodeid); continue; @@ -138,12 +141,14 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) nodes[nodeid].end = limit; prevbase = base; + + node_set(nodeid, nodes_parsed); } if (!found) return -1; - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, numnodes); if (memnode_shift < 0) { printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n"); return -1; @@ -154,8 +159,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) if (nodes[i].start != nodes[i].end) { /* assume 1:1 NODE:CPU */ cpu_to_node[i] = i; - setup_node_bootmem(i, nodes[i].start, nodes[i].end); - } + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + } } numa_init_array(); diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index b1a7db4f4d6dcc..ecc0c60989c034 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -34,9 +34,7 @@ cpumask_t node_to_cpumask[MAX_NUMNODES]; int numa_off __initdata; -unsigned long nodes_present; - -int __init compute_hash_shift(struct node *nodes) +int __init compute_hash_shift(struct node *nodes, int numnodes) { int i; int shift = 24; @@ -45,7 +43,7 @@ int __init compute_hash_shift(struct node *nodes) /* When in doubt use brute force. */ while (shift < 48) { memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); - for_each_online_node(i) { + for (i = 0; i < numnodes; i++) { if (nodes[i].start == nodes[i].end) continue; for (addr = nodes[i].start; @@ -197,7 +195,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) (nodes[i].end - nodes[i].start) >> 20); node_set_online(i); } - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, numa_fake); if (memnode_shift < 0) { memnode_shift = 0; printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); @@ -274,7 +272,7 @@ void __init paging_init(void) /* [numa=off] */ __init int numa_setup(char *opt) { - if (!strcmp(opt,"off")) + if (!strncmp(opt,"off",3)) numa_off = 1; #ifdef CONFIG_NUMA_EMU if(!strncmp(opt, "fake=", 5)) { diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 05074f17773041..5b3cd2000a54e4 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c @@ -131,28 +131,36 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, kpte_flags = pte_val(*kpte); if (pgprot_val(prot) != pgprot_val(ref_prot)) { if ((kpte_flags & _PAGE_PSE) == 0) { - pte_t old = *kpte; - pte_t standard = pfn_pte(pfn, ref_prot); - set_pte(kpte, pfn_pte(pfn, prot)); - if (pte_same(old,standard)) - get_page(kpte_page); } else { + /* + * split_large_page will take the reference for this change_page_attr + * on the split page. + */ struct page *split = split_large_page(address, prot, ref_prot); if (!split) return -ENOMEM; - get_page(split); set_pte(kpte,mk_pte(split, ref_prot)); + kpte_page = split; } + get_page(kpte_page); } else if ((kpte_flags & _PAGE_PSE) == 0) { set_pte(kpte, pfn_pte(pfn, ref_prot)); __put_page(kpte_page); - } + } else + BUG(); - if (page_count(kpte_page) == 1) { + /* on x86-64 the direct mapping set at boot is not using 4k pages */ + BUG_ON(PageReserved(kpte_page)); + + switch (page_count(kpte_page)) { + case 1: save_page(address, kpte_page); revert_page(address, ref_prot); - } + break; + case 0: + BUG(); /* memleak and failed 2M page regeneration */ + } return 0; } diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 1db7483a0564dc..3bd04832f041c9 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -20,17 +20,20 @@ static struct acpi_table_slit *acpi_slit; -static DECLARE_BITMAP(nodes_parsed, MAX_NUMNODES) __initdata; +static nodemask_t nodes_parsed __initdata; +static nodemask_t nodes_found __initdata; static struct node nodes[MAX_NUMNODES] __initdata; static __u8 pxm2node[256] __initdata = { [0 ... 255] = 0xff }; static __init int setup_node(int pxm) { - if (pxm2node[pxm] == 0xff) { - if (num_online_nodes() >= MAX_NUMNODES) + unsigned node = pxm2node[pxm]; + if (node == 0xff) { + if (nodes_weight(nodes_found) >= MAX_NUMNODES) return -1; - pxm2node[pxm] = num_online_nodes(); - node_set_online(num_online_nodes()); + node = first_unset_node(nodes_found); + node_set(node, nodes_found); + pxm2node[pxm] = node; } return pxm2node[pxm]; } @@ -140,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) return; } nd = &nodes[node]; - if (!test_and_set_bit(node, &nodes_parsed)) { + if (!node_test_and_set(node, nodes_parsed)) { nd->start = start; nd->end = end; } else { @@ -163,7 +166,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) int i; if (acpi_numa <= 0) return -1; - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed)); if (memnode_shift < 0) { printk(KERN_ERR "SRAT: No NUMA node hash function found. Contact maintainer\n"); @@ -171,7 +174,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) return -1; } for (i = 0; i < MAX_NUMNODES; i++) { - if (!test_bit(i, &nodes_parsed)) + if (!node_isset(i, nodes_parsed)) continue; cutoff_node(i, start, end); if (nodes[i].start == nodes[i].end) |