dl-inlines.h 4.0 KB

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