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