Add a vDSO function __vdso_riscv_hwprobe, which can sit in front of the riscv_hwprobe syscall and answer common queries. We stash a copy of static answers for the "all CPUs" case in the vDSO data page. This data is private to the vDSO, so we can decide later to change what's stored there or under what conditions we defer to the syscall. Currently all data can be discovered at boot, so the vDSO function answers all queries when the cpumask is set to the "all CPUs" hint. There's also a boolean in the data that lets the vDSO function know that all CPUs are the same. In that case, the vDSO will also answer queries for arbitrary CPU masks in addition to the "all CPUs" hint. Signed-off-by: Evan Green <evan@rivosinc.com> Link: https://lore.kernel.org/r/20230407231103.2622178-7-evan@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
91 lines
2.0 KiB
ArmAsm
91 lines
2.0 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2012 Regents of the University of California
|
|
*/
|
|
#include <asm/page.h>
|
|
#include <asm/vdso.h>
|
|
|
|
OUTPUT_ARCH(riscv)
|
|
|
|
SECTIONS
|
|
{
|
|
PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE);
|
|
#ifdef CONFIG_TIME_NS
|
|
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
|
|
#endif
|
|
. = 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) }
|
|
|
|
.note : { *(.note.*) } :text :note
|
|
.dynamic : { *(.dynamic) } :text :dynamic
|
|
|
|
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
|
|
.eh_frame : { KEEP (*(.eh_frame)) } :text
|
|
|
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
|
|
|
/*
|
|
* This linker script is used both with -r and with -shared.
|
|
* For the layouts to match, we need to skip more than enough
|
|
* space for the dynamic symbol table, etc. If this amount is
|
|
* insufficient, ld -shared will error; simply increase it here.
|
|
*/
|
|
. = 0x800;
|
|
.text : { *(.text .text.*) } :text
|
|
|
|
. = ALIGN(4);
|
|
.alternative : {
|
|
__alt_start = .;
|
|
*(.alternative)
|
|
__alt_end = .;
|
|
}
|
|
|
|
.data : {
|
|
*(.got.plt) *(.got)
|
|
*(.data .data.* .gnu.linkonce.d.*)
|
|
*(.dynbss)
|
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We must supply the ELF program headers explicitly to get just one
|
|
* PT_LOAD segment, and set the flags explicitly to make segments read-only.
|
|
*/
|
|
PHDRS
|
|
{
|
|
text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
|
|
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
|
|
note PT_NOTE FLAGS(4); /* PF_R */
|
|
eh_frame_hdr PT_GNU_EH_FRAME;
|
|
}
|
|
|
|
/*
|
|
* This controls what symbols we export from the DSO.
|
|
*/
|
|
VERSION
|
|
{
|
|
LINUX_4.15 {
|
|
global:
|
|
__vdso_rt_sigreturn;
|
|
#ifdef HAS_VGETTIMEOFDAY
|
|
__vdso_gettimeofday;
|
|
__vdso_clock_gettime;
|
|
__vdso_clock_getres;
|
|
#endif
|
|
__vdso_getcpu;
|
|
__vdso_flush_icache;
|
|
#ifndef COMPAT_VDSO
|
|
__vdso_riscv_hwprobe;
|
|
#endif
|
|
local: *;
|
|
};
|
|
}
|