Răsfoiți Sursa

[lwp][vdso] Add VDSO functionality under the aarch64 architecture (#9176)

Add VDSO functionality under the aarch64 architecture
rcitachi 9 luni în urmă
părinte
comite
14fb55933b

+ 4 - 0
.gitignore

@@ -50,3 +50,7 @@ tags
 CMakeLists.txt
 cmake-build-debug
 *.mk
+
+# vDSO
+vdso_sys.os
+vdso.lds

+ 1 - 0
components/lwp/Kconfig

@@ -81,5 +81,6 @@ if RT_USING_LWP
     endif
 
 rsource "terminal/Kconfig"
+rsource "vdso/Kconfig"
 endif
 

+ 8 - 2
components/lwp/SConscript

@@ -26,11 +26,16 @@ if platform in platform_file.keys(): # support platforms
     if arch in support_arch.keys() and cpu in support_arch[arch]:
         asm_path = 'arch/' + arch + '/' + cpu + '/*_' + platform_file[platform]
         arch_common = 'arch/' + arch + '/' + 'common/*.c'
+        if not GetDepend('RT_USING_VDSO'):
+            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]
+        else:
+            src += Glob(arch_common)
         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']
-            src += [f for f in Glob('*.c') if os.path.basename(str(f)) not in excluded_files] + Glob(asm_path) + Glob(arch_common)
+            src += [f for f in Glob('*.c') if os.path.basename(str(f)) not in excluded_files] + Glob(asm_path)
         else:
-            src += Glob('*.c') + Glob(asm_path) + Glob(arch_common)
+            src += Glob('*.c') + Glob(asm_path)
         src += Glob('arch/' + arch + '/' + cpu + '/*.c')
         CPPPATH = [cwd]
         CPPPATH += [cwd + '/arch/' + arch + '/' + cpu]
@@ -43,4 +48,5 @@ CPPPATH += ['./terminal/']
 
 group = DefineGroup('lwP', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH)
 
+group = group + SConscript(os.path.join('vdso', 'SConscript'))
 Return('group')

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

@@ -0,0 +1,110 @@
+/*
+ * 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);

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

@@ -0,0 +1,34 @@
+/*
+ * 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 <gtimer.h>
+#include <ktime.h>
+#include <time.h>
+#include <vdso_datapage.h>
+#include <vdso_data.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 = rt_hw_get_cntpct_val();
+    rt_vdso_write_end(vdata);
+}

+ 5 - 0
components/lwp/lwp.h

@@ -197,6 +197,10 @@ struct rt_lwp
     unsigned int asid;
 #endif
     struct rusage rt_rusage;
+
+#ifdef RT_USING_VDSO
+    void *vdso_vbase;
+#endif
 };
 
 
@@ -373,6 +377,7 @@ void lwp_jobctrl_on_exit(struct rt_lwp *lwp);
 #define AT_RANDOM 25
 #define AT_HWCAP2 26
 #define AT_EXECFN 31
+#define AT_SYSINFO_EHDR 33
 
 struct process_aux_item
 {

+ 15 - 0
components/lwp/lwp_elf.c

@@ -25,6 +25,10 @@
 #include <lwp_user_mm.h>
 #endif
 
+#ifdef RT_USING_VDSO
+#include <vdso.h>
+#endif
+
 #define DBG_TAG "load.elf"
 #ifdef ELF_DEBUG_ENABLE
 #define DBG_LVL DBG_LOG
@@ -607,6 +611,17 @@ static int elf_aux_fill(elf_load_info_t *load_info)
     ELF_AUX_ENT(aux_info, AT_CLKTCK, 0);
     ELF_AUX_ENT(aux_info, AT_SECURE, 0);
 
+#ifdef RT_USING_VDSO
+    if(RT_EOK == arch_setup_additional_pages(load_info->lwp))
+    {
+        ELF_AUX_ENT(aux_info, AT_SYSINFO_EHDR, (size_t)load_info->lwp->vdso_vbase);
+    }
+    else
+    {
+        LOG_W("vdso map error,VDSO currently only supports aarch64 architecture!");
+    }
+#endif
+
     return 0;
 }
 

+ 5 - 0
components/lwp/vdso/Kconfig

@@ -0,0 +1,5 @@
+menuconfig RT_USING_VDSO
+    bool "vDSO"
+    default y
+    depends on RT_USING_SMART
+

+ 48 - 0
components/lwp/vdso/SConscript

@@ -0,0 +1,48 @@
+import os
+import rtconfig
+import subprocess
+from building import *
+Import('RTT_ROOT')
+
+group = []
+
+cwd = GetCurrentDir()
+CPPPATH = [cwd, cwd + "/kernel"]
+
+if not GetDepend(['RT_USING_VDSO']):
+    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)
+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)
+Return('group')

+ 39 - 0
components/lwp/vdso/kernel/vdso.h

@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef _VDSO_H
+#define _VDSO_H
+
+#include <lwp.h>
+#include <mmu.h>
+#include <vdso_config.h>
+#include <vdso_datapage.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char __vdso_text_start[];
+extern char __vdso_text_end[];
+
+#define ELF_HEAD "\177ELF"
+#define ELF_HEAD_LEN 4
+#define MAX_PAGES 5
+
+#define __page_aligned_data	__attribute__((section(".data.vdso.datapage"))) __attribute__((aligned(VDSO_PAGE_SIZE)))
+
+int arch_setup_additional_pages(struct rt_lwp *lwp);
+void rt_vdso_update_glob_time(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VDSO_H */

+ 48 - 0
components/lwp/vdso/kernel/vdso_data.h

@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef _VDSO_KDATA_H
+#define _VDSO_KDATA_H
+
+#include <rtatomic.h>
+#include <vdso_datapage.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct vdso_data *vdso_data;
+
+rt_inline
+struct vdso_data *_get_k_vdso_data(void)
+{
+    return vdso_data;
+}
+#define get_k_vdso_data _get_k_vdso_data
+
+rt_inline
+void rt_vdso_write_begin(struct vdso_data *vd)
+{
+    rt_atomic_add(&vd[CS_HRES_COARSE].seq, 1);
+    rt_atomic_add(&vd[CS_RAW].seq, 1);
+}
+
+rt_inline
+void rt_vdso_write_end(struct vdso_data *vd)
+{
+    rt_atomic_add(&vd[CS_HRES_COARSE].seq, 1);
+    rt_atomic_add(&vd[CS_RAW].seq, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VDSO_KDATA_H */

+ 21 - 0
components/lwp/vdso/kernel/vdso_text.S

@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+ 
+#include <vdso_config.h>    
+
+    .globl __vdso_text_start, __vdso_text_end
+    .section .rodata
+    .balign VDSO_PAGE_SIZE
+__vdso_text_start:
+    .incbin VDSO_PATH
+    .balign VDSO_PAGE_SIZE
+__vdso_text_end:
+
+    .previous

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

@@ -0,0 +1,39 @@
+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)

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

@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+ 
+#include <vdso_config.h>
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+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.39 {
+    global:
+        __kernel_clock_gettime;
+    local: *;
+    };
+}

+ 95 - 0
components/lwp/vdso/user/vdso_sys.c

@@ -0,0 +1,95 @@
+/*
+ * 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 <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
+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
+__kernel_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+    return rt_vdso_clock_gettime_data(__arch_get_vdso_data(), clock, ts);
+}

+ 153 - 0
components/lwp/vdso/user/vdso_sys.h

@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+#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(val) do {    \
+    uint64_t tmp, _val = (val);                    \
+                                                   \
+    asm volatile(                                  \
+    "   eor %0, %1, %1\n"                          \
+    "   add %0, sp, %0\n"                          \
+    "   ldr xzr, [%0]"                             \
+    : "=r" (tmp) : "r" (_val));                    \
+} while (0)
+
+static inline uint64_t __arch_get_hw_counter()
+{
+    uint64_t res;
+
+    __asm__ volatile("mrs %0, CNTVCT_EL0":"=r"(res));
+
+    arch_counter_enforce_ordering(res);
+    return res;
+}
+
+static inline uint64_t __arch_get_hw_frq()
+{
+    uint64_t res;
+
+    __asm__ volatile("mrs %0, CNTFRQ_EL0":"=r"(res));
+
+    arch_counter_enforce_ordering(res);
+    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(isb)
+#define rt_hw_dmb() rt_hw_barrier(dmb, ish)
+#define rt_hw_wmb() rt_hw_barrier(dmb, ishst)
+#define rt_hw_rmb() rt_hw_barrier(dmb, ishld)
+#define rt_hw_dsb() rt_hw_barrier(dsb, ish)
+
+#ifndef barrier
+/* The "volatile" is due to gcc bugs */
+# define barrier() __asm__ __volatile__("": : :"memory")
+#endif
+
+static inline void cpu_relax(void)
+{
+    __asm__ volatile("yield" ::: "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

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

@@ -0,0 +1,58 @@
+/*
+ * 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()

+ 38 - 0
components/lwp/vdso/vdso_config.h

@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __VVAR_PAGES    2
+#define VDSO_PAGE_SHIFT     12
+#define VDSO_PAGE_SIZE      (1 << VDSO_PAGE_SHIFT)
+
+#define BIT_MASK(nr)         ((1) << (nr))
+
+#ifndef read_barrier_depends
+#define read_barrier_depends()      do { } while (0)
+#endif
+
+#ifndef smp_read_barrier_depends
+#define smp_read_barrier_depends()  read_barrier_depends()
+#endif
+
+#define VDSO_PATH "../user/build/librtos_vdso.so"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __ASM_VDSO_H */

+ 75 - 0
components/lwp/vdso/vdso_datapage.h

@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef _VDSO_DATAPAGE_H
+#define _VDSO_DATAPAGE_H
+
+#include <time.h>
+#include <sys/types.h>
+#include "vdso_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef signed char         __s8;
+typedef signed short        __s16;
+typedef signed int          __s32;
+typedef signed long         __s64;
+
+typedef unsigned char       __u8;
+typedef unsigned short      __u16;
+typedef unsigned int        __u32;
+typedef unsigned long       __u64;
+
+#define MAX_CLOCKS          16
+
+#define VDSO_BASES  (CLOCK_TAI + 1)
+#define VDSO_REALTIME   (BIT_MASK(CLOCK_REALTIME)    | \
+             BIT_MASK(CLOCK_REALTIME_COARSE))
+#define VDSO_MONOTIME   (BIT_MASK(CLOCK_MONOTONIC)   | \
+             BIT_MASK(CLOCK_MONOTONIC_COARSE)        | \
+             BIT_MASK(CLOCK_MONOTONIC_RAW)           | \
+             BIT_MASK(CLOCK_BOOTTIME))
+
+#define CS_HRES_COARSE  0
+#define CS_RAW      1
+#define CS_BASES    (CS_RAW + 1)
+
+/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50)  */
+#define RTC_VDSOTIME_INIT(year, month, day, hour, minute, second)        \
+    {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second}
+
+#ifndef SOFT_RTC_VDSOTIME_DEFAULT
+#define SOFT_RTC_VDSOTIME_DEFAULT                    RTC_VDSOTIME_INIT(2018, 1, 1, 0, 0 ,0)
+#endif
+
+struct vdso_data {
+    uint32_t       seq;
+    uint32_t       clock_mode;
+    uint64_t       realtime_initdata;
+    uint64_t       cycle_last;
+    struct timespec basetime[VDSO_BASES];
+};
+typedef struct vdso_data *vdso_data_t;
+
+#define MSEC_PER_SEC    1000L
+#define USEC_PER_MSEC   1000L
+#define NSEC_PER_USEC   1000L
+#define NSEC_PER_MSEC   1000000L
+#define USEC_PER_SEC    1000000L
+#define NSEC_PER_SEC    1000000000L
+#define FSEC_PER_SEC    1000000000000000LL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VDSO_DATAPAGE_H */

+ 23 - 0
components/lwp/vdso/vdso_weak.c

@@ -0,0 +1,23 @@
+/*
+ * 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 <lwp_user_mm.h>
+#include "vdso.h"
+
+rt_weak int arch_setup_additional_pages(struct rt_lwp *lwp)
+{
+    return -RT_ERROR;
+}
+
+rt_weak void rt_vdso_update_glob_time(void)
+{
+
+}

+ 4 - 0
libcpu/aarch64/cortex-a/entry_point.S

@@ -234,6 +234,10 @@ init_cpu_el:
     bic     x0, x0, #(1 << 1)       /* Disable Alignment check */
     msr     sctlr_el1, x0
 
+    mrs     x0, cntkctl_el1
+    orr     x0, x0, #(1 << 1)      /* Set EL0VCTEN, enabling the EL0 Virtual Count Timer */
+    msr     cntkctl_el1, x0
+
     /* Avoid trap from SIMD or float point instruction */
     mov     x0, #0x00300000         /* Don't trap any SIMD/FP instructions in both EL0 and EL1 */
     msr     cpacr_el1, x0

+ 8 - 0
src/clock.c

@@ -23,6 +23,10 @@
 #include <rtthread.h>
 #include <rtatomic.h>
 
+#if defined(RT_USING_SMART) && defined(RT_USING_VDSO)
+#include <vdso.h>
+#endif
+
 #ifdef RT_USING_SMP
 #define rt_tick rt_cpu_index(0)->tick
 #else
@@ -141,6 +145,10 @@ void rt_tick_increase(void)
     }
 #endif
     rt_timer_check();
+
+#ifdef RT_USING_VDSO
+    rt_vdso_update_glob_time();
+#endif
 }
 
 /**