vdso.c 2.6 KB

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