1
0

mprotect.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-25 tangzz98 the first version
  9. */
  10. #include "mprotect.h"
  11. #define DBG_ENABLE
  12. #define DBG_SECTION_NAME "MEMORY PROTECTION"
  13. #define DBG_LEVEL DBG_ERROR
  14. #include <rtdbg.h>
  15. rt_mem_exclusive_region_t exclusive_regions[NUM_EXCLUSIVE_REGIONS] = {};
  16. rt_mem_region_t *rt_mprotect_find_free_region(rt_thread_t thread)
  17. {
  18. rt_uint8_t i;
  19. rt_mem_region_t *free_region = RT_NULL;
  20. if (thread->mem_regions != RT_NULL)
  21. {
  22. for (i = 0U; i < NUM_DYNAMIC_REGIONS; i++)
  23. {
  24. if (((rt_mem_region_t *)thread->mem_regions)[i].size == 0)
  25. {
  26. free_region = &(((rt_mem_region_t *)thread->mem_regions)[i]);
  27. break;
  28. }
  29. }
  30. }
  31. return free_region;
  32. }
  33. rt_mem_region_t *rt_mprotect_find_region(rt_thread_t thread, rt_mem_region_t *region)
  34. {
  35. rt_uint8_t i;
  36. rt_mem_region_t *found_region = RT_NULL;
  37. if (thread->mem_regions != RT_NULL)
  38. {
  39. for (i = 0U; i < NUM_DYNAMIC_REGIONS; i++)
  40. {
  41. if ((((rt_mem_region_t *)thread->mem_regions)[i].start == region->start) && (((rt_mem_region_t *)thread->mem_regions)[i].size == region->size))
  42. {
  43. found_region = &(((rt_mem_region_t *)thread->mem_regions)[i]);
  44. break;
  45. }
  46. }
  47. }
  48. return found_region;
  49. }
  50. /**
  51. * @brief This function will initialize memory protection.
  52. *
  53. * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
  54. * When the return value is any other values, it means the initialization failed.
  55. */
  56. int rt_mprotect_init(void)
  57. {
  58. return (int)rt_hw_mpu_init();
  59. }
  60. /**
  61. * @brief The function will add a memory region configuraiton for a thread.
  62. *
  63. * @param thread is the thread that the memory region configuration will apply to.
  64. *
  65. * @param region is the configuration for the memory region to add.
  66. *
  67. * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
  68. * If the return value is any other values, it represents the operation failed.
  69. */
  70. rt_err_t rt_mprotect_add_region(rt_thread_t thread, rt_mem_region_t *region)
  71. {
  72. if (thread == RT_NULL)
  73. {
  74. thread = rt_thread_self();
  75. }
  76. if (thread->mem_regions == RT_NULL)
  77. {
  78. thread->mem_regions = RT_KERNEL_MALLOC(NUM_DYNAMIC_REGIONS * sizeof(rt_mem_region_t));
  79. if (thread->mem_regions == RT_NULL)
  80. {
  81. return RT_ERROR;
  82. }
  83. rt_memset(thread->mem_regions, 0U, sizeof(rt_mem_region_t ) * NUM_DYNAMIC_REGIONS);
  84. }
  85. return rt_hw_mpu_add_region(thread, region);
  86. }
  87. /**
  88. * @brief The function will delete an existing memory region configuraiton for a thread.
  89. *
  90. * @param thread is the thread that the memory region configuration will apply to.
  91. *
  92. * @param region is the configuration for the memory region to delete.
  93. *
  94. * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
  95. * If the return value is any other values, it represents the operation failed.
  96. */
  97. rt_err_t rt_mprotect_delete_region(rt_thread_t thread, rt_mem_region_t *region)
  98. {
  99. if (thread == RT_NULL)
  100. {
  101. thread = rt_thread_self();
  102. }
  103. return rt_hw_mpu_delete_region(thread, region);
  104. }
  105. /**
  106. * @brief The function will update an existing memory region configuraiton for a thread.
  107. *
  108. * @param thread is the thread that the memory region configuration will apply to.
  109. *
  110. * @param region is the new configuration for the memory region.
  111. *
  112. * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
  113. * If the return value is any other values, it represents the operation failed.
  114. */
  115. rt_err_t rt_mprotect_update_region(rt_thread_t thread, rt_mem_region_t *region)
  116. {
  117. if (thread == RT_NULL)
  118. {
  119. thread = rt_thread_self();
  120. }
  121. return rt_hw_mpu_update_region(thread, region);
  122. }
  123. /**
  124. * @brief The function will add a memory region that is only accessible by the calling thread.
  125. *
  126. * @param start is the start address of the memory region.
  127. *
  128. * @param size is the size of the memory region.
  129. *
  130. * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
  131. * If the return value is any other values, it represents the operation failed.
  132. */
  133. rt_err_t rt_mprotect_add_exclusive_region(void *start, rt_size_t size)
  134. {
  135. rt_uint8_t i;
  136. rt_mem_exclusive_region_t region;
  137. region.owner = rt_thread_self();
  138. region.region.start = start;
  139. region.region.size = size;
  140. region.region.attr = RT_MEM_REGION_P_NA_U_NA;
  141. if (rt_hw_mpu_add_region(RT_NULL, (rt_mem_region_t *)(&(region.region))) != RT_EOK)
  142. {
  143. return RT_ERROR;
  144. }
  145. rt_enter_critical();
  146. for (i = 0; i < NUM_EXCLUSIVE_REGIONS; i++)
  147. {
  148. if (exclusive_regions[i].owner == RT_NULL)
  149. {
  150. rt_memcpy(&(exclusive_regions[i]), &region, sizeof(rt_mem_exclusive_region_t));
  151. rt_exit_critical();
  152. return RT_EOK;
  153. }
  154. }
  155. rt_exit_critical();
  156. LOG_E("Insufficient regions");
  157. return RT_ERROR;
  158. }
  159. /**
  160. * @brief The function will delete a memory region that is only accessible by the calling thread.
  161. * The deleted region will be accessible by other threads.
  162. *
  163. * @param start is the start address of the memory region.
  164. *
  165. * @param size is the size of the memory region.
  166. *
  167. * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
  168. * If the return value is any other values, it represents the operation failed.
  169. */
  170. rt_err_t rt_mprotect_delete_exclusive_region(void *start, rt_size_t size)
  171. {
  172. rt_uint8_t i;
  173. rt_enter_critical();
  174. for (i = 0; i < NUM_EXCLUSIVE_REGIONS; i++)
  175. {
  176. if (exclusive_regions[i].owner == rt_thread_self() && exclusive_regions[i].region.start == start && exclusive_regions[i].region.size == size)
  177. {
  178. exclusive_regions[i].owner = RT_NULL;
  179. rt_exit_critical();
  180. return RT_EOK;
  181. }
  182. }
  183. rt_exit_critical();
  184. LOG_E("Region not found");
  185. return RT_ERROR;
  186. }
  187. INIT_BOARD_EXPORT(rt_mprotect_init);