Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /* Copyright (C) 2003, 2004 Red Hat, Inc.
* Contributed by Alexandre Oliva <aoliva@redhat.com>
* Copyright (C) 2006-2011 Analog Devices, Inc.
*
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
#include <bfin_sram.h>
#define __dl_loadaddr_unmap __dl_loadaddr_unmap
#include "../fdpic/dl-inlines.h"
static __always_inline void
__dl_loadaddr_unmap(struct elf32_fdpic_loadaddr loadaddr,
struct funcdesc_ht *funcdesc_ht)
{
int i;
for (i = 0; i < loadaddr.map->nsegs; i++) {
struct elf32_fdpic_loadseg *segdata;
ssize_t offs;
segdata = loadaddr.map->segs + i;
/* FIXME:
* A more cleaner way is to add type for struct elf32_fdpic_loadseg,
* and release the memory according to the type.
* Currently, we hardcode the memory address of L1 SRAM.
*/
if ((segdata->addr & 0xff800000) == 0xff800000) {
_dl_sram_free((void *)segdata->addr);
continue;
}
offs = (segdata->p_vaddr & ADDR_ALIGN);
_dl_munmap((void*)segdata->addr - offs,
segdata->p_memsz + offs);
}
/*
* _dl_unmap is only called for dlopen()ed libraries, for which
* calling free() is safe, or before we've completed the initial
* relocation, in which case calling free() is probably pointless,
* but still safe.
*/
_dl_free(loadaddr.map);
if (funcdesc_ht)
htab_delete(funcdesc_ht);
}
static __always_inline int
__dl_is_special_segment(Elf32_Ehdr *epnt, Elf32_Phdr *ppnt)
{
if (ppnt->p_type != PT_LOAD)
return 0;
/* Allow read-only executable segments to be loaded into L1 inst */
if ((epnt->e_flags & EF_BFIN_CODE_IN_L1) &&
!(ppnt->p_flags & PF_W) && (ppnt->p_flags & PF_X))
return 1;
/* Allow writable non-executable segments to be loaded into L1 data */
if ((epnt->e_flags & EF_BFIN_DATA_IN_L1) &&
(ppnt->p_flags & PF_W) && !(ppnt->p_flags & PF_X))
return 1;
/*
* These L1 memory addresses are also used in GNU ld and linux kernel.
* They need to be kept synchronized.
*/
switch (ppnt->p_vaddr) {
case 0xff700000:
case 0xff800000:
case 0xff900000:
case 0xffa00000:
case 0xfeb00000:
case 0xfec00000:
return 1;
default:
return 0;
}
}
static __always_inline char *
__dl_map_segment(Elf32_Ehdr *epnt, Elf32_Phdr *ppnt, int infile, int flags)
{
void *addr;
unsigned long sram_flags = 0;
/* Handle L1 inst mappings */
if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000) &&
!(ppnt->p_flags & PF_W) && (ppnt->p_flags & PF_X))
{
size_t size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
void *status = _dl_mmap(NULL, size, LXFLAGS(ppnt->p_flags),
flags | MAP_EXECUTABLE | MAP_DENYWRITE,
infile, ppnt->p_offset & OFFS_ALIGN);
if (_dl_mmap_check_error(status))
return NULL;
addr = _dl_sram_alloc(ppnt->p_filesz, L1_INST_SRAM);
if (addr)
_dl_dma_memcpy(addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz);
else
_dl_dprintf(2, "%s:%s: sram allocation %#x failed\n",
_dl_progname, __func__, ppnt->p_vaddr);
_dl_munmap(status, size);
return addr;
}
/* Handle L1 data mappings */
if (((epnt->e_flags & EF_BFIN_DATA_IN_L1) ||
ppnt->p_vaddr == 0xff700000 ||
ppnt->p_vaddr == 0xff800000 ||
ppnt->p_vaddr == 0xff900000) &&
(ppnt->p_flags & PF_W) && !(ppnt->p_flags & PF_X))
{
switch (ppnt->p_vaddr) {
case 0xff800000: sram_flags = L1_DATA_A_SRAM; break;
case 0xff900000: sram_flags = L1_DATA_B_SRAM; break;
default: sram_flags = L1_DATA_SRAM; break;
}
}
/* Handle L2 mappings */
if (ppnt->p_vaddr == 0xfeb00000 || ppnt->p_vaddr == 0xfec00000)
sram_flags = L2_SRAM;
if (sram_flags) {
addr = _dl_sram_alloc(ppnt->p_memsz, sram_flags);
if (addr) {
if (_DL_PREAD(infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
_dl_sram_free(addr);
return NULL;
}
if (ppnt->p_filesz < ppnt->p_memsz)
_dl_memset(addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
} else
_dl_dprintf(2, "%s:%s: sram allocation %#x failed\n",
_dl_progname, __func__, ppnt->p_vaddr);
return addr;
}
return 0;
}
|