From ee95fae075c68cf1ae0fc1ffb00acca685bfb2c8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 15 Jun 2021 10:21:37 -0700 Subject: [PATCH] linux-user/aarch64: Add vdso MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- linux-user/aarch64/Makefile.vdso | 15 +++++++ linux-user/aarch64/meson.build | 11 +++++ linux-user/aarch64/vdso-be.so | Bin 0 -> 3216 bytes linux-user/aarch64/vdso-le.so | Bin 0 -> 3216 bytes linux-user/aarch64/vdso.S | 71 ++++++++++++++++++++++++++++++ linux-user/aarch64/vdso.ld | 72 +++++++++++++++++++++++++++++++ linux-user/elfload.c | 6 +++ linux-user/meson.build | 1 + 8 files changed, 176 insertions(+) create mode 100644 linux-user/aarch64/Makefile.vdso create mode 100644 linux-user/aarch64/meson.build create mode 100755 linux-user/aarch64/vdso-be.so create mode 100755 linux-user/aarch64/vdso-le.so create mode 100644 linux-user/aarch64/vdso.S create mode 100644 linux-user/aarch64/vdso.ld diff --git a/linux-user/aarch64/Makefile.vdso b/linux-user/aarch64/Makefile.vdso new file mode 100644 index 0000000000..599958116b --- /dev/null +++ b/linux-user/aarch64/Makefile.vdso @@ -0,0 +1,15 @@ +include $(BUILD_DIR)/tests/tcg/aarch64-linux-user/config-target.mak + +SUBDIR = $(SRC_PATH)/linux-user/aarch64 +VPATH += $(SUBDIR) + +all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so + +LDFLAGS = -nostdlib -shared -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \ + -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld + +$(SUBDIR)/vdso-be.so: vdso.S vdso.ld + $(CC) -o $@ $(LDFLAGS) -mbig-endian $< + +$(SUBDIR)/vdso-le.so: vdso.S vdso.ld + $(CC) -o $@ $(LDFLAGS) -mlittle-endian $< diff --git a/linux-user/aarch64/meson.build b/linux-user/aarch64/meson.build new file mode 100644 index 0000000000..248c578d15 --- /dev/null +++ b/linux-user/aarch64/meson.build @@ -0,0 +1,11 @@ +# TARGET_BIG_ENDIAN is defined to 'n' for little-endian; which means it +# is always true as far as source_set.apply() is concerned. Always build +# both header files and include the right one via #if. + +vdso_be_inc = gen_vdso.process('vdso-be.so', + extra_args: ['-r', '__kernel_rt_sigreturn']) + +vdso_le_inc = gen_vdso.process('vdso-le.so', + extra_args: ['-r', '__kernel_rt_sigreturn']) + +linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [vdso_be_inc, vdso_le_inc]) diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so new file mode 100755 index 0000000000000000000000000000000000000000..6084f3d1a701316004894fcdd739c4e1e0463b68 GIT binary patch literal 3216 zcmb<-^>JfjVq|~=W`^wy3=BvDU>OH6$-prIOgk`GFt9Q>FbFX4GcYi)F)%Q&fW;XY zpz6?RMhS>KjAr0~+QAMH$3?PyfXF~;h^v?o_AxGi$YanDVT3n0Qc9i%AoQ_RKop?U z3?dM5I1Ta_41=5;0g-1!qZwQv;&2+|Kaf5F1_lOJcfU}E0}uruF=hx89A+T_9ZD^wkb;sX&33=C0F8e|Rw0|PV2PYn70|9ypsGdDnJ z2382oyaPgmVsYQ9IIq~VKB_)};srhLsiIoV^_O>0uhYT%+^pbkSb6*(*cPyFo5Hb zfw3xxfu%x@QJO~{Bn%37P}&5=H#p73t1w^H5N)``$iQ&r0CW5`FrN>V?}5b65QNBq z48w();pHAIe?wFa9|AM8M85p4DBRn6js9RGguk&k0t*0LixyHrSES{0=McATrDh4A6Yf0x8!a z!XQt9!Wm>fEI)u`7+J9AACOv59D@)=Z87*r}4;$0&B9DO~V8RFyJ{X*kiJ>uPh9DQBmJzRnq;@y4xog97Q{oUMx zT|?qS9G!ez<56=UJm14}IPR;R zCwG_~AayYPpmd*S z3<@AoBn-13MB9Mc98ft>Jp(cZ+)jYC7Z?~AKxHk|Z(x-meIN#?PO`}V|Nk3^11i`c zG^|{L(F_(KLm_ft5~d%-aYB-V*$>Sp@Nx{+?f|I=VOThT*k1Yn|NjRu5cab`%Q+Yg zuJ@7M548sz-r?x&6$W^D2rm~w?gxcGOdqoQ(~!a+Di14PU^KX%gE|pRfx->UU|?VX zC1aR>VERGv4JrqrG=m0AF_cEOzYfWMXuZG!4L=wS4u7atFokSC$Zn{;U^yfL+Ky&m zDqvt>0JSMap^`BBLFo@vhaiV7R0)V;PXLh&3=FHFG>ih-31bT)#Xn38N^?N#A%+&H J0E~j`2LK!QDDD6N literal 0 HcmV?d00001 diff --git a/linux-user/aarch64/vdso-le.so b/linux-user/aarch64/vdso-le.so new file mode 100755 index 0000000000000000000000000000000000000000..947d534ec1899740edbd6921da6bc6e70e2ecd09 GIT binary patch literal 3216 zcmb<-^>JfjWMqH=W`^wy2p$8215{!H2b94860=}nWpH2+VBlw9V_;xl0gFN8Vd`PD z1k^AX4KoHL%ns3lmHYrQl!1W(Ml(QN#RRo)0muLb1_pE*stl%_0cKyo(~=aBkrg0< zfq?;?7J<3~Mnjc>{RU!3KIaZr zAU;Tb^P>CgZjMFUJa4_Xk}u=BpC0-~7^IXBL@+QgL_ukg86ai=NFxIS!`FZR^FjOu zC?8}Wh`$5M2gMJFzW@|)3=9lhAPxfqLphY@hSCyH`p?9`&X)SUSA)RL0S+|>NEl*CGeXmU<|ayCp3 zi*QkDF+#McB)&K^y(qP$v?z}uCo`|KLboiXIA5POwZU7;(8_q z2n6vM86a@s{&&2f^elsvRzZGZVqj$GJRQ#tk^`v+#RG_DlxDUDiGkFB$_gEjAOiyf zEc_X(f*4pT^N2*T8%}RK5oiKSK~A z2i1<1VrF1ufaPyw1152-yq2d_jMRIasflEqKo?bqKN(zHY1w*_` zq@Sa&r!zx*yt`j$ysJmNTacr#YrKa`5JSAXkH3?nPrSdITd-?Le2Alyk83 zcn-&%mEmfMDI*y4iYs$V5|bG8ic5+hbOwx-mtT^~pqEmamzbNG3}zHp<}&D|B$gyH z=%weC>SZJrXF$YDiXb9osYS(^`FSXu_!I`c)QtGFqQu7by1dlu=)YUS7cxSw`pL>2bS(&G^~9AvIC?CrXQ9Lv=|r| zKy@n2epvYcqbGngF)%QI^n>ygOh2f614$Wy(>tha0r42%thz-J^Gz{_+Oh2rAh0z)yMMxOk{yM1rptb-=8LXUv z(J=Re + +/* ??? These are in include/elf.h, which is not ready for inclusion in asm. */ +#define NT_GNU_PROPERTY_TYPE_0 5 +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1) + +#define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \ + (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC) + + .section .note.gnu.property + .align 3 + .long 2f - 1f + .long 6f - 3f + .long NT_GNU_PROPERTY_TYPE_0 +1: .string "GNU" +2: .align 3 +3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND + .long 5f - 4f +4: .long GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT +5: .align 3 +6: + + .text + +.macro endf name + .globl \name + .type \name, @function + .size \name, . - \name +.endm + +.macro vdso_syscall name, nr +\name: + bti c + mov x8, #\nr + svc #0 + ret +endf \name +.endm + + .cfi_startproc + +vdso_syscall __kernel_gettimeofday, __NR_gettimeofday +vdso_syscall __kernel_clock_gettime, __NR_clock_gettime +vdso_syscall __kernel_clock_getres, __NR_clock_getres + + .cfi_endproc + + +/* + * TODO: The kernel makes a big deal of turning off the .cfi directives, + * because they cause libgcc to crash, but that's because they're wrong. + * + * For now, elide the unwind info for __kernel_rt_sigreturn and rely on + * the libgcc fallback routine as we have always done. This requires + * that the code sequence used be exact. + */ +__kernel_rt_sigreturn: + /* No BTI C insn here -- we arrive via RET. */ + mov x8, #__NR_rt_sigreturn + svc #0 +endf __kernel_rt_sigreturn diff --git a/linux-user/aarch64/vdso.ld b/linux-user/aarch64/vdso.ld new file mode 100644 index 0000000000..4c12f33352 --- /dev/null +++ b/linux-user/aarch64/vdso.ld @@ -0,0 +1,72 @@ +/* + * Linker script for linux aarch64 replacement vdso. + * + * Copyright 2021 Linaro, Ltd. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +VERSION { + LINUX_2.6.39 { + global: + __kernel_rt_sigreturn; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + + local: *; + }; +} + + +PHDRS { + phdr PT_PHDR FLAGS(4) PHDRS; + load PT_LOAD FLAGS(7) FILEHDR PHDRS; + dynamic PT_DYNAMIC FLAGS(4); + eh_frame_hdr PT_GNU_EH_FRAME; + note PT_NOTE FLAGS(4); +} + +SECTIONS { + /* + * We can't prelink to any address without knowing something about + * the virtual memory space of the host, since that leaks over into + * the available memory space of the guest. + */ + . = SIZEOF_HEADERS; + + /* + * The following, including the FILEHDRS and PHDRS, are modified + * when we relocate the binary. We want them to be initially + * writable for the relocation; we'll force them read-only after. + */ + .note : { *(.note*) } :load :note + .dynamic : { *(.dynamic) } :load :dynamic + .dynsym : { *(.dynsym) } :load + /* + * There ought not be any real read-write data. + * But since we manipulated the segment layout, + * we have to put these sections somewhere. + */ + .data : { + *(.data*) + *(.sdata*) + *(.got.plt) *(.got) + *(.gnu.linkonce.d.*) + *(.bss*) + *(.dynbss*) + *(.gnu.linkonce.b.*) + } + + .rodata : { *(.rodata*) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :load :eh_frame_hdr + .eh_frame : { *(.eh_frame) } :load + + .text : { *(.text*) } :load =0xd503201f +} diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 62a33481e1..0a3a57018b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -944,6 +944,12 @@ const char *elf_hwcap2_str(uint32_t bit) #undef GET_FEATURE_ID +#if TARGET_BIG_ENDIAN +# define VDSO_HEADER "vdso-be.c.inc" +#else +# define VDSO_HEADER "vdso-le.c.inc" +#endif + #endif /* not TARGET_AARCH64 */ #endif /* TARGET_ARM */ diff --git a/linux-user/meson.build b/linux-user/meson.build index e4cb70ed2d..dd24389052 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -35,6 +35,7 @@ gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c', gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc', arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@']) +subdir('aarch64') subdir('alpha') subdir('arm') subdir('hppa')