vdso.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. */
  11. #include <rtthread.h>
  12. #include <mmu.h>
  13. #include <lwp_user_mm.h>
  14. #include "vdso.h"
  15. #include "vdso_datapage.h"
  16. #define DBG_TAG "vdso"
  17. #define DBG_LVL DBG_INFO
  18. #include <rtdbg.h>
  19. enum vdso_abi
  20. {
  21. VDSO_ABI_COMMON,
  22. };
  23. enum vvar_pages
  24. {
  25. VVAR_DATA_PAGE_OFFSET,
  26. VVAR_TIMENS_PAGE_OFFSET,
  27. VVAR_NR_PAGES,
  28. };
  29. struct vdso_abi_info
  30. {
  31. const char *name;
  32. const char *vdso_code_start;
  33. const char *vdso_code_end;
  34. unsigned long vdso_pages;
  35. };
  36. static struct vdso_abi_info vdso_info[] = {
  37. [VDSO_ABI_COMMON] = {
  38. .name = "vdso_common",
  39. .vdso_code_start = __vdso_text_start,
  40. .vdso_code_end = __vdso_text_end,
  41. },
  42. };
  43. static union {
  44. struct vdso_data data[CS_BASES];
  45. uint8_t page[ARCH_PAGE_SIZE];
  46. } vdso_data_store __page_aligned_data;
  47. struct vdso_data *vdso_data = vdso_data_store.data;
  48. int init_ret_flag = RT_EOK;
  49. static int __setup_additional_pages(enum vdso_abi abi, struct rt_lwp *lwp)
  50. {
  51. RT_ASSERT(lwp != RT_NULL);
  52. int ret;
  53. void *vdso_base = RT_NULL;
  54. unsigned long vdso_data_len, vdso_text_len;
  55. vdso_data_len = VVAR_NR_PAGES * ARCH_PAGE_SIZE;
  56. vdso_text_len = vdso_info[abi].vdso_pages << ARCH_PAGE_SHIFT;
  57. vdso_base = lwp_map_user_phy(lwp, RT_NULL, rt_kmem_v2p((void *)vdso_data), vdso_data_len, 0);
  58. if (vdso_base != RT_NULL)
  59. {
  60. ret = RT_EOK;
  61. }
  62. else
  63. {
  64. ret = RT_ERROR;
  65. }
  66. vdso_base += vdso_data_len;
  67. vdso_base = lwp_map_user_phy(lwp, vdso_base, rt_kmem_v2p((void *)vdso_info[abi].vdso_code_start), vdso_text_len, 0);
  68. lwp->vdso_vbase = vdso_base;
  69. return ret;
  70. }
  71. int arch_setup_additional_pages(struct rt_lwp *lwp)
  72. {
  73. int ret;
  74. if (init_ret_flag != RT_EOK) return -RT_ERROR;
  75. ret = __setup_additional_pages(VDSO_ABI_COMMON, lwp);
  76. return ret;
  77. }
  78. static void __initdata(void)
  79. {
  80. struct tm time_vdso = SOFT_RTC_VDSOTIME_DEFAULT;
  81. vdso_data->realtime_initdata = timegm(&time_vdso);
  82. }
  83. static int validate_vdso_elf(void)
  84. {
  85. if (rt_memcmp(vdso_info[VDSO_ABI_COMMON].vdso_code_start, ELF_HEAD, ELF_HEAD_LEN))
  86. {
  87. LOG_E("vDSO is not a valid ELF object!");
  88. init_ret_flag = -RT_ERROR;
  89. return -RT_ERROR;
  90. }
  91. vdso_info[VDSO_ABI_COMMON].vdso_pages = (vdso_info[VDSO_ABI_COMMON].vdso_code_end - vdso_info[VDSO_ABI_COMMON].vdso_code_start) >> ARCH_PAGE_SHIFT;
  92. __initdata();
  93. return RT_EOK;
  94. }
  95. INIT_COMPONENT_EXPORT(validate_vdso_elf);