From 6765e988e12825e9464a10b6451aeb25b29bfbc3 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:57 +0300 Subject: bsd-user: Introduce bsd-mem.h to the source tree Preserve the copyright notice and help with the 'Author' info for subsequent changes to the file. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-12-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 bsd-user/bsd-mem.h (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h new file mode 100644 index 0000000000..d865e0807d --- /dev/null +++ b/bsd-user/bsd-mem.h @@ -0,0 +1,64 @@ +/* + * memory management system call shims and definitions + * + * Copyright (c) 2013-15 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef BSD_USER_BSD_MEM_H +#define BSD_USER_BSD_MEM_H + +#include +#include +#include +#include +#include + +#include "qemu-bsd.h" + +extern struct bsd_shm_regions bsd_shm_regions[]; +extern abi_ulong target_brk; +extern abi_ulong initial_target_brk; + +#endif /* BSD_USER_BSD_MEM_H */ -- cgit 1.4.1 From 87dcb4ad485424dcbfedbc7a298279e8738f1a40 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:58 +0300 Subject: bsd-user: Implement mmap(2) and munmap(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-13-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 20 ++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 9 +++++++++ 2 files changed, 29 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index d865e0807d..76b504f70c 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -61,4 +61,24 @@ extern struct bsd_shm_regions bsd_shm_regions[]; extern abi_ulong target_brk; extern abi_ulong initial_target_brk; +/* mmap(2) */ +static inline abi_long do_bsd_mmap(void *cpu_env, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7, + abi_long arg8) +{ + if (regpairs_aligned(cpu_env) != 0) { + arg6 = arg7; + arg7 = arg8; + } + return get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, target_arg64(arg6, arg7))); +} + +/* munmap(2) */ +static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2) +{ + return get_errno(target_munmap(arg1, arg2)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7887ad4c0c..b03837d032 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -798,6 +798,15 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, /* * Memory management system calls. */ + case TARGET_FREEBSD_NR_mmap: /* mmap(2) */ + ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8); + break; + + case TARGET_FREEBSD_NR_munmap: /* munmap(2) */ + ret = do_bsd_munmap(arg1, arg2); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From ecbe22494d970b7811a1764d2f98e083b02f73d0 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:59 +0300 Subject: bsd-user: Implement mprotect(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-14-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 7 +++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 76b504f70c..0f9e4a1d4b 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -81,4 +81,11 @@ static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2) return get_errno(target_munmap(arg1, arg2)); } +/* mprotect(2) */ +static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + return get_errno(target_mprotect(arg1, arg2, arg3)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index b03837d032..2d8f1a953b 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -807,6 +807,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_munmap(arg1, arg2); break; + case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */ + ret = do_bsd_mprotect(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From f28a1e4bab4cfdd067bde3d958529575aa8e8f6b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:00 +0300 Subject: bsd-user: Implement msync(2) Co-authored-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-15-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 11 +++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 15 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 0f9e4a1d4b..5e885823a7 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -88,4 +88,15 @@ static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2, return get_errno(target_mprotect(arg1, arg2, arg3)); } +/* msync(2) */ +static inline abi_long do_bsd_msync(abi_long addr, abi_long len, abi_long flags) +{ + if (!guest_range_valid_untagged(addr, len)) { + /* It seems odd, but POSIX wants this to be ENOMEM */ + return -TARGET_ENOMEM; + } + + return get_errno(msync(g2h_untagged(addr), len, flags)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 2d8f1a953b..2525e0bc31 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -811,6 +811,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_mprotect(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_msync: /* msync(2) */ + ret = do_bsd_msync(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From 0a49ef02a643864a9c6a36ebaf452e0d30c96b0b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:01 +0300 Subject: bsd-user: Implement mlock(2), munlock(2), mlockall(2), munlockall(2), minherit(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-16-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 37 +++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 20 ++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 5e885823a7..16c22593bf 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -99,4 +99,41 @@ static inline abi_long do_bsd_msync(abi_long addr, abi_long len, abi_long flags) return get_errno(msync(g2h_untagged(addr), len, flags)); } +/* mlock(2) */ +static inline abi_long do_bsd_mlock(abi_long arg1, abi_long arg2) +{ + if (!guest_range_valid_untagged(arg1, arg2)) { + return -TARGET_EINVAL; + } + return get_errno(mlock(g2h_untagged(arg1), arg2)); +} + +/* munlock(2) */ +static inline abi_long do_bsd_munlock(abi_long arg1, abi_long arg2) +{ + if (!guest_range_valid_untagged(arg1, arg2)) { + return -TARGET_EINVAL; + } + return get_errno(munlock(g2h_untagged(arg1), arg2)); +} + +/* mlockall(2) */ +static inline abi_long do_bsd_mlockall(abi_long arg1) +{ + return get_errno(mlockall(arg1)); +} + +/* munlockall(2) */ +static inline abi_long do_bsd_munlockall(void) +{ + return get_errno(munlockall()); +} + +/* minherit(2) */ +static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, + abi_long inherit) +{ + return get_errno(minherit(g2h_untagged(addr), len, inherit)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 2525e0bc31..7a7ae26793 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -815,6 +815,26 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_msync(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_mlock: /* mlock(2) */ + ret = do_bsd_mlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_munlock: /* munlock(2) */ + ret = do_bsd_munlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */ + ret = do_bsd_mlockall(arg1); + break; + + case TARGET_FREEBSD_NR_munlockall: /* munlockall(2) */ + ret = do_bsd_munlockall(); + break; + + case TARGET_FREEBSD_NR_minherit: /* minherit(2) */ + ret = do_bsd_minherit(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From 0c1ced42c84bdd8beeef6c40dff8d143cf409f15 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:27:02 +0300 Subject: bsd-user: Implment madvise(2) to match the linux-user implementation. Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-17-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 53 +++++++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ bsd-user/syscall_defs.h | 2 ++ 3 files changed, 59 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 16c22593bf..b00ab3aed8 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -129,6 +129,59 @@ static inline abi_long do_bsd_munlockall(void) return get_errno(munlockall()); } +/* madvise(2) */ +static inline abi_long do_bsd_madvise(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_ulong len; + int ret = 0; + abi_long start = arg1; + abi_long len_in = arg2; + abi_long advice = arg3; + + if (start & ~TARGET_PAGE_MASK) { + return -TARGET_EINVAL; + } + if (len_in == 0) { + return 0; + } + len = TARGET_PAGE_ALIGN(len_in); + if (len == 0 || !guest_range_valid_untagged(start, len)) { + return -TARGET_EINVAL; + } + + /* + * Most advice values are hints, so ignoring and returning success is ok. + * + * However, some advice values such as MADV_DONTNEED, are not hints and + * need to be emulated. + * + * A straight passthrough for those may not be safe because qemu sometimes + * turns private file-backed mappings into anonymous mappings. + * If all guest pages have PAGE_PASSTHROUGH set, mappings have the + * same semantics for the host as for the guest. + * + * MADV_DONTNEED is passed through, if possible. + * If passthrough isn't possible, we nevertheless (wrongly!) return + * success, which is broken but some userspace programs fail to work + * otherwise. Completely implementing such emulation is quite complicated + * though. + */ + mmap_lock(); + switch (advice) { + case MADV_DONTNEED: + if (page_check_range(start, len, PAGE_PASSTHROUGH)) { + ret = get_errno(madvise(g2h_untagged(start), len, advice)); + if (ret == 0) { + page_reset_target_data(start, start + len - 1); + } + } + } + mmap_unlock(); + + return ret; +} + /* minherit(2) */ static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, abi_long inherit) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7a7ae26793..b8c44cea0f 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -831,6 +831,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_munlockall(); break; + case TARGET_FREEBSD_NR_madvise: /* madvise(2) */ + ret = do_bsd_madvise(arg1, arg2, arg3); + break; + case TARGET_FREEBSD_NR_minherit: /* minherit(2) */ ret = do_bsd_minherit(arg1, arg2, arg3); break; diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index ff69281433..52f84d5dd1 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -95,6 +95,8 @@ struct bsd_shm_regions { /* * sys/mman.h */ +#define TARGET_MADV_DONTNEED 4 /* dont need these pages */ + #define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented */ /* MAP_INHERIT */ #define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented */ -- cgit 1.4.1 From 83b045ad4e0106836963185ed696991883104359 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:03 +0300 Subject: bsd-user: Implement mincore(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-18-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 23 +++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 27 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b00ab3aed8..0c8d96d9a4 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -189,4 +189,27 @@ static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, return get_errno(minherit(g2h_untagged(addr), len, inherit)); } +/* mincore(2) */ +static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len, + abi_ulong target_vec) +{ + abi_long ret; + void *p; + abi_ulong vec_len = DIV_ROUND_UP(len, TARGET_PAGE_SIZE); + + if (!guest_range_valid_untagged(target_addr, len) + || !page_check_range(target_addr, len, PAGE_VALID)) { + return -TARGET_EFAULT; + } + + p = lock_user(VERIFY_WRITE, target_vec, vec_len, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(mincore(g2h_untagged(target_addr), len, p)); + unlock_user(p, target_vec, vec_len); + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index b8c44cea0f..f054241cd6 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -839,6 +839,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_minherit(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_mincore: /* mincore(2) */ + ret = do_bsd_mincore(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From a99d74034754b1d8735d814cf17db6bf0eb4bfd1 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:04 +0300 Subject: bsd-user: Implement do_obreak function Match linux-user, by manually applying the following commits, in order: d28b3c90cfad1a7e211ae2bce36ecb9071086129 linux-user: Make sure initial brk(0) is page-aligned 15ad98536ad9410fb32ddf1ff09389b677643faa linux-user: Fix qemu brk() to not zero bytes on current page dfe49864afb06e7e452a4366051697bc4fcfc1a5 linux-user: Prohibit brk() to to shrink below initial heap address eac78a4b0b7da4de2c0a297f4d528ca9cc6256a3 linux-user: Fix signed math overflow in brk() syscall c6cc059eca18d9f6e4e26bb8b6d1135ddb35d81a linux-user: Do not call get_errno() in do_brk() e69e032d1a8ee8d754ca119009a3c2c997f8bb30 linux-user: Use MAP_FIXED_NOREPLACE for do_brk() cb9d5d1fda0bc2312fc0c779b4ea1d7bf826f31f linux-user: Do nothing if too small brk is specified 2aea137a425a87b930a33590177b04368fd7cc12 linux-user: Do not align brk with host page size Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-19-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 45 +++++++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 7 +++++++ 2 files changed, 52 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 0c8d96d9a4..b296c5c6f0 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -212,4 +212,49 @@ static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len, return ret; } +/* do_brk() must return target values and target errnos. */ +static inline abi_long do_obreak(abi_ulong brk_val) +{ + abi_long mapped_addr; + abi_ulong new_brk; + abi_ulong old_brk; + + /* brk pointers are always untagged */ + + /* do not allow to shrink below initial brk value */ + if (brk_val < initial_target_brk) { + return target_brk; + } + + new_brk = TARGET_PAGE_ALIGN(brk_val); + old_brk = TARGET_PAGE_ALIGN(target_brk); + + /* new and old target_brk might be on the same page */ + if (new_brk == old_brk) { + target_brk = brk_val; + return target_brk; + } + + /* Release heap if necesary */ + if (new_brk < old_brk) { + target_munmap(new_brk, old_brk - new_brk); + + target_brk = brk_val; + return target_brk; + } + + mapped_addr = target_mmap(old_brk, new_brk - old_brk, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_EXCL | MAP_ANON | MAP_PRIVATE, + -1, 0); + + if (mapped_addr == old_brk) { + target_brk = brk_val; + return target_brk; + } + + /* For everything else, return the previous break. */ + return target_brk; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index f054241cd6..92793ab1fb 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -855,6 +855,13 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; #endif + /* + * Misc + */ + case TARGET_FREEBSD_NR_break: + ret = do_obreak(arg1); + break; + /* * sys{ctl, arch, call} */ -- cgit 1.4.1 From 4f0be683e399e7685608b83240da099ea45d84e6 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:05 +0300 Subject: bsd-user: Implement shm_open(2) Co-authored-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-20-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 25 +++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 29 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b296c5c6f0..f8dc943c23 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -257,4 +257,29 @@ static inline abi_long do_obreak(abi_ulong brk_val) return target_brk; } +/* shm_open(2) */ +static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2, + abi_long arg3) +{ + int ret; + void *p; + + if (arg1 == (uintptr_t)SHM_ANON) { + p = SHM_ANON; + } else { + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + } + ret = get_errno(shm_open(p, target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + + if (p != SHM_ANON) { + unlock_user(p, arg1, 0); + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 92793ab1fb..0d4c3118f0 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -843,6 +843,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_mincore(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_freebsd12_shm_open: /* shm_open(2) */ + ret = do_bsd_shm_open(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); -- cgit 1.4.1 From 9d14db15b121c81a008098c46053d98cd6a0da6b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:06 +0300 Subject: bsd-user: Implement shm_unlink(2) and shmget(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-21-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 23 +++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 31 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index f8dc943c23..c362cc07a3 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -282,4 +282,27 @@ static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2, return ret; } +/* shm_unlink(2) */ +static inline abi_long do_bsd_shm_unlink(abi_ulong arg1) +{ + int ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(shm_unlink(p)); /* XXX path(p)? */ + unlock_user(p, arg1, 0); + + return ret; +} + +/* shmget(2) */ +static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2, + abi_long arg3) +{ + return get_errno(shmget(arg1, arg2, arg3)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 0d4c3118f0..4f67677eb9 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -859,6 +859,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; #endif + case TARGET_FREEBSD_NR_shm_unlink: /* shm_unlink(2) */ + ret = do_bsd_shm_unlink(arg1); + break; + + case TARGET_FREEBSD_NR_shmget: /* shmget(2) */ + ret = do_bsd_shmget(arg1, arg2, arg3); + break; + /* * Misc */ -- cgit 1.4.1 From f9bbe3cf28ae7157724a364da6f4a7231f2fdfb3 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:07 +0300 Subject: bsd-user: Implement shmctl(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-22-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 39 +++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 43 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index c362cc07a3..b82f3eaa25 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -305,4 +305,43 @@ static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2, return get_errno(shmget(arg1, arg2, arg3)); } +/* shmctl(2) */ +static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd, + abi_ulong buff) +{ + struct shmid_ds dsarg; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + if (target_to_host_shmid_ds(&dsarg, buff)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (host_to_target_shmid_ds(buff, &dsarg)) { + return -TARGET_EFAULT; + } + break; + + case IPC_SET: + if (target_to_host_shmid_ds(&dsarg, buff)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + break; + + case IPC_RMID: + ret = get_errno(shmctl(shmid, cmd, NULL)); + break; + + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 4f67677eb9..0512d41db7 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -867,6 +867,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmget(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */ + ret = do_bsd_shmctl(arg1, arg2, arg3); + break; + /* * Misc */ -- cgit 1.4.1 From 4e00b7d85d0dcc2064c68168163d3a411e32798f Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:08 +0300 Subject: bsd-user: Implement shmat(2) and shmdt(2) Use `WITH_MMAP_LOCK_GUARD` instead of mmap_lock() and mmap_unlock(), to match linux-user implementation, according to the following commits: 69fa2708a216df715ba5102a0f98468b540a464e linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt} ceda5688b650646248f269a992c06b11148c5759 linux-user: Fix shmdt Signed-off-by: Stacey Son Signed-off-by: Karim Taha Message-Id: <20230925182709.4834-23-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 87 +++++++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++ bsd-user/mmap.c | 2 +- bsd-user/qemu.h | 1 + 4 files changed, 97 insertions(+), 1 deletion(-) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b82f3eaa25..c512a4e375 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -344,4 +344,91 @@ static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd, return ret; } +/* shmat(2) */ +static inline abi_long do_bsd_shmat(int shmid, abi_ulong shmaddr, int shmflg) +{ + abi_ulong raddr; + abi_long ret; + struct shmid_ds shm_info; + + /* Find out the length of the shared memory segment. */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* Can't get the length */ + return ret; + } + + if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) { + return -TARGET_EINVAL; + } + + WITH_MMAP_LOCK_GUARD() { + void *host_raddr; + + if (shmaddr) { + host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg); + } else { + abi_ulong mmap_start; + + mmap_start = mmap_find_vma(0, shm_info.shm_segsz); + + if (mmap_start == -1) { + return -TARGET_ENOMEM; + } + host_raddr = shmat(shmid, g2h_untagged(mmap_start), + shmflg | SHM_REMAP); + } + + if (host_raddr == (void *)-1) { + return get_errno(-1); + } + raddr = h2g(host_raddr); + + page_set_flags(raddr, raddr + shm_info.shm_segsz - 1, + PAGE_VALID | PAGE_RESET | PAGE_READ | + (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE)); + + for (int i = 0; i < N_BSD_SHM_REGIONS; i++) { + if (bsd_shm_regions[i].start == 0) { + bsd_shm_regions[i].start = raddr; + bsd_shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + } + + return raddr; +} + +/* shmdt(2) */ +static inline abi_long do_bsd_shmdt(abi_ulong shmaddr) +{ + abi_long ret; + + WITH_MMAP_LOCK_GUARD() { + int i; + + for (i = 0; i < N_BSD_SHM_REGIONS; ++i) { + if (bsd_shm_regions[i].start == shmaddr) { + break; + } + } + + if (i == N_BSD_SHM_REGIONS) { + return -TARGET_EINVAL; + } + + ret = get_errno(shmdt(g2h_untagged(shmaddr))); + if (ret == 0) { + abi_ulong size = bsd_shm_regions[i].size; + + bsd_shm_regions[i].start = 0; + page_set_flags(shmaddr, shmaddr + size - 1, 0); + mmap_reserve(shmaddr, size); + } + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 0512d41db7..39e66312da 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -871,6 +871,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmctl(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_shmat: /* shmat(2) */ + ret = do_bsd_shmat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shmdt: /* shmdt(2) */ + ret = do_bsd_shmdt(arg1); + break; + /* * Misc */ diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c index 8e148a2ea3..3ef11b2807 100644 --- a/bsd-user/mmap.c +++ b/bsd-user/mmap.c @@ -636,7 +636,7 @@ fail: return -1; } -static void mmap_reserve(abi_ulong start, abi_ulong size) +void mmap_reserve(abi_ulong start, abi_ulong size) { abi_ulong real_start; abi_ulong real_end; diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 6047805ae3..dc842fffa7 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -233,6 +233,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, int target_msync(abi_ulong start, abi_ulong len, int flags); extern abi_ulong mmap_next_start; abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size); +void mmap_reserve(abi_ulong start, abi_ulong size); void TSA_NO_TSA mmap_fork_start(void); void TSA_NO_TSA mmap_fork_end(int child); -- cgit 1.4.1 From dfa1d915756b2d9d22946cbd7d2587f30cdcb7a3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 25 Sep 2023 21:27:09 +0300 Subject: bsd-user: Add stubs for vadvise(), sbrk() and sstk() The above system calls are not supported by qemu. Signed-off-by: Warner Losh Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-24-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 18 ++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 12 ++++++++++++ 2 files changed, 30 insertions(+) (limited to 'bsd-user/bsd-mem.h') diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index c512a4e375..c3e72e3b86 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -431,4 +431,22 @@ static inline abi_long do_bsd_shmdt(abi_ulong shmaddr) return ret; } +static inline abi_long do_bsd_vadvise(void) +{ + /* See sys_ovadvise() in vm_unix.c */ + return -TARGET_EINVAL; +} + +static inline abi_long do_bsd_sbrk(void) +{ + /* see sys_sbrk() in vm_mmap.c */ + return -TARGET_EOPNOTSUPP; +} + +static inline abi_long do_bsd_sstk(void) +{ + /* see sys_sstk() in vm_mmap.c */ + return -TARGET_EOPNOTSUPP; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 39e66312da..ca2f6fdb66 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -879,6 +879,18 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmdt(arg1); break; + case TARGET_FREEBSD_NR_freebsd11_vadvise: + ret = do_bsd_vadvise(); + break; + + case TARGET_FREEBSD_NR_sbrk: + ret = do_bsd_sbrk(); + break; + + case TARGET_FREEBSD_NR_sstk: + ret = do_bsd_sstk(); + break; + /* * Misc */ -- cgit 1.4.1