diff options
author | Peter Maydell | 2019-09-12 17:17:26 +0200 |
---|---|---|
committer | Peter Maydell | 2019-09-12 17:17:26 +0200 |
commit | a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b (patch) | |
tree | f31eb44f95cfcee9525b4ba0a9fd5656c3ed6041 | |
parent | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-next-100919-2... (diff) | |
parent | linux-user: Add support for FDRESET, FDRAWCMD, FDTWADDLE, and FDEJECT ioctls (diff) | |
download | qemu-a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b.tar.gz qemu-a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b.tar.xz qemu-a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b.zip |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.2-pull-request' into staging
Add several floppy drive ioctl,
xtensa call0 ABI support, arm MAX_RESERVED_VA for M-profile,
aarch64 AT_HWCAP2, qOffsets' query for ELF, memfd_create,
and some code cleanup
# gpg: Signature made Wed 11 Sep 2019 07:48:45 BST
# gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg: issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C
* remotes/vivier2/tags/linux-user-for-4.2-pull-request:
linux-user: Add support for FDRESET, FDRAWCMD, FDTWADDLE, and FDEJECT ioctls
linux-user: Add support for FDMSGON and FDMSGOFF ioctls
linux-user: Add support for FDFLUSH ioctl
linux-user: Add support for FIOGETOWN and FIOSETOWN ioctls
linux-user: Add support for RNDRESEEDCRNG ioctl
linux-user: drop redundant handling of environment variables
target/xtensa: linux-user: add call0 ABI support
linux-user: Support gdb 'qOffsets' query for ELF
linux-user/arm: Adjust MAX_RESERVED_VA for M-profile
linux-user: Pass CPUState to MAX_RESERVED_VA
linux-user: add memfd_create
linux-user: fail and report on bad dfilter specs
linux-user: erroneous fd_trans_unregister call
linux-user: Add AT_HWCAP2 for aarch64-linux-user
linux-user: remove useless variable
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | include/qemu/memfd.h | 4 | ||||
-rw-r--r-- | linux-user/arm/target_cpu.h | 24 | ||||
-rw-r--r-- | linux-user/elfload.c | 33 | ||||
-rw-r--r-- | linux-user/ioctls.h | 13 | ||||
-rw-r--r-- | linux-user/main.c | 69 | ||||
-rw-r--r-- | linux-user/syscall.c | 14 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 15 | ||||
-rw-r--r-- | linux-user/xtensa/signal.c | 25 | ||||
-rw-r--r-- | target/xtensa/cpu.c | 24 | ||||
-rw-r--r-- | target/xtensa/cpu.h | 3 | ||||
-rw-r--r-- | util/memfd.c | 2 |
11 files changed, 175 insertions, 51 deletions
diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index d551c28b68..975b6bdb77 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -32,6 +32,10 @@ #define MFD_HUGE_SHIFT 26 #endif +#if defined CONFIG_LINUX && !defined CONFIG_MEMFD +int memfd_create(const char *name, unsigned int flags); +#endif + int qemu_memfd_create(const char *name, size_t size, bool hugetlb, uint64_t hugetlbsize, unsigned int seals, Error **errp); bool qemu_memfd_alloc_check(void); diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h index 8a3764919a..3f79356a07 100644 --- a/linux-user/arm/target_cpu.h +++ b/linux-user/arm/target_cpu.h @@ -19,9 +19,27 @@ #ifndef ARM_TARGET_CPU_H #define ARM_TARGET_CPU_H -/* We need to be able to map the commpage. - See validate_guest_space in linux-user/elfload.c. */ -#define MAX_RESERVED_VA 0xffff0000ul +static inline unsigned long arm_max_reserved_va(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + + if (arm_feature(&cpu->env, ARM_FEATURE_M)) { + /* + * There are magic return addresses above 0xfe000000, + * and in general a lot of M-profile system stuff in + * the high addresses. Restrict linux-user to the + * cached write-back RAM in the system map. + */ + return 0x80000000ul; + } else { + /* + * We need to be able to map the commpage. + * See validate_guest_space in linux-user/elfload.c. + */ + return 0xffff0000ul; + } +} +#define MAX_RESERVED_VA arm_max_reserved_va static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) { diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 3365e192eb..f6693e5760 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -607,9 +607,23 @@ enum { ARM_HWCAP_A64_SB = 1 << 29, ARM_HWCAP_A64_PACA = 1 << 30, ARM_HWCAP_A64_PACG = 1UL << 31, + + ARM_HWCAP2_A64_DCPODP = 1 << 0, + ARM_HWCAP2_A64_SVE2 = 1 << 1, + ARM_HWCAP2_A64_SVEAES = 1 << 2, + ARM_HWCAP2_A64_SVEPMULL = 1 << 3, + ARM_HWCAP2_A64_SVEBITPERM = 1 << 4, + ARM_HWCAP2_A64_SVESHA3 = 1 << 5, + ARM_HWCAP2_A64_SVESM4 = 1 << 6, + ARM_HWCAP2_A64_FLAGM2 = 1 << 7, + ARM_HWCAP2_A64_FRINT = 1 << 8, }; -#define ELF_HWCAP get_elf_hwcap() +#define ELF_HWCAP get_elf_hwcap() +#define ELF_HWCAP2 get_elf_hwcap2() + +#define GET_FEATURE_ID(feat, hwcap) \ + do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) static uint32_t get_elf_hwcap(void) { @@ -621,8 +635,6 @@ static uint32_t get_elf_hwcap(void) hwcaps |= ARM_HWCAP_A64_CPUID; /* probe for the extra features */ -#define GET_FEATURE_ID(feat, hwcap) \ - do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES); GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL); @@ -645,11 +657,22 @@ static uint32_t get_elf_hwcap(void) GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB); GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM); -#undef GET_FEATURE_ID + return hwcaps; +} + +static uint32_t get_elf_hwcap2(void) +{ + ARMCPU *cpu = ARM_CPU(thread_cpu); + uint32_t hwcaps = 0; + + GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2); + GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT); return hwcaps; } +#undef GET_FEATURE_ID + #endif /* not TARGET_AARCH64 */ #endif /* TARGET_ARM */ @@ -2380,6 +2403,8 @@ static void load_elf_image(const char *image_name, int image_fd, } info->load_bias = load_bias; + info->code_offset = load_bias; + info->data_offset = load_bias; info->load_addr = load_addr; info->entry = ehdr->e_entry + load_bias; info->start_code = -1; diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 3281c97ca2..c6b9d6ad66 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -112,6 +112,14 @@ IOCTL(BLKZEROOUT, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2))) #endif + IOCTL(FDMSGON, 0, TYPE_NULL) + IOCTL(FDMSGOFF, 0, TYPE_NULL) + IOCTL(FDFLUSH, 0, TYPE_NULL) + IOCTL(FDRESET, 0, TYPE_NULL) + IOCTL(FDRAWCMD, 0, TYPE_NULL) + IOCTL(FDTWADDLE, 0, TYPE_NULL) + IOCTL(FDEJECT, 0, TYPE_NULL) + #ifdef FIBMAP IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG)) #endif @@ -177,6 +185,8 @@ #endif #endif /* CONFIG_USBFS */ + IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT)) + IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT)) IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) @@ -246,6 +256,9 @@ IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT)) IOCTL(RNDZAPENTCNT, 0, TYPE_NULL) IOCTL(RNDCLEARPOOL, 0, TYPE_NULL) +#ifdef RNDRESEEDCRNG + IOCTL(RNDRESEEDCRNG, 0, TYPE_NULL) +#endif IOCTL(CDROMPAUSE, 0, TYPE_NULL) IOCTL(CDROMSTART, 0, TYPE_NULL) diff --git a/linux-user/main.c b/linux-user/main.c index 47917bbb20..560d053f72 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -49,7 +49,6 @@ char *exec_path; int singlestep; -static const char *filename; static const char *argv0; static int gdbstub_port; static envlist_t *envlist; @@ -78,12 +77,12 @@ int have_guest_base; (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) /* There are a number of places where we assign reserved_va to a variable of type abi_ulong and expect it to fit. Avoid the last page. */ -# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK) +# define MAX_RESERVED_VA(CPU) (0xfffffffful & TARGET_PAGE_MASK) # else -# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS) +# define MAX_RESERVED_VA(CPU) (1ul << TARGET_VIRT_ADDR_SPACE_BITS) # endif # else -# define MAX_RESERVED_VA 0 +# define MAX_RESERVED_VA(CPU) 0 # endif #endif @@ -236,7 +235,7 @@ static void handle_arg_log(const char *arg) static void handle_arg_dfilter(const char *arg) { - qemu_set_dfilter_ranges(arg, NULL); + qemu_set_dfilter_ranges(arg, &error_fatal); } static void handle_arg_log_filename(const char *arg) @@ -357,8 +356,7 @@ static void handle_arg_reserved_va(const char *arg) unsigned long unshifted = reserved_va; p++; reserved_va <<= shift; - if (reserved_va >> shift != unshifted - || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) { + if (reserved_va >> shift != unshifted) { fprintf(stderr, "Reserved virtual address too big\n"); exit(EXIT_FAILURE); } @@ -393,6 +391,13 @@ static void handle_arg_trace(const char *arg) trace_file = trace_opt_parse(arg); } +#if defined(TARGET_XTENSA) +static void handle_arg_abi_call0(const char *arg) +{ + xtensa_set_abi_call0(); +} +#endif + struct qemu_argument { const char *argv; const char *env; @@ -446,6 +451,10 @@ static const struct qemu_argument arg_table[] = { "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"}, {"version", "QEMU_VERSION", false, handle_arg_version, "", "display version information and exit"}, +#if defined(TARGET_XTENSA) + {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0, + "", "assume CALL0 Xtensa ABI"}, +#endif {NULL, NULL, false, NULL, NULL, NULL} }; @@ -586,7 +595,6 @@ static int parse_args(int argc, char **argv) exit(EXIT_FAILURE); } - filename = argv[optind]; exec_path = argv[optind]; return optind; @@ -607,6 +615,7 @@ int main(int argc, char **argv, char **envp) int i; int ret; int execfd; + unsigned long max_reserved_va; error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); @@ -657,9 +666,9 @@ int main(int argc, char **argv, char **envp) execfd = qemu_getauxval(AT_EXECFD); if (execfd == 0) { - execfd = open(filename, O_RDONLY); + execfd = open(exec_path, O_RDONLY); if (execfd < 0) { - printf("Error while loading %s: %s\n", filename, strerror(errno)); + printf("Error while loading %s: %s\n", exec_path, strerror(errno)); _exit(EXIT_FAILURE); } } @@ -672,31 +681,31 @@ int main(int argc, char **argv, char **envp) /* init tcg before creating CPUs and to get qemu_host_page_size */ tcg_exec_init(0); - /* Reserving *too* much vm space via mmap can run into problems - with rlimits, oom due to page table creation, etc. We will still try it, - if directed by the command-line option, but not by default. */ - if (HOST_LONG_BITS == 64 && - TARGET_VIRT_ADDR_SPACE_BITS <= 32 && - reserved_va == 0) { - /* reserved_va must be aligned with the host page size - * as it is used with mmap() - */ - reserved_va = MAX_RESERVED_VA & qemu_host_page_mask; - } - cpu = cpu_create(cpu_type); env = cpu->env_ptr; cpu_reset(cpu); - thread_cpu = cpu; - if (getenv("QEMU_STRACE")) { - do_strace = 1; + /* + * Reserving too much vm space via mmap can run into problems + * with rlimits, oom due to page table creation, etc. We will + * still try it, if directed by the command-line option, but + * not by default. + */ + max_reserved_va = MAX_RESERVED_VA(cpu); + if (reserved_va != 0) { + if (max_reserved_va && reserved_va > max_reserved_va) { + fprintf(stderr, "Reserved virtual address too big\n"); + exit(EXIT_FAILURE); + } + } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) { + /* + * reserved_va must be aligned with the host page size + * as it is used with mmap() + */ + reserved_va = max_reserved_va & qemu_host_page_mask; } - if (seed_optarg == NULL) { - seed_optarg = getenv("QEMU_RAND_SEED"); - } { Error *err = NULL; if (seed_optarg != NULL) { @@ -784,10 +793,10 @@ int main(int argc, char **argv, char **envp) cpu->opaque = ts; task_settid(ts); - ret = loader_exec(execfd, filename, target_argv, target_environ, regs, + ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs, info, &bprm); if (ret != 0) { - printf("Error while loading %s: %s\n", filename, strerror(-ret)); + printf("Error while loading %s: %s\n", exec_path, strerror(-ret)); _exit(EXIT_FAILURE); } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8b41a03901..e2af3c1494 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" #include "qemu/path.h" +#include "qemu/memfd.h" #include "qemu/queue.h" #include <elf.h> #include <endian.h> @@ -88,6 +89,7 @@ #include <linux/kd.h> #include <linux/mtio.h> #include <linux/fs.h> +#include <linux/fd.h> #if defined(CONFIG_FIEMAP) #include <linux/fiemap.h> #endif @@ -11847,7 +11849,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_getoverrun(htimer)); } - fd_trans_unregister(ret); return ret; } #endif @@ -11939,6 +11940,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, /* PowerPC specific. */ return do_swapcontext(cpu_env, arg1, arg2, arg3); #endif +#ifdef TARGET_NR_memfd_create + case TARGET_NR_memfd_create: + p = lock_user_string(arg1); + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(memfd_create(p, arg2)); + fd_trans_unregister(ret); + unlock_user(p, arg1, 0); + return ret; +#endif default: qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 0662270300..fa69c6ab8d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -758,10 +758,14 @@ struct target_pollfd { #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) || \ defined(TARGET_XTENSA) +#define TARGET_FIOGETOWN TARGET_IOR('f', 123, int) +#define TARGET_FIOSETOWN TARGET_IOW('f', 124, int) #define TARGET_SIOCATMARK TARGET_IOR('s', 7, int) #define TARGET_SIOCSPGRP TARGET_IOW('s', 8, pid_t) #define TARGET_SIOCGPGRP TARGET_IOR('s', 9, pid_t) #else +#define TARGET_FIOGETOWN 0x8903 +#define TARGET_FIOSETOWN 0x8901 #define TARGET_SIOCATMARK 0x8905 #define TARGET_SIOCSPGRP 0x8902 #define TARGET_SIOCGPGRP 0x8904 @@ -850,6 +854,7 @@ struct target_pollfd { #define TARGET_RNDADDTOENTCNT TARGET_IOW('R', 0x01, int) #define TARGET_RNDZAPENTCNT TARGET_IO('R', 0x04) #define TARGET_RNDCLEARPOOL TARGET_IO('R', 0x06) +#define TARGET_RNDRESEEDCRNG TARGET_IO('R', 0x07) /* From <linux/fs.h> */ @@ -883,6 +888,16 @@ struct target_pollfd { #define TARGET_BLKROTATIONAL TARGET_IO(0x12, 126) #define TARGET_BLKZEROOUT TARGET_IO(0x12, 127) +/* From <linux/fd.h> */ + +#define TARGET_FDMSGON TARGET_IO(2, 0x45) +#define TARGET_FDMSGOFF TARGET_IO(2, 0x46) +#define TARGET_FDFLUSH TARGET_IO(2, 0x4b) +#define TARGET_FDRESET TARGET_IO(2, 0x54) +#define TARGET_FDRAWCMD TARGET_IO(2, 0x58) +#define TARGET_FDTWADDLE TARGET_IO(2, 0x59) +#define TARGET_FDEJECT TARGET_IO(2, 0x5a) + #define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */ #define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */ diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 8d54ef3ae3..590f0313ff 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -134,6 +134,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, abi_ulong frame_addr; struct target_rt_sigframe *frame; uint32_t ra; + bool abi_call0; + unsigned base; int i; frame_addr = get_sigframe(ka, env, sizeof(*frame)); @@ -182,20 +184,27 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, __put_user(0x00, &frame->retcode[5]); #endif } - env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT); - if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) { - env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT); - } memset(env->regs, 0, sizeof(env->regs)); env->pc = ka->_sa_handler; env->regs[1] = frame_addr; env->sregs[WINDOW_BASE] = 0; env->sregs[WINDOW_START] = 1; - env->regs[4] = (ra & 0x3fffffff) | 0x40000000; - env->regs[6] = sig; - env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info); - env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc); + abi_call0 = (env->sregs[PS] & PS_WOE) == 0; + env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT); + + if (abi_call0) { + base = 0; + env->regs[base] = ra; + } else { + env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT); + base = 4; + env->regs[base] = (ra & 0x3fffffff) | 0x40000000; + } + env->regs[base + 2] = sig; + env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe, + info); + env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc); unlock_user_struct(frame, frame_addr, 1); return; diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 76db1741a7..c65dcf9dd7 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -53,6 +53,20 @@ static bool xtensa_cpu_has_work(CPUState *cs) #endif } +#ifdef CONFIG_USER_ONLY +static bool abi_call0; + +void xtensa_set_abi_call0(void) +{ + abi_call0 = true; +} + +bool xtensa_abi_call0(void) +{ + return abi_call0; +} +#endif + /* CPUClass::reset() */ static void xtensa_cpu_reset(CPUState *s) { @@ -70,10 +84,12 @@ static void xtensa_cpu_reset(CPUState *s) XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; env->pending_irq_level = 0; #else - env->sregs[PS] = - (xtensa_option_enabled(env->config, - XTENSA_OPTION_WINDOWED_REGISTER) ? PS_WOE : 0) | - PS_UM | (3 << PS_RING_SHIFT); + env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT); + if (xtensa_option_enabled(env->config, + XTENSA_OPTION_WINDOWED_REGISTER) && + !xtensa_abi_call0()) { + env->sregs[PS] |= PS_WOE; + } #endif env->sregs[VECBASE] = env->config->vecbase; env->sregs[IBREAKENABLE] = 0; diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 0459243e6b..b363ffcf10 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -673,6 +673,9 @@ static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env) { return env->system_er; } +#else +void xtensa_set_abi_call0(void); +bool xtensa_abi_call0(void); #endif static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env) diff --git a/util/memfd.c b/util/memfd.c index 00334e5b21..4a3c07e0be 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -35,7 +35,7 @@ #include <sys/syscall.h> #include <asm/unistd.h> -static int memfd_create(const char *name, unsigned int flags) +int memfd_create(const char *name, unsigned int flags) { #ifdef __NR_memfd_create return syscall(__NR_memfd_create, name, flags); |