cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

module.c (3457B)


      1/*
      2 * Kernel module support for Nios II.
      3 *
      4 * Copyright (C) 2004 Microtronix Datacom Ltd.
      5 *   Written by Wentao Xu <xuwentao@microtronix.com>
      6 * Copyright (C) 2001, 2003 Rusty Russell
      7 *
      8 * This file is subject to the terms and conditions of the GNU General
      9 * Public License.  See the file COPYING in the main directory of this
     10 * archive for more details.
     11 */
     12
     13#include <linux/moduleloader.h>
     14#include <linux/elf.h>
     15#include <linux/mm.h>
     16#include <linux/vmalloc.h>
     17#include <linux/slab.h>
     18#include <linux/fs.h>
     19#include <linux/string.h>
     20#include <linux/kernel.h>
     21
     22#include <asm/cacheflush.h>
     23
     24/*
     25 * Modules should NOT be allocated with kmalloc for (obvious) reasons.
     26 * But we do it for now to avoid relocation issues. CALL26/PCREL26 cannot reach
     27 * from 0x80000000 (vmalloc area) to 0xc00000000 (kernel) (kmalloc returns
     28 * addresses in 0xc0000000)
     29 */
     30void *module_alloc(unsigned long size)
     31{
     32	if (size == 0)
     33		return NULL;
     34	return kmalloc(size, GFP_KERNEL);
     35}
     36
     37/* Free memory returned from module_alloc */
     38void module_memfree(void *module_region)
     39{
     40	kfree(module_region);
     41}
     42
     43int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
     44			unsigned int symindex, unsigned int relsec,
     45			struct module *mod)
     46{
     47	unsigned int i;
     48	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
     49
     50	pr_debug("Applying relocate section %u to %u\n", relsec,
     51		 sechdrs[relsec].sh_info);
     52
     53	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
     54		/* This is where to make the change */
     55		uint32_t word;
     56		uint32_t *loc
     57			= ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
     58			   + rela[i].r_offset);
     59		/* This is the symbol it is referring to.  Note that all
     60		   undefined symbols have been resolved.  */
     61		Elf32_Sym *sym
     62			= ((Elf32_Sym *)sechdrs[symindex].sh_addr
     63				+ ELF32_R_SYM(rela[i].r_info));
     64		uint32_t v = sym->st_value + rela[i].r_addend;
     65
     66		pr_debug("reltype %d 0x%x name:<%s>\n",
     67			ELF32_R_TYPE(rela[i].r_info),
     68			rela[i].r_offset, strtab + sym->st_name);
     69
     70		switch (ELF32_R_TYPE(rela[i].r_info)) {
     71		case R_NIOS2_NONE:
     72			break;
     73		case R_NIOS2_BFD_RELOC_32:
     74			*loc += v;
     75			break;
     76		case R_NIOS2_PCREL16:
     77			v -= (uint32_t)loc + 4;
     78			if ((int32_t)v > 0x7fff ||
     79				(int32_t)v < -(int32_t)0x8000) {
     80				pr_err("module %s: relocation overflow\n",
     81					mod->name);
     82				return -ENOEXEC;
     83			}
     84			word = *loc;
     85			*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
     86				(word & 0x3f);
     87			break;
     88		case R_NIOS2_CALL26:
     89			if (v & 3) {
     90				pr_err("module %s: dangerous relocation\n",
     91					mod->name);
     92				return -ENOEXEC;
     93			}
     94			if ((v >> 28) != ((uint32_t)loc >> 28)) {
     95				pr_err("module %s: relocation overflow\n",
     96					mod->name);
     97				return -ENOEXEC;
     98			}
     99			*loc = (*loc & 0x3f) | ((v >> 2) << 6);
    100			break;
    101		case R_NIOS2_HI16:
    102			word = *loc;
    103			*loc = ((((word >> 22) << 16) |
    104				((v >> 16) & 0xffff)) << 6) | (word & 0x3f);
    105			break;
    106		case R_NIOS2_LO16:
    107			word = *loc;
    108			*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
    109					(word & 0x3f);
    110			break;
    111		case R_NIOS2_HIADJ16:
    112			{
    113				Elf32_Addr word2;
    114
    115				word = *loc;
    116				word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
    117				*loc = ((((word >> 22) << 16) | word2) << 6) |
    118						(word & 0x3f);
    119			}
    120			break;
    121
    122		default:
    123			pr_err("module %s: Unknown reloc: %u\n",
    124				mod->name, ELF32_R_TYPE(rela[i].r_info));
    125			return -ENOEXEC;
    126		}
    127	}
    128
    129	return 0;
    130}
    131
    132int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
    133			struct module *me)
    134{
    135	flush_cache_all();
    136	return 0;
    137}