summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Makefile6
-rw-r--r--arch/alpha/kernel/Makefile1
-rw-r--r--arch/alpha/kernel/module.c306
-rw-r--r--arch/alpha/kernel/traps.c5
-rw-r--r--arch/alpha/mm/extable.c43
-rw-r--r--arch/alpha/mm/fault.c5
-rw-r--r--arch/arm/kernel/module.c6
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/elanfreq.c59
-rw-r--r--arch/i386/kernel/cpu/cpufreq/p4-clockmod.c90
-rw-r--r--arch/i386/kernel/entry.S12
-rw-r--r--arch/i386/kernel/ioport.c2
-rw-r--r--arch/i386/kernel/module.c6
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/signal.c2
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c54
-rw-r--r--arch/i386/kernel/traps.c56
-rw-r--r--arch/i386/mm/extable.c48
-rw-r--r--arch/i386/mm/fault.c7
-rw-r--r--arch/i386/mm/hugetlbpage.c6
-rw-r--r--arch/i386/mm/init.c10
-rw-r--r--arch/m68k/kernel/traps.c36
-rw-r--r--arch/mips/kernel/pci.c2
-rw-r--r--arch/mips64/sgi-ip27/ip27-rtc.c10
-rw-r--r--arch/parisc/kernel/perf.c10
-rw-r--r--arch/parisc/kernel/traps.c25
-rw-r--r--arch/ppc/kernel/module.c2
-rw-r--r--arch/ppc/kernel/traps.c5
-rw-r--r--arch/ppc/mm/extable.c46
-rw-r--r--arch/ppc/mm/fault.c8
-rw-r--r--arch/ppc64/kernel/rtc.c13
-rw-r--r--arch/ppc64/kernel/signal32.c2
-rw-r--r--arch/s390/kernel/module.c6
-rw-r--r--arch/s390/kernel/traps.c44
-rw-r--r--arch/s390x/kernel/module.c6
-rw-r--r--arch/s390x/kernel/traps.c44
-rw-r--r--arch/sparc/kernel/module.c6
-rw-r--r--arch/sparc64/kernel/ioctl32.c62
-rw-r--r--arch/sparc64/kernel/module.c6
-rw-r--r--arch/sparc64/kernel/sunos_ioctl32.c5
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c85
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c24
-rw-r--r--arch/sparc64/kernel/traps.c10
-rw-r--r--arch/sparc64/kernel/unaligned.c3
-rw-r--r--arch/sparc64/mm/extable.c65
-rw-r--r--arch/sparc64/mm/fault.c3
-rw-r--r--arch/sparc64/mm/hugetlbpage.c9
-rw-r--r--arch/um/kernel/sysrq.c43
-rw-r--r--arch/x86_64/kernel/module.c6
-rw-r--r--arch/x86_64/kernel/traps.c38
-rw-r--r--arch/x86_64/mm/hugetlbpage.c6
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);
}