diff --git a/components/lwp/arch/common/vdso.c b/components/lwp/arch/common/vdso.c new file mode 100644 index 0000000000..823fd5b61e --- /dev/null +++ b/components/lwp/arch/common/vdso.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-07-04 rcitach init ver. + * 2025-04-22 ScuDays Add VDSO functionality under the riscv64 architecture. + */ + +#include +#include +#include + +#include "vdso.h" +#include "vdso_datapage.h" +#define DBG_TAG "vdso" +#define DBG_LVL DBG_INFO +#include + +enum vdso_abi +{ + VDSO_ABI_COMMON, +}; + +enum vvar_pages +{ + VVAR_DATA_PAGE_OFFSET, + VVAR_TIMENS_PAGE_OFFSET, + VVAR_NR_PAGES, +}; + + +struct vdso_abi_info +{ + const char *name; + const char *vdso_code_start; + const char *vdso_code_end; + unsigned long vdso_pages; +}; + +static struct vdso_abi_info vdso_info[] = { + [VDSO_ABI_COMMON] = { + .name = "vdso_common", + .vdso_code_start = __vdso_text_start, + .vdso_code_end = __vdso_text_end, + }, +}; + +static union { + struct vdso_data data[CS_BASES]; + uint8_t page[ARCH_PAGE_SIZE]; +} vdso_data_store __page_aligned_data; +struct vdso_data *vdso_data = vdso_data_store.data; +int init_ret_flag = RT_EOK; + +static int __setup_additional_pages(enum vdso_abi abi, struct rt_lwp *lwp) +{ + RT_ASSERT(lwp != RT_NULL); + + int ret; + void *vdso_base = RT_NULL; + unsigned long vdso_data_len, vdso_text_len; + + vdso_data_len = VVAR_NR_PAGES * ARCH_PAGE_SIZE; + vdso_text_len = vdso_info[abi].vdso_pages << ARCH_PAGE_SHIFT; + + vdso_base = lwp_map_user_phy(lwp, RT_NULL, rt_kmem_v2p((void *)vdso_data), vdso_data_len, 0); + if (vdso_base != RT_NULL) + { + ret = RT_EOK; + } + else + { + ret = RT_ERROR; + } + + vdso_base += vdso_data_len; + vdso_base = lwp_map_user_phy(lwp, vdso_base, rt_kmem_v2p((void *)vdso_info[abi].vdso_code_start), vdso_text_len, 0); + + lwp->vdso_vbase = vdso_base; + return ret; +} + +int arch_setup_additional_pages(struct rt_lwp *lwp) +{ + int ret; + if (init_ret_flag != RT_EOK) return -RT_ERROR; + ret = __setup_additional_pages(VDSO_ABI_COMMON, lwp); + + return ret; +} + + +static void __initdata(void) +{ + struct tm time_vdso = SOFT_RTC_VDSOTIME_DEFAULT; + vdso_data->realtime_initdata = timegm(&time_vdso); +} + + +static int validate_vdso_elf(void) +{ + if (rt_memcmp(vdso_info[VDSO_ABI_COMMON].vdso_code_start, ELF_HEAD, ELF_HEAD_LEN)) + { + LOG_E("vDSO is not a valid ELF object!"); + init_ret_flag = -RT_ERROR; + return -RT_ERROR; + } + 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; + + __initdata(); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(validate_vdso_elf);