linux/arch/xtensa/kernel/module.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/kernel/module.c
   3 *
   4 * Module support.
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file "COPYING" in the main directory of this archive
   8 * for more details.
   9 *
  10 * Copyright (C) 2001 - 2006 Tensilica Inc.
  11 *
  12 * Chris Zankel <chris@zankel.net>
  13 *
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/moduleloader.h>
  18#include <linux/elf.h>
  19#include <linux/vmalloc.h>
  20#include <linux/fs.h>
  21#include <linux/string.h>
  22#include <linux/kernel.h>
  23#include <linux/cache.h>
  24
  25#undef DEBUG_RELOCATE
  26
  27void *module_alloc(unsigned long size)
  28{
  29        if (size == 0)
  30                return NULL;
  31        return vmalloc(size);
  32}
  33
  34void module_free(struct module *mod, void *module_region)
  35{
  36        vfree(module_region);
  37        /* FIXME: If module_region == mod->init_region, trim exception
  38           table entries. */
  39}
  40
  41int module_frob_arch_sections(Elf32_Ehdr *hdr,
  42                              Elf32_Shdr *sechdrs,
  43                              char *secstrings,
  44                              struct module *mod)
  45{
  46        return 0;
  47}
  48
  49static int
  50decode_calln_opcode (unsigned char *location)
  51{
  52#ifdef __XTENSA_EB__
  53        return (location[0] & 0xf0) == 0x50;
  54#endif
  55#ifdef __XTENSA_EL__
  56        return (location[0] & 0xf) == 0x5;
  57#endif
  58}
  59
  60static int
  61decode_l32r_opcode (unsigned char *location)
  62{
  63#ifdef __XTENSA_EB__
  64        return (location[0] & 0xf0) == 0x10;
  65#endif
  66#ifdef __XTENSA_EL__
  67        return (location[0] & 0xf) == 0x1;
  68#endif
  69}
  70
  71int apply_relocate(Elf32_Shdr *sechdrs,
  72                   const char *strtab,
  73                   unsigned int symindex,
  74                   unsigned int relsec,
  75                   struct module *mod)
  76{
  77        printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
  78               mod->name);
  79        return -ENOEXEC;
  80
  81}
  82
  83int apply_relocate_add(Elf32_Shdr *sechdrs,
  84                       const char *strtab,
  85                       unsigned int symindex,
  86                       unsigned int relsec,
  87                       struct module *mod)
  88{
  89        unsigned int i;
  90        Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
  91        Elf32_Sym *sym;
  92        unsigned char *location;
  93        uint32_t value;
  94
  95#ifdef DEBUG_RELOCATE
  96        printk("Applying relocate section %u to %u\n", relsec,
  97               sechdrs[relsec].sh_info);
  98#endif
  99        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
 100                location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr
 101                        + rela[i].r_offset;
 102                sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
 103                        + ELF32_R_SYM(rela[i].r_info);
 104                value = sym->st_value + rela[i].r_addend;
 105
 106                switch (ELF32_R_TYPE(rela[i].r_info)) {
 107                case R_XTENSA_NONE:
 108                case R_XTENSA_DIFF8:
 109                case R_XTENSA_DIFF16:
 110                case R_XTENSA_DIFF32:
 111                case R_XTENSA_ASM_EXPAND:
 112                        break;
 113
 114                case R_XTENSA_32:
 115                case R_XTENSA_PLT:
 116                        *(uint32_t *)location += value;
 117                        break;
 118
 119                case R_XTENSA_SLOT0_OP:
 120                        if (decode_calln_opcode(location)) {
 121                                value -= ((unsigned long)location & -4) + 4;
 122                                if ((value & 3) != 0 ||
 123                                    ((value + (1 << 19)) >> 20) != 0) {
 124                                        printk("%s: relocation out of range, "
 125                                               "section %d reloc %d "
 126                                               "sym '%s'\n",
 127                                               mod->name, relsec, i,
 128                                               strtab + sym->st_name);
 129                                        return -ENOEXEC;
 130                                }
 131                                value = (signed int)value >> 2;
 132#ifdef __XTENSA_EB__
 133                                location[0] = ((location[0] & ~0x3) |
 134                                            ((value >> 16) & 0x3));
 135                                location[1] = (value >> 8) & 0xff;
 136                                location[2] = value & 0xff;
 137#endif
 138#ifdef __XTENSA_EL__
 139                                location[0] = ((location[0] & ~0xc0) |
 140                                            ((value << 6) & 0xc0));
 141                                location[1] = (value >> 2) & 0xff;
 142                                location[2] = (value >> 10) & 0xff;
 143#endif
 144                        } else if (decode_l32r_opcode(location)) {
 145                                value -= (((unsigned long)location + 3) & -4);
 146                                if ((value & 3) != 0 ||
 147                                    (signed int)value >> 18 != -1) {
 148                                        printk("%s: relocation out of range, "
 149                                               "section %d reloc %d "
 150                                               "sym '%s'\n",
 151                                               mod->name, relsec, i,
 152                                               strtab + sym->st_name);
 153                                        return -ENOEXEC;
 154                                }
 155                                value = (signed int)value >> 2;
 156
 157#ifdef __XTENSA_EB__
 158                                location[1] = (value >> 8) & 0xff;
 159                                location[2] = value & 0xff;
 160#endif
 161#ifdef __XTENSA_EL__
 162                                location[1] = value & 0xff;
 163                                location[2] = (value >> 8) & 0xff;
 164#endif
 165                        }
 166                        /* FIXME: Ignore any other opcodes.  The Xtensa
 167                           assembler currently assumes that the linker will
 168                           always do relaxation and so all PC-relative
 169                           operands need relocations.  (The assembler also
 170                           writes out the tentative PC-relative values,
 171                           assuming no link-time relaxation, so it is usually
 172                           safe to ignore the relocations.)  If the
 173                           assembler's "--no-link-relax" flag can be made to
 174                           work, and if all kernel modules can be assembled
 175                           with that flag, then unexpected relocations could
 176                           be detected here.  */
 177                        break;
 178
 179                case R_XTENSA_SLOT1_OP:
 180                case R_XTENSA_SLOT2_OP:
 181                case R_XTENSA_SLOT3_OP:
 182                case R_XTENSA_SLOT4_OP:
 183                case R_XTENSA_SLOT5_OP:
 184                case R_XTENSA_SLOT6_OP:
 185                case R_XTENSA_SLOT7_OP:
 186                case R_XTENSA_SLOT8_OP:
 187                case R_XTENSA_SLOT9_OP:
 188                case R_XTENSA_SLOT10_OP:
 189                case R_XTENSA_SLOT11_OP:
 190                case R_XTENSA_SLOT12_OP:
 191                case R_XTENSA_SLOT13_OP:
 192                case R_XTENSA_SLOT14_OP:
 193                        printk("%s: unexpected FLIX relocation: %u\n",
 194                               mod->name,
 195                               ELF32_R_TYPE(rela[i].r_info));
 196                        return -ENOEXEC;
 197
 198                case R_XTENSA_SLOT0_ALT:
 199                case R_XTENSA_SLOT1_ALT:
 200                case R_XTENSA_SLOT2_ALT:
 201                case R_XTENSA_SLOT3_ALT:
 202                case R_XTENSA_SLOT4_ALT:
 203                case R_XTENSA_SLOT5_ALT:
 204                case R_XTENSA_SLOT6_ALT:
 205                case R_XTENSA_SLOT7_ALT:
 206                case R_XTENSA_SLOT8_ALT:
 207                case R_XTENSA_SLOT9_ALT:
 208                case R_XTENSA_SLOT10_ALT:
 209                case R_XTENSA_SLOT11_ALT:
 210                case R_XTENSA_SLOT12_ALT:
 211                case R_XTENSA_SLOT13_ALT:
 212                case R_XTENSA_SLOT14_ALT:
 213                        printk("%s: unexpected ALT relocation: %u\n",
 214                               mod->name,
 215                               ELF32_R_TYPE(rela[i].r_info));
 216                        return -ENOEXEC;
 217
 218                default:
 219                        printk("%s: unexpected relocation: %u\n",
 220                               mod->name,
 221                               ELF32_R_TYPE(rela[i].r_info));
 222                        return -ENOEXEC;
 223                }
 224        }
 225        return 0;
 226}
 227
 228int module_finalize(const Elf_Ehdr *hdr,
 229                    const Elf_Shdr *sechdrs,
 230                    struct module *mod)
 231{
 232        return 0;
 233}
 234
 235void module_arch_cleanup(struct module *mod)
 236{
 237}
 238