Loading Documentation/filesystems/ocfs2.txt +2 −1 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ Features which OCFS2 does not support yet: - quotas - quotas - Directory change notification (F_NOTIFY) - Directory change notification (F_NOTIFY) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - POSIX ACLs Mount options Mount options ============= ============= Loading Loading @@ -79,3 +78,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at bits of significance. bits of significance. user_xattr (*) Enables Extended User Attributes. user_xattr (*) Enables Extended User Attributes. nouser_xattr Disables Extended User Attributes. nouser_xattr Disables Extended User Attributes. acl Enables POSIX Access Control Lists support. noacl (*) Disables POSIX Access Control Lists support. MAINTAINERS +5 −10 Original line number Original line Diff line number Diff line Loading @@ -4015,10 +4015,12 @@ L: alsa-devel@alsa-project.org (subscribers-only) W: http://alsa-project.org/main/index.php/ASoC W: http://alsa-project.org/main/index.php/ASoC S: Supported S: Supported SPARC (sparc32) SPARC + UltraSPARC (sparc/sparc64) P: William L. Irwin P: David S. Miller M: wli@holomorphy.com M: davem@davemloft.net L: sparclinux@vger.kernel.org L: sparclinux@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git S: Maintained S: Maintained SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER Loading Loading @@ -4302,13 +4304,6 @@ M: dushistov@mail.ru L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org S: Maintained S: Maintained UltraSPARC (sparc64) P: David S. Miller M: davem@davemloft.net L: sparclinux@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git S: Maintained ULTRA-WIDEBAND (UWB) SUBSYSTEM: ULTRA-WIDEBAND (UWB) SUBSYSTEM: P: David Vrabel P: David Vrabel M: david.vrabel@csr.com M: david.vrabel@csr.com Loading arch/arm/mach-omap2/clock24xx.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = { }; }; static struct clk i2chs2_fck = { static struct clk i2chs2_fck = { .name = "i2chs_fck", .name = "i2c_fck", .id = 2, .id = 2, .parent = &func_96m_ck, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X, Loading Loading @@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = { }; }; static struct clk i2chs1_fck = { static struct clk i2chs1_fck = { .name = "i2chs_fck", .name = "i2c_fck", .id = 1, .id = 1, .parent = &func_96m_ck, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X, Loading arch/parisc/include/asm/module.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -23,8 +23,10 @@ struct mod_arch_specific { { unsigned long got_offset, got_count, got_max; unsigned long got_offset, got_count, got_max; unsigned long fdesc_offset, fdesc_count, fdesc_max; unsigned long fdesc_offset, fdesc_count, fdesc_max; unsigned long stub_offset, stub_count, stub_max; struct { unsigned long init_stub_offset, init_stub_count, init_stub_max; unsigned long stub_offset; unsigned int stub_entries; } *section; int unwind_section; int unwind_section; struct unwind_table *unwind; struct unwind_table *unwind; }; }; Loading arch/parisc/kernel/module.c +135 −81 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ * * * Linux/PA-RISC Project (http://www.parisc-linux.org/) * Linux/PA-RISC Project (http://www.parisc-linux.org/) * Copyright (C) 2003 Randolph Chung <tausq at debian . org> * Copyright (C) 2003 Randolph Chung <tausq at debian . org> * Copyright (C) 2008 Helge Deller <deller@gmx.de> * * * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify Loading @@ -24,6 +25,19 @@ * * * * * Notes: * Notes: * - PLT stub handling * On 32bit (and sometimes 64bit) and with big kernel modules like xfs or * ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may * fail to reach their PLT stub if we only create one big stub array for * all sections at the beginning of the core or init section. * Instead we now insert individual PLT stub entries directly in front of * of the code sections where the stubs are actually called. * This reduces the distance between the PCREL location and the stub entry * so that the relocations can be fulfilled. * While calculating the final layout of the kernel module in memory, the * kernel module loader calls arch_mod_section_prepend() to request the * to be reserved amount of memory in front of each individual section. * * - SEGREL32 handling * - SEGREL32 handling * We are not doing SEGREL32 handling correctly. According to the ABI, we * We are not doing SEGREL32 handling correctly. According to the ABI, we * should do a value offset, like this: * should do a value offset, like this: Loading Loading @@ -58,9 +72,13 @@ #define DEBUGP(fmt...) #define DEBUGP(fmt...) #endif #endif #define RELOC_REACHABLE(val, bits) \ (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \ 0 : 1) #define CHECK_RELOC(val, bits) \ #define CHECK_RELOC(val, bits) \ if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ if (!RELOC_REACHABLE(val, bits)) { \ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ me->name, strtab + sym->st_name, (unsigned long)val, bits); \ me->name, strtab + sym->st_name, (unsigned long)val, bits); \ return -ENOEXEC; \ return -ENOEXEC; \ Loading Loading @@ -92,13 +110,6 @@ static inline int in_local(struct module *me, void *loc) return in_init(me, loc) || in_core(me, loc); return in_init(me, loc) || in_core(me, loc); } } static inline int in_local_section(struct module *me, void *loc, void *dot) { return (in_init(me, loc) && in_init(me, dot)) || (in_core(me, loc) && in_core(me, dot)); } #ifndef CONFIG_64BIT #ifndef CONFIG_64BIT struct got_entry { struct got_entry { Elf32_Addr addr; Elf32_Addr addr; Loading Loading @@ -258,23 +269,42 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) /* Free memory returned from module_alloc */ /* Free memory returned from module_alloc */ void module_free(struct module *mod, void *module_region) void module_free(struct module *mod, void *module_region) { { kfree(mod->arch.section); mod->arch.section = NULL; vfree(module_region); vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception /* FIXME: If module_region == mod->init_region, trim exception table entries. */ table entries. */ } } /* Additional bytes needed in front of individual sections */ unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section) { /* size needed for all stubs of this section (including * one additional for correct alignment of the stubs) */ return (mod->arch.section[section].stub_entries + 1) * sizeof(struct stub_entry); } #define CONST #define CONST int module_frob_arch_sections(CONST Elf_Ehdr *hdr, int module_frob_arch_sections(CONST Elf_Ehdr *hdr, CONST Elf_Shdr *sechdrs, CONST Elf_Shdr *sechdrs, CONST char *secstrings, CONST char *secstrings, struct module *me) struct module *me) { { unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; unsigned long gots = 0, fdescs = 0, len; unsigned int i; unsigned int i; len = hdr->e_shnum * sizeof(me->arch.section[0]); me->arch.section = kzalloc(len, GFP_KERNEL); if (!me->arch.section) return -ENOMEM; for (i = 1; i < hdr->e_shnum; i++) { for (i = 1; i < hdr->e_shnum; i++) { const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; const Elf_Rela *rels = (void *)sechdrs[i].sh_addr; unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); unsigned int count, s; if (strncmp(secstrings + sechdrs[i].sh_name, if (strncmp(secstrings + sechdrs[i].sh_name, ".PARISC.unwind", 14) == 0) ".PARISC.unwind", 14) == 0) Loading @@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, */ */ gots += count_gots(rels, nrels); gots += count_gots(rels, nrels); fdescs += count_fdescs(rels, nrels); fdescs += count_fdescs(rels, nrels); if(strncmp(secstrings + sechdrs[i].sh_name, ".rela.init", 10) == 0) /* XXX: By sorting the relocs and finding duplicate entries init_stubs += count_stubs(rels, nrels); * we could reduce the number of necessary stubs and save else * some memory. */ stubs += count_stubs(rels, nrels); count = count_stubs(rels, nrels); if (!count) continue; /* so we need relocation stubs. reserve necessary memory. */ /* sh_info gives the section for which we need to add stubs. */ s = sechdrs[i].sh_info; /* each code section should only have one relocation section */ WARN_ON(me->arch.section[s].stub_entries); /* store number of stubs we need for this section */ me->arch.section[s].stub_entries += count; } } /* align things a bit */ /* align things a bit */ Loading @@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, me->arch.fdesc_offset = me->core_size; me->arch.fdesc_offset = me->core_size; me->core_size += fdescs * sizeof(Elf_Fdesc); me->core_size += fdescs * sizeof(Elf_Fdesc); me->core_size = ALIGN(me->core_size, 16); me->arch.stub_offset = me->core_size; me->core_size += stubs * sizeof(struct stub_entry); me->init_size = ALIGN(me->init_size, 16); me->arch.init_stub_offset = me->init_size; me->init_size += init_stubs * sizeof(struct stub_entry); me->arch.got_max = gots; me->arch.got_max = gots; me->arch.fdesc_max = fdescs; me->arch.fdesc_max = fdescs; me->arch.stub_max = stubs; me->arch.init_stub_max = init_stubs; return 0; return 0; } } Loading Loading @@ -380,23 +412,27 @@ enum elf_stub_type { }; }; static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, enum elf_stub_type stub_type, int init_section) enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec) { { unsigned long i; struct stub_entry *stub; struct stub_entry *stub; if(init_section) { /* initialize stub_offset to point in front of the section */ i = me->arch.init_stub_count++; if (!me->arch.section[targetsec].stub_offset) { BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); loc0 -= (me->arch.section[targetsec].stub_entries + 1) * stub = me->module_init + me->arch.init_stub_offset + sizeof(struct stub_entry); i * sizeof(struct stub_entry); /* get correct alignment for the stubs */ } else { loc0 = ALIGN(loc0, sizeof(struct stub_entry)); i = me->arch.stub_count++; me->arch.section[targetsec].stub_offset = loc0; BUG_ON(me->arch.stub_count > me->arch.stub_max); stub = me->module_core + me->arch.stub_offset + i * sizeof(struct stub_entry); } } /* get address of stub entry */ stub = (void *) me->arch.section[targetsec].stub_offset; me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry); /* do not write outside available stub area */ BUG_ON(0 == me->arch.section[targetsec].stub_entries--); #ifndef CONFIG_64BIT #ifndef CONFIG_64BIT /* for 32-bit the stub looks like this: /* for 32-bit the stub looks like this: * ldil L'XXX,%r1 * ldil L'XXX,%r1 Loading Loading @@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf32_Addr val; Elf32_Addr val; Elf32_Sword addend; Elf32_Sword addend; Elf32_Addr dot; Elf32_Addr dot; Elf_Addr loc0; unsigned int targetsec = sechdrs[relsec].sh_info; //unsigned long dp = (unsigned long)$global$; //unsigned long dp = (unsigned long)$global$; register unsigned long dp asm ("r27"); register unsigned long dp asm ("r27"); DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ /* This is where to make the change */ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr + rel[i].r_offset; + rel[i].r_offset; /* This is the start of the target section */ loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */ /* This is the symbol it is referring to */ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + ELF32_R_SYM(rel[i].r_info); + ELF32_R_SYM(rel[i].r_info); Loading Loading @@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs, break; break; case R_PARISC_PCREL17F: case R_PARISC_PCREL17F: /* 17-bit PC relative address */ /* 17-bit PC relative address */ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */ val += addend; val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 17) if (!RELOC_REACHABLE(val, 17)) { /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); val = (val - dot - 8)/4; CHECK_RELOC(val, 17); } *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); break; break; case R_PARISC_PCREL22F: case R_PARISC_PCREL22F: /* 22-bit PC relative address; only defined for pa20 */ /* 22-bit PC relative address; only defined for pa20 */ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */ DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", val += addend; strtab + sym->st_name, (unsigned long)loc, addend, val = (val - dot - 8)/4; val) if (!RELOC_REACHABLE(val, 22)) { /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 22); CHECK_RELOC(val, 22); } *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; break; Loading Loading @@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf64_Addr val; Elf64_Addr val; Elf64_Sxword addend; Elf64_Sxword addend; Elf64_Addr dot; Elf64_Addr dot; Elf_Addr loc0; unsigned int targetsec = sechdrs[relsec].sh_info; DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ /* This is where to make the change */ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr + rel[i].r_offset; + rel[i].r_offset; /* This is the start of the target section */ loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */ /* This is the symbol it is referring to */ sym = (Elf64_Sym *)sechdrs[symindex].sh_addr sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + ELF64_R_SYM(rel[i].r_info); + ELF64_R_SYM(rel[i].r_info); Loading Loading @@ -672,42 +729,40 @@ int apply_relocate_add(Elf_Shdr *sechdrs, DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", strtab + sym->st_name, strtab + sym->st_name, loc, val); loc, val); val += addend; /* can we reach it locally? */ /* can we reach it locally? */ if(!in_local_section(me, (void *)val, (void *)dot)) { if (in_local(me, (void *)val)) { /* this is the case where the symbol is local if (in_local(me, (void *)val)) * to the module, but in a different section, /* this is the case where the * so stub the jump in case it's more than 22 * symbol is local to the * module, but in a different * section, so stub the jump * in case it's more than 22 * bits away */ * bits away */ val = get_stub(me, val, addend, ELF_STUB_DIRECT, val = (val - dot - 8)/4; in_init(me, loc)); if (!RELOC_REACHABLE(val, 22)) { else if (strncmp(strtab + sym->st_name, "$$", 2) /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); } else { /* Ok, we can reach it directly. */ val = sym->st_value; val += addend; } } else { val = sym->st_value; if (strncmp(strtab + sym->st_name, "$$", 2) == 0) == 0) val = get_stub(me, val, addend, ELF_STUB_MILLI, val = get_stub(me, val, addend, ELF_STUB_MILLI, in_init(me, loc)); loc0, targetsec); else else val = get_stub(me, val, addend, ELF_STUB_GOT, val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); loc0, targetsec); } } DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", strtab + sym->st_name, loc, sym->st_value, strtab + sym->st_name, loc, sym->st_value, addend, val); addend, val); /* FIXME: local symbols work as long as the * core and init pieces aren't separated too * far. If this is ever broken, you will trip * the check below. The way to fix it would * be to generate local stubs to go between init * and core */ if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 || (Elf64_Sxword)(val - dot - 8) < -0x800000) { printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n", me->name, strtab + sym->st_name); return -ENOEXEC; } val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 22); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; break; case R_PARISC_DIR64: case R_PARISC_DIR64: Loading Loading @@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr, addr = (u32 *)entry->addr; addr = (u32 *)entry->addr; printk("INSNS: %x %x %x %x\n", printk("INSNS: %x %x %x %x\n", addr[0], addr[1], addr[2], addr[3]); addr[0], addr[1], addr[2], addr[3]); printk("stubs used %ld, stubs max %ld\n" printk("got entries used %ld, gots max %ld\n" "init_stubs used %ld, init stubs max %ld\n" "got entries used %ld, gots max %ld\n" "fdescs used %ld, fdescs max %ld\n", "fdescs used %ld, fdescs max %ld\n", me->arch.stub_count, me->arch.stub_max, me->arch.init_stub_count, me->arch.init_stub_max, me->arch.got_count, me->arch.got_max, me->arch.got_count, me->arch.got_max, me->arch.fdesc_count, me->arch.fdesc_max); me->arch.fdesc_count, me->arch.fdesc_max); #endif #endif Loading Loading @@ -830,6 +881,9 @@ int module_finalize(const Elf_Ehdr *hdr, return -EINVAL; return -EINVAL; } } kfree(me->arch.section); me->arch.section = NULL; /* no symbol table */ /* no symbol table */ if(symhdr == NULL) if(symhdr == NULL) return 0; return 0; Loading Loading
Documentation/filesystems/ocfs2.txt +2 −1 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ Features which OCFS2 does not support yet: - quotas - quotas - Directory change notification (F_NOTIFY) - Directory change notification (F_NOTIFY) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - POSIX ACLs Mount options Mount options ============= ============= Loading Loading @@ -79,3 +78,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at bits of significance. bits of significance. user_xattr (*) Enables Extended User Attributes. user_xattr (*) Enables Extended User Attributes. nouser_xattr Disables Extended User Attributes. nouser_xattr Disables Extended User Attributes. acl Enables POSIX Access Control Lists support. noacl (*) Disables POSIX Access Control Lists support.
MAINTAINERS +5 −10 Original line number Original line Diff line number Diff line Loading @@ -4015,10 +4015,12 @@ L: alsa-devel@alsa-project.org (subscribers-only) W: http://alsa-project.org/main/index.php/ASoC W: http://alsa-project.org/main/index.php/ASoC S: Supported S: Supported SPARC (sparc32) SPARC + UltraSPARC (sparc/sparc64) P: William L. Irwin P: David S. Miller M: wli@holomorphy.com M: davem@davemloft.net L: sparclinux@vger.kernel.org L: sparclinux@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git S: Maintained S: Maintained SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER Loading Loading @@ -4302,13 +4304,6 @@ M: dushistov@mail.ru L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org S: Maintained S: Maintained UltraSPARC (sparc64) P: David S. Miller M: davem@davemloft.net L: sparclinux@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git S: Maintained ULTRA-WIDEBAND (UWB) SUBSYSTEM: ULTRA-WIDEBAND (UWB) SUBSYSTEM: P: David Vrabel P: David Vrabel M: david.vrabel@csr.com M: david.vrabel@csr.com Loading
arch/arm/mach-omap2/clock24xx.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = { }; }; static struct clk i2chs2_fck = { static struct clk i2chs2_fck = { .name = "i2chs_fck", .name = "i2c_fck", .id = 2, .id = 2, .parent = &func_96m_ck, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X, Loading Loading @@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = { }; }; static struct clk i2chs1_fck = { static struct clk i2chs1_fck = { .name = "i2chs_fck", .name = "i2c_fck", .id = 1, .id = 1, .parent = &func_96m_ck, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X, Loading
arch/parisc/include/asm/module.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -23,8 +23,10 @@ struct mod_arch_specific { { unsigned long got_offset, got_count, got_max; unsigned long got_offset, got_count, got_max; unsigned long fdesc_offset, fdesc_count, fdesc_max; unsigned long fdesc_offset, fdesc_count, fdesc_max; unsigned long stub_offset, stub_count, stub_max; struct { unsigned long init_stub_offset, init_stub_count, init_stub_max; unsigned long stub_offset; unsigned int stub_entries; } *section; int unwind_section; int unwind_section; struct unwind_table *unwind; struct unwind_table *unwind; }; }; Loading
arch/parisc/kernel/module.c +135 −81 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ * * * Linux/PA-RISC Project (http://www.parisc-linux.org/) * Linux/PA-RISC Project (http://www.parisc-linux.org/) * Copyright (C) 2003 Randolph Chung <tausq at debian . org> * Copyright (C) 2003 Randolph Chung <tausq at debian . org> * Copyright (C) 2008 Helge Deller <deller@gmx.de> * * * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify Loading @@ -24,6 +25,19 @@ * * * * * Notes: * Notes: * - PLT stub handling * On 32bit (and sometimes 64bit) and with big kernel modules like xfs or * ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may * fail to reach their PLT stub if we only create one big stub array for * all sections at the beginning of the core or init section. * Instead we now insert individual PLT stub entries directly in front of * of the code sections where the stubs are actually called. * This reduces the distance between the PCREL location and the stub entry * so that the relocations can be fulfilled. * While calculating the final layout of the kernel module in memory, the * kernel module loader calls arch_mod_section_prepend() to request the * to be reserved amount of memory in front of each individual section. * * - SEGREL32 handling * - SEGREL32 handling * We are not doing SEGREL32 handling correctly. According to the ABI, we * We are not doing SEGREL32 handling correctly. According to the ABI, we * should do a value offset, like this: * should do a value offset, like this: Loading Loading @@ -58,9 +72,13 @@ #define DEBUGP(fmt...) #define DEBUGP(fmt...) #endif #endif #define RELOC_REACHABLE(val, bits) \ (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \ 0 : 1) #define CHECK_RELOC(val, bits) \ #define CHECK_RELOC(val, bits) \ if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ if (!RELOC_REACHABLE(val, bits)) { \ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ me->name, strtab + sym->st_name, (unsigned long)val, bits); \ me->name, strtab + sym->st_name, (unsigned long)val, bits); \ return -ENOEXEC; \ return -ENOEXEC; \ Loading Loading @@ -92,13 +110,6 @@ static inline int in_local(struct module *me, void *loc) return in_init(me, loc) || in_core(me, loc); return in_init(me, loc) || in_core(me, loc); } } static inline int in_local_section(struct module *me, void *loc, void *dot) { return (in_init(me, loc) && in_init(me, dot)) || (in_core(me, loc) && in_core(me, dot)); } #ifndef CONFIG_64BIT #ifndef CONFIG_64BIT struct got_entry { struct got_entry { Elf32_Addr addr; Elf32_Addr addr; Loading Loading @@ -258,23 +269,42 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) /* Free memory returned from module_alloc */ /* Free memory returned from module_alloc */ void module_free(struct module *mod, void *module_region) void module_free(struct module *mod, void *module_region) { { kfree(mod->arch.section); mod->arch.section = NULL; vfree(module_region); vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception /* FIXME: If module_region == mod->init_region, trim exception table entries. */ table entries. */ } } /* Additional bytes needed in front of individual sections */ unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section) { /* size needed for all stubs of this section (including * one additional for correct alignment of the stubs) */ return (mod->arch.section[section].stub_entries + 1) * sizeof(struct stub_entry); } #define CONST #define CONST int module_frob_arch_sections(CONST Elf_Ehdr *hdr, int module_frob_arch_sections(CONST Elf_Ehdr *hdr, CONST Elf_Shdr *sechdrs, CONST Elf_Shdr *sechdrs, CONST char *secstrings, CONST char *secstrings, struct module *me) struct module *me) { { unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; unsigned long gots = 0, fdescs = 0, len; unsigned int i; unsigned int i; len = hdr->e_shnum * sizeof(me->arch.section[0]); me->arch.section = kzalloc(len, GFP_KERNEL); if (!me->arch.section) return -ENOMEM; for (i = 1; i < hdr->e_shnum; i++) { for (i = 1; i < hdr->e_shnum; i++) { const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; const Elf_Rela *rels = (void *)sechdrs[i].sh_addr; unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); unsigned int count, s; if (strncmp(secstrings + sechdrs[i].sh_name, if (strncmp(secstrings + sechdrs[i].sh_name, ".PARISC.unwind", 14) == 0) ".PARISC.unwind", 14) == 0) Loading @@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, */ */ gots += count_gots(rels, nrels); gots += count_gots(rels, nrels); fdescs += count_fdescs(rels, nrels); fdescs += count_fdescs(rels, nrels); if(strncmp(secstrings + sechdrs[i].sh_name, ".rela.init", 10) == 0) /* XXX: By sorting the relocs and finding duplicate entries init_stubs += count_stubs(rels, nrels); * we could reduce the number of necessary stubs and save else * some memory. */ stubs += count_stubs(rels, nrels); count = count_stubs(rels, nrels); if (!count) continue; /* so we need relocation stubs. reserve necessary memory. */ /* sh_info gives the section for which we need to add stubs. */ s = sechdrs[i].sh_info; /* each code section should only have one relocation section */ WARN_ON(me->arch.section[s].stub_entries); /* store number of stubs we need for this section */ me->arch.section[s].stub_entries += count; } } /* align things a bit */ /* align things a bit */ Loading @@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, me->arch.fdesc_offset = me->core_size; me->arch.fdesc_offset = me->core_size; me->core_size += fdescs * sizeof(Elf_Fdesc); me->core_size += fdescs * sizeof(Elf_Fdesc); me->core_size = ALIGN(me->core_size, 16); me->arch.stub_offset = me->core_size; me->core_size += stubs * sizeof(struct stub_entry); me->init_size = ALIGN(me->init_size, 16); me->arch.init_stub_offset = me->init_size; me->init_size += init_stubs * sizeof(struct stub_entry); me->arch.got_max = gots; me->arch.got_max = gots; me->arch.fdesc_max = fdescs; me->arch.fdesc_max = fdescs; me->arch.stub_max = stubs; me->arch.init_stub_max = init_stubs; return 0; return 0; } } Loading Loading @@ -380,23 +412,27 @@ enum elf_stub_type { }; }; static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, enum elf_stub_type stub_type, int init_section) enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec) { { unsigned long i; struct stub_entry *stub; struct stub_entry *stub; if(init_section) { /* initialize stub_offset to point in front of the section */ i = me->arch.init_stub_count++; if (!me->arch.section[targetsec].stub_offset) { BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); loc0 -= (me->arch.section[targetsec].stub_entries + 1) * stub = me->module_init + me->arch.init_stub_offset + sizeof(struct stub_entry); i * sizeof(struct stub_entry); /* get correct alignment for the stubs */ } else { loc0 = ALIGN(loc0, sizeof(struct stub_entry)); i = me->arch.stub_count++; me->arch.section[targetsec].stub_offset = loc0; BUG_ON(me->arch.stub_count > me->arch.stub_max); stub = me->module_core + me->arch.stub_offset + i * sizeof(struct stub_entry); } } /* get address of stub entry */ stub = (void *) me->arch.section[targetsec].stub_offset; me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry); /* do not write outside available stub area */ BUG_ON(0 == me->arch.section[targetsec].stub_entries--); #ifndef CONFIG_64BIT #ifndef CONFIG_64BIT /* for 32-bit the stub looks like this: /* for 32-bit the stub looks like this: * ldil L'XXX,%r1 * ldil L'XXX,%r1 Loading Loading @@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf32_Addr val; Elf32_Addr val; Elf32_Sword addend; Elf32_Sword addend; Elf32_Addr dot; Elf32_Addr dot; Elf_Addr loc0; unsigned int targetsec = sechdrs[relsec].sh_info; //unsigned long dp = (unsigned long)$global$; //unsigned long dp = (unsigned long)$global$; register unsigned long dp asm ("r27"); register unsigned long dp asm ("r27"); DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ /* This is where to make the change */ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr + rel[i].r_offset; + rel[i].r_offset; /* This is the start of the target section */ loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */ /* This is the symbol it is referring to */ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + ELF32_R_SYM(rel[i].r_info); + ELF32_R_SYM(rel[i].r_info); Loading Loading @@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs, break; break; case R_PARISC_PCREL17F: case R_PARISC_PCREL17F: /* 17-bit PC relative address */ /* 17-bit PC relative address */ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */ val += addend; val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 17) if (!RELOC_REACHABLE(val, 17)) { /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); val = (val - dot - 8)/4; CHECK_RELOC(val, 17); } *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); break; break; case R_PARISC_PCREL22F: case R_PARISC_PCREL22F: /* 22-bit PC relative address; only defined for pa20 */ /* 22-bit PC relative address; only defined for pa20 */ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */ DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", val += addend; strtab + sym->st_name, (unsigned long)loc, addend, val = (val - dot - 8)/4; val) if (!RELOC_REACHABLE(val, 22)) { /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 22); CHECK_RELOC(val, 22); } *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; break; Loading Loading @@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf64_Addr val; Elf64_Addr val; Elf64_Sxword addend; Elf64_Sxword addend; Elf64_Addr dot; Elf64_Addr dot; Elf_Addr loc0; unsigned int targetsec = sechdrs[relsec].sh_info; DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ /* This is where to make the change */ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr + rel[i].r_offset; + rel[i].r_offset; /* This is the start of the target section */ loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */ /* This is the symbol it is referring to */ sym = (Elf64_Sym *)sechdrs[symindex].sh_addr sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + ELF64_R_SYM(rel[i].r_info); + ELF64_R_SYM(rel[i].r_info); Loading Loading @@ -672,42 +729,40 @@ int apply_relocate_add(Elf_Shdr *sechdrs, DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", strtab + sym->st_name, strtab + sym->st_name, loc, val); loc, val); val += addend; /* can we reach it locally? */ /* can we reach it locally? */ if(!in_local_section(me, (void *)val, (void *)dot)) { if (in_local(me, (void *)val)) { /* this is the case where the symbol is local if (in_local(me, (void *)val)) * to the module, but in a different section, /* this is the case where the * so stub the jump in case it's more than 22 * symbol is local to the * module, but in a different * section, so stub the jump * in case it's more than 22 * bits away */ * bits away */ val = get_stub(me, val, addend, ELF_STUB_DIRECT, val = (val - dot - 8)/4; in_init(me, loc)); if (!RELOC_REACHABLE(val, 22)) { else if (strncmp(strtab + sym->st_name, "$$", 2) /* direct distance too far, create * stub entry instead */ val = get_stub(me, sym->st_value, addend, ELF_STUB_DIRECT, loc0, targetsec); } else { /* Ok, we can reach it directly. */ val = sym->st_value; val += addend; } } else { val = sym->st_value; if (strncmp(strtab + sym->st_name, "$$", 2) == 0) == 0) val = get_stub(me, val, addend, ELF_STUB_MILLI, val = get_stub(me, val, addend, ELF_STUB_MILLI, in_init(me, loc)); loc0, targetsec); else else val = get_stub(me, val, addend, ELF_STUB_GOT, val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); loc0, targetsec); } } DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", strtab + sym->st_name, loc, sym->st_value, strtab + sym->st_name, loc, sym->st_value, addend, val); addend, val); /* FIXME: local symbols work as long as the * core and init pieces aren't separated too * far. If this is ever broken, you will trip * the check below. The way to fix it would * be to generate local stubs to go between init * and core */ if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 || (Elf64_Sxword)(val - dot - 8) < -0x800000) { printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n", me->name, strtab + sym->st_name); return -ENOEXEC; } val = (val - dot - 8)/4; val = (val - dot - 8)/4; CHECK_RELOC(val, 22); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; break; case R_PARISC_DIR64: case R_PARISC_DIR64: Loading Loading @@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr, addr = (u32 *)entry->addr; addr = (u32 *)entry->addr; printk("INSNS: %x %x %x %x\n", printk("INSNS: %x %x %x %x\n", addr[0], addr[1], addr[2], addr[3]); addr[0], addr[1], addr[2], addr[3]); printk("stubs used %ld, stubs max %ld\n" printk("got entries used %ld, gots max %ld\n" "init_stubs used %ld, init stubs max %ld\n" "got entries used %ld, gots max %ld\n" "fdescs used %ld, fdescs max %ld\n", "fdescs used %ld, fdescs max %ld\n", me->arch.stub_count, me->arch.stub_max, me->arch.init_stub_count, me->arch.init_stub_max, me->arch.got_count, me->arch.got_max, me->arch.got_count, me->arch.got_max, me->arch.fdesc_count, me->arch.fdesc_max); me->arch.fdesc_count, me->arch.fdesc_max); #endif #endif Loading Loading @@ -830,6 +881,9 @@ int module_finalize(const Elf_Ehdr *hdr, return -EINVAL; return -EINVAL; } } kfree(me->arch.section); me->arch.section = NULL; /* no symbol table */ /* no symbol table */ if(symhdr == NULL) if(symhdr == NULL) return 0; return 0; Loading