mem_region.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <common/debug.h>
  8. #include <lib/utils.h>
  9. #include <lib/xlat_tables/xlat_tables_compat.h>
  10. /*
  11. * All the regions defined in mem_region_t must have the following properties
  12. *
  13. * - Any contiguous regions must be merged into a single entry.
  14. * - The number of bytes of each region must be greater than zero.
  15. * - The calculation of the highest address within the region (base + nbytes-1)
  16. * doesn't produce an overflow.
  17. *
  18. * These conditions must be fulfilled by the caller and they aren't checked
  19. * at runtime.
  20. */
  21. /*
  22. * zero_normalmem all the regions defined in tbl.
  23. * It assumes that MMU is enabled and the memory is Normal memory.
  24. * tbl must be a valid pointer to a memory mem_region_t array,
  25. * nregions is the size of the array.
  26. */
  27. void clear_mem_regions(mem_region_t *tbl, size_t nregions)
  28. {
  29. size_t i;
  30. assert(tbl != NULL);
  31. assert(nregions > 0U);
  32. for (i = 0; i < nregions; i++) {
  33. assert(tbl->nbytes > 0);
  34. assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
  35. zero_normalmem((void *) (tbl->base), tbl->nbytes);
  36. tbl++;
  37. }
  38. }
  39. #if defined(PLAT_XLAT_TABLES_DYNAMIC)
  40. /*
  41. * zero_normalmem all the regions defined in regions.
  42. * It assumes that MMU is enabled and the memory is Normal memory.
  43. * regions must be a valid pointer to a memory mem_region_t array,
  44. * nregions is the size of the array. va is the virtual address
  45. * where we want to map the physical pages that are going to
  46. * be cleared, and chunk is the amount of memory mapped and
  47. * cleared in every iteration.
  48. */
  49. void clear_map_dyn_mem_regions(struct mem_region *regions,
  50. size_t nregions,
  51. uintptr_t va,
  52. size_t chunk)
  53. {
  54. uintptr_t begin;
  55. int r;
  56. size_t size;
  57. const unsigned int attr = MT_MEMORY | MT_RW | MT_NS;
  58. assert(regions != NULL);
  59. assert(nregions != 0U);
  60. assert(chunk != 0U);
  61. for (unsigned int i = 0U; i < nregions; i++) {
  62. begin = regions[i].base;
  63. size = regions[i].nbytes;
  64. if (((begin & (chunk-1U)) != 0U) ||
  65. ((size & (chunk-1U)) != 0U)) {
  66. INFO("PSCI: Not correctly aligned region\n");
  67. panic();
  68. }
  69. while (size > 0U) {
  70. r = mmap_add_dynamic_region(begin, va, chunk, attr);
  71. if (r != 0) {
  72. INFO("PSCI: %s failed with %d\n",
  73. "mmap_add_dynamic_region", r);
  74. panic();
  75. }
  76. zero_normalmem((void *)va, chunk);
  77. r = mmap_remove_dynamic_region(va, chunk);
  78. if (r != 0) {
  79. INFO("PSCI: %s failed with %d\n",
  80. "mmap_remove_dynamic_region", r);
  81. panic();
  82. }
  83. begin += chunk;
  84. size -= chunk;
  85. }
  86. }
  87. }
  88. #endif
  89. /*
  90. * This function checks that a region (addr + nbytes-1) of memory is totally
  91. * covered by one of the regions defined in tbl.
  92. * tbl must be a valid pointer to a memory mem_region_t array, nregions
  93. * is the size of the array and the region described by addr and nbytes must
  94. * not generate an overflow.
  95. * Returns:
  96. * -1 means that the region is not covered by any of the regions
  97. * described in tbl.
  98. * 0 the region (addr + nbytes-1) is covered by one of the regions described
  99. * in tbl
  100. */
  101. int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
  102. uintptr_t addr, size_t nbytes)
  103. {
  104. uintptr_t region_start, region_end, start, end;
  105. size_t i;
  106. assert(tbl != NULL);
  107. assert(nbytes != 0U);
  108. assert(!check_uptr_overflow(addr, nbytes-1));
  109. region_start = addr;
  110. region_end = addr + (nbytes - 1U);
  111. for (i = 0U; i < nregions; i++) {
  112. assert(tbl->nbytes > 0);
  113. assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
  114. start = tbl->base;
  115. end = start + (tbl->nbytes - 1);
  116. if ((region_start >= start) && (region_end <= end)) {
  117. return 0;
  118. }
  119. tbl++;
  120. }
  121. return -1;
  122. }