فهرست منبع

[smart] Add vDSO support for RISC-V architecture and refactor related components

- Implemented vDSO functionality for the RISC-V architecture, including the necessary source files and linker scripts.
- Introduced a new `vdso_sys.c` file for RISC-V, containing functions to handle time retrieval using the vDSO mechanism.
- Created architecture-specific linker scripts (`vdso.lds.S`) for both AArch64 and RISC-V.
- Updated the build system to support vDSO compilation for RISC-V, including necessary adjustments in `SConstruct` files.
- Refactored existing vDSO code to improve compatibility and maintainability across architectures.
- Adjusted the maximum number of PTY devices in the terminal configuration from 64 to 32 for better resource management.
- Fixed minor issues in existing code, including correcting the path for the vDSO shared library and ensuring proper function definitions.
bernard 1 هفته پیش
والد
کامیت
721dfbfe01

+ 1 - 2
components/lwp/Kconfig

@@ -1,5 +1,5 @@
 menuconfig RT_USING_LWP
 menuconfig RT_USING_LWP
-    bool "light-weight process"
+    bool "lwP(light weight Process)"
     depends on RT_USING_SMART
     depends on RT_USING_SMART
     default y
     default y
     help
     help
@@ -87,4 +87,3 @@ if RT_USING_LWP
 rsource "terminal/Kconfig"
 rsource "terminal/Kconfig"
 rsource "vdso/Kconfig"
 rsource "vdso/Kconfig"
 endif
 endif
-

+ 3 - 0
components/lwp/SConscript

@@ -25,11 +25,14 @@ if platform in platform_file.keys(): # support platforms
     if arch in support_arch.keys() and cpu in support_arch[arch]:
     if arch in support_arch.keys() and cpu in support_arch[arch]:
         asm_path = 'arch/' + arch + '/' + cpu + '/*_' + platform_file[platform]
         asm_path = 'arch/' + arch + '/' + cpu + '/*_' + platform_file[platform]
         arch_common = 'arch/' + arch + '/' + 'common/*.c'
         arch_common = 'arch/' + arch + '/' + 'common/*.c'
+        common = 'arch/common/*.c'
         if not GetDepend('RT_USING_VDSO'):
         if not GetDepend('RT_USING_VDSO'):
             vdso_files = ['vdso_data.c', 'vdso.c']
             vdso_files = ['vdso_data.c', 'vdso.c']
             src += [f for f in Glob(arch_common) if os.path.basename(str(f)) not in vdso_files]
             src += [f for f in Glob(arch_common) if os.path.basename(str(f)) not in vdso_files]
+            src += [f for f in Glob(common) if os.path.basename(str(f)) not in vdso_files]
         else:
         else:
             src += Glob(arch_common)
             src += Glob(arch_common)
+            src += Glob(common)
         if not GetDepend('ARCH_MM_MMU'):
         if not GetDepend('ARCH_MM_MMU'):
             excluded_files = ['ioremap.c', 'lwp_futex.c', 'lwp_mm_area.c', 'lwp_pmutex.c', 'lwp_shm.c', 'lwp_user_mm.c']
             excluded_files = ['ioremap.c', 'lwp_futex.c', 'lwp_mm_area.c', 'lwp_pmutex.c', 'lwp_shm.c', 'lwp_user_mm.c']
             src += [f for f in Glob('*.c') if os.path.basename(str(f)) not in excluded_files] + Glob(asm_path)
             src += [f for f in Glob('*.c') if os.path.basename(str(f)) not in excluded_files] + Glob(asm_path)

+ 0 - 110
components/lwp/arch/aarch64/common/vdso.c

@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author         Notes
- * 2024-07-04     rcitach        init ver.
- */
-
-#include <rtthread.h>
-#include <mmu.h>
-#include <gtimer.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_AA64,
-};
-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_AA64] = {
-        .name = "vdso_aarch64",
-        .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_AA64, 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_AA64].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_AA64].vdso_pages = (
-        vdso_info[VDSO_ABI_AA64].vdso_code_end -
-        vdso_info[VDSO_ABI_AA64].vdso_code_start) >>
-        ARCH_PAGE_SHIFT;
-
-    __initdata();
-    return RT_EOK;
-}
-INIT_COMPONENT_EXPORT(validate_vdso_elf);

+ 12 - 12
components/lwp/arch/risc-v/rv64/reloc.c → components/lwp/arch/risc-v/common/reloc.c

@@ -10,19 +10,19 @@
 
 
 typedef struct
 typedef struct
 {
 {
-    Elf64_Word st_name;
-    Elf64_Addr st_value;
-    Elf64_Word st_size;
+    Elf64_Word    st_name;
+    Elf64_Addr    st_value;
+    Elf64_Word    st_size;
     unsigned char st_info;
     unsigned char st_info;
     unsigned char st_other;
     unsigned char st_other;
-    Elf64_Half st_shndx;
+    Elf64_Half    st_shndx;
 } Elf64_sym;
 } Elf64_sym;
 
 
 #ifdef ARCH_MM_MMU
 #ifdef ARCH_MM_MMU
 void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
 void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
 {
 {
     size_t rel_off;
     size_t rel_off;
-    void* addr;
+    void  *addr;
 
 
     if (rel_dyn_size && !dynsym)
     if (rel_dyn_size && !dynsym)
     {
     {
@@ -40,7 +40,7 @@ void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, s
         addr = rt_hw_mmu_v2p(aspace, (void *)((rt_size_t)text_start + v1));
         addr = rt_hw_mmu_v2p(aspace, (void *)((rt_size_t)text_start + v1));
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         {
         {
-            *(rt_size_t*)addr += (rt_size_t)text_start;
+            *(rt_size_t *)addr += (rt_size_t)text_start;
         }
         }
         else if ((v2 & 0xff) == R_ARM_ABS32)
         else if ((v2 & 0xff) == R_ARM_ABS32)
         {
         {
@@ -48,18 +48,18 @@ void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, s
             t = (v2 >> 8);
             t = (v2 >> 8);
             if (t) /* 0 is UDF */
             if (t) /* 0 is UDF */
             {
             {
-                *(rt_size_t*)addr = (((rt_size_t)text_start) + dynsym[t].st_value);
+                *(rt_size_t *)addr = (((rt_size_t)text_start) + dynsym[t].st_value);
             }
             }
         }
         }
     }
     }
     /* modify got */
     /* modify got */
     if (got_size)
     if (got_size)
     {
     {
-        uint32_t *got_item = (uint32_t*)got_start;
+        uint32_t *got_item = (uint32_t *)got_start;
 
 
         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
         {
         {
-            addr = rt_hw_mmu_v2p(aspace, got_item);
+            addr                = rt_hw_mmu_v2p(aspace, got_item);
             *(rt_size_t *)addr += (rt_size_t)text_start;
             *(rt_size_t *)addr += (rt_size_t)text_start;
         }
         }
     }
     }
@@ -83,7 +83,7 @@ void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size,
 
 
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         {
         {
-            *(uint32_t*)(((rt_size_t)text_start) + v1) += (uint32_t)text_start;
+            *(uint32_t *)(((rt_size_t)text_start) + v1) += (uint32_t)text_start;
         }
         }
         else if ((v2 & 0xff) == R_ARM_ABS32)
         else if ((v2 & 0xff) == R_ARM_ABS32)
         {
         {
@@ -91,14 +91,14 @@ void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size,
             t = (v2 >> 8);
             t = (v2 >> 8);
             if (t) /* 0 is UDF */
             if (t) /* 0 is UDF */
             {
             {
-                *(uint32_t*)(((rt_size_t)text_start) + v1) = (uint32_t)(((rt_size_t)text_start) + dynsym[t].st_value);
+                *(uint32_t *)(((rt_size_t)text_start) + v1) = (uint32_t)(((rt_size_t)text_start) + dynsym[t].st_value);
             }
             }
         }
         }
     }
     }
     /* modify got */
     /* modify got */
     if (got_size)
     if (got_size)
     {
     {
-        uint32_t *got_item = (uint32_t*)got_start;
+        uint32_t *got_item = (uint32_t *)got_start;
 
 
         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
         {
         {

+ 34 - 0
components/lwp/arch/risc-v/common/vdso_data.c

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2025-04-22     ScuDays        Add VDSO functionality under the riscv64 architecture.
+ */
+
+#include <rtthread.h>
+#include <ktime.h>
+#include <time.h>
+#include <vdso_datapage.h>
+#include <vdso_data.h>
+#include <encoding.h>
+
+void rt_vdso_update_glob_time(void)
+{
+    struct vdso_data *vdata = get_k_vdso_data();
+    struct timespec  *vdso_ts;
+    uint64_t          initdata = vdata->realtime_initdata;
+    rt_vdso_write_begin(vdata);
+
+    vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
+    rt_ktime_boottime_get_ns(vdso_ts);
+    vdso_ts->tv_sec = initdata + vdso_ts->tv_sec;
+
+    vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
+    rt_ktime_boottime_get_ns(vdso_ts);
+
+    vdata->cycle_last = rdtime();
+    rt_vdso_write_end(vdata);
+}

+ 1 - 1
components/lwp/terminal/Kconfig

@@ -7,7 +7,7 @@ menuconfig LWP_USING_TERMINAL
 if LWP_USING_TERMINAL
 if LWP_USING_TERMINAL
     config LWP_PTY_MAX_PARIS_LIMIT
     config LWP_PTY_MAX_PARIS_LIMIT
         int "Max number of pty devices registered at the same time"
         int "Max number of pty devices registered at the same time"
-        default 64
+        default 32
         help
         help
             This upper limit is set to protect kernel memory from draining
             This upper limit is set to protect kernel memory from draining
             out by the application if it keeps allocating pty devices.
             out by the application if it keeps allocating pty devices.

+ 3 - 3
components/lwp/vdso/Kconfig

@@ -1,4 +1,4 @@
-menuconfig RT_USING_VDSO
-    bool "vDSO"
+config RT_USING_VDSO
+    bool "vDSO (??Virtual Dynamic Shared Object)"
+    depends on (ARCH_ARMV8 || ARCH_RISCV)
     default y
     default y
-    depends on RT_USING_SMART && ARCH_ARMV8

+ 40 - 36
components/lwp/vdso/SConscript

@@ -2,47 +2,51 @@ import os
 import rtconfig
 import rtconfig
 import subprocess
 import subprocess
 from building import *
 from building import *
-Import('RTT_ROOT')
 
 
-group = []
-
-cwd = GetCurrentDir()
+group   = []
+cwd     = GetCurrentDir()
 CPPPATH = [cwd, cwd + "/kernel"]
 CPPPATH = [cwd, cwd + "/kernel"]
+list    = os.listdir(cwd)
+src     = Glob('kernel/*.c') + Glob('kernel/*.S')
 
 
 if not GetDepend(['RT_USING_VDSO']):
 if not GetDepend(['RT_USING_VDSO']):
     Return('group')
     Return('group')
 
 
-if rtconfig.ARCH != "aarch64":
-    src = Glob('*.c')
-    group = DefineGroup('VDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
-    Return('group')
-
-list = os.listdir(cwd)
-src    = Glob('kernel/*.c')
-src    +=Glob('kernel/*.S')
-
-if not os.path.exists(cwd + "/user/vdso.lds"):
-    Preprocessing("user/vdso.lds.S", ".lds", CPPPATH=[cwd])
-
-#aarch64 vdso xmake
-# vdso_file = os.path.join(cwd, 'usr', 'xmake.lua')
-# command = ["xmake", "-F", vdso_file]
-# clean = ["xmake", "clean"]
-
-vdso_file = os.path.join(cwd, 'user', 'SConstruct')
-command = ["scons", "-f", vdso_file]
-clean = ["scons", "-f", vdso_file, "--clean"]
-
-if not GetOption('clean'):
-    result = subprocess.run(command)
+if rtconfig.ARCH != "aarch64" and rtconfig.ARCH != "risc-v":
+    # not supported arch
+    src = []
 else:
 else:
-    result = subprocess.run(clean)
-
-if result.returncode == 0:
-    print("Command executed successfully")
-else:
-    print("Command failed with exit code:", result.returncode)
-    exit(1)
-
-group = DefineGroup('VDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
+    if not hasattr(rtconfig, 'CPP') or rtconfig.CPP is None:
+        rtconfig.CPP = rtconfig.PREFIX + 'cpp'
+    if not hasattr(rtconfig, 'CPPFLAGS') or rtconfig.CPPFLAGS is None:
+        rtconfig.CPPFLAGS = ' -E -P -x assembler-with-cpp'
+
+    if not os.path.exists(cwd + "/user" + "/arch" +"/" + rtconfig.ARCH + "/vdso.lds"):
+        Preprocessing("user/arch/" + rtconfig.ARCH + "/vdso.lds.S", ".lds", CPPPATH=[cwd])
+
+    vdso_arch = os.path.join(cwd, 'user',"arch", rtconfig.ARCH)
+
+    process_env = os.environ.copy()
+    if hasattr(rtconfig, 'EXEC_PATH') and rtconfig.EXEC_PATH is not None:
+        process_env['RTT_EXEC_PATH'] = rtconfig.EXEC_PATH
+    if hasattr(rtconfig, 'PREFIX') and rtconfig.PREFIX is not None:
+        process_env['RTT_CC_PREFIX'] = rtconfig.PREFIX
+    if hasattr(rtconfig, 'DEVICE') and rtconfig.DEVICE is not None:
+        process_env['RTT_DEVICE'] = rtconfig.DEVICE
+
+    command = ["scons", "-C", vdso_arch]
+    clean_command = ["scons", "-C", vdso_arch, "--clean"] 
+
+    if not GetOption('clean'):    
+        result = subprocess.run(command, env=process_env, check=True)
+    else:
+        result = subprocess.run(clean_command, env=process_env, check=True)
+
+    if result.returncode == 0:
+        print("Command executed successfully")
+    else:
+        print("Command failed with exit code:", result.returncode)
+        exit(1)
+
+group = DefineGroup('vDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
 Return('group')
 Return('group')

+ 1 - 1
components/lwp/vdso/kernel/vdso_text.S

@@ -8,7 +8,7 @@
  * 2024-07-04     rcitach        init ver.
  * 2024-07-04     rcitach        init ver.
  */
  */
  
  
-#include <vdso_config.h>    
+#include <vdso_config.h>
 
 
     .globl __vdso_text_start, __vdso_text_end
     .globl __vdso_text_start, __vdso_text_end
     .section .rodata
     .section .rodata

+ 0 - 39
components/lwp/vdso/user/SConstruct

@@ -1,39 +0,0 @@
-import os
-import sys
-import subprocess
-
-arguments = sys.argv[2]
-vdso_usr = os.path.dirname(arguments)
-vdso_root = os.path.dirname(vdso_usr)
-
-
-EXEC_PATH  = os.getenv('RTT_EXEC_PATH') or '/usr/bin'
-PREFIX     = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
-
-CC      = PREFIX + 'gcc'
-CXX     = PREFIX + 'g++'
-CPP     = PREFIX + 'cpp'
-AS      = PREFIX + 'gcc'
-AR      = PREFIX + 'ar'
-LINK    = PREFIX + 'gcc'
-
-DEVICE   = ' -march=armv8-a -mtune=cortex-a53 -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing'
-CXXFLAGS = DEVICE + ' -Wall -fdiagnostics-color=always'
-AFLAGS   = ' -x assembler-with-cpp'
-CFLAGS  = DEVICE + ' -Wall -Wno-cpp -std=gnu99 -fdiagnostics-color=always -fPIC -O2'
-LFLAGS  = DEVICE + ' -Bsymbolic -Wl,--gc-sections,-u,system_vectors -T {path}/vdso.lds'.format(path=vdso_usr)
-CFLAGS += " -I {path} -I{path}/user".format(path=vdso_root)
-
-env = Environment(tools=['gcc', 'link'],
-    AS   = AS,   ASFLAGS = AFLAGS,
-    CC   = CC,   CFLAGS = CFLAGS,
-    CXX  = CXX,  CXXFLAGS = CXXFLAGS,
-    AR   = AR,   
-    LINK = LINK, LINKFLAGS = LFLAGS)
-env.PrependENVPath('PATH', EXEC_PATH)
-
-src = os.path.join(vdso_usr,'vdso_sys.c')
-target_name = 'librtos_vdso.so'
-target = os.path.join(vdso_usr, "build", target_name)
-shared_lib = env.SharedLibrary(target=target, source=src)
-env.Default(shared_lib)

+ 33 - 0
components/lwp/vdso/user/arch/aarch64/SConstruct

@@ -0,0 +1,33 @@
+import os
+import sys
+
+arguments = sys.argv[2]
+vdso_usr  = arguments
+vdso_path = os.path.join(vdso_usr, '..', '..', '..')
+
+EXEC_PATH = os.getenv('RTT_EXEC_PATH') or '/usr/bin'
+PREFIX    = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
+DEVICE    = os.getenv('RTT_DEVICE') or ' -march=armv8-a -mtune=cortex-a53'
+
+CC      = PREFIX + 'gcc'
+CPP     = PREFIX + 'cpp'
+AS      = PREFIX + 'gcc'
+AR      = PREFIX + 'ar'
+LINK    = PREFIX + 'gcc'
+
+AFLAGS  = ' -x assembler-with-cpp'
+CFLAGS  = DEVICE + '  -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing -Wall -Wno-cpp -std=gnu99 -fdiagnostics-color=always -fPIC -O2'
+LFLAGS  = DEVICE + ' -Bsymbolic -Wl,--gc-sections,-u,system_vectors -T {path}/vdso.lds'.format(path=vdso_usr)
+CFLAGS += " -I . -I {vdso_path} ".format(vdso_path=vdso_path)
+
+src = Glob('*.c')
+env = Environment(tools=['gcc', 'link'],
+    AS   = AS,   ASFLAGS = AFLAGS,
+    CC   = CC,   CFLAGS  = CFLAGS,
+    CPP  = CPP,  AR      = AR,   
+    LINK = LINK, LINKFLAGS = LFLAGS)
+env.PrependENVPath('PATH', EXEC_PATH)
+
+target = os.path.join(vdso_path, 'user', 'build', 'libvdso.so')
+shared_lib = env.SharedLibrary(target=target, source=src)
+env.Default(shared_lib)

+ 0 - 0
components/lwp/vdso/user/vdso.lds.S → components/lwp/vdso/user/arch/aarch64/vdso.lds.S


+ 0 - 0
components/lwp/vdso/user/vdso_sys.c → components/lwp/vdso/user/arch/aarch64/vdso_sys.c


+ 0 - 0
components/lwp/vdso/user/vdso_sys.h → components/lwp/vdso/user/arch/aarch64/vdso_sys.h


+ 33 - 0
components/lwp/vdso/user/arch/risc-v/SConstruct

@@ -0,0 +1,33 @@
+import os
+import sys
+
+arguments = sys.argv[2]
+vdso_usr  = arguments
+vdso_path = os.path.join(vdso_usr, '..', '..', '..')
+
+EXEC_PATH = os.getenv('RTT_EXEC_PATH') or '/usr/bin'
+PREFIX    = os.getenv('RTT_CC_PREFIX') or 'riscv64-none-elf-'
+DEVICE    = os.getenv('RTT_DEVICE') or ' -march=rv64imafdc -mabi=lp64'
+
+CC      = PREFIX + 'gcc'
+CPP     = PREFIX + 'cpp'
+AS      = PREFIX + 'gcc'
+AR      = PREFIX + 'ar'
+LINK    = PREFIX + 'gcc'
+
+AFLAGS  = ' -x assembler-with-cpp'
+CFLAGS  = DEVICE + ' -Wall -Wno-cpp -std=gnu99 -fdiagnostics-color=always -fPIC -O2'
+LFLAGS  = DEVICE + ' -Bsymbolic -Wl,--gc-sections -T {path}/vdso.lds'.format(path=vdso_usr)
+CFLAGS += " -I . -I {vdso_path} ".format(vdso_path=vdso_path)
+
+src = Glob('*.c')
+env = Environment(tools=['gcc', 'link'],
+    AS   = AS,   ASFLAGS = AFLAGS,
+    CC   = CC,   CFLAGS  = CFLAGS,
+    CPP  = CPP,  AR      = AR,
+    LINK = LINK, LINKFLAGS = LFLAGS)
+env.PrependENVPath('PATH', EXEC_PATH)
+
+target = os.path.join(vdso_path, 'user', 'build', 'libvdso.so')
+shared_lib = env.SharedLibrary(target=target, source=src)
+env.Default(shared_lib)

+ 60 - 0
components/lwp/vdso/user/arch/risc-v/vdso.lds.S

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2025-04-22     ScuDays        Add VDSO functionality under the riscv64 architecture.
+ */
+ 
+#include <vdso_config.h>
+
+OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
+OUTPUT_ARCH(riscv)
+
+SECTIONS
+{
+    PROVIDE(_vdso_data = . - __VVAR_PAGES * VDSO_PAGE_SIZE);
+    . = SIZEOF_HEADERS;
+
+    .hash        : { *(.hash) }     :text
+    .gnu.hash    : { *(.gnu.hash) }
+    .dynsym      : { *(.dynsym) }
+    .dynstr      : { *(.dynstr) }
+    .gnu.version    : { *(.gnu.version) }
+    .gnu.version_d  : { *(.gnu.version_d) }
+    .gnu.version_r  : { *(.gnu.version_r) }
+
+    .dynamic     : { *(.dynamic) }    :text    :dynamic
+    .rela.dyn    : ALIGN(8) { *(.rela .rela*) }
+
+    .rodata      : {
+        *(.rodata*) 
+        *(.got)
+        *(.got.plt)
+        *(.plt)
+        *(.plt.*)
+        *(.iplt)
+        *(.igot .igot.plt)
+    }    :text
+    /DISCARD/    : {
+        *(.data .data.* .sdata*)
+        *(.bss .sbss .dynbss .dynsbss)
+    }
+}
+
+PHDRS
+{
+    text        PT_LOAD       FLAGS(5) FILEHDR PHDRS;
+    dynamic     PT_DYNAMIC    FLAGS(4);
+}
+
+VERSION
+{
+    LINUX_2.6 {
+    global:
+        __vdso_clock_gettime;
+    local: *;
+    };
+}

+ 101 - 0
components/lwp/vdso/user/arch/risc-v/vdso_sys.c

@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2025-04-22     ScuDays        Add VDSO functionality under the riscv64 architecture.
+ * 2025-05-10     Bernard        Move __arch_get_hw_frq() to vdso_sys.c as a weak function.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <vdso_sys.h>
+
+#ifndef rt_vdso_cycles_ready
+static inline bool rt_vdso_cycles_ready(uint64_t cycles)
+{
+    return true;
+}
+#endif
+
+#ifndef rt_vdso_get_ns
+/* Implement as a weak function because there is no CPU cycle for RISCV */
+__attribute__((weak)) uint64_t __arch_get_hw_frq()
+{
+    return 10000000;
+}
+
+static inline uint64_t rt_vdso_get_ns(uint64_t cycles, uint64_t last)
+{
+    return (cycles - last) * NSEC_PER_SEC / __arch_get_hw_frq();
+}
+#endif
+
+static int
+__rt_vdso_getcoarse(struct timespec *ts, clockid_t clock, const struct vdso_data *vdns)
+{
+    const struct vdso_data *vd;
+    const struct timespec  *vdso_ts;
+    uint32_t                seq;
+    uint64_t                sec, last, ns, cycles;
+
+    if (clock != CLOCK_MONOTONIC_RAW)
+        vd = &vdns[CS_HRES_COARSE];
+    else
+        vd = &vdns[CS_RAW];
+
+    vdso_ts = &vd->basetime[clock];
+
+    do {
+        seq    = rt_vdso_read_begin(vd);
+        cycles = __arch_get_hw_counter(vd->clock_mode, vd);
+        if (unlikely(!rt_vdso_cycles_ready(cycles)))
+            return -1;
+        ns    = vdso_ts->tv_nsec;
+        last  = vd->cycle_last;
+        ns   += rt_vdso_get_ns(cycles, last);
+        sec   = vdso_ts->tv_sec;
+    } while (unlikely(rt_vdso_read_retry(vd, seq)));
+
+    ts->tv_sec  = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+    ts->tv_nsec = ns;
+
+    return 0;
+}
+
+static inline int
+__vdso_clock_gettime_common(const struct vdso_data *vd, clockid_t clock,
+                            struct timespec *ts)
+{
+    u_int32_t msk;
+
+    if (unlikely((u_int32_t)clock >= MAX_CLOCKS))
+        return -1;
+
+    msk = 1U << clock;
+    if (likely(msk & VDSO_REALTIME))
+        return __rt_vdso_getcoarse(ts, CLOCK_REALTIME, vd);
+    else if (msk & VDSO_MONOTIME)
+        return __rt_vdso_getcoarse(ts, CLOCK_MONOTONIC, vd);
+    else
+        return ENOENT;
+}
+
+static __maybe_unused int
+rt_vdso_clock_gettime_data(const struct vdso_data *vd, clockid_t clock,
+                           struct timespec *ts)
+{
+    int ret = 0;
+    ret     = __vdso_clock_gettime_common(vd, clock, ts);
+    return ret;
+}
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+    return rt_vdso_clock_gettime_data(__arch_get_vdso_data(), clock, ts);
+}

+ 147 - 0
components/lwp/vdso/user/arch/risc-v/vdso_sys.h

@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2025-04-22     ScuDays        Add VDSO functionality under the riscv64 architecture.
+ */
+
+#ifndef ASM_VDSO_SYS_H
+#define ASM_VDSO_SYS_H
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <vdso_config.h>
+#include <vdso_datapage.h>
+
+#define __always_unused __attribute__((__unused__))
+#define __maybe_unused  __attribute__((__unused__))
+
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define arch_counter_enforce_ordering \
+    __asm__ volatile("fence rw, rw" ::: "memory")
+
+static inline uint64_t __arch_get_hw_counter()
+{
+    uint64_t res;
+    __asm__ volatile("rdtime %0" : "=r"(res));
+    arch_counter_enforce_ordering;
+    return res;
+}
+
+static inline uint32_t
+__iter_div_u64_rem(uint64_t dividend, uint32_t divisor, uint64_t *remainder)
+{
+    uint32_t ret = 0;
+
+    while (dividend >= divisor)
+    {
+        /* The following asm() prevents the compiler from
+        optimising this loop into a modulo operation.  */
+        __asm__("" : "+rm"(dividend));
+
+        dividend -= divisor;
+        ret++;
+    }
+
+    *remainder = dividend;
+
+    return ret;
+}
+
+#define __RT_STRINGIFY(x...) #x
+#define RT_STRINGIFY(x...)   __RT_STRINGIFY(x)
+#define rt_hw_barrier(cmd, ...) \
+    __asm__ volatile(RT_STRINGIFY(cmd) " " RT_STRINGIFY(__VA_ARGS__)::: "memory")
+
+#define rt_hw_isb() rt_hw_barrier(fence.i)
+#define rt_hw_dmb() rt_hw_barrier(fence, rw, rw)
+#define rt_hw_wmb() rt_hw_barrier(fence, w, w)
+#define rt_hw_rmb() rt_hw_barrier(fence, r, r)
+#define rt_hw_dsb() rt_hw_barrier(fence, rw, rw)
+
+#ifndef barrier
+
+#define barrier() __asm__ __volatile__("fence" : : : "memory")
+#endif
+
+static inline void cpu_relax(void)
+{
+    __asm__ volatile("nop" ::: "memory");
+}
+
+#define __READ_ONCE_SIZE                                          \
+    ({                                                            \
+        switch (size)                                             \
+        {                                                         \
+        case 1:                                                   \
+            *(__u8 *)res = *(volatile __u8 *)p;                   \
+            break;                                                \
+        case 2:                                                   \
+            *(__u16 *)res = *(volatile __u16 *)p;                 \
+            break;                                                \
+        case 4:                                                   \
+            *(__u32 *)res = *(volatile __u32 *)p;                 \
+            break;                                                \
+        case 8:                                                   \
+            *(__u64 *)res = *(volatile __u64 *)p;                 \
+            break;                                                \
+        default:                                                  \
+            barrier();                                            \
+            __builtin_memcpy((void *)res, (const void *)p, size); \
+            barrier();                                            \
+        }                                                         \
+    })
+
+static inline void __read_once_size(const volatile void *p, void *res, int size)
+{
+    __READ_ONCE_SIZE;
+}
+
+#define __READ_ONCE(x, check)                                                \
+    ({                                                                       \
+        union {                                                              \
+            typeof(x) __val;                                                 \
+            char      __c[1];                                                \
+        } __u;                                                               \
+        if (check)                                                           \
+            __read_once_size(&(x), __u.__c, sizeof(x));                      \
+        smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \
+        __u.__val;                                                           \
+    })
+#define READ_ONCE(x) __READ_ONCE(x, 1)
+
+extern struct vdso_data         _vdso_data[CS_BASES] __attribute__((visibility("hidden")));
+static inline struct vdso_data *__arch_get_vdso_data(void)
+{
+    return _vdso_data;
+}
+
+static inline uint32_t rt_vdso_read_begin(const struct vdso_data *vd)
+{
+    uint32_t seq;
+
+    while (unlikely((seq = READ_ONCE(vd->seq)) & 1))
+        cpu_relax();
+
+    rt_hw_rmb();
+    return seq;
+}
+
+static inline uint32_t rt_vdso_read_retry(const struct vdso_data *vd,
+                                          uint32_t                start)
+{
+    uint32_t seq;
+
+    rt_hw_rmb();
+    seq = READ_ONCE(vd->seq);
+    return seq != start;
+}
+
+#endif

+ 0 - 58
components/lwp/vdso/user/xmake.lua

@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author         Notes
- * 2024-07-04     rcitach        init ver.
- */
- 
-toolchain("aarch64-smart-musleabi")
-    set_kind("standalone")
-    
-    local exec_path = os.getenv("RTT_EXEC_PATH") or "/opt/aarch64-linux-musleabi/bin/"
-    local sdkdir = exec_path .. "/../"
-    local incdir = os.curdir() .. "/../include"
-    local device = '-march=armv8-a -mtune=cortex-a53 -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing'
-    
-    set_bindir(exec_path)
-    set_sdkdir(sdkdir)
-    
-    set_toolset("sh", "aarch64-linux-musleabi-gcc")
-    on_load(function(toolchain)
-        toolchain:load_cross_toolchain()
-        toolchain:add("cxflags", device)
-        toolchain:add("cxflags", "-Wall -Wno-cpp -std=gnu99")
-        toolchain:add("cxflags", "-fdiagnostics-color=always")
-        toolchain:add("cxflags", "-O2")
-        toolchain:add("cxflags", "-I" .. incdir)
-
-        toolchain:add("shflags", device)
-        toolchain:add("shflags", "-Wl,--gc-sections")
-        toolchain:add("shflags", "-u,system_vectors")
-        toolchain:add("shflags", "-T vdso.lds")
-    end)
-toolchain_end()
-
-set_config("plat", "cross")
-set_config("target_os", "rt-smart")
-set_config("arch", "aarch64")
-
-rule("vdso_lds")
-    set_extensions(".lds.S")
-    on_buildcmd_file(function (target, batchcmds, sourcefile, opt)
-        local incdir = os.curdir() .. "/../include"
-        local targetfile = path.basename(sourcefile)
-        local prefix = os.getenv("RTT_CC_PREFIX=") or "aarch64-linux-musleabi-"
-        batchcmds:vrunv(prefix .. "gcc", {"-E", "-P", sourcefile, "-o", targetfile, "-I", incdir})
-    end)
-
-target("rtos_vdso")
-    set_toolchains("aarch64-smart-musleabi")
-    add_rules("vdso_lds")
-    set_kind("shared")
-    add_files("vdso.lds.S")
-    add_files("vdso_sys.c")
-    set_targetdir("build")
-target_end()

+ 3 - 3
components/lwp/vdso/vdso_config.h

@@ -15,11 +15,11 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define __VVAR_PAGES    2
+#define __VVAR_PAGES        2
 #define VDSO_PAGE_SHIFT     12
 #define VDSO_PAGE_SHIFT     12
 #define VDSO_PAGE_SIZE      (1 << VDSO_PAGE_SHIFT)
 #define VDSO_PAGE_SIZE      (1 << VDSO_PAGE_SHIFT)
 
 
-#define BIT_MASK(nr)         ((1) << (nr))
+#define BIT_MASK(nr)        ((1) << (nr))
 
 
 #ifndef read_barrier_depends
 #ifndef read_barrier_depends
 #define read_barrier_depends()      do { } while (0)
 #define read_barrier_depends()      do { } while (0)
@@ -29,7 +29,7 @@ extern "C" {
 #define smp_read_barrier_depends()  read_barrier_depends()
 #define smp_read_barrier_depends()  read_barrier_depends()
 #endif
 #endif
 
 
-#define VDSO_PATH "../user/build/librtos_vdso.so"
+#define VDSO_PATH "../user/build/libvdso.so"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 1 - 1
components/lwp/vdso/vdso_weak.c

@@ -19,5 +19,5 @@ rt_weak int arch_setup_additional_pages(struct rt_lwp *lwp)
 
 
 rt_weak void rt_vdso_update_glob_time(void)
 rt_weak void rt_vdso_update_glob_time(void)
 {
 {
-
+    return ;
 }
 }