Browse Source

[smart] move vdso.c to arch/common folder.

bernard 2 months ago
parent
commit
921abdfb41
1 changed files with 116 additions and 0 deletions
  1. 116 0
      components/lwp/arch/common/vdso.c

+ 116 - 0
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 <rtthread.h>
+#include <mmu.h>
+#include <lwp_user_mm.h>
+
+#include "vdso.h"
+#include "vdso_datapage.h"
+#define DBG_TAG "vdso"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+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);