mirror of https://github.com/RT-Thread/rt-thread
[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:
parent
2a525e82be
commit
721dfbfe01
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
|
@ -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++)
|
||||
{
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -0,0 +1,33 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
arguments = sys.argv[2]
|
||||
vdso_usr = arguments
|
||||
vdso_path = os.path.join(vdso_usr, '..', '..', '..')
|
||||
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH') or '/usr/bin'
|
||||
PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
|
||||
DEVICE = os.getenv('RTT_DEVICE') or ' -march=armv8-a -mtune=cortex-a53'
|
||||
|
||||
CC = PREFIX + 'gcc'
|
||||
CPP = PREFIX + 'cpp'
|
||||
AS = PREFIX + 'gcc'
|
||||
AR = PREFIX + 'ar'
|
||||
LINK = PREFIX + 'gcc'
|
||||
|
||||
AFLAGS = ' -x assembler-with-cpp'
|
||||
CFLAGS = DEVICE + ' -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing -Wall -Wno-cpp -std=gnu99 -fdiagnostics-color=always -fPIC -O2'
|
||||
LFLAGS = DEVICE + ' -Bsymbolic -Wl,--gc-sections,-u,system_vectors -T {path}/vdso.lds'.format(path=vdso_usr)
|
||||
CFLAGS += " -I . -I {vdso_path} ".format(vdso_path=vdso_path)
|
||||
|
||||
src = Glob('*.c')
|
||||
env = Environment(tools=['gcc', 'link'],
|
||||
AS = AS, ASFLAGS = AFLAGS,
|
||||
CC = CC, CFLAGS = CFLAGS,
|
||||
CPP = CPP, AR = AR,
|
||||
LINK = LINK, LINKFLAGS = LFLAGS)
|
||||
env.PrependENVPath('PATH', EXEC_PATH)
|
||||
|
||||
target = os.path.join(vdso_path, 'user', 'build', 'libvdso.so')
|
||||
shared_lib = env.SharedLibrary(target=target, source=src)
|
||||
env.Default(shared_lib)
|
|
@ -0,0 +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)
|
|
@ -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: *;
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 ;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue