Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ tags
CMakeLists.txt
cmake-build-debug
*.mk

# vDSO
vdso_sys.os
vdso.lds
1 change: 1 addition & 0 deletions components/lwp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,6 @@ if RT_USING_LWP
endif

rsource "terminal/Kconfig"
rsource "vdso/Kconfig"
endif

10 changes: 8 additions & 2 deletions components/lwp/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -43,4 +48,5 @@ CPPPATH += ['./terminal/']

group = DefineGroup('lwP', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH)

group = group + SConscript(os.path.join('vdso', 'SConscript'))
Return('group')
110 changes: 110 additions & 0 deletions components/lwp/arch/aarch64/common/vdso.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-04 rcitach init ver.
*/

#include <rtthread.h>
#include <mmu.h>
#include <gtimer.h>
#include <lwp_user_mm.h>

#include "vdso.h"
#include "vdso_datapage.h"
#define DBG_TAG "vdso"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

enum vdso_abi {
VDSO_ABI_AA64,
};
enum vvar_pages {
VVAR_DATA_PAGE_OFFSET,
VVAR_TIMENS_PAGE_OFFSET,
VVAR_NR_PAGES,
};
struct vdso_abi_info {
const char *name;
const char *vdso_code_start;
const char *vdso_code_end;
unsigned long vdso_pages;

};

static struct vdso_abi_info vdso_info[] = {
[VDSO_ABI_AA64] = {
.name = "vdso_aarch64",
.vdso_code_start = __vdso_text_start,
.vdso_code_end = __vdso_text_end,
},
};

static union {
struct vdso_data data[CS_BASES];
uint8_t page[ARCH_PAGE_SIZE];
} vdso_data_store __page_aligned_data;
struct vdso_data *vdso_data = vdso_data_store.data;
int init_ret_flag = RT_EOK;

static int __setup_additional_pages(enum vdso_abi abi, struct rt_lwp *lwp)
{
RT_ASSERT(lwp != RT_NULL);

int ret;
void *vdso_base = RT_NULL;
unsigned long vdso_data_len, vdso_text_len;

vdso_data_len = VVAR_NR_PAGES * ARCH_PAGE_SIZE;
vdso_text_len = vdso_info[abi].vdso_pages << ARCH_PAGE_SHIFT;

vdso_base = lwp_map_user_phy(lwp, RT_NULL, rt_kmem_v2p((void *)vdso_data), vdso_data_len, 0);
if(vdso_base != RT_NULL)
{
ret = RT_EOK;
}
else
{
ret = RT_ERROR;
}
vdso_base += vdso_data_len;
vdso_base = lwp_map_user_phy(lwp, vdso_base, rt_kmem_v2p((void *)vdso_info[abi].vdso_code_start), vdso_text_len, 0);

lwp->vdso_vbase = vdso_base;
return ret;
}

int arch_setup_additional_pages(struct rt_lwp *lwp)
{
int ret;
if (init_ret_flag != RT_EOK) return -RT_ERROR;
ret = __setup_additional_pages(VDSO_ABI_AA64, lwp);

return ret;
}

static void __initdata(void)
{
struct tm time_vdso = SOFT_RTC_VDSOTIME_DEFAULT;
vdso_data->realtime_initdata = timegm(&time_vdso);
}

static int validate_vdso_elf(void)
{
if (rt_memcmp(vdso_info[VDSO_ABI_AA64].vdso_code_start, ELF_HEAD, ELF_HEAD_LEN)) {
LOG_E("vDSO is not a valid ELF object!");
init_ret_flag = -RT_ERROR;
return -RT_ERROR;
}
vdso_info[VDSO_ABI_AA64].vdso_pages = (
vdso_info[VDSO_ABI_AA64].vdso_code_end -
vdso_info[VDSO_ABI_AA64].vdso_code_start) >>
ARCH_PAGE_SHIFT;

__initdata();
return RT_EOK;
}
INIT_COMPONENT_EXPORT(validate_vdso_elf);
34 changes: 34 additions & 0 deletions components/lwp/arch/aarch64/common/vdso_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-04 rcitach init ver.
*/

#include <rtthread.h>
#include <gtimer.h>
#include <ktime.h>
#include <time.h>
#include <vdso_datapage.h>
#include <vdso_data.h>

void rt_vdso_update_glob_time(void)
{
struct vdso_data *vdata = get_k_vdso_data();
struct timespec *vdso_ts;
uint64_t initdata = vdata->realtime_initdata;
rt_vdso_write_begin(vdata);

vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
rt_ktime_boottime_get_ns(vdso_ts);
vdso_ts->tv_sec = initdata + vdso_ts->tv_sec;

vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
rt_ktime_boottime_get_ns(vdso_ts);

vdata->cycle_last = rt_hw_get_cntpct_val();
rt_vdso_write_end(vdata);
}
5 changes: 5 additions & 0 deletions components/lwp/lwp.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ struct rt_lwp
unsigned int asid;
#endif
struct rusage rt_rusage;

#ifdef RT_USING_VDSO
void *vdso_vbase;
#endif
};


Expand Down Expand Up @@ -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
{
Expand Down
15 changes: 15 additions & 0 deletions components/lwp/lwp_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down
5 changes: 5 additions & 0 deletions components/lwp/vdso/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
menuconfig RT_USING_VDSO
bool "vDSO"
default y
depends on RT_USING_SMART

48 changes: 48 additions & 0 deletions components/lwp/vdso/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import rtconfig
import subprocess
from building import *
Import('RTT_ROOT')

group = []

cwd = GetCurrentDir()
CPPPATH = [cwd, cwd + "/kernel"]

if not GetDepend(['RT_USING_VDSO']):
Return('group')

if rtconfig.ARCH != "aarch64":
src = Glob('*.c')
group = DefineGroup('VDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
Return('group')

list = os.listdir(cwd)
src = Glob('kernel/*.c')
src +=Glob('kernel/*.S')

if not os.path.exists(cwd + "/user/vdso.lds"):
Preprocessing("user/vdso.lds.S", ".lds", CPPPATH=[cwd])

#aarch64 vdso xmake
# vdso_file = os.path.join(cwd, 'usr', 'xmake.lua')
# command = ["xmake", "-F", vdso_file]
# clean = ["xmake", "clean"]

vdso_file = os.path.join(cwd, 'user', 'SConstruct')
command = ["scons", "-f", vdso_file]
clean = ["scons", "-f", vdso_file, "--clean"]

if not GetOption('clean'):
result = subprocess.run(command)
else:
result = subprocess.run(clean)

if result.returncode == 0:
print("Command executed successfully")
else:
print("Command failed with exit code:", result.returncode)
exit(1)

group = DefineGroup('VDSO', src, depend = ['RT_USING_SMART','RT_USING_VDSO'], CPPPATH = CPPPATH)
Return('group')
39 changes: 39 additions & 0 deletions components/lwp/vdso/kernel/vdso.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-04 rcitach init ver.
*/

#ifndef _VDSO_H
#define _VDSO_H

#include <lwp.h>
#include <mmu.h>
#include <vdso_config.h>
#include <vdso_datapage.h>

#ifdef __cplusplus
extern "C" {
#endif

extern char __vdso_text_start[];
extern char __vdso_text_end[];

#define ELF_HEAD "\177ELF"
#define ELF_HEAD_LEN 4
#define MAX_PAGES 5

#define __page_aligned_data __attribute__((section(".data.vdso.datapage"))) __attribute__((aligned(VDSO_PAGE_SIZE)))

int arch_setup_additional_pages(struct rt_lwp *lwp);
void rt_vdso_update_glob_time(void);

#ifdef __cplusplus
}
#endif

#endif /* _VDSO_H */
48 changes: 48 additions & 0 deletions components/lwp/vdso/kernel/vdso_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-04 rcitach init ver.
*/

#ifndef _VDSO_KDATA_H
#define _VDSO_KDATA_H

#include <rtatomic.h>
#include <vdso_datapage.h>

#ifdef __cplusplus
extern "C" {
#endif

extern struct vdso_data *vdso_data;

rt_inline
struct vdso_data *_get_k_vdso_data(void)
{
return vdso_data;
}
#define get_k_vdso_data _get_k_vdso_data

rt_inline
void rt_vdso_write_begin(struct vdso_data *vd)
{
rt_atomic_add(&vd[CS_HRES_COARSE].seq, 1);
rt_atomic_add(&vd[CS_RAW].seq, 1);
}

rt_inline
void rt_vdso_write_end(struct vdso_data *vd)
{
rt_atomic_add(&vd[CS_HRES_COARSE].seq, 1);
rt_atomic_add(&vd[CS_RAW].seq, 1);
}

#ifdef __cplusplus
}
#endif

#endif /* _VDSO_KDATA_H */
21 changes: 21 additions & 0 deletions components/lwp/vdso/kernel/vdso_text.S
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading