111 lines
2.6 KiB
C
111 lines
2.6 KiB
C
/*
|
|
* 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);
|