vdso_kernel.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (c) 2006-2025 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-07-04 rcitach init ver.
  9. * 2025-04-22 ScuDays Add VDSO functionality under the riscv64 architecture.
  10. * 2026-04-21 rcitach Refactor vDSO runtime around the clock data page.
  11. */
  12. #include <rtthread.h>
  13. #include <mmu.h>
  14. #include <elf.h>
  15. #include <time.h>
  16. #include <lwp_user_mm.h>
  17. #include <drivers/clock_time.h>
  18. #ifdef RT_USING_RTC
  19. #include <rtdevice.h>
  20. #endif
  21. #include <vdso_kernel.h>
  22. #include <vdso_kernel_internal.h>
  23. #define DBG_TAG "vdso"
  24. #define DBG_LVL DBG_INFO
  25. #include <rtdbg.h>
  26. enum rt_vdso_binary_id
  27. {
  28. RT_VDSO_BINARY_COMMON,
  29. };
  30. struct rt_vdso_binary_info
  31. {
  32. const char *name;
  33. const char *image_start;
  34. const char *image_end;
  35. unsigned long page_count;
  36. };
  37. static struct rt_vdso_binary_info rt_vdso_binaries[] = {
  38. [RT_VDSO_BINARY_COMMON] = {
  39. .name = "rt_vdso_common",
  40. .image_start = __rt_vdso_image_start,
  41. .image_end = __rt_vdso_image_end,
  42. },
  43. };
  44. static union
  45. {
  46. struct rt_vdso_data_page data_page;
  47. uint8_t raw[RT_VDSO_DATA_PAGE_COUNT * ARCH_PAGE_SIZE];
  48. } rt_vdso_data_page_store RT_VDSO_DATA_PAGE_ALIGNED;
  49. struct rt_vdso_data_page *rt_vdso_kernel_data_page = &rt_vdso_data_page_store.data_page;
  50. static struct rt_spinlock rt_vdso_data_page_lock;
  51. static int rt_vdso_runtime_status = RT_EOK;
  52. static struct timespec rt_vdso_realtime_offset;
  53. static rt_bool_t rt_vdso_realtime_offset_ready;
  54. #ifdef MMU_MAP_U_ROCB_XN
  55. #define RT_VDSO_DATA_PAGE_ATTR MMU_MAP_U_ROCB_XN
  56. #elif defined(MMU_MAP_U_ROCB)
  57. #define RT_VDSO_DATA_PAGE_ATTR MMU_MAP_U_ROCB
  58. #else
  59. #error "No user-read-only mapping available for vDSO data page!"
  60. #endif
  61. #define RT_VDSO_IMAGE_PAGE_ATTR MMU_MAP_U_ROCB
  62. static void rt_vdso_normalize_timespec(struct timespec *ts)
  63. {
  64. while (ts->tv_nsec >= RT_VDSO_NSEC_PER_SEC)
  65. {
  66. ts->tv_sec += 1;
  67. ts->tv_nsec -= RT_VDSO_NSEC_PER_SEC;
  68. }
  69. while (ts->tv_nsec < 0)
  70. {
  71. ts->tv_sec -= 1;
  72. ts->tv_nsec += RT_VDSO_NSEC_PER_SEC;
  73. }
  74. }
  75. static void rt_vdso_counter_to_timespec(rt_uint64_t counter_value,
  76. struct timespec *ts)
  77. {
  78. rt_uint64_t monotonic_ns;
  79. monotonic_ns = rt_clock_time_counter_to_ns(counter_value);
  80. ts->tv_sec = monotonic_ns / RT_VDSO_NSEC_PER_SEC;
  81. ts->tv_nsec = monotonic_ns % RT_VDSO_NSEC_PER_SEC;
  82. }
  83. static rt_uint64_t rt_vdso_read_arch_counter(void)
  84. {
  85. rt_uint64_t counter;
  86. #if defined(__aarch64__)
  87. __asm__ volatile("mrs %0, CNTVCT_EL0" : "=r"(counter));
  88. #elif defined(__arm__)
  89. rt_uint32_t lo;
  90. rt_uint32_t hi;
  91. __asm__ volatile("mrrc p15, 1, %0, %1, c14" : "=r"(lo), "=r"(hi));
  92. counter = ((rt_uint64_t)hi << 32) | lo;
  93. #elif defined(__riscv)
  94. __asm__ volatile("rdtime %0" : "=r"(counter));
  95. #else
  96. counter = rt_clock_time_get_counter();
  97. #endif
  98. return counter;
  99. }
  100. static struct timespec rt_vdso_timespec_subtract(const struct timespec *lhs,
  101. const struct timespec *rhs)
  102. {
  103. struct timespec ret;
  104. ret.tv_sec = lhs->tv_sec - rhs->tv_sec;
  105. ret.tv_nsec = lhs->tv_nsec - rhs->tv_nsec;
  106. rt_vdso_normalize_timespec(&ret);
  107. return ret;
  108. }
  109. static struct timespec rt_vdso_add_timespec(const struct timespec *lhs,
  110. const struct timespec *rhs)
  111. {
  112. struct timespec ret;
  113. ret.tv_sec = lhs->tv_sec + rhs->tv_sec;
  114. ret.tv_nsec = lhs->tv_nsec + rhs->tv_nsec;
  115. rt_vdso_normalize_timespec(&ret);
  116. return ret;
  117. }
  118. static int rt_vdso_read_monotonic_snapshot(struct timespec *monotonic_time,
  119. rt_uint64_t *counter_value,
  120. rt_uint64_t *counter_freq)
  121. {
  122. rt_uint64_t monotonic_counter;
  123. monotonic_counter = rt_clock_time_get_counter();
  124. *counter_freq = rt_clock_time_get_freq();
  125. if (*counter_freq == 0)
  126. {
  127. return -RT_ERROR;
  128. }
  129. /* User vDSO computes deltas from the raw architecture counter. */
  130. *counter_value = rt_vdso_read_arch_counter();
  131. rt_vdso_counter_to_timespec(monotonic_counter, monotonic_time);
  132. return RT_EOK;
  133. }
  134. static void rt_vdso_update_data_page_flags(void)
  135. {
  136. rt_uint64_t flags = 0;
  137. if (rt_vdso_realtime_offset_ready)
  138. {
  139. flags |= RT_VDSO_FLAG_REALTIME_VALID;
  140. }
  141. rt_vdso_kernel_data_page->flags = flags;
  142. }
  143. static void rt_vdso_store_clock_snapshot(const struct timespec *monotonic_time,
  144. rt_uint64_t counter_value,
  145. rt_uint64_t counter_freq)
  146. {
  147. rt_vdso_kernel_data_page->counter_last = counter_value;
  148. rt_vdso_kernel_data_page->counter_freq = counter_freq;
  149. rt_vdso_update_data_page_flags();
  150. rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_MONOTONIC_INDEX] = *monotonic_time;
  151. if (rt_vdso_realtime_offset_ready)
  152. {
  153. rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_REALTIME_INDEX] =
  154. rt_vdso_add_timespec(monotonic_time, &rt_vdso_realtime_offset);
  155. }
  156. else
  157. {
  158. rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_REALTIME_INDEX] = *monotonic_time;
  159. }
  160. }
  161. void rt_vdso_set_realtime(const struct timespec *realtime)
  162. {
  163. struct timespec monotonic;
  164. rt_uint64_t counter;
  165. rt_uint64_t freq;
  166. rt_base_t level;
  167. if (rt_vdso_runtime_status != RT_EOK || realtime == RT_NULL)
  168. {
  169. return;
  170. }
  171. if (rt_vdso_read_monotonic_snapshot(&monotonic, &counter, &freq) != RT_EOK)
  172. {
  173. return;
  174. }
  175. level = rt_spin_lock_irqsave(&rt_vdso_data_page_lock);
  176. rt_vdso_data_page_write_begin(rt_vdso_kernel_data_page);
  177. rt_vdso_realtime_offset = rt_vdso_timespec_subtract(realtime, &monotonic);
  178. rt_vdso_realtime_offset_ready = RT_TRUE;
  179. rt_vdso_store_clock_snapshot(&monotonic, counter, freq);
  180. rt_vdso_data_page_write_end(rt_vdso_kernel_data_page);
  181. rt_spin_unlock_irqrestore(&rt_vdso_data_page_lock, level);
  182. }
  183. static void *rt_vdso_map_physical_pages(struct rt_lwp *lwp, void *user_va,
  184. void *kernel_pa, size_t map_size,
  185. rt_size_t attr)
  186. {
  187. int err;
  188. char *va;
  189. size_t offset = 0;
  190. if (!map_size)
  191. {
  192. return RT_NULL;
  193. }
  194. if (user_va)
  195. {
  196. if (((size_t)user_va & ARCH_PAGE_MASK) !=
  197. ((size_t)kernel_pa & ARCH_PAGE_MASK))
  198. {
  199. return RT_NULL;
  200. }
  201. }
  202. offset = (size_t)kernel_pa & ARCH_PAGE_MASK;
  203. map_size += offset + ARCH_PAGE_SIZE - 1;
  204. map_size &= ~ARCH_PAGE_MASK;
  205. kernel_pa = (void *)((size_t)kernel_pa & ~ARCH_PAGE_MASK);
  206. struct rt_mm_va_hint hint = {
  207. .flags = 0,
  208. .limit_range_size = lwp->aspace->size,
  209. .limit_start = lwp->aspace->start,
  210. .prefer = user_va,
  211. .map_size = map_size,
  212. };
  213. if (user_va != RT_NULL)
  214. {
  215. hint.flags |= MMF_MAP_FIXED;
  216. }
  217. err = rt_aspace_map_phy(lwp->aspace, &hint, attr, MM_PA_TO_OFF(kernel_pa),
  218. (void **)&va);
  219. if (err != RT_EOK)
  220. {
  221. return RT_NULL;
  222. }
  223. return va + offset;
  224. }
  225. static int rt_vdso_map_binary_pages(enum rt_vdso_binary_id binary_id,
  226. struct rt_lwp *lwp)
  227. {
  228. void *data_page_base = RT_NULL;
  229. void *image_base = RT_NULL;
  230. unsigned long data_page_len;
  231. unsigned long image_len;
  232. RT_ASSERT(lwp != RT_NULL);
  233. data_page_len = RT_VDSO_DATA_PAGE_COUNT * ARCH_PAGE_SIZE;
  234. image_len = rt_vdso_binaries[binary_id].page_count << ARCH_PAGE_SHIFT;
  235. data_page_base = rt_vdso_map_physical_pages(
  236. lwp, RT_NULL, rt_kmem_v2p((void *)rt_vdso_get_kernel_data_page()),
  237. data_page_len, RT_VDSO_DATA_PAGE_ATTR);
  238. if (data_page_base == RT_NULL)
  239. {
  240. lwp->vdso_vbase = RT_NULL;
  241. return -RT_ERROR;
  242. }
  243. image_base = (uint8_t *)data_page_base + data_page_len;
  244. image_base = rt_vdso_map_physical_pages(
  245. lwp, image_base,
  246. rt_kmem_v2p((void *)rt_vdso_binaries[binary_id].image_start),
  247. image_len, RT_VDSO_IMAGE_PAGE_ATTR);
  248. if (image_base == RT_NULL)
  249. {
  250. lwp_unmap_user_phy(lwp, data_page_base);
  251. lwp->vdso_vbase = RT_NULL;
  252. return -RT_ERROR;
  253. }
  254. lwp->vdso_vbase = image_base;
  255. return RT_EOK;
  256. }
  257. int rt_vdso_map_process_image(struct rt_lwp *lwp)
  258. {
  259. if (rt_vdso_runtime_status != RT_EOK)
  260. {
  261. return -RT_ERROR;
  262. }
  263. return rt_vdso_map_binary_pages(RT_VDSO_BINARY_COMMON, lwp);
  264. }
  265. void rt_vdso_sync_clock_data(void)
  266. {
  267. struct timespec monotonic;
  268. rt_uint64_t counter;
  269. rt_uint64_t freq;
  270. if (rt_vdso_runtime_status != RT_EOK)
  271. {
  272. return;
  273. }
  274. if (rt_vdso_read_monotonic_snapshot(&monotonic, &counter, &freq) != RT_EOK)
  275. {
  276. return;
  277. }
  278. rt_spin_lock(&rt_vdso_data_page_lock);
  279. rt_vdso_data_page_write_begin(rt_vdso_kernel_data_page);
  280. rt_vdso_store_clock_snapshot(&monotonic, counter, freq);
  281. rt_vdso_data_page_write_end(rt_vdso_kernel_data_page);
  282. rt_spin_unlock(&rt_vdso_data_page_lock);
  283. }
  284. static int rt_vdso_validate_elf_header(const void *image)
  285. {
  286. const unsigned char *ident = (const unsigned char *)image;
  287. #if defined(__aarch64__)
  288. const Elf64_Ehdr *ehdr = (const Elf64_Ehdr *)image;
  289. if (ident[EI_CLASS] != ELFCLASS64)
  290. {
  291. LOG_E("vDSO ELF class mismatch: expect ELF64");
  292. return -RT_ERROR;
  293. }
  294. if (ehdr->e_type != ET_DYN)
  295. {
  296. LOG_E("vDSO ELF type mismatch!");
  297. return -RT_ERROR;
  298. }
  299. if (ehdr->e_machine != EM_AARCH64)
  300. {
  301. LOG_E("vDSO machine mismatch: expect AArch64");
  302. return -RT_ERROR;
  303. }
  304. #elif defined(__arm__)
  305. const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)image;
  306. if (ident[EI_CLASS] != ELFCLASS32)
  307. {
  308. LOG_E("vDSO ELF class mismatch: expect ELF32");
  309. return -RT_ERROR;
  310. }
  311. if (ehdr->e_type != ET_DYN)
  312. {
  313. LOG_E("vDSO ELF type mismatch!");
  314. return -RT_ERROR;
  315. }
  316. if (ehdr->e_machine != EM_ARM)
  317. {
  318. LOG_E("vDSO machine mismatch: expect ARM");
  319. return -RT_ERROR;
  320. }
  321. #elif defined(__riscv)
  322. const Elf64_Ehdr *ehdr = (const Elf64_Ehdr *)image;
  323. if (ident[EI_CLASS] != ELFCLASS64)
  324. {
  325. LOG_E("vDSO ELF class mismatch: expect ELF64");
  326. return -RT_ERROR;
  327. }
  328. if (ehdr->e_type != ET_DYN)
  329. {
  330. LOG_E("vDSO ELF type mismatch!");
  331. return -RT_ERROR;
  332. }
  333. if (ehdr->e_machine != EM_RISCV)
  334. {
  335. LOG_E("vDSO machine mismatch: expect RISC-V");
  336. return -RT_ERROR;
  337. }
  338. #else
  339. LOG_E("vDSO unsupported architecture!");
  340. return -RT_ERROR;
  341. #endif
  342. return RT_EOK;
  343. }
  344. static int rt_vdso_validate_image(void)
  345. {
  346. const void *image = rt_vdso_binaries[RT_VDSO_BINARY_COMMON].image_start;
  347. rt_memset(rt_vdso_data_page_store.raw, 0, sizeof(rt_vdso_data_page_store.raw));
  348. rt_vdso_realtime_offset_ready = RT_FALSE;
  349. rt_memset(&rt_vdso_realtime_offset, 0, sizeof(rt_vdso_realtime_offset));
  350. if (rt_memcmp(image, RT_VDSO_IMAGE_ELF_MAGIC, RT_VDSO_IMAGE_ELF_MAGIC_LEN))
  351. {
  352. LOG_E("vDSO is not a valid ELF object!");
  353. rt_vdso_runtime_status = -RT_ERROR;
  354. return -RT_ERROR;
  355. }
  356. if (rt_vdso_validate_elf_header(image) != RT_EOK)
  357. {
  358. rt_vdso_runtime_status = -RT_ERROR;
  359. return -RT_ERROR;
  360. }
  361. rt_vdso_binaries[RT_VDSO_BINARY_COMMON].page_count =
  362. (rt_vdso_binaries[RT_VDSO_BINARY_COMMON].image_end -
  363. rt_vdso_binaries[RT_VDSO_BINARY_COMMON].image_start) >>
  364. ARCH_PAGE_SHIFT;
  365. if (rt_vdso_binaries[RT_VDSO_BINARY_COMMON].page_count == 0)
  366. {
  367. LOG_E("vDSO image is empty!");
  368. rt_vdso_runtime_status = -RT_ERROR;
  369. return -RT_ERROR;
  370. }
  371. return RT_EOK;
  372. }
  373. INIT_COMPONENT_EXPORT(rt_vdso_validate_image);