123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /* 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;
- }
|