[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.
This commit is contained in:
bernard 2025-05-12 19:29:35 +08:00 committed by Rbb666
parent 2a525e82be
commit 721dfbfe01
21 changed files with 471 additions and 264 deletions

View File

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

View File

@ -25,11 +25,14 @@ 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'
common = '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]
src += [f for f in Glob(common) if os.path.basename(str(f)) not in vdso_files]
else:
src += Glob(arch_common)
src += Glob(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)

View File

@ -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);

View File

@ -10,19 +10,19 @@
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_other;
Elf64_Half st_shndx;
Elf64_Half st_shndx;
} Elf64_sym;
#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)
{
size_t rel_off;
void* addr;
void *addr;
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));
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)
{
@ -48,18 +48,18 @@ void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, s
t = (v2 >> 8);
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 */
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++)
{
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;
}
}
@ -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)
{
*(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)
{
@ -91,14 +91,14 @@ void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size,
t = (v2 >> 8);
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 */
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++)
{

View File

@ -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);
}

View File

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

View File

@ -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
depends on RT_USING_SMART && ARCH_ARMV8

View File

@ -2,47 +2,51 @@ import os
import rtconfig
import subprocess
from building import *
Import('RTT_ROOT')
group = []
cwd = GetCurrentDir()
group = []
cwd = GetCurrentDir()
CPPPATH = [cwd, cwd + "/kernel"]
list = os.listdir(cwd)
src = Glob('kernel/*.c') + Glob('kernel/*.S')
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)
if rtconfig.ARCH != "aarch64" and rtconfig.ARCH != "risc-v":
# not supported arch
src = []
else:
result = subprocess.run(clean)
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 result.returncode == 0:
print("Command executed successfully")
else:
print("Command failed with exit code:", result.returncode)
exit(1)
if not os.path.exists(cwd + "/user" + "/arch" +"/" + rtconfig.ARCH + "/vdso.lds"):
Preprocessing("user/arch/" + rtconfig.ARCH + "/vdso.lds.S", ".lds", CPPPATH=[cwd])
group = DefineGroup('VDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
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')

View File

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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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: *;
};
}

View File

@ -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);
}

View File

@ -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

View File

@ -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()

View File

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

View File

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