diff options
Diffstat (limited to 'arch')
51 files changed, 672 insertions, 686 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 79f400d4888f..d2fadd634e45 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -121,8 +121,10 @@ include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s archclean: $(Q)$(MAKE) -f scripts/Makefile.clean obj=$(boot) -CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \ - include/asm-$(ARCH)/offset.h +archmrproper: + +CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \ + include/asm-$(ARCH)/asm_offsets.h define archhelp echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)' diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index b22cbaeae0b8..d9523688bf66 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_VGA_HOSE) += console.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PCI) += pci.o pci_iommu.o obj-$(CONFIG_SRM_ENV) += srm_env.o +obj-$(CONFIG_MODULES) += module.o ifdef CONFIG_ALPHA_GENERIC diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c new file mode 100644 index 000000000000..0d3f1f35a937 --- /dev/null +++ b/arch/alpha/kernel/module.c @@ -0,0 +1,306 @@ +/* Kernel module help for Alpha. + Copyright (C) 2002 Richard Henderson. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <linux/moduleloader.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/slab.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt...) +#endif + +void * +module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + +void +module_free(struct module *mod, void *module_region) +{ + vfree(module_region); +} + +/* Allocate the GOT at the end of the core sections. */ + +struct got_entry { + struct got_entry *next; + Elf64_Addr r_offset; + int got_offset; +}; + +static inline void +process_reloc_for_got(Elf64_Rela *rela, + struct got_entry *chains, Elf64_Xword *poffset) +{ + unsigned long r_sym = ELF64_R_SYM (rela->r_info); + unsigned long r_type = ELF64_R_TYPE (rela->r_info); + Elf64_Addr r_offset = rela->r_offset; + struct got_entry *g; + + if (r_type != R_ALPHA_LITERAL) + return; + + for (g = chains + r_sym; g ; g = g->next) + if (g->r_offset == r_offset) { + if (g->got_offset == 0) { + g->got_offset = *poffset; + *poffset += 8; + } + goto found_entry; + } + + g = kmalloc (sizeof (*g), GFP_KERNEL); + g->next = chains[r_sym].next; + g->r_offset = r_offset; + g->got_offset = *poffset; + *poffset += 8; + chains[r_sym].next = g; + + found_entry: + /* Trick: most of the ELF64_R_TYPE field is unused. There are + 42 valid relocation types, and a 32-bit field. Co-opt the + bits above 256 to store the got offset for this reloc. */ + rela->r_info |= g->got_offset << 8; +} + +int +module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs, + const char *secstrings, struct module *me) +{ + struct got_entry *chains; + Elf64_Rela *rela; + const Elf64_Shdr *esechdrs, *symtab, *s; + Elf64_Shdr *got; + unsigned long nsyms, nrela, i; + + esechdrs = sechdrs + hdr->e_shnum; + symtab = got = NULL; + + /* Find out how large the symbol table is. Allocate one got_entry + head per symbol. Normally this will be enough, but not always. + We'll chain different offsets for the symbol down each head. */ + for (s = sechdrs; s < esechdrs; ++s) + if (s->sh_type == SHT_SYMTAB) + symtab = s; + else if (!strcmp(".got", secstrings + s->sh_name)) { + got = (Elf64_Shdr *) s; + me->arch.gotsecindex = s - sechdrs; + } + + if (!symtab) { + printk(KERN_ERR "module %s: no symbol table\n", me->name); + return -ENOEXEC; + } + if (!got) { + printk(KERN_ERR "module %s: no got section\n", me->name); + return -ENOEXEC; + } + + nsyms = symtab->sh_size / sizeof(Elf64_Sym); + chains = kmalloc(nsyms * sizeof(struct got_entry), GFP_KERNEL); + memset(chains, 0, nsyms * sizeof(struct got_entry)); + + got->sh_size = 0; + got->sh_addralign = 8; + got->sh_type = SHT_NOBITS; + + /* Examine all LITERAL relocations to find out what GOT entries + are required. This sizes the GOT section as well. */ + for (s = sechdrs; s < esechdrs; ++s) + if (s->sh_type == SHT_RELA) { + nrela = s->sh_size / sizeof(Elf64_Rela); + rela = (void *)hdr + s->sh_offset; + for (i = 0; i < nrela; ++i) + process_reloc_for_got(rela+i, chains, + &got->sh_size); + } + + /* Free the memory we allocated. */ + for (i = 0; i < nsyms; ++i) { + struct got_entry *g, *n; + for (g = chains[i].next; g ; g = n) { + n = g->next; + kfree(g); + } + } + kfree(chains); + + return 0; +} + +int +apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, + unsigned int relsec, struct module *me) +{ + printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); + return -ENOEXEC; +} + +int +apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, + struct module *me) +{ + Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr; + unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela); + Elf64_Sym *symtab, *sym; + void *base, *location; + unsigned long got, gp; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + + base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr; + symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr; + + /* The small sections were sorted to the end of the segment. + The following should definitely cover them. */ + gp = (u64)me->module_core + me->core_size - 0x8000; + got = sechdrs[me->arch.gotsecindex].sh_addr; + + for (i = 0; i < n; i++) { + unsigned long r_sym = ELF64_R_SYM (rela[i].r_info); + unsigned long r_type = ELF64_R_TYPE (rela[i].r_info); + unsigned long r_got_offset = r_type >> 8; + unsigned long value, hi, lo; + r_type &= 0xff; + + /* This is where to make the change. */ + location = base + rela[i].r_offset; + + /* This is the symbol it is referring to. */ + sym = symtab + r_sym; + value = sym->st_value; + if (!value) { + printk(KERN_ERR "module %s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + value += rela[i].r_addend; + + switch (r_type) { + case R_ALPHA_NONE: + break; + case R_ALPHA_REFQUAD: + *(u64 *)location = value; + break; + case R_ALPHA_GPREL32: + value -= gp; + if ((int)value != value) + goto reloc_overflow; + *(u32 *)location = value; + break; + case R_ALPHA_LITERAL: + hi = got + r_got_offset; + lo = hi - gp; + if ((short)lo != lo) + goto reloc_overflow; + *(u16 *)location = lo; + *(u64 *)hi = value; + break; + case R_ALPHA_LITUSE: + break; + case R_ALPHA_GPDISP: + value = gp - (u64)location; + lo = (short)value; + hi = (int)(value - lo); + if (hi + lo != value) + goto reloc_overflow; + *(u16 *)location = hi >> 16; + *(u16 *)(location + rela[i].r_addend) = lo; + break; + case R_ALPHA_BRSGP: + /* BRSGP is only allowed to bind to local symbols. + If the section is undef, this means that the + value was resolved from somewhere else. */ + if (sym->st_shndx == SHN_UNDEF) + goto reloc_overflow; + /* FALLTHRU */ + case R_ALPHA_BRADDR: + value -= (u64)location + 4; + if (value & 3) + goto reloc_overflow; + value = (long)value >> 2; + if (value + (1<<21) >= 1<<22) + goto reloc_overflow; + value &= 0x1fffff; + value |= *(u32 *)location & ~0x1fffff; + *(u32 *)location = value; + break; + case R_ALPHA_HINT: + break; + case R_ALPHA_SREL32: + value -= (u64)location; + if ((int)value != value) + goto reloc_overflow; + *(u32 *)location = value; + break; + case R_ALPHA_SREL64: + value -= (u64)location; + *(u64 *)location = value; + break; + case R_ALPHA_GPRELHIGH: + value = (value - gp + 0x8000) >> 16; + if ((short) value != value) + goto reloc_overflow; + *(u16 *)location = value; + break; + case R_ALPHA_GPRELLOW: + value -= gp; + *(u16 *)location = value; + break; + case R_ALPHA_GPREL16: + value -= gp; + if ((short) value != value) + goto reloc_overflow; + *(u16 *)location = value; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %lu\n", + me->name, r_type); + return -ENOEXEC; + reloc_overflow: + if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION) + printk(KERN_ERR + "module %s: Relocation overflow vs section %d\n", + me->name, sym->st_shndx); + else + printk(KERN_ERR + "module %s: Relocation overflow vs %s\n", + me->name, strtab + sym->st_name); + return -ENOEXEC; + } + } + + return 0; +} + +int +module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 7f30895ca719..4963bab746af 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -14,6 +14,7 @@ #include <linux/tty.h> #include <linux/delay.h> #include <linux/smp_lock.h> +#include <linux/module.h> #include <asm/gentrap.h> #include <asm/uaccess.h> @@ -465,7 +466,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, { long error, tmp1, tmp2, tmp3, tmp4; unsigned long pc = regs.pc - 4; - unsigned fixup; + const struct exception_table_entry *fixup; unaligned[0].count++; unaligned[0].va = (unsigned long) va; @@ -638,7 +639,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, got_exception: /* Ok, we caught the exception, but we don't want it. Is there someone to pass it along to? */ - if ((fixup = search_exception_table(pc)) != 0) { + if ((fixup = search_exception_tables(pc)) != 0) { unsigned long newpc; newpc = fixup_exception(una_reg, fixup, pc); diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index c856eea015f3..310c9fd5604f 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -6,13 +6,10 @@ #include <linux/module.h> #include <asm/uaccess.h> -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -static inline unsigned -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { while (first <= last) { const struct exception_table_entry *mid; @@ -21,40 +18,12 @@ search_one_table(const struct exception_table_entry *first, mid = (last - first) / 2 + first; mid_value = (unsigned long)&mid->insn + mid->insn; if (mid_value == value) - return mid->fixup.unit; + return mid; else if (mid_value < value) first = mid+1; else last = mid-1; } - return 0; -} - -unsigned -search_exception_table(unsigned long addr) -{ - unsigned ret; - -#ifndef CONFIG_MODULES - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); -#else - extern spinlock_t modlist_lock; - unsigned long flags; - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - - ret = 0; - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp ; mp = mp->next) { - if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) - continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); -#endif - return ret; + return NULL; } diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 8285db87a801..d0c12c8de82e 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -24,6 +24,7 @@ #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -88,7 +89,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - unsigned int fixup; + const struct exception_table_entry *fixup; int fault, si_code = SEGV_MAPERR; siginfo_t info; @@ -176,7 +177,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, no_context: /* Are we prepared to handle this fault as an exception? */ - if ((fixup = search_exception_table(regs->pc)) != 0) { + if ((fixup = search_exception_tables(regs->pc)) != 0) { unsigned long newpc; newpc = fixup_exception(dpf_reg, fixup, regs->pc); regs->pc = newpc; diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 3a2b5aaaa3b6..8e22b9bb6726 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -67,9 +67,9 @@ void module_free(struct module *module, void *region) vfree(region); } -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { return 0; diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index a81108dfb113..2fc083a98278 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -718,7 +718,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) * same format. */ -static int __init apm_driver_version(u_short *val) +static int apm_driver_version(u_short *val) { u32 eax; diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c index 2623e01b2d87..08fac292dff8 100644 --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c @@ -31,8 +31,6 @@ #define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ #define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ -#define SAFE_FREQ 33000 /* every Elan CPU can run at 33 MHz */ - static struct cpufreq_driver *elanfreq_driver; /* Module parameter */ @@ -184,7 +182,7 @@ static int elanfreq_verify (struct cpufreq_policy *policy) cpufreq_verify_within_limits(policy, 1000, max_freq); - for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) + for (i=7; i>=0; i--) if ((elan_multiplier[i].clock >= policy->min) && (elan_multiplier[i].clock <= policy->max)) number_states++; @@ -192,57 +190,46 @@ static int elanfreq_verify (struct cpufreq_policy *policy) if (number_states) return 0; - for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) + for (i=7; i>=0; i--) if (elan_multiplier[i].clock < policy->max) break; policy->max = elan_multiplier[i+1].clock; + cpufreq_verify_within_limits(policy, 1000, max_freq); + return 0; } static int elanfreq_setpolicy (struct cpufreq_policy *policy) { - unsigned int number_states = 0; - unsigned int i, j=4; + unsigned int i; + unsigned int optimal = 8; if (!elanfreq_driver) return -EINVAL; - for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) - if ((elan_multiplier[i].clock >= policy->min) && - (elan_multiplier[i].clock <= policy->max)) - { - number_states++; - j = i; + for (i=0; i<8; i++) { + if ((elan_multiplier[i].clock > policy->max) || + (elan_multiplier[i].clock < policy->min)) + continue; + switch(policy->policy) { + case CPUFREQ_POLICY_POWERSAVE: + if (optimal == 8) + optimal = i; + break; + case CPUFREQ_POLICY_PERFORMANCE: + optimal = i; + break; + default: + return -EINVAL; } - - if (number_states == 1) { - elanfreq_set_cpu_state(j); - return 0; } - - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) - if ((elan_multiplier[i].clock >= policy->min) && - (elan_multiplier[i].clock <= policy->max)) - j = i; - break; - case CPUFREQ_POLICY_PERFORMANCE: - for (i=0; i<(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i++) - if ((elan_multiplier[i].clock >= policy->min) && - (elan_multiplier[i].clock <= policy->max)) - j = i; - break; - default: + if ((optimal == 8) || (elan_multiplier[optimal].clock > max_freq)) return -EINVAL; - } - if (elan_multiplier[j].clock > max_freq) - return -EINVAL; + elanfreq_set_cpu_state(optimal); - elanfreq_set_cpu_state(j); return 0; } @@ -307,7 +294,7 @@ static int __init elanfreq_init(void) driver->policy[0].max = max_freq; driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; driver->policy[0].cpuinfo.max_freq = max_freq; - driver->policy[0].cpuinfo.min_freq = min_freq; + driver->policy[0].cpuinfo.min_freq = 1000; driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL; elanfreq_driver = driver; diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index 52cb1a4ab188..88b88508c4e1 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -82,12 +82,17 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) /* get current state */ rdmsr(MSR_IA32_THERM_CONTROL, l, h); - l = l >> 1; - l &= 0x7; - + if (l & 0x10) { + l = l >> 1; + l &= 0x7; + } else + l = DC_DISABLE; + if (l == newstate) { set_cpus_allowed(current, cpus_allowed); return 0; + } else if (l == DC_RESV) { + printk(KERN_ERR PFX "BIG FAT WARNING: currently in invalid setting\n"); } /* notifiers */ @@ -141,13 +146,18 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) unsigned int i; unsigned int newstate = 0; unsigned int number_states = 0; + unsigned int minstate = 1; - if (!cpufreq_p4_driver || !stock_freq || !policy) + if (!cpufreq_p4_driver || !stock_freq || + !policy || !cpu_online(policy->cpu)) return -EINVAL; + if (has_N44_O17_errata) + minstate = 3; + if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { - for (i=8; i>0; i--) + for (i=8; i>=minstate; i--) if ((policy->min <= ((stock_freq / 8) * i)) && (policy->max >= ((stock_freq / 8) * i))) { @@ -155,7 +165,7 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) number_states++; } } else { - for (i=1; i<=8; i++) + for (i=minstate; i<=8; i++) if ((policy->min <= ((stock_freq / 8) * i)) && (policy->max >= ((stock_freq / 8) * i))) { @@ -164,25 +174,8 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) } } - /* if (number_states == 1) */ - { - if (policy->cpu == CPUFREQ_ALL_CPUS) { - for (i=0; i<NR_CPUS; i++) - if (cpu_online(i)) - cpufreq_p4_setdc(i, newstate); - } else { - cpufreq_p4_setdc(policy->cpu, newstate); - } - } - /* else { - if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { - min_state = newstate; - max_state = newstate + (number_states - 1); - } else { - max_state = newstate; - min_state = newstate - (number_states - 1); - } - } */ + cpufreq_p4_setdc(policy->cpu, newstate); + return 0; } @@ -190,17 +183,21 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) static int cpufreq_p4_verify(struct cpufreq_policy *policy) { unsigned int number_states = 0; - unsigned int i; + unsigned int i = 1; - if (!cpufreq_p4_driver || !stock_freq || !policy) + if (!cpufreq_p4_driver || !stock_freq || + !policy || !cpu_online(policy->cpu)) return -EINVAL; - if (!cpu_online(policy->cpu)) - policy->cpu = CPUFREQ_ALL_CPUS; - cpufreq_verify_within_limits(policy, (stock_freq / 8), stock_freq); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + if (has_N44_O17_errata) + i = 3; - /* is there at least one state within limit? */ - for (i=1; i<=8; i++) + /* is there at least one state within the limit? */ + for (; i<=8; i++) if ((policy->min <= ((stock_freq / 8) * i)) && (policy->max >= ((stock_freq / 8) * i))) number_states++; @@ -209,11 +206,14 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) return 0; policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); return 0; } -int __init cpufreq_p4_init(void) +static int __init cpufreq_p4_init(void) { struct cpuinfo_x86 *c = cpu_data; int cpuid; @@ -245,6 +245,16 @@ int __init cpufreq_p4_init(void) } printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); + + if (!stock_freq) { + if (cpu_khz) + stock_freq = cpu_khz; + else { + printk(KERN_INFO PFX "unknown core frequency - please use module parameter 'stock_freq'\n"); + return -EINVAL; + } + } + driver = kmalloc(sizeof(struct cpufreq_driver) + NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL); if (!driver) @@ -252,9 +262,6 @@ int __init cpufreq_p4_init(void) driver->policy = (struct cpufreq_policy *) (driver + 1); - if (!stock_freq) - stock_freq = cpu_khz; - #ifdef CONFIG_CPU_FREQ_24_API for (i=0;i<NR_CPUS;i++) { driver->cpu_cur_freq[i] = stock_freq; @@ -290,15 +297,16 @@ int __init cpufreq_p4_init(void) } -void __exit cpufreq_p4_exit(void) +static void __exit cpufreq_p4_exit(void) { - u32 l, h; + unsigned int i; if (cpufreq_p4_driver) { + for (i=0; i<NR_CPUS; i++) { + if (cpu_online(i)) + cpufreq_p4_setdc(i, DC_DISABLE); + } cpufreq_unregister(); - /* return back to a non modulated state */ - rdmsr(MSR_IA32_THERM_CONTROL, l, h); - wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); kfree(cpufreq_p4_driver); } } diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 5da9aae308d6..198def807850 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -253,11 +253,11 @@ ENTRY(sysenter_entry) * Careful about security. */ cmpl $__PAGE_OFFSET-3,%ebp - jae syscall_badsys + jae syscall_fault 1: movl (%ebp),%ebp .section __ex_table,"a" .align 4 - .long 1b,syscall_badsys + .long 1b,syscall_fault .previous pushl %eax @@ -367,6 +367,14 @@ syscall_exit_work: jmp resume_userspace ALIGN +syscall_fault: + pushl %eax # save orig_eax + SAVE_ALL + GET_THREAD_INFO(%ebx) + movl $-EFAULT,EAX(%esp) + jmp resume_userspace + + ALIGN syscall_badsys: movl $-ENOSYS,EAX(%esp) jmp resume_userspace diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index a795bafc6f17..fcaa3693e115 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -124,6 +124,6 @@ asmlinkage int sys_iopl(unsigned long unused) } regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12); /* Make sure we return the long way (not sysenter) */ - set_thread_flag(TIF_SIGPENDING); + set_thread_flag(TIF_IRET); return 0; } diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c index d71b0e367eb6..d92e448a2c8c 100644 --- a/arch/i386/kernel/module.c +++ b/arch/i386/kernel/module.c @@ -45,9 +45,9 @@ void module_free(struct module *mod, void *module_region) } /* We don't need anything special. */ -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { return 0; diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index c6108fa910e1..fbcfc1f2c2bd 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -555,7 +555,7 @@ asmlinkage int sys_execve(struct pt_regs regs) if (error == 0) { current->ptrace &= ~PT_DTRACE; /* Make sure we don't return using sysenter.. */ - set_thread_flag(TIF_SIGPENDING); + set_thread_flag(TIF_IRET); } putname(filename); out: diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 444e1c24a808..1c17237fe978 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -617,4 +617,6 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs,oldset); + + clear_thread_flag(TIF_IRET); } diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 2f84d4172cd8..4e56b5f99a60 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -189,39 +189,38 @@ bad_ctc: #ifdef CONFIG_CPU_FREQ +static unsigned int ref_freq = 0; +static unsigned long loops_per_jiffy_ref = 0; + +#ifndef CONFIG_SMP +static unsigned long fast_gettimeoffset_ref = 0; +static unsigned long cpu_khz_ref = 0; +#endif static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_freqs *freq = data; - unsigned int i; - if (!cpu_has_tsc) - return 0; + if (!ref_freq) { + ref_freq = freq->old; + loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; +#ifndef CONFIG_SMP + fast_gettimeoffset_ref = fast_gettimeoffset_quotient; + cpu_khz_ref = cpu_khz; +#endif + } - switch (val) { - case CPUFREQ_PRECHANGE: - if ((freq->old < freq->new) && - ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) { - cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new); - fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old); - } - for (i=0; i<NR_CPUS; i++) - if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i)) - cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new); - break; - - case CPUFREQ_POSTCHANGE: - if ((freq->new < freq->old) && - ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) { - cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new); - fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old); + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { + cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); +#ifndef CONFIG_SMP + if (use_tsc) { + fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); + cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); } - for (i=0; i<NR_CPUS; i++) - if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i)) - cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new); - break; +#endif } return 0; @@ -260,6 +259,10 @@ static int init_tsc(void) * moaned if you have the only one in the world - you fix it! */ +#ifdef CONFIG_CPU_FREQ + cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); +#endif + if (cpu_has_tsc) { unsigned long tsc_quotient = calibrate_tsc(); if (tsc_quotient) { @@ -282,9 +285,6 @@ static int init_tsc(void) "0" (eax), "1" (edx)); printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); } -#ifdef CONFIG_CPU_FREQ - cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); -#endif return 0; } } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c028ac4ab667..332ccea33b8b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -87,50 +87,6 @@ asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; - -/* - * If the address is either in the .text section of the - * kernel, or in the vmalloc'ed module regions, it *may* - * be the address of a calling routine - */ - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - int retval = 0; - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void *)addr, 0, mod)) { - retval = 1; - break; - } - } - - return retval; -} - -#else - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif - void show_trace(unsigned long * stack) { int i; @@ -338,7 +294,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86, } kernel_trap: { - unsigned long fixup; + const struct exception_table_entry *fixup; #ifdef CONFIG_PNPBIOS if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */ { @@ -354,9 +310,9 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86, } #endif - fixup = search_exception_table(regs->eip); + fixup = search_exception_tables(regs->eip); if (fixup) - regs->eip = fixup; + regs->eip = fixup->fixup; else die(str, regs, error_code); return; @@ -435,10 +391,10 @@ gp_in_vm86: gp_in_kernel: { - unsigned long fixup; - fixup = search_exception_table(regs->eip); + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->eip); if (fixup) { - regs->eip = fixup; + regs->eip = fixup->fixup; return; } die("general protection fault", regs, error_code); diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c index b94fb8d234da..946e7ad6fbcb 100644 --- a/arch/i386/mm/extable.c +++ b/arch/i386/mm/extable.c @@ -7,13 +7,11 @@ #include <linux/spinlock.h> #include <asm/uaccess.h> -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { while (first <= last) { const struct exception_table_entry *mid; @@ -22,43 +20,11 @@ search_one_table(const struct exception_table_entry *first, mid = (last - first) / 2 + first; diff = mid->insn - value; if (diff == 0) - return mid->fixup; + return mid; else if (diff < 0) first = mid+1; else last = mid-1; } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); - return ret; -#else - unsigned long flags; - struct list_head *i; - - /* The kernel is the last "module" -- no need to treat it special. */ - spin_lock_irqsave(&modlist_lock, flags); - list_for_each(i, &extables) { - struct exception_table *ex - = list_entry(i, struct exception_table, list); - if (ex->num_entries == 0) - continue; - ret = search_one_table(ex->entry, - ex->entry + ex->num_entries - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + return NULL; } diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 56827d817963..e1ebd7239849 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/tty.h> #include <linux/vt_kern.h> /* For unblank_screen() */ +#include <linux/module.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -154,7 +155,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) struct vm_area_struct * vma; unsigned long address; unsigned long page; - unsigned long fixup; + const struct exception_table_entry *fixup; int write; siginfo_t info; @@ -310,8 +311,8 @@ bad_area: no_context: /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->eip)) != 0) { - regs->eip = fixup; + if ((fixup = search_exception_tables(regs->eip)) != NULL) { + regs->eip = fixup->fixup; return; } diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index 14a61a9bf5c4..1663e7730a18 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -234,8 +234,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) ret = -ENOMEM; goto out; } - add_to_page_cache(page, mapping, idx); + ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); unlock_page(page); + if (ret) { + free_huge_page(page); + goto out; + } } set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 8d1e2c1e5148..0d33b4830d84 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -438,6 +438,16 @@ void __init mem_init(void) bad_ppro = ppro_with_ram_bug(); +#ifdef CONFIG_HIGHMEM + /* check that fixmap and pkmap do not overlap */ + if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) { + printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n"); + printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n", + PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START); + BUG(); + } +#endif + set_max_mapnr_init(); #ifdef CONFIG_HIGHMEM diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index ad20bedba50c..65860c3865a5 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -821,42 +821,6 @@ asmlinkage void buserr_c(struct frame *fp) static int kstack_depth_to_print = 48; -extern char _stext, _etext; - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void *)addr, 0, mod)) - return 1; - } - - return 0; -} - -#else // !CONFIG_MODULES - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif // !CONFIG_MODULES - void show_trace(unsigned long *stack) { unsigned long *endstack; diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c index 0437fc375d0c..a7672504939b 100644 --- a/arch/mips/kernel/pci.c +++ b/arch/mips/kernel/pci.c @@ -3,7 +3,7 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Modified to be mips generic, ppopov@mvista.com - * arch/mips/kernl/pci.c + * arch/mips/kernel/pci.c * Common MIPS PCI routines. * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c index 3a71a4b8b2fd..084d341a8b5b 100644 --- a/arch/mips64/sgi-ip27/ip27-rtc.c +++ b/arch/mips64/sgi-ip27/ip27-rtc.c @@ -202,9 +202,15 @@ static int __init rtc_init(void) KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0; printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); - if (misc_register(&rtc_dev)) + if (misc_register(&rtc_dev)) { + printk(KERN_ERR "rtc: cannot register misc device.\n"); return -ENODEV; - create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL); + } + if (!create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL)) { + printk(KERN_ERR "rtc: cannot create /proc/rtc.\n"); + misc_deregister(&rtc_dev); + return -ENOENT; + } save_flags(flags); cli(); diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index e597f1478e46..e8544761df0a 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -500,6 +500,8 @@ static struct miscdevice perf_dev = { */ static int __init perf_init(void) { + int retval; + /* Determine correct processor interface to use */ bitmask_array = perf_bitmasks; @@ -518,11 +520,17 @@ static int __init perf_init(void) return -ENODEV; } + retval = misc_register(&perf_dev); + if (retval < 0) { + printk(KERN_ERR "Performance monitoring counters: " + "cannot register misc device.\n"); + return retval; + } + /* Patch the images to match the system */ perf_patch_images(); spin_lock_init(&perf_lock); - misc_register(&perf_dev); /* TODO: this only lets us access the first cpu.. what to do for SMP? */ cpu_device = cpu_data[0].dev; diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f108dbc1614e..ed250fadcd89 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -123,31 +123,6 @@ void dump_stack(void) static int kstack_depth_to_print = 48; -extern struct module kernel_module; - -static inline int kernel_text_address(unsigned long addr) -{ -#ifdef CONFIG_MODULES - struct module *mod; -#endif - extern char _stext, _etext; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - -#ifdef CONFIG_MODULES - for (mod = module_list; mod != &kernel_module; mod = mod->next) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound(addr, 0, mod)) - return 1; - } -#endif - - return 0; -} void show_stack(unsigned long *sp) { diff --git a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c index 696a4faaeb3c..639b07c008ba 100644 --- a/arch/ppc/kernel/module.c +++ b/arch/ppc/kernel/module.c @@ -103,7 +103,7 @@ static unsigned long get_plt_size(const Elf32_Ehdr *hdr, int module_frob_arch_sections(Elf32_Ehdr *hdr, Elf32_Shdr *sechdrs, - const char *secstrings, + char *secstrings, struct module *me) { unsigned int i; diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 16a8128d5aaa..9d4fc78b2dc9 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -29,6 +29,7 @@ #include <linux/interrupt.h> #include <linux/config.h> #include <linux/init.h> +#include <linux/module.h> #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -115,7 +116,7 @@ void MachineCheckException(struct pt_regs *regs) { #ifdef CONFIG_ALL_PPC - unsigned long fixup; + const struct exception_table_entry *entry; #endif /* CONFIG_ALL_PPC */ unsigned long msr = regs->msr; @@ -148,7 +149,7 @@ MachineCheckException(struct pt_regs *regs) * -- paulus. */ if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000))) - && (fixup = search_exception_table(regs->nip)) != 0) { + && (entry = search_exception_tables(regs->nip)) != NULL) { /* * Check that it's a sync instruction, or somewhere * in the twi; isync; nop sequence that inb/inw/inl uses. diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c index aee3118d18d2..3b8f08b47ab3 100644 --- a/arch/ppc/mm/extable.c +++ b/arch/ppc/mm/extable.c @@ -6,6 +6,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <linux/init.h> #include <asm/uaccess.h> extern struct exception_table_entry __start___ex_table[]; @@ -40,16 +41,17 @@ sort_ex_table(struct exception_table_entry *start, } } -void +void __init sort_exception_table(void) { sort_ex_table(__start___ex_table, __stop___ex_table); } -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { while (first <= last) { const struct exception_table_entry *mid; @@ -58,41 +60,11 @@ search_one_table(const struct exception_table_entry *first, mid = (last - first) / 2 + first; diff = mid->insn - value; if (diff == 0) - return mid->fixup; + return mid; else if (diff < 0) first = mid+1; else last = mid-1; } - return 0; -} - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); -#else - unsigned long flags; - struct list_head *i; - - /* The kernel is the last "module" -- no need to treat it special. */ - spin_lock_irqsave(&modlist_lock, flags); - list_for_each(i, &extables) { - struct exception_table *ex - = list_entry(i, struct exception_table, list); - if (ex->num_entries == 0) - continue; - ret = search_one_table(ex->entry, - ex->entry + ex->num_entries - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); -#endif - - return ret; + return NULL; } diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index de7d090e7b47..686745055096 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -27,6 +27,7 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/highmem.h> +#include <linux/module.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -263,12 +264,11 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { extern void die(const char *,struct pt_regs *,long); - - unsigned long fixup; + const struct exception_table_entry *entry; /* Are we prepared to handle this fault? */ - if ((fixup = search_exception_table(regs->nip)) != 0) { - regs->nip = fixup; + if ((entry = search_exception_tables(regs->nip)) != NULL) { + regs->nip = entry->fixup; return; } diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 4dce1e9e74f2..20e1d2bc0e2d 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -196,8 +196,17 @@ static struct miscdevice rtc_dev= static int __init rtc_init(void) { - misc_register(&rtc_dev); - create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + int retval; + + retval = misc_register(&rtc_dev); + if(retval < 0) + return retval; + +#ifdef CONFIG_PROC_FS + if(create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL) == NULL) + misc_deregister(&rtc_dev); + return -ENOMEM; +#endif printk(KERN_INFO "i/pSeries Real Time Clock Driver v" RTC_VERSION "\n"); diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index ef722cd2058f..1898fd9aeaa4 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -57,7 +57,7 @@ struct sigregs32 { /* * the gp_regs array is 32 bit representation of the pt_regs - * structure that was stored on the kernle stack during the + * structure that was stored on the kernel stack during the * system call that was interrupted for the signal. * * Note that the entire pt_regs regs structure will fit in diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index d1d4dd05c212..537a5e802070 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -51,9 +51,9 @@ void module_free(struct module *mod, void *module_region) table entries. */ } -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { // FIXME: add space needed for GOT/PLT diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5eb5923e001b..8706fc762fd7 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -63,50 +63,6 @@ static ext_int_info_t ext_int_pfault; static int kstack_depth_to_print = 12; -/* - * If the address is either in the .text section of the - * kernel, or in the vmalloc'ed module regions, it *may* - * be the address of a calling routine - */ -extern char _stext, _etext; - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - int retval = 0; - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void*)addr, 0, mod)) { - retval = 1; - break; - } - } - - return retval; -} - -#else - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif - void show_trace(unsigned long * stack) { unsigned long backchain, low_addr, high_addr, ret_addr; diff --git a/arch/s390x/kernel/module.c b/arch/s390x/kernel/module.c index 61f3b34e90be..f35512379467 100644 --- a/arch/s390x/kernel/module.c +++ b/arch/s390x/kernel/module.c @@ -52,9 +52,9 @@ void module_free(struct module *mod, void *module_region) } /* s390/s390x needs additional memory for GOT/PLT sections. */ -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { // FIXME: add space needed for GOT/PLT diff --git a/arch/s390x/kernel/traps.c b/arch/s390x/kernel/traps.c index e67855f55ac4..1c5cd64b3ecd 100644 --- a/arch/s390x/kernel/traps.c +++ b/arch/s390x/kernel/traps.c @@ -65,50 +65,6 @@ static ext_int_info_t ext_int_pfault; static int kstack_depth_to_print = 20; -/* - * If the address is either in the .text section of the - * kernel, or in the vmalloc'ed module regions, it *may* - * be the address of a calling routine - */ -extern char _stext, _etext; - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - int retval = 0; - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void*)addr, 0, mod)) { - retval = 1; - break; - } - } - - return retval; -} - -#else - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif - void show_trace(unsigned long * stack) { unsigned long backchain, low_addr, high_addr, ret_addr; diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 348c24f63d85..26aa5e1259d4 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -37,9 +37,9 @@ void module_free(struct module *mod, void *module_region) } /* We don't need anything special. */ -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { return 0; diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index f6107871dfd3..035c7bf4232a 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -450,13 +450,13 @@ struct ifreq32 { struct ifmap32 ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; - __kernel_caddr_t32 ifru_data; + compat_caddr_t ifru_data; } ifr_ifru; }; struct ifconf32 { int ifc_len; /* size of buffer */ - __kernel_caddr_t32 ifcbuf; + compat_caddr_t ifcbuf; }; #ifdef CONFIG_NET @@ -1009,7 +1009,7 @@ static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) struct fb_fix_screeninfo32 { char id[16]; - __kernel_caddr_t32 smem_start; + compat_caddr_t smem_start; __u32 smem_len; __u32 type; __u32 type_aux; @@ -1018,7 +1018,7 @@ struct fb_fix_screeninfo32 { __u16 ypanstep; __u16 ywrapstep; __u32 line_length; - __kernel_caddr_t32 mmio_start; + compat_caddr_t mmio_start; __u32 mmio_len; __u32 accel; __u16 reserved[3]; @@ -1027,10 +1027,10 @@ struct fb_fix_screeninfo32 { struct fb_cmap32 { __u32 start; __u32 len; - __kernel_caddr_t32 red; - __kernel_caddr_t32 green; - __kernel_caddr_t32 blue; - __kernel_caddr_t32 transp; + compat_caddr_t red; + compat_caddr_t green; + compat_caddr_t blue; + compat_caddr_t transp; }; static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) @@ -1169,7 +1169,7 @@ struct floppy_struct32 { unsigned char rate; unsigned char spec1; unsigned char fmt_gap; - const __kernel_caddr_t32 name; + const compat_caddr_t name; }; struct floppy_drive_params32 { @@ -1208,7 +1208,7 @@ struct floppy_drive_struct32 { int fd_ref; int fd_device; int last_checked; - __kernel_caddr_t32 dmabuf; + compat_caddr_t dmabuf; int bufblocks; }; @@ -1732,7 +1732,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigne } struct ppp_option_data32 { - __kernel_caddr_t32 ptr; + compat_caddr_t ptr; __u32 length; int transmit; }; @@ -1813,8 +1813,8 @@ struct mtget32 { __u32 mt_dsreg; __u32 mt_gstat; __u32 mt_erreg; - __kernel_daddr_t32 mt_fileno; - __kernel_daddr_t32 mt_blkno; + compat_daddr_t mt_fileno; + compat_daddr_t mt_blkno; }; #define MTIOCGET32 _IOR('m', 2, struct mtget32) @@ -1932,7 +1932,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) struct cdrom_read32 { int cdread_lba; - __kernel_caddr_t32 cdread_bufaddr; + compat_caddr_t cdread_bufaddr; int cdread_buflen; }; @@ -1940,16 +1940,16 @@ struct cdrom_read_audio32 { union cdrom_addr addr; u_char addr_format; int nframes; - __kernel_caddr_t32 buf; + compat_caddr_t buf; }; struct cdrom_generic_command32 { unsigned char cmd[CDROM_PACKET_SIZE]; - __kernel_caddr_t32 buffer; + compat_caddr_t buffer; unsigned int buflen; int stat; - __kernel_caddr_t32 sense; - __kernel_caddr_t32 reserved[3]; + compat_caddr_t sense; + compat_caddr_t reserved[3]; }; static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) @@ -1958,7 +1958,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar struct cdrom_read cdread; struct cdrom_read_audio cdreadaudio; struct cdrom_generic_command cgc; - __kernel_caddr_t32 addr; + compat_caddr_t addr; char *data = 0; void *karg; int err = 0; @@ -2041,9 +2041,9 @@ out: if (data) struct loop_info32 { int lo_number; /* ioctl r/o */ - __kernel_dev_t32 lo_device; /* ioctl r/o */ + compat_dev_t lo_device; /* ioctl r/o */ unsigned int lo_inode; /* ioctl r/o */ - __kernel_dev_t32 lo_rdevice; /* ioctl r/o */ + compat_dev_t lo_rdevice; /* ioctl r/o */ int lo_offset; int lo_encrypt_type; int lo_encrypt_key_size; /* ioctl w/o */ @@ -2248,7 +2248,7 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a set_fs(old_fs); if (err >= 0) - err = put_user(kuid, (__kernel_uid_t32 *)arg); + err = put_user(kuid, (compat_uid_t *)arg); return err; } @@ -2256,7 +2256,7 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a struct ncp_ioctl_request_32 { unsigned int function; unsigned int size; - __kernel_caddr_t32 data; + compat_caddr_t data; }; struct ncp_fs_info_v2_32 { @@ -2277,13 +2277,13 @@ struct ncp_objectname_ioctl_32 { int auth_type; unsigned int object_name_len; - __kernel_caddr_t32 object_name; /* an userspace data, in most cases user name */ + compat_caddr_t object_name; /* an userspace data, in most cases user name */ }; struct ncp_privatedata_ioctl_32 { unsigned int len; - __kernel_caddr_t32 data; /* ~1000 for NDS */ + compat_caddr_t data; /* ~1000 for NDS */ }; #define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32) @@ -2557,12 +2557,12 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon struct atmif_sioc32 { int number; int length; - __kernel_caddr_t32 arg; + compat_caddr_t arg; }; struct atm_iobuf32 { int length; - __kernel_caddr_t32 buffer; + compat_caddr_t buffer; }; #define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) @@ -2623,7 +2623,7 @@ static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) iobuf.length = iobuf32.length; - if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) { + if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) { iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; } else { iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); @@ -2677,7 +2677,7 @@ static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) sioc.number = sioc32.number; sioc.length = sioc32.length; - if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) { + if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) { sioc.arg = (void*)(unsigned long)sioc32.arg; } else { sioc.arg = kmalloc(sioc.length, GFP_KERNEL); @@ -2835,7 +2835,7 @@ typedef struct { } lv_status_byindex_req32_t; typedef struct { - __kernel_dev_t32 dev; + compat_dev_t dev; u32 lv; } lv_status_bydev_req32_t; @@ -5128,7 +5128,7 @@ HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl) HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl) HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl) /* One SMB ioctl needs translations. */ -#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32) +#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) /* NCPFS */ HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c index dc0daa59aac1..cf6aa58b9564 100644 --- a/arch/sparc64/kernel/module.c +++ b/arch/sparc64/kernel/module.c @@ -144,9 +144,9 @@ void module_free(struct module *mod, void *module_region) } /* We don't need anything special. */ -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { return 0; diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c index bcfa77a396bf..c95f15885c18 100644 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ b/arch/sparc64/kernel/sunos_ioctl32.c @@ -22,6 +22,7 @@ #include <linux/mm.h> #include <linux/smp.h> #include <linux/smp_lock.h> +#include <linux/compat.h> #include <asm/kbio.h> /* Use this to get at 32-bit user passed pointers. */ @@ -80,13 +81,13 @@ struct ifreq32 { int ifru_mtu; struct ifmap32 ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - __kernel_caddr_t32 ifru_data; + compat_caddr_t ifru_data; } ifr_ifru; }; struct ifconf32 { int ifc_len; /* size of buffer */ - __kernel_caddr_t32 ifcbuf; + compat_caddr_t ifcbuf; }; extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index e22bbcc94a97..d18415e983c9 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -290,11 +290,11 @@ struct msgbuf32 { s32 mtype; char mtext[1]; }; struct ipc_perm32 { key_t key; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_uid_t32 cuid; - __kernel_gid_t32 cgid; - __kernel_mode_t32 mode; + compat_uid_t uid; + compat_gid_t gid; + compat_uid_t cuid; + compat_gid_t cgid; + compat_mode_t mode; unsigned short seq; }; @@ -333,8 +333,8 @@ struct msqid_ds32 unsigned short msg_cbytes; unsigned short msg_qnum; unsigned short msg_qbytes; - __kernel_ipc_pid_t32 msg_lspid; - __kernel_ipc_pid_t32 msg_lrpid; + compat_ipc_pid_t msg_lspid; + compat_ipc_pid_t msg_lrpid; }; struct msqid64_ds32 { @@ -348,8 +348,8 @@ struct msqid64_ds32 { unsigned int msg_cbytes; unsigned int msg_qnum; unsigned int msg_qbytes; - __kernel_pid_t32 msg_lspid; - __kernel_pid_t32 msg_lrpid; + compat_pid_t msg_lspid; + compat_pid_t msg_lrpid; unsigned int __unused1; unsigned int __unused2; }; @@ -361,8 +361,8 @@ struct shmid_ds32 { compat_time_t shm_atime; compat_time_t shm_dtime; compat_time_t shm_ctime; - __kernel_ipc_pid_t32 shm_cpid; - __kernel_ipc_pid_t32 shm_lpid; + compat_ipc_pid_t shm_cpid; + compat_ipc_pid_t shm_lpid; unsigned short shm_nattch; }; @@ -375,8 +375,8 @@ struct shmid64_ds32 { unsigned int __pad3; compat_time_t shm_ctime; compat_size_t shm_segsz; - __kernel_pid_t32 shm_cpid; - __kernel_pid_t32 shm_lpid; + compat_pid_t shm_cpid; + compat_pid_t shm_lpid; unsigned int shm_nattch; unsigned int __unused1; unsigned int __unused2; @@ -1378,6 +1378,9 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { int err; + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; + err = put_user(stat->dev, &statbuf->st_dev); err |= put_user(stat->ino, &statbuf->st_ino); err |= put_user(stat->mode, &statbuf->st_mode); @@ -1385,8 +1388,6 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); err |= put_user(stat->rdev, &statbuf->st_rdev); - if (stat->size > MAX_NON_LFS) - return -EOVERFLOW; err |= put_user(stat->size, &statbuf->st_size); err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); err |= put_user(0, &statbuf->__unused1); @@ -1412,16 +1413,16 @@ asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2) struct ncp_mount_data32_v3 { int version; unsigned int ncp_fd; - __kernel_uid_t32 mounted_uid; - __kernel_pid_t32 wdog_pid; + compat_uid_t mounted_uid; + compat_pid_t wdog_pid; unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; unsigned int time_out; unsigned int retry_count; unsigned int flags; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; + compat_uid_t uid; + compat_gid_t gid; + compat_mode_t file_mode; + compat_mode_t dir_mode; }; struct ncp_mount_data32_v4 { @@ -1492,11 +1493,11 @@ static void *do_ncp_super_data_conv(void *raw_data) struct smb_mount_data32 { int version; - __kernel_uid_t32 mounted_uid; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; + compat_uid_t mounted_uid; + compat_uid_t uid; + compat_gid_t gid; + compat_mode_t file_mode; + compat_mode_t dir_mode; }; static void *do_smb_super_data_conv(void *raw_data) @@ -1656,7 +1657,7 @@ static int put_rusage (struct rusage32 *ru, struct rusage *r) return err; } -asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru) +asmlinkage int sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, struct rusage32 *ru) { if (!ru) return sys_wait4(pid, stat_addr, options, NULL); @@ -1718,7 +1719,7 @@ asmlinkage int sys32_sysinfo(struct sysinfo32 *info) extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); -asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct compat_timespec *interval) +asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval) { struct timespec t; int ret; @@ -3027,27 +3028,27 @@ struct nfsctl_client32 { struct nfsctl_export32 { s8 ex32_client[NFSCLNT_IDMAX+1]; s8 ex32_path[NFS_MAXPATHLEN+1]; - __kernel_dev_t32 ex32_dev; - __kernel_ino_t32 ex32_ino; + compat_dev_t ex32_dev; + compat_ino_t ex32_ino; s32 ex32_flags; - __kernel_uid_t32 ex32_anon_uid; - __kernel_gid_t32 ex32_anon_gid; + compat_uid_t ex32_anon_uid; + compat_gid_t ex32_anon_gid; }; struct nfsctl_uidmap32 { u32 ug32_ident; /* char * */ - __kernel_uid_t32 ug32_uidbase; + compat_uid_t ug32_uidbase; s32 ug32_uidlen; u32 ug32_udimap; /* uid_t * */ - __kernel_uid_t32 ug32_gidbase; + compat_uid_t ug32_gidbase; s32 ug32_gidlen; u32 ug32_gdimap; /* gid_t * */ }; struct nfsctl_fhparm32 { struct sockaddr gf32_addr; - __kernel_dev_t32 gf32_dev; - __kernel_ino_t32 gf32_ino; + compat_dev_t gf32_dev; + compat_ino_t gf32_ino; s32 gf32_version; }; @@ -3176,7 +3177,7 @@ static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_uidlen; i++) err |= __get_user(karg->ca_umap.ug_udimap[i], - &(((__kernel_uid_t32 *)A(uaddr))[i])); + &(((compat_uid_t *)A(uaddr))[i])); err |= __get_user(karg->ca_umap.ug_gidbase, &arg32->ca32_umap.ug32_gidbase); err |= __get_user(karg->ca_umap.ug_uidlen, @@ -3190,7 +3191,7 @@ static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_gidlen; i++) err |= __get_user(karg->ca_umap.ug_gdimap[i], - &(((__kernel_gid_t32 *)A(uaddr))[i])); + &(((compat_gid_t *)A(uaddr))[i])); return (err ? -EFAULT : 0); } @@ -3482,7 +3483,7 @@ asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 coun extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); -asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count) +asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); int ret; @@ -3503,7 +3504,7 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count); -asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count) +asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); int ret; @@ -3737,7 +3738,7 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); -asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len, +asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len, u32 *user_mask_ptr) { unsigned long kernel_mask; @@ -3761,7 +3762,7 @@ asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len, extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); -asmlinkage int sys32_sched_getaffinity(__kernel_pid_t32 pid, unsigned int len, +asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len, u32 *user_mask_ptr) { unsigned long kernel_mask; diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index cb27fd8fb5aa..3fae734358c5 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -798,14 +798,14 @@ asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) } /* So stupid... */ -extern asmlinkage int sys32_wait4(__kernel_pid_t32 pid, +extern asmlinkage int sys32_wait4(compat_pid_t pid, u32 stat_addr, int options, u32 ru); -asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru) +asmlinkage int sunos_wait4(compat_pid_t pid, u32 stat_addr, int options, u32 ru) { int ret; - ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)), + ret = sys32_wait4((pid ? pid : ((compat_pid_t)-1)), stat_addr, options, ru); return ret; } @@ -931,11 +931,11 @@ struct msgbuf32 { struct ipc_perm32 { key_t key; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_uid_t32 cuid; - __kernel_gid_t32 cgid; - __kernel_mode_t32 mode; + compat_uid_t uid; + compat_gid_t gid; + compat_uid_t cuid; + compat_gid_t cgid; + compat_mode_t mode; unsigned short seq; }; @@ -952,8 +952,8 @@ struct msqid_ds32 unsigned short msg_cbytes; unsigned short msg_qnum; unsigned short msg_qbytes; - __kernel_ipc_pid_t32 msg_lspid; - __kernel_ipc_pid_t32 msg_lrpid; + compat_ipc_pid_t msg_lspid; + compat_ipc_pid_t msg_lrpid; }; static inline int sunos_msqid_get(struct msqid_ds32 *user, @@ -1084,8 +1084,8 @@ struct shmid_ds32 { compat_time_t shm_atime; compat_time_t shm_dtime; compat_time_t shm_ctime; - __kernel_ipc_pid_t32 shm_cpid; - __kernel_ipc_pid_t32 shm_lpid; + compat_ipc_pid_t shm_cpid; + compat_ipc_pid_t shm_lpid; unsigned short shm_nattch; }; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 6c0db000fcf1..23e5a862f088 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -149,10 +149,10 @@ void data_access_exception (struct pt_regs *regs, if (regs->tstate & TSTATE_PRIV) { /* Test if this comes from uaccess places. */ - unsigned long fixup, g2; + unsigned long fixup; + unsigned long g2 = regs->u_regs[UREG_G2]; - g2 = regs->u_regs[UREG_G2]; - if ((fixup = search_exception_table (regs->tpc, &g2))) { + if ((fixup = search_extables_range(regs->tpc, &g2))) { /* Ouch, somebody is trying ugly VM hole tricks on us... */ #ifdef DEBUG_EXCEPTIONS printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); @@ -1370,7 +1370,7 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned recoverable = 1; } else { unsigned long g2 = regs->u_regs[UREG_G2]; - unsigned long fixup = search_exception_table(regs->tpc, &g2); + unsigned long fixup = search_extables_range(regs->tpc, &g2); if (fixup != 0UL) { /* OK, kernel access to userspace. */ @@ -1390,7 +1390,7 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned /* Only perform fixup if we still have a * recoverable condition. */ - if (fixup != 0UL && recoverable) { + if (recoverable) { regs->tpc = fixup; regs->tnpc = regs->tpc + 4; regs->u_regs[UREG_G2] = g2; diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index d5f8f8eb0360..1d403a089e01 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/module.h> #include <asm/asi.h> #include <asm/ptrace.h> #include <asm/pstate.h> @@ -360,7 +361,7 @@ void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("ke void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) { unsigned long g2 = regs->u_regs [UREG_G2]; - unsigned long fixup = search_exception_table (regs->tpc, &g2); + unsigned long fixup = search_extables_range(regs->tpc, &g2); if (!fixup) { unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c index 638a68166332..54a17bc63324 100644 --- a/arch/sparc64/mm/extable.c +++ b/arch/sparc64/mm/extable.c @@ -9,10 +9,11 @@ extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; -static unsigned long -search_one_table(const struct exception_table_entry *start, - const struct exception_table_entry *end, - unsigned long value, unsigned long *g2) +/* Caller knows they are in a range if ret->fixup == 0 */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *start, + const struct exception_table_entry *last, + unsigned long value) { const struct exception_table_entry *walk; @@ -30,7 +31,7 @@ search_one_table(const struct exception_table_entry *start, */ /* 1. Try to find an exact match. */ - for (walk = start; walk <= end; walk++) { + for (walk = start; walk <= last; walk++) { if (walk->fixup == 0) { /* A range entry, skip both parts. */ walk++; @@ -38,55 +39,37 @@ search_one_table(const struct exception_table_entry *start, } if (walk->insn == value) - return walk->fixup; + return walk; } /* 2. Try to find a range match. */ - for (walk = start; walk <= (end - 1); walk++) { + for (walk = start; walk <= (last - 1); walk++) { if (walk->fixup) continue; - if (walk[0].insn <= value && - walk[1].insn > value) { - *g2 = (value - walk[0].insn) / 4; - return walk[1].fixup; - } + if (walk[0].insn <= value && walk[1].insn > value) + return walk; + walk++; } - return 0; + return NULL; } -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr, unsigned long *g2) +/* Special extable search, which handles ranges. Returns fixup */ +unsigned long search_extables_range(unsigned long addr, unsigned long *g2) { - unsigned long ret = 0; + const struct exception_table_entry *entry; -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, - __stop___ex_table-1, addr, g2); - return ret; -#else - unsigned long flags; - struct list_head *i; + entry = search_exception_tables(addr); + if (!entry) + return 0; - /* The kernel is the last "module" -- no need to treat it special. */ - spin_lock_irqsave(&modlist_lock, flags); - list_for_each(i, &extables) { - struct exception_table *ex = - list_entry(i, struct exception_table, list); - if (ex->num_entries == 0) - continue; - ret = search_one_table(ex->entry, - ex->entry + ex->num_entries - 1, - addr, g2); - if (ret) - break; + /* Inside range? Fix g2 and return correct fixup */ + if (!entry->fixup) { + *g2 = (addr - entry->insn) / 4; + return (entry + 1)->fixup; } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + + return entry->fixup; } diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index e5aa61b9f52d..5c4a56023668 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -14,6 +14,7 @@ #include <linux/mman.h> #include <linux/signal.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -285,7 +286,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, /* Look in asi.h: All _S asis have LS bit set */ if ((asi & 0x1) && - (fixup = search_exception_table (regs->tpc, &g2))) { + (fixup = search_extables_range(regs->tpc, &g2))) { regs->tpc = fixup; regs->tnpc = regs->tpc + 4; regs->u_regs[UREG_G2] = g2; diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c index e48dbcb2c497..98045169d9c1 100644 --- a/arch/sparc64/mm/hugetlbpage.c +++ b/arch/sparc64/mm/hugetlbpage.c @@ -476,9 +476,16 @@ try_again: page = alloc_hugetlb_page(); if (page == NULL) { pte_unmap(pte); + retval = -ENOMEM; + goto out; + } + retval = add_to_page_cache(page, mapping, + idx, GFP_ATOMIC); + if (retval) { + pte_unmap(pte); + free_hugetlb_page(page); goto out; } - add_to_page_cache(page, mapping, idx); } set_huge_pte(mm, vma, page, pte, (vma->vm_flags & VM_WRITE)); diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 2bf29ad7ad27..4936445793b7 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -11,49 +11,6 @@ #include "sysrq.h" #include "user_util.h" - /* - * If the address is either in the .text section of the - * kernel, or in the vmalloc'ed module regions, it *may* - * be the address of a calling routine - */ - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - int retval = 0; - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void *) addr, 0, mod)) { - retval = 1; - break; - } - } - - return retval; -} - -#else - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif - void show_trace(unsigned long * stack) { int i; diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c index c585076087db..9331fa3cda4d 100644 --- a/arch/x86_64/kernel/module.c +++ b/arch/x86_64/kernel/module.c @@ -26,9 +26,9 @@ #define DEBUGP(fmt...) /* We don't need anything special. */ -int module_frob_arch_sections(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) { return 0; diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 20c4811bad6b..af118388f169 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -104,44 +104,6 @@ int printk_address(unsigned long address) } #endif - -#ifdef CONFIG_MODULES - -/* FIXME: Accessed without a lock --RR */ -extern struct list_head modules; - -static inline int kernel_text_address(unsigned long addr) -{ - int retval = 0; - struct module *mod; - - if (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext) - return 1; - - list_for_each_entry(mod, &modules, list) { - /* mod_bound tests for addr being inside the vmalloc'ed - * module area. Of course it'd be better to test only - * for the .text subset... */ - if (mod_bound((void *)addr, 0, mod)) { - retval = 1; - break; - } - } - - return retval; -} - -#else - -static inline int kernel_text_address(unsigned long addr) -{ - return (addr >= (unsigned long) &_stext && - addr <= (unsigned long) &_etext); -} - -#endif - static inline unsigned long *in_exception_stack(int cpu, unsigned long stack) { int k; diff --git a/arch/x86_64/mm/hugetlbpage.c b/arch/x86_64/mm/hugetlbpage.c index bf5ea4753b28..d4515d57af34 100644 --- a/arch/x86_64/mm/hugetlbpage.c +++ b/arch/x86_64/mm/hugetlbpage.c @@ -232,8 +232,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) ret = -ENOMEM; goto out; } - add_to_page_cache(page, mapping, idx); + ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); unlock_page(page); + if (ret) { + free_huge_page(page); + goto out; + } } set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); } |
