From 14fb55933b173811467159df3e80e314b2e4415c Mon Sep 17 00:00:00 2001 From: rcitachi Date: Mon, 15 Jul 2024 17:58:29 +0800 Subject: [lwp][vdso] Add VDSO functionality under the aarch64 architecture (#9176) Add VDSO functionality under the aarch64 architecture --- components/lwp/Kconfig | 1 + components/lwp/SConscript | 10 +- components/lwp/arch/aarch64/common/vdso.c | 110 ++++++++++++++++++ components/lwp/arch/aarch64/common/vdso_data.c | 34 ++++++ components/lwp/lwp.h | 5 + components/lwp/lwp_elf.c | 15 +++ components/lwp/vdso/Kconfig | 5 + components/lwp/vdso/SConscript | 48 ++++++++ components/lwp/vdso/kernel/vdso.h | 39 +++++++ components/lwp/vdso/kernel/vdso_data.h | 48 ++++++++ components/lwp/vdso/kernel/vdso_text.S | 21 ++++ components/lwp/vdso/user/SConstruct | 39 +++++++ components/lwp/vdso/user/vdso.lds.S | 60 ++++++++++ components/lwp/vdso/user/vdso_sys.c | 95 +++++++++++++++ components/lwp/vdso/user/vdso_sys.h | 153 +++++++++++++++++++++++++ components/lwp/vdso/user/xmake.lua | 58 ++++++++++ components/lwp/vdso/vdso_config.h | 38 ++++++ components/lwp/vdso/vdso_datapage.h | 75 ++++++++++++ components/lwp/vdso/vdso_weak.c | 23 ++++ 19 files changed, 875 insertions(+), 2 deletions(-) create mode 100644 components/lwp/arch/aarch64/common/vdso.c create mode 100644 components/lwp/arch/aarch64/common/vdso_data.c create mode 100644 components/lwp/vdso/Kconfig create mode 100644 components/lwp/vdso/SConscript create mode 100644 components/lwp/vdso/kernel/vdso.h create mode 100644 components/lwp/vdso/kernel/vdso_data.h create mode 100644 components/lwp/vdso/kernel/vdso_text.S create mode 100644 components/lwp/vdso/user/SConstruct create mode 100644 components/lwp/vdso/user/vdso.lds.S create mode 100644 components/lwp/vdso/user/vdso_sys.c create mode 100644 components/lwp/vdso/user/vdso_sys.h create mode 100644 components/lwp/vdso/user/xmake.lua create mode 100644 components/lwp/vdso/vdso_config.h create mode 100644 components/lwp/vdso/vdso_datapage.h create mode 100644 components/lwp/vdso/vdso_weak.c (limited to 'components') 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 +#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_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 +#include +#include +#include +#include +#include + +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 #endif +#ifdef RT_USING_VDSO +#include +#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 +#include +#include +#include + +#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 +#include + +#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 + + .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 + +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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#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 +#include +#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) +{ + +} -- cgit v1.3.1 From 1b581d0755450788b161f05486ecd97ee4f88ff3 Mon Sep 17 00:00:00 2001 From: Shell Date: Tue, 16 Jul 2024 17:03:54 +0800 Subject: [dfs] Mark dirty on unmap on shared mapping only (#9195) [dfs] feat: Mark dirty on unmap for shared mapping This patch optimizes the pcache varea management by refining the conditions under which pages are marked dirty, specifically targeting the unmap operations in the dfs_pcache component. These changes were necessary to enhance the efficiency of page cache management. Changes: - Adjusted include statements in `dfs_pcache.c` for better organization. - Modified `dfs_aspace_unmap` function: - Added a check to ensure `varea` is not privately locked before marking a page as dirty. - Updated `dfs_aspace_page_unmap` function: - Added a similar check for `varea` lock status before marking a page as dirty. Signed-off-by: Shell --- components/dfs/dfs_v2/src/dfs_pcache.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'components') diff --git a/components/dfs/dfs_v2/src/dfs_pcache.c b/components/dfs/dfs_v2/src/dfs_pcache.c index 350ad1f061..6868170b9c 100644 --- a/components/dfs/dfs_v2/src/dfs_pcache.c +++ b/components/dfs/dfs_v2/src/dfs_pcache.c @@ -13,10 +13,11 @@ #define DBG_LVL DBG_WARNING #include -#include "dfs_pcache.h" -#include "dfs_dentry.h" -#include "dfs_mnt.h" -#include "mm_page.h" +#include +#include +#include +#include +#include #include #include @@ -1380,7 +1381,8 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea) rt_varea_unmap_page(map_varea, vaddr); - if (varea->attr == MMU_MAP_U_RWCB && page->fpos < page->aspace->vnode->size) + if (!rt_varea_is_private_locked(varea) && + page->fpos < page->aspace->vnode->size) { dfs_page_dirty(page); } @@ -1425,7 +1427,7 @@ int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *v if (map && varea->aspace == map->aspace && vaddr == map->vaddr) { - if (varea->attr == MMU_MAP_U_RWCB) + if (!rt_varea_is_private_locked(varea)) { dfs_page_dirty(page); } -- cgit v1.3.1 From 1d78d11567bc2187d10ca94e63c39cc95ff1195d Mon Sep 17 00:00:00 2001 From: Shell Date: Tue, 16 Jul 2024 20:38:55 +0800 Subject: [smart] feat: add unmap for null mapper (#9186) Do unmap before shrink so we don't see mapped entry on page table insertion, which is not acceptable for riscv implementation of architecture porting. Changes: - add un-mapping of pte on `_null_shrink()` Signed-off-by: Shell --- components/lwp/lwp_user_mm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'components') diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index 01640d5a07..18f10e176f 100644 --- a/components/lwp/lwp_user_mm.c +++ b/components/lwp/lwp_user_mm.c @@ -70,11 +70,29 @@ static void _null_page_fault(struct rt_varea *varea, static rt_err_t _null_shrink(rt_varea_t varea, void *new_start, rt_size_t size) { + char *varea_start = varea->start; + void *rm_start; + void *rm_end; + + if (varea_start == (char *)new_start) + { + rm_start = varea_start + size; + rm_end = varea_start + varea->size; + } + else /* if (varea_start < (char *)new_start) */ + { + RT_ASSERT(varea_start < (char *)new_start); + rm_start = varea_start; + rm_end = new_start; + } + + rt_varea_unmap_range(varea, rm_start, rm_end - rm_start); return RT_EOK; } static rt_err_t _null_split(struct rt_varea *existed, void *unmap_start, rt_size_t unmap_len, struct rt_varea *subset) { + rt_varea_unmap_range(existed, unmap_start, unmap_len); return RT_EOK; } -- cgit v1.3.1 From 4ad194bb47101345ce3b3fa631ab2215a0c190c0 Mon Sep 17 00:00:00 2001 From: zhuzhuzhu <945386260@qq.com> Date: Wed, 17 Jul 2024 09:08:10 +0800 Subject: [fix] fix cromfs read out of mem range (#9197) Update dfs_cromfs.c --- components/dfs/dfs_v2/filesystems/cromfs/dfs_cromfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components') diff --git a/components/dfs/dfs_v2/filesystems/cromfs/dfs_cromfs.c b/components/dfs/dfs_v2/filesystems/cromfs/dfs_cromfs.c index 0d82914df4..ae67887a4d 100644 --- a/components/dfs/dfs_v2/filesystems/cromfs/dfs_cromfs.c +++ b/components/dfs/dfs_v2/filesystems/cromfs/dfs_cromfs.c @@ -786,18 +786,18 @@ static ssize_t dfs_cromfs_read(struct dfs_file *file, void *buf, size_t count, o rt_err_t result = RT_EOK; file_info *fi = NULL; cromfs_info *ci = NULL; - uint32_t length = 0; + ssize_t length = 0; ci = (cromfs_info *)file->dentry->mnt->data; fi = (file_info *)file->vnode->data; - if (count < file->vnode->size - *pos) + if ((off_t)count < (off_t)file->vnode->size - *pos) { length = count; } else { - length = file->vnode->size - *pos; + length = (off_t)file->vnode->size - *pos; } if (length > 0) -- cgit v1.3.1