summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrcitachi <[email protected]>2024-07-15 17:58:29 +0800
committerGitHub <[email protected]>2024-07-15 17:58:29 +0800
commit14fb55933b173811467159df3e80e314b2e4415c (patch)
tree70e9adf971168d7d16b5bf27806abb707ab3a0c6
parent96ba787e252c38abe08f039c052a4be378dfa42c (diff)
[lwp][vdso] Add VDSO functionality under the aarch64 architecture (#9176)
Add VDSO functionality under the aarch64 architecture
-rw-r--r--.gitignore4
-rw-r--r--components/lwp/Kconfig1
-rw-r--r--components/lwp/SConscript10
-rw-r--r--components/lwp/arch/aarch64/common/vdso.c110
-rw-r--r--components/lwp/arch/aarch64/common/vdso_data.c34
-rw-r--r--components/lwp/lwp.h5
-rw-r--r--components/lwp/lwp_elf.c15
-rw-r--r--components/lwp/vdso/Kconfig5
-rw-r--r--components/lwp/vdso/SConscript48
-rw-r--r--components/lwp/vdso/kernel/vdso.h39
-rw-r--r--components/lwp/vdso/kernel/vdso_data.h48
-rw-r--r--components/lwp/vdso/kernel/vdso_text.S21
-rw-r--r--components/lwp/vdso/user/SConstruct39
-rw-r--r--components/lwp/vdso/user/vdso.lds.S60
-rw-r--r--components/lwp/vdso/user/vdso_sys.c95
-rw-r--r--components/lwp/vdso/user/vdso_sys.h153
-rw-r--r--components/lwp/vdso/user/xmake.lua58
-rw-r--r--components/lwp/vdso/vdso_config.h38
-rw-r--r--components/lwp/vdso/vdso_datapage.h75
-rw-r--r--components/lwp/vdso/vdso_weak.c23
-rw-r--r--libcpu/aarch64/cortex-a/entry_point.S4
-rw-r--r--src/clock.c8
22 files changed, 891 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 9ddfece39e..cff9ff536b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,7 @@ tags
CMakeLists.txt
cmake-build-debug
*.mk
+
+# vDSO
+vdso_sys.os
+vdso.lds
diff --git a/components/lwp/Kconfig b/components/lwp/Kconfig
index 22cfbea47c..d88a0b6a9d 100644
--- a/components/lwp/Kconfig
+++ b/components/lwp/Kconfig
@@ -81,5 +81,6 @@ if RT_USING_LWP
endif
rsource "terminal/Kconfig"
+rsource "vdso/Kconfig"
endif
diff --git a/components/lwp/SConscript b/components/lwp/SConscript
index 5f4a618d48..be7b4f7b64 100644
--- a/components/lwp/SConscript
+++ b/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')
diff --git a/components/lwp/arch/aarch64/common/vdso.c b/components/lwp/arch/aarch64/common/vdso.c
new file mode 100644
index 0000000000..41b0a6d8f0
--- /dev/null
+++ b/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);
diff --git a/components/lwp/arch/aarch64/common/vdso_data.c b/components/lwp/arch/aarch64/common/vdso_data.c
new file mode 100644
index 0000000000..13c055ec56
--- /dev/null
+++ b/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);
+}
diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h
index e2cf2e8bd7..24b4150270 100644
--- a/components/lwp/lwp.h
+++ b/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
{
diff --git a/components/lwp/lwp_elf.c b/components/lwp/lwp_elf.c
index da698e3674..69021a496d 100644
--- a/components/lwp/lwp_elf.c
+++ b/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;
}
diff --git a/components/lwp/vdso/Kconfig b/components/lwp/vdso/Kconfig
new file mode 100644
index 0000000000..a10e016271
--- /dev/null
+++ b/components/lwp/vdso/Kconfig
@@ -0,0 +1,5 @@
+menuconfig RT_USING_VDSO
+ bool "vDSO"
+ default y
+ depends on RT_USING_SMART
+
diff --git a/components/lwp/vdso/SConscript b/components/lwp/vdso/SConscript
new file mode 100644
index 0000000000..addcdfc840
--- /dev/null
+++ b/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')
diff --git a/components/lwp/vdso/kernel/vdso.h b/components/lwp/vdso/kernel/vdso.h
new file mode 100644
index 0000000000..1cb3b44e8c
--- /dev/null
+++ b/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 */
diff --git a/components/lwp/vdso/kernel/vdso_data.h b/components/lwp/vdso/kernel/vdso_data.h
new file mode 100644
index 0000000000..5d077e4a9e
--- /dev/null
+++ b/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 */
diff --git a/components/lwp/vdso/kernel/vdso_text.S b/components/lwp/vdso/kernel/vdso_text.S
new file mode 100644
index 0000000000..f9c1f8aa72
--- /dev/null
+++ b/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
diff --git a/components/lwp/vdso/user/SConstruct b/components/lwp/vdso/user/SConstruct
new file mode 100644
index 0000000000..a7cee1127f
--- /dev/null
+++ b/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)
diff --git a/components/lwp/vdso/user/vdso.lds.S b/components/lwp/vdso/user/vdso.lds.S
new file mode 100644
index 0000000000..8b0038ee2d
--- /dev/null
+++ b/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: *;
+ };
+}
diff --git a/components/lwp/vdso/user/vdso_sys.c b/components/lwp/vdso/user/vdso_sys.c
new file mode 100644
index 0000000000..61da379f04
--- /dev/null
+++ b/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);
+}
diff --git a/components/lwp/vdso/user/vdso_sys.h b/components/lwp/vdso/user/vdso_sys.h
new file mode 100644
index 0000000000..ecc7b366ad
--- /dev/null
+++ b/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
diff --git a/components/lwp/vdso/user/xmake.lua b/components/lwp/vdso/user/xmake.lua
new file mode 100644
index 0000000000..c36448131f
--- /dev/null
+++ b/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()
diff --git a/components/lwp/vdso/vdso_config.h b/components/lwp/vdso/vdso_config.h
new file mode 100644
index 0000000000..ec5d775a33
--- /dev/null
+++ b/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 */
diff --git a/components/lwp/vdso/vdso_datapage.h b/components/lwp/vdso/vdso_datapage.h
new file mode 100644
index 0000000000..243af48bf1
--- /dev/null
+++ b/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 */
diff --git a/components/lwp/vdso/vdso_weak.c b/components/lwp/vdso/vdso_weak.c
new file mode 100644
index 0000000000..56f452cc87
--- /dev/null
+++ b/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)
+{
+
+}
diff --git a/libcpu/aarch64/cortex-a/entry_point.S b/libcpu/aarch64/cortex-a/entry_point.S
index 315e331aac..c0acacb2ca 100644
--- a/libcpu/aarch64/cortex-a/entry_point.S
+++ b/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
diff --git a/src/clock.c b/src/clock.c
index 6a2366a0ac..34684d2885 100644
--- a/src/clock.c
+++ b/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
}
/**