Index: head/sys/amd64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- head/sys/amd64/cloudabi64/cloudabi64_sysvec.c +++ head/sys/amd64/cloudabi64/cloudabi64_sysvec.c @@ -196,7 +196,6 @@ .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, - .sv_usrstack = USRSTACK, .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, .sv_copyout_strings = cloudabi64_copyout_strings, .sv_setregs = cloudabi64_proc_setregs, Index: head/sys/arm64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- head/sys/arm64/cloudabi64/cloudabi64_sysvec.c +++ head/sys/arm64/cloudabi64/cloudabi64_sysvec.c @@ -165,7 +165,6 @@ .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, - .sv_usrstack = USRSTACK, .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, .sv_copyout_strings = cloudabi64_copyout_strings, .sv_setregs = cloudabi64_proc_setregs, Index: head/sys/compat/cloudabi/cloudabi_util.h =================================================================== --- head/sys/compat/cloudabi/cloudabi_util.h +++ head/sys/compat/cloudabi/cloudabi_util.h @@ -33,6 +33,7 @@ #include struct file; +struct sysentvec; struct thread; struct timespec; @@ -76,4 +77,8 @@ cloudabi_scope_t, cloudabi_clockid_t, cloudabi_timestamp_t, cloudabi_timestamp_t); +/* vDSO setup and teardown. */ +void cloudabi_vdso_init(struct sysentvec *, char *, char *); +void cloudabi_vdso_destroy(struct sysentvec *); + #endif Index: head/sys/compat/cloudabi/cloudabi_vdso.c =================================================================== --- head/sys/compat/cloudabi/cloudabi_vdso.c +++ head/sys/compat/cloudabi/cloudabi_vdso.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2016 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +void +cloudabi_vdso_init(struct sysentvec *sv, char *begin, char *end) +{ + vm_page_t m; + vm_object_t obj; + vm_offset_t addr; + size_t i, pages, pages_length, vdso_length; + + /* Determine the number of pages needed to store the vDSO. */ + vdso_length = end - begin; + pages = howmany(vdso_length, PAGE_SIZE); + pages_length = pages * PAGE_SIZE; + + /* Allocate a VM object and fill it with the vDSO. */ + obj = vm_pager_allocate(OBJT_PHYS, 0, pages_length, + VM_PROT_DEFAULT, 0, NULL); + addr = kva_alloc(PAGE_SIZE); + for (i = 0; i < pages; ++i) { + VM_OBJECT_WLOCK(obj); + m = vm_page_grab(obj, i, VM_ALLOC_NOBUSY | VM_ALLOC_ZERO); + m->valid = VM_PAGE_BITS_ALL; + VM_OBJECT_WUNLOCK(obj); + + pmap_qenter(addr, &m, 1); + memcpy((void *)addr, begin + i * PAGE_SIZE, + MIN(vdso_length - i * PAGE_SIZE, PAGE_SIZE)); + pmap_qremove(addr, 1); + } + kva_free(addr, PAGE_SIZE); + + /* + * Place the vDSO at the top of the address space. The user + * stack can start right below it. + */ + sv->sv_shared_page_base = sv->sv_maxuser - pages_length; + sv->sv_shared_page_len = pages_length; + sv->sv_shared_page_obj = obj; + sv->sv_usrstack = sv->sv_shared_page_base; +} + +void +cloudabi_vdso_destroy(struct sysentvec *sv) +{ + + vm_object_deallocate(sv->sv_shared_page_obj); +} Index: head/sys/compat/cloudabi64/cloudabi64_module.c =================================================================== --- head/sys/compat/cloudabi64/cloudabi64_module.c +++ head/sys/compat/cloudabi64/cloudabi64_module.c @@ -38,8 +38,13 @@ #include +#include + #include +extern char _binary_cloudabi64_vdso_o_start[]; +extern char _binary_cloudabi64_vdso_o_end[]; + register_t * cloudabi64_copyout_strings(struct image_params *imgp) { @@ -107,6 +112,8 @@ PTR(CLOUDABI_AT_PHDR, args->phdr), VAL(CLOUDABI_AT_PHNUM, args->phnum), VAL(CLOUDABI_AT_TID, td->td_tid), + PTR(CLOUDABI_AT_SYSINFO_EHDR, + imgp->proc->p_sysent->sv_shared_page_base), #undef VAL #undef PTR { .a_type = CLOUDABI_AT_NULL }, @@ -127,6 +134,9 @@ switch (type) { case MOD_LOAD: + cloudabi_vdso_init(cloudabi64_brand.sysvec, + _binary_cloudabi64_vdso_o_start, + _binary_cloudabi64_vdso_o_end); if (elf64_insert_brand_entry(&cloudabi64_brand) < 0) { printf("Failed to add CloudABI ELF brand handler\n"); return (EINVAL); @@ -139,6 +149,7 @@ printf("Failed to remove CloudABI ELF brand handler\n"); return (EINVAL); } + cloudabi_vdso_destroy(cloudabi64_brand.sysvec); return (0); default: return (EOPNOTSUPP); Index: head/sys/compat/cloudabi64/cloudabi64_vdso.lds.s =================================================================== --- head/sys/compat/cloudabi64/cloudabi64_vdso.lds.s +++ head/sys/compat/cloudabi64/cloudabi64_vdso.lds.s @@ -0,0 +1,51 @@ +/* + * Linker script for 64-bit vDSO for CloudABI. + * Based on sys/amd64/linux/linux_vdso.lds.s + * + * $FreeBSD$ + */ + +SECTIONS +{ + . = . + 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 + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + + .dynamic : { *(.dynamic) } :text :dynamic + + .rodata : { *(.rodata*) } :text + .data : { + *(.data*) + *(.sdata*) + *(.got.plt) *(.got) + *(.gnu.linkonce.d.*) + *(.bss*) + *(.dynbss*) + *(.gnu.linkonce.b.*) + } + + .altinstructions : { *(.altinstructions) } + .altinstr_replacement : { *(.altinstr_replacement) } + + . = ALIGN(0x100); + .text : { *(.test .text*) } :text =0x90909090 +} + +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; +} Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -284,6 +284,7 @@ compat/cloudabi/cloudabi_random.c optional compat_cloudabi64 compat/cloudabi/cloudabi_sock.c optional compat_cloudabi64 compat/cloudabi/cloudabi_thread.c optional compat_cloudabi64 +compat/cloudabi/cloudabi_vdso.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_fd.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_module.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_poll.c optional compat_cloudabi64 Index: head/sys/conf/files.amd64 =================================================================== --- head/sys/conf/files.amd64 +++ head/sys/conf/files.amd64 @@ -8,6 +8,18 @@ # dependency lines other than the first are silently ignored. # # +cloudabi64_vdso.o optional compat_cloudabi64 \ + dependency "$S/contrib/cloudabi/cloudabi_vdso_x86_64.c" \ + compile-with "${CC} -shared -nostdinc -nostdlib -Wl,-T$S/compat/cloudabi64/cloudabi64_vdso.lds.s -D_KERNEL -I. -I$S -I$S/contrib/cloudabi -O2 -fomit-frame-pointer $S/contrib/cloudabi/cloudabi_vdso_x86_64.c -o ${.TARGET}" \ + no-obj no-implicit-rule \ + clean "cloudabi64_vdso.o" +# +cloudabi64_vdso_blob.o optional compat_cloudabi64 \ + dependency "cloudabi64_vdso.o" \ + compile-with "${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd --binary-architecture i386 cloudabi64_vdso.o ${.TARGET}" \ + no-implicit-rule \ + clean "cloudabi64_vdso_blob.o" +# linux32_genassym.o optional compat_linux32 \ dependency "$S/amd64/linux32/linux32_genassym.c" \ compile-with "${CC} ${CFLAGS:N-fno-common} -c ${.IMPSRC}" \ Index: head/sys/conf/files.arm64 =================================================================== --- head/sys/conf/files.arm64 +++ head/sys/conf/files.arm64 @@ -1,4 +1,16 @@ # $FreeBSD$ +cloudabi64_vdso.o optional compat_cloudabi64 \ + dependency "$S/contrib/cloudabi/cloudabi_vdso_aarch64.c" \ + compile-with "${CC} -shared -nostdinc -nostdlib -Wl,-T$S/compat/cloudabi64/cloudabi64_vdso.lds.s -D_KERNEL -I. -I$S -I$S/contrib/cloudabi -O2 -fomit-frame-pointer $S/contrib/cloudabi/cloudabi_vdso_aarch64.c -o ${.TARGET}" \ + no-obj no-implicit-rule \ + clean "cloudabi64_vdso.o" +# +cloudabi64_vdso_blob.o optional compat_cloudabi64 \ + dependency "cloudabi64_vdso.o" \ + compile-with "${OBJCOPY} --input-target binary --output-target elf64-littleaarch64 --binary-architecture aarch64 cloudabi64_vdso.o ${.TARGET}" \ + no-implicit-rule \ + clean "cloudabi64_vdso_blob.o" +# arm/arm/generic_timer.c standard arm/arm/gic.c standard arm/arm/gic_fdt.c optional fdt Index: head/sys/modules/cloudabi/Makefile =================================================================== --- head/sys/modules/cloudabi/Makefile +++ head/sys/modules/cloudabi/Makefile @@ -5,6 +5,6 @@ KMOD= cloudabi SRCS= cloudabi_clock.c cloudabi_errno.c cloudabi_fd.c cloudabi_file.c \ cloudabi_futex.c cloudabi_mem.c cloudabi_proc.c cloudabi_random.c \ - cloudabi_sock.c cloudabi_thread.c vnode_if.h + cloudabi_sock.c cloudabi_thread.c cloudabi_vdso.c vnode_if.h .include Index: head/sys/modules/cloudabi64/Makefile =================================================================== --- head/sys/modules/cloudabi64/Makefile +++ head/sys/modules/cloudabi64/Makefile @@ -1,11 +1,39 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../compat/cloudabi64 -.PATH: ${.CURDIR}/../../${MACHINE}/cloudabi64 +SYSDIR?=${.CURDIR}/../.. + +.PATH: ${SYSDIR}/compat/cloudabi64 +.PATH: ${SYSDIR}/${MACHINE}/cloudabi64 KMOD= cloudabi64 SRCS= cloudabi64_fd.c cloudabi64_module.c cloudabi64_poll.c \ cloudabi64_sock.c cloudabi64_syscalls.c cloudabi64_sysent.c \ cloudabi64_sysvec.c cloudabi64_thread.c +OBJS= cloudabi64_vdso_blob.o +CLEANFILES=cloudabi64_vdso.o + +.if ${MACHINE_CPUARCH} == "aarch64" +VDSO_SRCS=${SYSDIR}/contrib/cloudabi/cloudabi_vdso_aarch64.c +OUTPUT_TARGET=elf64-littleaarch64 +BINARY_ARCHITECTURE=aarch64 +.elif ${MACHINE_CPUARCH} == "amd64" +VDSO_SRCS=${SYSDIR}/contrib/cloudabi/cloudabi_vdso_x86_64.c +OUTPUT_TARGET=elf64-x86-64-freebsd +BINARY_ARCHITECTURE=i386 +.endif + +cloudabi64_vdso.o: ${VDSO_SRCS} + ${CC} -shared -nostdinc -nostdlib \ + -Wl,-T${SYSDIR}/compat/cloudabi64/cloudabi64_vdso.lds.s \ + -D_KERNEL -I. -I${SYSDIR} -I${SYSDIR}/contrib/cloudabi \ + -O2 -fomit-frame-pointer \ + ${VDSO_SRCS} -o ${.TARGET} + +cloudabi64_vdso_blob.o: cloudabi64_vdso.o + ${OBJCOPY} --input-target binary \ + --output-target ${OUTPUT_TARGET} \ + --binary-architecture ${BINARY_ARCHITECTURE} \ + cloudabi64_vdso.o ${.TARGET} + .include