aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS12
-rw-r--r--bsd-user/bsd-mem.c104
-rw-r--r--bsd-user/bsd-mem.h452
-rw-r--r--bsd-user/bsd-proc.c145
-rw-r--r--bsd-user/bsd-proc.h379
-rw-r--r--bsd-user/freebsd/meson.build1
-rw-r--r--bsd-user/freebsd/os-misc.h98
-rw-r--r--bsd-user/freebsd/os-proc.c480
-rw-r--r--bsd-user/freebsd/os-proc.h293
-rw-r--r--bsd-user/freebsd/os-syscall.c313
-rw-r--r--bsd-user/main.c2
-rw-r--r--bsd-user/meson.build7
-rw-r--r--bsd-user/mmap.c2
-rw-r--r--bsd-user/qemu-bsd.h58
-rw-r--r--bsd-user/qemu.h8
-rw-r--r--bsd-user/signal-common.h1
-rw-r--r--bsd-user/signal.c6
-rw-r--r--bsd-user/syscall_defs.h89
-rw-r--r--chardev/char-pty.c22
-rw-r--r--hw/core/machine.c10
-rw-r--r--hw/display/ramfb.c1
-rw-r--r--hw/i386/pc.c39
-rw-r--r--include/migration/vmstate.h4
-rw-r--r--include/qemu/compiler.h6
-rw-r--r--include/qemu/osdep.h4
-rw-r--r--include/ui/console.h1
-rw-r--r--include/ui/input.h2
-rw-r--r--include/ui/qemu-pixman.h4
-rw-r--r--meson.build10
-rw-r--r--migration/file.c103
-rw-r--r--migration/file.h14
-rw-r--r--migration/meson.build1
-rw-r--r--migration/migration.c5
-rw-r--r--migration/rdma.c2
-rw-r--r--migration/savevm.c19
-rw-r--r--migration/trace-events5
-rw-r--r--migration/vmstate.c53
-rw-r--r--qemu-options.hx7
-rwxr-xr-xscripts/analyze-migration.py4
-rw-r--r--tests/migration/i386/a-b-bootblock.S18
-rw-r--r--tests/migration/i386/a-b-bootblock.h16
-rw-r--r--tests/migration/s390x/a-b-bios.c8
-rw-r--r--tests/migration/s390x/a-b-bios.h380
-rw-r--r--ui/cocoa.m2
-rw-r--r--ui/console.c24
-rw-r--r--ui/dbus-console.c6
-rw-r--r--ui/gtk.c20
-rw-r--r--ui/input.c29
-rw-r--r--ui/qemu-pixman.c4
-rw-r--r--ui/sdl2.c26
-rw-r--r--ui/spice-input.c2
-rw-r--r--ui/trace-events1
-rw-r--r--ui/vnc.c2
-rw-r--r--util/coroutine-sigaltstack.c4
-rw-r--r--util/coroutine-ucontext.c4
-rw-r--r--util/oslib-win32.c2
56 files changed, 2963 insertions, 351 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 7819910..1200b69 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3206,7 +3206,8 @@ F: scripts/checkpatch.pl
Migration
M: Juan Quintela <quintela@redhat.com>
-R: Peter Xu <peterx@redhat.com>
+M: Peter Xu <peterx@redhat.com>
+M: Fabiano Rosas <farosas@suse.de>
R: Leonardo Bras <leobras@redhat.com>
S: Maintained
F: hw/core/vmstate-if.c
@@ -3221,6 +3222,15 @@ F: docs/devel/migration.rst
F: qapi/migration.json
F: tests/migration/
F: util/userfaultfd.c
+X: migration/rdma*
+
+RDMA Migration
+M: Juan Quintela <quintela@redhat.com>
+R: Li Zhijian <lizhijian@fujitsu.com>
+R: Peter Xu <peterx@redhat.com>
+R: Leonardo Bras <leobras@redhat.com>
+S: Odd Fixes
+F: migration/rdma*
Migration dirty limit and dirty page rate
M: Hyman Huang <yong.huang@smartx.com>
diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c
new file mode 100644
index 0000000..2ab1334
--- /dev/null
+++ b/bsd-user/bsd-mem.c
@@ -0,0 +1,104 @@
+/*
+ * memory management system conversion routines
+ *
+ * Copyright (c) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "qemu-bsd.h"
+
+struct bsd_shm_regions bsd_shm_regions[N_BSD_SHM_REGIONS];
+
+abi_ulong target_brk;
+abi_ulong initial_target_brk;
+
+void target_set_brk(abi_ulong new_brk)
+{
+ target_brk = TARGET_PAGE_ALIGN(new_brk);
+ initial_target_brk = target_brk;
+}
+
+void target_to_host_ipc_perm__locked(struct ipc_perm *host_ip,
+ struct target_ipc_perm *target_ip)
+{
+ __get_user(host_ip->cuid, &target_ip->cuid);
+ __get_user(host_ip->cgid, &target_ip->cgid);
+ __get_user(host_ip->uid, &target_ip->uid);
+ __get_user(host_ip->gid, &target_ip->gid);
+ __get_user(host_ip->mode, &target_ip->mode);
+ __get_user(host_ip->seq, &target_ip->seq);
+ __get_user(host_ip->key, &target_ip->key);
+}
+
+abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
+ abi_ulong target_addr)
+{
+ struct target_shmid_ds *target_sd;
+
+ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
+ return -TARGET_EFAULT;
+ }
+
+ target_to_host_ipc_perm__locked(&(host_sd->shm_perm),
+ &(target_sd->shm_perm));
+
+ __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
+ __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
+ __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
+ __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
+ __get_user(host_sd->shm_atime, &target_sd->shm_atime);
+ __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
+ __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
+ unlock_user_struct(target_sd, target_addr, 0);
+
+ return 0;
+}
+
+void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip,
+ struct ipc_perm *host_ip)
+{
+ __put_user(host_ip->cuid, &target_ip->cuid);
+ __put_user(host_ip->cgid, &target_ip->cgid);
+ __put_user(host_ip->uid, &target_ip->uid);
+ __put_user(host_ip->gid, &target_ip->gid);
+ __put_user(host_ip->mode, &target_ip->mode);
+ __put_user(host_ip->seq, &target_ip->seq);
+ __put_user(host_ip->key, &target_ip->key);
+}
+
+abi_long host_to_target_shmid_ds(abi_ulong target_addr,
+ struct shmid_ds *host_sd)
+{
+ struct target_shmid_ds *target_sd;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+
+ host_to_target_ipc_perm__locked(&(target_sd->shm_perm),
+ &(host_sd->shm_perm));
+
+ __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
+ __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
+ __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
+ __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
+ __put_user(host_sd->shm_atime, &target_sd->shm_atime);
+ __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
+ __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
+ unlock_user_struct(target_sd, target_addr, 1);
+
+ return 0;
+}
diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h
new file mode 100644
index 0000000..c3e72e3
--- /dev/null
+++ b/bsd-user/bsd-mem.h
@@ -0,0 +1,452 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * 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 <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <fcntl.h>
+
+#include "qemu-bsd.h"
+
+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));
+}
+
+/* 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));
+}
+
+/* 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));
+}
+
+/* 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());
+}
+
+/* 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)
+{
+ 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;
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/* 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));
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+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/bsd-proc.c b/bsd-user/bsd-proc.c
new file mode 100644
index 0000000..ca3c1bf
--- /dev/null
+++ b/bsd-user/bsd-proc.c
@@ -0,0 +1,145 @@
+/*
+ * BSD process related system call helpers
+ *
+ * Copyright (c) 2013-14 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 <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cpuset.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include "qemu.h"
+#include "qemu-bsd.h"
+#include "signal-common.h"
+
+#include "bsd-proc.h"
+
+/*
+ * resource/rusage conversion
+ */
+int target_to_host_resource(int code)
+{
+ return code;
+}
+
+rlim_t target_to_host_rlim(abi_llong target_rlim)
+{
+ return tswap64(target_rlim);
+}
+
+abi_llong host_to_target_rlim(rlim_t rlim)
+{
+ return tswap64(rlim);
+}
+
+void h2g_rusage(const struct rusage *rusage,
+ struct target_freebsd_rusage *target_rusage)
+{
+ __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec);
+ __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec);
+
+ __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec);
+ __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec);
+
+ __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss);
+ __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
+ __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
+ __put_user(rusage->ru_isrss, &target_rusage->ru_isrss);
+ __put_user(rusage->ru_minflt, &target_rusage->ru_minflt);
+ __put_user(rusage->ru_majflt, &target_rusage->ru_majflt);
+ __put_user(rusage->ru_nswap, &target_rusage->ru_nswap);
+ __put_user(rusage->ru_inblock, &target_rusage->ru_inblock);
+ __put_user(rusage->ru_oublock, &target_rusage->ru_oublock);
+ __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd);
+ __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv);
+ __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals);
+ __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw);
+ __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw);
+}
+
+abi_long host_to_target_rusage(abi_ulong target_addr,
+ const struct rusage *rusage)
+{
+ struct target_freebsd_rusage *target_rusage;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ h2g_rusage(rusage, target_rusage);
+ unlock_user_struct(target_rusage, target_addr, 1);
+
+ return 0;
+}
+
+abi_long host_to_target_wrusage(abi_ulong target_addr,
+ const struct __wrusage *wrusage)
+{
+ struct target_freebsd__wrusage *target_wrusage;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_wrusage, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ h2g_rusage(&wrusage->wru_self, &target_wrusage->wru_self);
+ h2g_rusage(&wrusage->wru_children, &target_wrusage->wru_children);
+ unlock_user_struct(target_wrusage, target_addr, 1);
+
+ return 0;
+}
+
+/*
+ * wait status conversion.
+ *
+ * Map host to target signal numbers for the wait family of syscalls.
+ * Assume all other status bits are the same.
+ */
+int host_to_target_waitstatus(int status)
+{
+ if (WIFSIGNALED(status)) {
+ return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
+ }
+ if (WIFSTOPPED(status)) {
+ return (host_to_target_signal(WSTOPSIG(status)) << 8) | (status & 0xff);
+ }
+ return status;
+}
+
+int bsd_get_ncpu(void)
+{
+ int ncpu = -1;
+ cpuset_t mask;
+
+ CPU_ZERO(&mask);
+
+ if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask),
+ &mask) == 0) {
+ ncpu = CPU_COUNT(&mask);
+ }
+
+ if (ncpu == -1) {
+ ncpu = sysconf(_SC_NPROCESSORS_ONLN);
+ }
+
+ if (ncpu == -1) {
+ gemu_log("XXX Missing bsd_get_ncpu() implementation\n");
+ ncpu = 1;
+ }
+
+ return ncpu;
+}
+
diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h
index 0e1d461..8b1c2de 100644
--- a/bsd-user/bsd-proc.h
+++ b/bsd-user/bsd-proc.h
@@ -22,6 +22,13 @@
#include <sys/resource.h>
+#include "qemu-bsd.h"
+#include "gdbstub/syscalls.h"
+#include "qemu/plugin.h"
+
+extern int _getlogin(char*, int);
+int bsd_get_ncpu(void);
+
/* exit(2) */
static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
{
@@ -32,4 +39,376 @@ static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
return 0;
}
+/* getgroups(2) */
+static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2)
+{
+ abi_long ret;
+ uint32_t *target_grouplist;
+ g_autofree gid_t *grouplist;
+ int i;
+
+ grouplist = g_try_new(gid_t, gidsetsize);
+ ret = get_errno(getgroups(gidsetsize, grouplist));
+ if (gidsetsize != 0) {
+ if (!is_error(ret)) {
+ target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
+ if (!target_grouplist) {
+ return -TARGET_EFAULT;
+ }
+ for (i = 0; i < ret; i++) {
+ target_grouplist[i] = tswap32(grouplist[i]);
+ }
+ unlock_user(target_grouplist, arg2, gidsetsize * 2);
+ }
+ }
+ return ret;
+}
+
+/* setgroups(2) */
+static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2)
+{
+ uint32_t *target_grouplist;
+ g_autofree gid_t *grouplist;
+ int i;
+
+ grouplist = g_try_new(gid_t, gidsetsize);
+ target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
+ if (!target_grouplist) {
+ return -TARGET_EFAULT;
+ }
+ for (i = 0; i < gidsetsize; i++) {
+ grouplist[i] = tswap32(target_grouplist[i]);
+ }
+ unlock_user(target_grouplist, arg2, 0);
+ return get_errno(setgroups(gidsetsize, grouplist));
+}
+
+/* umask(2) */
+static inline abi_long do_bsd_umask(abi_long arg1)
+{
+ return get_errno(umask(arg1));
+}
+
+/* setlogin(2) */
+static inline abi_long do_bsd_setlogin(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user_string(arg1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setlogin(p));
+ unlock_user(p, arg1, 0);
+
+ return ret;
+}
+
+/* getlogin(2) */
+static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(_getlogin(p, arg2));
+ unlock_user(p, arg1, arg2);
+
+ return ret;
+}
+
+/* getrusage(2) */
+static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr)
+{
+ abi_long ret;
+ struct rusage rusage;
+
+ ret = get_errno(getrusage(who, &rusage));
+ if (!is_error(ret)) {
+ host_to_target_rusage(target_addr, &rusage);
+ }
+ return ret;
+}
+
+/* getrlimit(2) */
+static inline abi_long do_bsd_getrlimit(abi_long arg1, abi_ulong arg2)
+{
+ abi_long ret;
+ int resource = target_to_host_resource(arg1);
+ struct target_rlimit *target_rlim;
+ struct rlimit rlim;
+
+ switch (resource) {
+ case RLIMIT_STACK:
+ rlim.rlim_cur = target_dflssiz;
+ rlim.rlim_max = target_maxssiz;
+ ret = 0;
+ break;
+
+ case RLIMIT_DATA:
+ rlim.rlim_cur = target_dfldsiz;
+ rlim.rlim_max = target_maxdsiz;
+ ret = 0;
+ break;
+
+ default:
+ ret = get_errno(getrlimit(resource, &rlim));
+ break;
+ }
+ if (!is_error(ret)) {
+ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) {
+ return -TARGET_EFAULT;
+ }
+ target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
+ target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
+ unlock_user_struct(target_rlim, arg2, 1);
+ }
+ return ret;
+}
+
+/* setrlimit(2) */
+static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2)
+{
+ abi_long ret;
+ int resource = target_to_host_resource(arg1);
+ struct target_rlimit *target_rlim;
+ struct rlimit rlim;
+
+ if (RLIMIT_STACK == resource) {
+ /* XXX We should, maybe, allow the stack size to shrink */
+ ret = -TARGET_EPERM;
+ } else {
+ if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) {
+ return -TARGET_EFAULT;
+ }
+ rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
+ rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
+ unlock_user_struct(target_rlim, arg2, 0);
+ ret = get_errno(setrlimit(resource, &rlim));
+ }
+ return ret;
+}
+
+/* getpid(2) */
+static inline abi_long do_bsd_getpid(void)
+{
+ return get_errno(getpid());
+}
+
+/* getppid(2) */
+static inline abi_long do_bsd_getppid(void)
+{
+ return get_errno(getppid());
+}
+
+/* getuid(2) */
+static inline abi_long do_bsd_getuid(void)
+{
+ return get_errno(getuid());
+}
+
+/* geteuid(2) */
+static inline abi_long do_bsd_geteuid(void)
+{
+ return get_errno(geteuid());
+}
+
+/* getgid(2) */
+static inline abi_long do_bsd_getgid(void)
+{
+ return get_errno(getgid());
+}
+
+/* getegid(2) */
+static inline abi_long do_bsd_getegid(void)
+{
+ return get_errno(getegid());
+}
+
+/* setuid(2) */
+static inline abi_long do_bsd_setuid(abi_long arg1)
+{
+ return get_errno(setuid(arg1));
+}
+
+/* seteuid(2) */
+static inline abi_long do_bsd_seteuid(abi_long arg1)
+{
+ return get_errno(seteuid(arg1));
+}
+
+/* setgid(2) */
+static inline abi_long do_bsd_setgid(abi_long arg1)
+{
+ return get_errno(setgid(arg1));
+}
+
+/* setegid(2) */
+static inline abi_long do_bsd_setegid(abi_long arg1)
+{
+ return get_errno(setegid(arg1));
+}
+
+/* getpgid(2) */
+static inline abi_long do_bsd_getpgid(pid_t pid)
+{
+ return get_errno(getpgid(pid));
+}
+
+/* setpgid(2) */
+static inline abi_long do_bsd_setpgid(int pid, int pgrp)
+{
+ return get_errno(setpgid(pid, pgrp));
+}
+
+/* getpgrp(2) */
+static inline abi_long do_bsd_getpgrp(void)
+{
+ return get_errno(getpgrp());
+}
+
+/* setreuid(2) */
+static inline abi_long do_bsd_setreuid(abi_long arg1, abi_long arg2)
+{
+ return get_errno(setreuid(arg1, arg2));
+}
+
+/* setregid(2) */
+static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2)
+{
+ return get_errno(setregid(arg1, arg2));
+}
+
+/* setresgid(2) */
+static inline abi_long do_bsd_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+ return get_errno(setresgid(rgid, egid, sgid));
+}
+
+/* setresuid(2) */
+static inline abi_long do_bsd_setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+ return get_errno(setresuid(ruid, euid, suid));
+}
+
+/* getresuid(2) */
+static inline abi_long do_bsd_getresuid(abi_ulong arg1, abi_ulong arg2,
+ abi_ulong arg3)
+{
+ abi_long ret;
+ uid_t ruid, euid, suid;
+
+ ret = get_errno(getresuid(&ruid, &euid, &suid));
+ if (is_error(ret)) {
+ return ret;
+ }
+ if (put_user_s32(ruid, arg1)) {
+ return -TARGET_EFAULT;
+ }
+ if (put_user_s32(euid, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ if (put_user_s32(suid, arg3)) {
+ return -TARGET_EFAULT;
+ }
+ return ret;
+}
+
+/* getresgid(2) */
+static inline abi_long do_bsd_getresgid(abi_ulong arg1, abi_ulong arg2,
+ abi_ulong arg3)
+{
+ abi_long ret;
+ uid_t ruid, euid, suid;
+
+ ret = get_errno(getresgid(&ruid, &euid, &suid));
+ if (is_error(ret)) {
+ return ret;
+ }
+ if (put_user_s32(ruid, arg1)) {
+ return -TARGET_EFAULT;
+ }
+ if (put_user_s32(euid, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ if (put_user_s32(suid, arg3)) {
+ return -TARGET_EFAULT;
+ }
+ return ret;
+}
+
+/* getsid(2) */
+static inline abi_long do_bsd_getsid(abi_long arg1)
+{
+ return get_errno(getsid(arg1));
+}
+
+/* setsid(2) */
+static inline abi_long do_bsd_setsid(void)
+{
+ return get_errno(setsid());
+}
+
+/* issetugid(2) */
+static inline abi_long do_bsd_issetugid(void)
+{
+ return get_errno(issetugid());
+}
+
+/* profil(2) */
+static inline abi_long do_bsd_profil(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ return -TARGET_ENOSYS;
+}
+
+/* ktrace(2) */
+static inline abi_long do_bsd_ktrace(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ return -TARGET_ENOSYS;
+}
+
+/* utrace(2) */
+static inline abi_long do_bsd_utrace(abi_long arg1, abi_long arg2)
+{
+ return -TARGET_ENOSYS;
+}
+
+
+/* ptrace(2) */
+static inline abi_long do_bsd_ptrace(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ return -TARGET_ENOSYS;
+}
+
+/* getpriority(2) */
+static inline abi_long do_bsd_getpriority(abi_long which, abi_long who)
+{
+ abi_long ret;
+ /*
+ * Note that negative values are valid for getpriority, so we must
+ * differentiate based on errno settings.
+ */
+ errno = 0;
+ ret = getpriority(which, who);
+ if (ret == -1 && errno != 0) {
+ return -host_to_target_errno(errno);
+ }
+
+ return ret;
+}
+
+/* setpriority(2) */
+static inline abi_long do_bsd_setpriority(abi_long which, abi_long who,
+ abi_long prio)
+{
+ return get_errno(setpriority(which, who, prio));
+}
+
#endif /* !BSD_PROC_H_ */
diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build
index f2f047c..8fd6c7c 100644
--- a/bsd-user/freebsd/meson.build
+++ b/bsd-user/freebsd/meson.build
@@ -1,5 +1,6 @@
bsd_user_ss.add(files(
'os-stat.c',
+ 'os-proc.c',
'os-sys.c',
'os-syscall.c',
))
diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h
new file mode 100644
index 0000000..7114576
--- /dev/null
+++ b/bsd-user/freebsd/os-misc.h
@@ -0,0 +1,98 @@
+/*
+ * miscellaneous FreeBSD system call shims
+ *
+ * Copyright (c) 2013-14 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef OS_MISC_H
+#define OS_MISC_H
+
+#include <sys/cpuset.h>
+#include <sys/random.h>
+#include <sched.h>
+
+/*
+ * shm_open2 isn't exported, but the __sys_ alias is. We can use either for the
+ * static version, but to dynamically link we have to use the sys version.
+ */
+int __sys_shm_open2(const char *path, int flags, mode_t mode, int shmflags,
+ const char *);
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048
+/* shm_open2(2) */
+static inline abi_long do_freebsd_shm_open2(abi_ulong pathptr, abi_ulong flags,
+ abi_long mode, abi_ulong shmflags, abi_ulong nameptr)
+{
+ int ret;
+ void *uname, *upath;
+
+ if (pathptr == (uintptr_t)SHM_ANON) {
+ upath = SHM_ANON;
+ } else {
+ upath = lock_user_string(pathptr);
+ if (upath == NULL) {
+ return -TARGET_EFAULT;
+ }
+ }
+
+ uname = NULL;
+ if (nameptr != 0) {
+ uname = lock_user_string(nameptr);
+ if (uname == NULL) {
+ unlock_user(upath, pathptr, 0);
+ return -TARGET_EFAULT;
+ }
+ }
+ ret = get_errno(__sys_shm_open2(upath,
+ target_to_host_bitmask(flags, fcntl_flags_tbl), mode,
+ target_to_host_bitmask(shmflags, shmflag_flags_tbl), uname));
+
+ if (upath != SHM_ANON) {
+ unlock_user(upath, pathptr, 0);
+ }
+ if (uname != NULL) {
+ unlock_user(uname, nameptr, 0);
+ }
+ return ret;
+}
+#endif /* __FreeBSD_version >= 1300048 */
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049
+/* shm_rename(2) */
+static inline abi_long do_freebsd_shm_rename(abi_ulong fromptr, abi_ulong toptr,
+ abi_ulong flags)
+{
+ int ret;
+ void *ufrom, *uto;
+
+ ufrom = lock_user_string(fromptr);
+ if (ufrom == NULL) {
+ return -TARGET_EFAULT;
+ }
+ uto = lock_user_string(toptr);
+ if (uto == NULL) {
+ unlock_user(ufrom, fromptr, 0);
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(shm_rename(ufrom, uto, flags));
+ unlock_user(ufrom, fromptr, 0);
+ unlock_user(uto, toptr, 0);
+
+ return ret;
+}
+#endif /* __FreeBSD_version >= 1300049 */
+
+#endif /* OS_MISC_H */
diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c
new file mode 100644
index 0000000..4e67ae4
--- /dev/null
+++ b/bsd-user/freebsd/os-proc.c
@@ -0,0 +1,480 @@
+/*
+ * FreeBSD process related emulation code
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+struct kinfo_proc;
+#include <libprocstat.h>
+
+#include "qemu.h"
+
+/*
+ * Get the filename for the given file descriptor.
+ * Note that this may return NULL (fail) if no longer cached in the kernel.
+ */
+static char *
+get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
+{
+ char *ret = NULL;
+ unsigned int cnt;
+ struct procstat *procstat = NULL;
+ struct kinfo_proc *kp = NULL;
+ struct filestat_list *head = NULL;
+ struct filestat *fst;
+
+ procstat = procstat_open_sysctl();
+ if (procstat == NULL) {
+ goto out;
+ }
+
+ kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
+ if (kp == NULL) {
+ goto out;
+ }
+
+ head = procstat_getfiles(procstat, kp, 0);
+ if (head == NULL) {
+ goto out;
+ }
+
+ STAILQ_FOREACH(fst, head, next) {
+ if (fd == fst->fs_fd) {
+ if (fst->fs_path != NULL) {
+ (void)strlcpy(filename, fst->fs_path, len);
+ ret = filename;
+ }
+ break;
+ }
+ }
+
+out:
+ if (head != NULL) {
+ procstat_freefiles(procstat, head);
+ }
+ if (kp != NULL) {
+ procstat_freeprocs(procstat, kp);
+ }
+ if (procstat != NULL) {
+ procstat_close(procstat);
+ }
+ return ret;
+}
+
+/*
+ * execve/fexecve
+ */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+ abi_ulong guest_envp, int do_fexec)
+{
+ char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
+ int argc, envc;
+ abi_ulong gp;
+ abi_ulong addr;
+ char **q;
+ int total_size = 0;
+ void *p;
+ abi_long ret;
+
+ argc = 0;
+ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+ if (get_user_ual(addr, gp)) {
+ return -TARGET_EFAULT;
+ }
+ if (!addr) {
+ break;
+ }
+ argc++;
+ }
+ envc = 0;
+ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+ if (get_user_ual(addr, gp)) {
+ return -TARGET_EFAULT;
+ }
+ if (!addr) {
+ break;
+ }
+ envc++;
+ }
+
+ qarg0 = argp = g_new0(char *, argc + 9);
+ /* save the first agrument for the emulator */
+ *argp++ = (char *)getprogname();
+ qargp = argp;
+ *argp++ = (char *)getprogname();
+ qarg1 = argp;
+ envp = g_new0(char *, envc + 1);
+ for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp)) {
+ ret = -TARGET_EFAULT;
+ goto execve_end;
+ }
+ if (!addr) {
+ break;
+ }
+ *q = lock_user_string(addr);
+ if (*q == NULL) {
+ ret = -TARGET_EFAULT;
+ goto execve_end;
+ }
+ total_size += strlen(*q) + 1;
+ }
+ *q++ = NULL;
+ qargend = q;
+
+ for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp)) {
+ ret = -TARGET_EFAULT;
+ goto execve_end;
+ }
+ if (!addr) {
+ break;
+ }
+ *q = lock_user_string(addr);
+ if (*q == NULL) {
+ ret = -TARGET_EFAULT;
+ goto execve_end;
+ }
+ total_size += strlen(*q) + 1;
+ }
+ *q = NULL;
+
+ /*
+ * This case will not be caught by the host's execve() if its
+ * page size is bigger than the target's.
+ */
+ if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
+ ret = -TARGET_E2BIG;
+ goto execve_end;
+ }
+
+ if (do_fexec) {
+ if (((int)path_or_fd > 0 &&
+ is_target_elf_binary((int)path_or_fd)) == 1) {
+ char execpath[PATH_MAX];
+
+ /*
+ * The executable is an elf binary for the target
+ * arch. execve() it using the emulator if we can
+ * determine the filename path from the fd.
+ */
+ if (get_filename_from_fd(getpid(), (int)path_or_fd, execpath,
+ sizeof(execpath)) != NULL) {
+ memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+ qarg1[1] = qarg1[0];
+ qarg1[0] = (char *)"-0";
+ qarg1 += 2;
+ qargend += 2;
+ *qarg1 = execpath;
+#ifndef DONT_INHERIT_INTERP_PREFIX
+ memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+ *qarg1++ = (char *)"-L";
+ *qarg1++ = (char *)interp_prefix;
+#endif
+ ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+ } else {
+ /* Getting the filename path failed. */
+ ret = -TARGET_EBADF;
+ goto execve_end;
+ }
+ } else {
+ ret = get_errno(fexecve((int)path_or_fd, argp, envp));
+ }
+ } else {
+ int fd;
+
+ p = lock_user_string(path_or_fd);
+ if (p == NULL) {
+ ret = -TARGET_EFAULT;
+ goto execve_end;
+ }
+
+ /*
+ * Check the header and see if it a target elf binary. If so
+ * then execute using qemu user mode emulator.
+ */
+ fd = open(p, O_RDONLY | O_CLOEXEC);
+ if (fd > 0 && is_target_elf_binary(fd) == 1) {
+ close(fd);
+ /* execve() as a target binary using emulator. */
+ memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+ qarg1[1] = qarg1[0];
+ qarg1[0] = (char *)"-0";
+ qarg1 += 2;
+ qargend += 2;
+ *qarg1 = (char *)p;
+#ifndef DONT_INHERIT_INTERP_PREFIX
+ memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+ *qarg1++ = (char *)"-L";
+ *qarg1++ = (char *)interp_prefix;
+#endif
+ ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+ } else {
+ close(fd);
+ /* Execve() as a host native binary. */
+ ret = get_errno(execve(p, argp, envp));
+ }
+ unlock_user(p, path_or_fd, 0);
+ }
+
+execve_end:
+ for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp) || !addr) {
+ break;
+ }
+ unlock_user(*q, addr, 0);
+ }
+
+ for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp) || !addr) {
+ break;
+ }
+ unlock_user(*q, addr, 0);
+ }
+
+ g_free(qarg0);
+ g_free(envp);
+
+ return ret;
+}
+
+#include <sys/procctl.h>
+
+static abi_long
+t2h_procctl_cmd(int target_cmd, int *host_cmd)
+{
+ switch (target_cmd) {
+ case TARGET_PROC_SPROTECT:
+ *host_cmd = PROC_SPROTECT;
+ break;
+
+ case TARGET_PROC_REAP_ACQUIRE:
+ *host_cmd = PROC_REAP_ACQUIRE;
+ break;
+
+ case TARGET_PROC_REAP_RELEASE:
+ *host_cmd = PROC_REAP_RELEASE;
+ break;
+
+ case TARGET_PROC_REAP_STATUS:
+ *host_cmd = PROC_REAP_STATUS;
+ break;
+
+ case TARGET_PROC_REAP_KILL:
+ *host_cmd = PROC_REAP_KILL;
+ break;
+
+ default:
+ return -TARGET_EINVAL;
+ }
+
+ return 0;
+}
+
+static abi_long
+h2t_reaper_status(struct procctl_reaper_status *host_rs,
+ abi_ulong target_rs_addr)
+{
+ struct target_procctl_reaper_status *target_rs;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_rs, target_rs_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(host_rs->rs_flags, &target_rs->rs_flags);
+ __put_user(host_rs->rs_children, &target_rs->rs_children);
+ __put_user(host_rs->rs_descendants, &target_rs->rs_descendants);
+ __put_user(host_rs->rs_reaper, &target_rs->rs_reaper);
+ __put_user(host_rs->rs_pid, &target_rs->rs_pid);
+ unlock_user_struct(target_rs, target_rs_addr, 1);
+
+ return 0;
+}
+
+static abi_long
+t2h_reaper_kill(abi_ulong target_rk_addr, struct procctl_reaper_kill *host_rk)
+{
+ struct target_procctl_reaper_kill *target_rk;
+
+ if (!lock_user_struct(VERIFY_READ, target_rk, target_rk_addr, 1)) {
+ return -TARGET_EFAULT;
+ }
+ __get_user(host_rk->rk_sig, &target_rk->rk_sig);
+ __get_user(host_rk->rk_flags, &target_rk->rk_flags);
+ __get_user(host_rk->rk_subtree, &target_rk->rk_subtree);
+ __get_user(host_rk->rk_killed, &target_rk->rk_killed);
+ __get_user(host_rk->rk_fpid, &target_rk->rk_fpid);
+ unlock_user_struct(target_rk, target_rk_addr, 0);
+
+ return 0;
+}
+
+static abi_long
+h2t_reaper_kill(struct procctl_reaper_kill *host_rk, abi_ulong target_rk_addr)
+{
+ struct target_procctl_reaper_kill *target_rk;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_rk, target_rk_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(host_rk->rk_sig, &target_rk->rk_sig);
+ __put_user(host_rk->rk_flags, &target_rk->rk_flags);
+ __put_user(host_rk->rk_subtree, &target_rk->rk_subtree);
+ __put_user(host_rk->rk_killed, &target_rk->rk_killed);
+ __put_user(host_rk->rk_fpid, &target_rk->rk_fpid);
+ unlock_user_struct(target_rk, target_rk_addr, 1);
+
+ return 0;
+}
+
+static abi_long
+h2t_procctl_reaper_pidinfo(struct procctl_reaper_pidinfo *host_pi,
+ abi_ulong target_pi_addr)
+{
+ struct target_procctl_reaper_pidinfo *target_pi;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_pi, target_pi_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(host_pi->pi_pid, &target_pi->pi_pid);
+ __put_user(host_pi->pi_subtree, &target_pi->pi_subtree);
+ __put_user(host_pi->pi_flags, &target_pi->pi_flags);
+ unlock_user_struct(target_pi, target_pi_addr, 1);
+
+ return 0;
+}
+
+abi_long
+do_freebsd_procctl(void *cpu_env, int idtype, abi_ulong arg2, abi_ulong arg3,
+ abi_ulong arg4, abi_ulong arg5, abi_ulong arg6)
+{
+ abi_long error = 0, target_rp_pids;
+ void *data;
+ int host_cmd, flags;
+ uint32_t u, target_rp_count;
+ g_autofree union {
+ struct procctl_reaper_status rs;
+ struct procctl_reaper_pids rp;
+ struct procctl_reaper_kill rk;
+ } host;
+ struct target_procctl_reaper_pids *target_rp;
+ id_t id; /* 64-bit */
+ int target_cmd;
+ abi_ulong target_arg;
+
+#if TARGET_ABI_BITS == 32
+ /* See if we need to align the register pairs. */
+ if (regpairs_aligned(cpu_env)) {
+ id = (id_t)target_arg64(arg3, arg4);
+ target_cmd = (int)arg5;
+ target_arg = arg6;
+ } else {
+ id = (id_t)target_arg64(arg2, arg3);
+ target_cmd = (int)arg4;
+ target_arg = arg5;
+ }
+#else
+ id = (id_t)arg2;
+ target_cmd = (int)arg3;
+ target_arg = arg4;
+#endif
+
+ error = t2h_procctl_cmd(target_cmd, &host_cmd);
+ if (error) {
+ return error;
+ }
+ switch (host_cmd) {
+ case PROC_SPROTECT:
+ data = &flags;
+ break;
+
+ case PROC_REAP_ACQUIRE:
+ case PROC_REAP_RELEASE:
+ if (target_arg == 0) {
+ data = NULL;
+ } else {
+ error = -TARGET_EINVAL;
+ }
+ break;
+
+ case PROC_REAP_STATUS:
+ data = &host.rs;
+ break;
+
+ case PROC_REAP_GETPIDS:
+ if (!lock_user_struct(VERIFY_READ, target_rp, target_arg, 1)) {
+ return -TARGET_EFAULT;
+ }
+ __get_user(target_rp_count, &target_rp->rp_count);
+ __get_user(target_rp_pids, &target_rp->rp_pids);
+ unlock_user_struct(target_rp, target_arg, 0);
+ host.rp.rp_count = target_rp_count;
+ host.rp.rp_pids = g_try_new(struct procctl_reaper_pidinfo,
+ target_rp_count);
+
+ if (host.rp.rp_pids == NULL) {
+ error = -TARGET_ENOMEM;
+ } else {
+ data = &host.rp;
+ }
+ break;
+
+ case PROC_REAP_KILL:
+ error = t2h_reaper_kill(target_arg, &host.rk);
+ break;
+ }
+
+ if (error) {
+ return error;
+ }
+ error = get_errno(procctl(idtype, id, host_cmd, data));
+
+ if (error) {
+ return error;
+ }
+ switch (host_cmd) {
+ case PROC_SPROTECT:
+ if (put_user_s32(flags, target_arg)) {
+ return -TARGET_EFAULT;
+ }
+ break;
+
+ case PROC_REAP_STATUS:
+ error = h2t_reaper_status(&host.rs, target_arg);
+ break;
+
+ case PROC_REAP_GETPIDS:
+ /* copyout reaper pidinfo */
+ for (u = 0; u < target_rp_count; u++) {
+ error = h2t_procctl_reaper_pidinfo(&host.rp.rp_pids[u],
+ target_rp_pids +
+ (u * sizeof(struct target_procctl_reaper_pidinfo)));
+ if (error) {
+ break;
+ }
+ }
+ break;
+
+ case PROC_REAP_KILL:
+ error = h2t_reaper_kill(&host.rk, target_arg);
+ break;
+ }
+
+ return error;
+}
diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h
new file mode 100644
index 0000000..d641878
--- /dev/null
+++ b/bsd-user/freebsd/os-proc.h
@@ -0,0 +1,293 @@
+/*
+ * process related system call shims and definitions
+ *
+ * Copyright (c) 2013-14 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BSD_USER_FREEBSD_OS_PROC_H
+#define BSD_USER_FREEBSD_OS_PROC_H
+
+#include <sys/param.h>
+#include <sys/procctl.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/procdesc.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "target_arch_cpu.h"
+
+pid_t safe_wait4(pid_t wpid, int *status, int options, struct rusage *rusage);
+pid_t safe_wait6(idtype_t idtype, id_t id, int *status, int options,
+ struct __wrusage *wrusage, siginfo_t *infop);
+
+extern int __setugid(int flag);
+
+/* execve(2) */
+static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
+ abi_ulong envp)
+{
+
+ return freebsd_exec_common(path_or_fd, argp, envp, 0);
+}
+
+/* fexecve(2) */
+static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
+ abi_ulong envp)
+{
+
+ return freebsd_exec_common(path_or_fd, argp, envp, 1);
+}
+
+/* wait4(2) */
+static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
+ abi_long arg3, abi_ulong target_rusage)
+{
+ abi_long ret;
+ int status;
+ struct rusage rusage, *rusage_ptr = NULL;
+
+ if (target_rusage) {
+ rusage_ptr = &rusage;
+ }
+ ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
+
+ if (ret < 0) {
+ return ret;
+ }
+ if (target_status != 0) {
+ status = host_to_target_waitstatus(status);
+ if (put_user_s32(status, target_status) != 0) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (target_rusage != 0) {
+ host_to_target_rusage(target_rusage, &rusage);
+ }
+ return ret;
+}
+
+/* wait6(2) */
+static inline abi_long do_freebsd_wait6(void *cpu_env, abi_long idtype,
+ abi_long id1, abi_long id2,
+ abi_ulong target_status, abi_long options, abi_ulong target_wrusage,
+ abi_ulong target_infop, abi_ulong pad1)
+{
+ abi_long ret;
+ int status;
+ struct __wrusage wrusage, *wrusage_ptr = NULL;
+ siginfo_t info;
+ void *p;
+
+ if (regpairs_aligned(cpu_env) != 0) {
+ /* printf("shifting args\n"); */
+ /* 64-bit id is aligned, so shift all the arguments over by one */
+ id1 = id2;
+ id2 = target_status;
+ target_status = options;
+ options = target_wrusage;
+ target_wrusage = target_infop;
+ target_infop = pad1;
+ }
+
+ if (target_wrusage) {
+ wrusage_ptr = &wrusage;
+ }
+ ret = get_errno(safe_wait6(idtype, target_arg64(id1, id2),
+ &status, options, wrusage_ptr, &info));
+
+ if (ret < 0) {
+ return ret;
+ }
+ if (target_status != 0) {
+ status = host_to_target_waitstatus(status);
+ if (put_user_s32(status, target_status) != 0) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (target_wrusage != 0) {
+ host_to_target_wrusage(target_wrusage, &wrusage);
+ }
+ if (target_infop != 0) {
+ p = lock_user(VERIFY_WRITE, target_infop, sizeof(target_siginfo_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_siginfo(p, &info);
+ unlock_user(p, target_infop, sizeof(target_siginfo_t));
+ }
+ return ret;
+}
+
+/* setloginclass(2) */
+static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user_string(arg1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setloginclass(p));
+ unlock_user(p, arg1, 0);
+
+ return ret;
+}
+
+/* getloginclass(2) */
+static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(getloginclass(p, arg2));
+ unlock_user(p, arg1, arg2);
+
+ return ret;
+}
+
+/* pdgetpid(2) */
+static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
+{
+ abi_long ret;
+ pid_t pid;
+
+ ret = get_errno(pdgetpid(fd, &pid));
+ if (!is_error(ret)) {
+ if (put_user_u32(pid, target_pidp)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* undocumented __setugid */
+static inline abi_long do_freebsd___setugid(abi_long arg1)
+{
+ return -TARGET_ENOSYS;
+}
+
+/* fork(2) */
+static inline abi_long do_freebsd_fork(void *cpu_env)
+{
+ abi_long ret;
+ abi_ulong child_flag;
+
+ fork_start();
+ ret = fork();
+ if (ret == 0) {
+ /* child */
+ child_flag = 1;
+ target_cpu_clone_regs(cpu_env, 0);
+ } else {
+ /* parent */
+ child_flag = 0;
+ }
+
+ /*
+ * The fork system call sets a child flag in the second return
+ * value: 0 for parent process, 1 for child process.
+ */
+ set_second_rval(cpu_env, child_flag);
+
+ fork_end(child_flag);
+
+ return ret;
+}
+
+/* vfork(2) */
+static inline abi_long do_freebsd_vfork(void *cpu_env)
+{
+ return do_freebsd_fork(cpu_env);
+}
+
+/* rfork(2) */
+static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
+{
+ abi_long ret;
+ abi_ulong child_flag;
+
+ /*
+ * XXX We need to handle RFMEM here, as well. Neither are safe to execute
+ * as-is on x86 hosts because they'll split memory but not the stack,
+ * wreaking havoc on host architectures that use the stack to store the
+ * return address as both threads try to pop it off. Rejecting RFSPAWN
+ * entirely for now is ok, the only consumer at the moment is posix_spawn
+ * and it will fall back to classic vfork(2) if we return EINVAL.
+ */
+ if ((flags & TARGET_RFSPAWN) != 0) {
+ return -TARGET_EINVAL;
+ }
+ fork_start();
+ ret = rfork(flags);
+ if (ret == 0) {
+ /* child */
+ child_flag = 1;
+ target_cpu_clone_regs(cpu_env, 0);
+ } else {
+ /* parent */
+ child_flag = 0;
+ }
+
+ /*
+ * The fork system call sets a child flag in the second return
+ * value: 0 for parent process, 1 for child process.
+ */
+ set_second_rval(cpu_env, child_flag);
+ fork_end(child_flag);
+
+ return ret;
+
+}
+
+/* pdfork(2) */
+static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong target_fdp,
+ abi_long flags)
+{
+ abi_long ret;
+ abi_ulong child_flag;
+ int fd;
+
+ fork_start();
+ ret = pdfork(&fd, flags);
+ if (ret == 0) {
+ /* child */
+ child_flag = 1;
+ target_cpu_clone_regs(cpu_env, 0);
+ } else {
+ /* parent */
+ child_flag = 0;
+ if (put_user_s32(fd, target_fdp)) {
+ return -TARGET_EFAULT;
+ }
+ }
+
+ /*
+ * The fork system call sets a child flag in the second return
+ * value: 0 for parent process, 1 for child process.
+ */
+ set_second_rval(cpu_env, child_flag);
+ fork_end(child_flag);
+
+ return ret;
+}
+
+#endif /* BSD_USER_FREEBSD_OS_PROC_H */
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
index fa60df5..ca2f6fd 100644
--- a/bsd-user/freebsd/os-syscall.c
+++ b/bsd-user/freebsd/os-syscall.c
@@ -33,11 +33,15 @@
#include "signal-common.h"
#include "user/syscall-trace.h"
+/* BSD independent syscall shims */
#include "bsd-file.h"
+#include "bsd-mem.h"
#include "bsd-proc.h"
-/* *BSD dependent syscall shims */
+/* BSD dependent syscall shims */
#include "os-stat.h"
+#include "os-proc.h"
+#include "os-misc.h"
/* I/O */
safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode);
@@ -58,9 +62,11 @@ safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt);
safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
off_t, offset);
-void target_set_brk(abi_ulong new_brk)
-{
-}
+/* used in os-proc */
+safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options,
+ struct rusage *, rusage);
+safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int,
+ options, struct __wrusage *, wrusage, siginfo_t *, infop);
/*
* errno conversion.
@@ -219,10 +225,207 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
/*
* process system calls
*/
+ case TARGET_FREEBSD_NR_fork: /* fork(2) */
+ ret = do_freebsd_fork(cpu_env);
+ break;
+
+ case TARGET_FREEBSD_NR_vfork: /* vfork(2) */
+ ret = do_freebsd_vfork(cpu_env);
+ break;
+
+ case TARGET_FREEBSD_NR_rfork: /* rfork(2) */
+ ret = do_freebsd_rfork(cpu_env, arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_pdfork: /* pdfork(2) */
+ ret = do_freebsd_pdfork(cpu_env, arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_execve: /* execve(2) */
+ ret = do_freebsd_execve(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_fexecve: /* fexecve(2) */
+ ret = do_freebsd_fexecve(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_wait4: /* wait4(2) */
+ ret = do_freebsd_wait4(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_wait6: /* wait6(2) */
+ ret = do_freebsd_wait6(cpu_env, arg1, arg2, arg3,
+ arg4, arg5, arg6, arg7, arg8);
+ break;
+
case TARGET_FREEBSD_NR_exit: /* exit(2) */
ret = do_bsd_exit(cpu_env, arg1);
break;
+ case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */
+ ret = do_bsd_getgroups(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */
+ ret = do_bsd_setgroups(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_umask: /* umask(2) */
+ ret = do_bsd_umask(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_setlogin: /* setlogin(2) */
+ ret = do_bsd_setlogin(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_getlogin: /* getlogin(2) */
+ ret = do_bsd_getlogin(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_getrusage: /* getrusage(2) */
+ ret = do_bsd_getrusage(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_getrlimit: /* getrlimit(2) */
+ ret = do_bsd_getrlimit(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setrlimit: /* setrlimit(2) */
+ ret = do_bsd_setrlimit(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_getpid: /* getpid(2) */
+ ret = do_bsd_getpid();
+ break;
+
+ case TARGET_FREEBSD_NR_getppid: /* getppid(2) */
+ ret = do_bsd_getppid();
+ break;
+
+ case TARGET_FREEBSD_NR_getuid: /* getuid(2) */
+ ret = do_bsd_getuid();
+ break;
+
+ case TARGET_FREEBSD_NR_geteuid: /* geteuid(2) */
+ ret = do_bsd_geteuid();
+ break;
+
+ case TARGET_FREEBSD_NR_getgid: /* getgid(2) */
+ ret = do_bsd_getgid();
+ break;
+
+ case TARGET_FREEBSD_NR_getegid: /* getegid(2) */
+ ret = do_bsd_getegid();
+ break;
+
+ case TARGET_FREEBSD_NR_setuid: /* setuid(2) */
+ ret = do_bsd_setuid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_seteuid: /* seteuid(2) */
+ ret = do_bsd_seteuid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_setgid: /* setgid(2) */
+ ret = do_bsd_setgid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_setegid: /* setegid(2) */
+ ret = do_bsd_setegid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_getpgrp: /* getpgrp(2) */
+ ret = do_bsd_getpgrp();
+ break;
+
+ case TARGET_FREEBSD_NR_getpgid: /* getpgid(2) */
+ ret = do_bsd_getpgid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_setpgid: /* setpgid(2) */
+ ret = do_bsd_setpgid(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setreuid: /* setreuid(2) */
+ ret = do_bsd_setreuid(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setregid: /* setregid(2) */
+ ret = do_bsd_setregid(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_getresuid: /* getresuid(2) */
+ ret = do_bsd_getresuid(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getresgid: /* getresgid(2) */
+ ret = do_bsd_getresgid(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_setresuid: /* setresuid(2) */
+ ret = do_bsd_setresuid(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_setresgid: /* setresgid(2) */
+ ret = do_bsd_setresgid(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getsid: /* getsid(2) */
+ ret = do_bsd_getsid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_setsid: /* setsid(2) */
+ ret = do_bsd_setsid();
+ break;
+
+ case TARGET_FREEBSD_NR_issetugid: /* issetugid(2) */
+ ret = do_bsd_issetugid();
+ break;
+
+ case TARGET_FREEBSD_NR_profil: /* profil(2) */
+ ret = do_bsd_profil(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_ktrace: /* ktrace(2) */
+ ret = do_bsd_ktrace(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_setloginclass: /* setloginclass(2) */
+ ret = do_freebsd_setloginclass(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */
+ ret = do_freebsd_getloginclass(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_pdgetpid: /* pdgetpid(2) */
+ ret = do_freebsd_pdgetpid(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR___setugid: /* undocumented */
+ ret = do_freebsd___setugid(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_utrace: /* utrace(2) */
+ ret = do_bsd_utrace(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_ptrace: /* ptrace(2) */
+ ret = do_bsd_ptrace(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_getpriority: /* getpriority(2) */
+ ret = do_bsd_getpriority(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setpriority: /* setpriority(2) */
+ ret = do_bsd_setpriority(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_procctl: /* procctl(2) */
+ ret = do_freebsd_procctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+
/*
* File system calls.
*/
@@ -592,6 +795,108 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_freebsd_fcntl(arg1, arg2, arg3);
break;
+ /*
+ * 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;
+
+ case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */
+ ret = do_bsd_mprotect(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_msync: /* msync(2) */
+ 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_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;
+
+ case TARGET_FREEBSD_NR_mincore: /* mincore(2) */
+ 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);
+ break;
+#endif
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049
+ case TARGET_FREEBSD_NR_shm_rename: /* shm_rename(2) */
+ ret = do_freebsd_shm_rename(arg1, arg2, arg3);
+ 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;
+
+ case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */
+ 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;
+
+ 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
+ */
+ case TARGET_FREEBSD_NR_break:
+ ret = do_obreak(arg1);
+ break;
/*
* sys{ctl, arch, call}
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 703f3e2..c402fad 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -88,7 +88,7 @@ unsigned long reserved_va = MAX_RESERVED_VA;
unsigned long reserved_va;
#endif
-static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
+const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
diff --git a/bsd-user/meson.build b/bsd-user/meson.build
index 5243122..c6bfd3b 100644
--- a/bsd-user/meson.build
+++ b/bsd-user/meson.build
@@ -7,6 +7,8 @@ bsd_user_ss = ss.source_set()
common_user_inc += include_directories('include')
bsd_user_ss.add(files(
+ 'bsd-mem.c',
+ 'bsd-proc.c',
'bsdload.c',
'elfload.c',
'main.c',
@@ -16,6 +18,11 @@ bsd_user_ss.add(files(
'uaccess.c',
))
+elf = cc.find_library('elf', required: true)
+procstat = cc.find_library('procstat', required: true)
+kvm = cc.find_library('kvm', required: true)
+bsd_user_ss.add(elf, procstat, kvm)
+
# Pull in the OS-specific build glue, if any
subdir(targetos)
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 8e148a2..3ef11b2 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-bsd.h b/bsd-user/qemu-bsd.h
new file mode 100644
index 0000000..ffc64bb
--- /dev/null
+++ b/bsd-user/qemu-bsd.h
@@ -0,0 +1,58 @@
+/*
+ * BSD conversion extern declarations
+ *
+ * Copyright (c) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_BSD_H
+#define QEMU_BSD_H
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/resource.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uuid.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+
+/* bsd-proc.c */
+int target_to_host_resource(int code);
+rlim_t target_to_host_rlim(abi_llong target_rlim);
+abi_llong host_to_target_rlim(rlim_t rlim);
+abi_long host_to_target_rusage(abi_ulong target_addr,
+ const struct rusage *rusage);
+abi_long host_to_target_wrusage(abi_ulong target_addr,
+ const struct __wrusage *wrusage);
+int host_to_target_waitstatus(int status);
+void h2g_rusage(const struct rusage *rusage,
+ struct target_freebsd_rusage *target_rusage);
+
+/* bsd-mem.c */
+void target_to_host_ipc_perm__locked(struct ipc_perm *host_ip,
+ struct target_ipc_perm *target_ip);
+void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip,
+ struct ipc_perm *host_ip);
+abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
+ abi_ulong target_addr);
+abi_long host_to_target_shmid_ds(abi_ulong target_addr,
+ struct shmid_ds *host_sd);
+
+#endif /* QEMU_BSD_H */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index d950713..dc842ff 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -111,6 +111,7 @@ typedef struct TaskState {
} __attribute__((aligned(16))) TaskState;
void stop_all_tasks(void);
+extern const char *interp_prefix;
extern const char *qemu_uname_release;
/*
@@ -232,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);
@@ -249,6 +251,12 @@ abi_long get_errno(abi_long ret);
bool is_error(abi_long ret);
int host_to_target_errno(int err);
+/* os-proc.c */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+ abi_ulong guest_envp, int do_fexec);
+abi_long do_freebsd_procctl(void *cpu_env, int idtype, abi_ulong arg2,
+ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, abi_ulong arg6);
+
/* os-sys.c */
abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen);
diff --git a/bsd-user/signal-common.h b/bsd-user/signal-common.h
index c044e81..77d7c7a 100644
--- a/bsd-user/signal-common.h
+++ b/bsd-user/signal-common.h
@@ -35,6 +35,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
long do_sigreturn(CPUArchState *env, abi_ulong addr);
void force_sig_fault(int sig, int code, abi_ulong addr);
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
int host_to_target_signal(int sig);
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
void process_pending_signals(CPUArchState *env);
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index f82df50..ca31470 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -311,6 +311,12 @@ static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
}
}
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
+{
+ host_to_target_siginfo_noswap(tinfo, info);
+ tswap_siginfo(tinfo, tinfo);
+}
+
int block_signals(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
index 9c90616..52f84d5 100644
--- a/bsd-user/syscall_defs.h
+++ b/bsd-user/syscall_defs.h
@@ -56,8 +56,47 @@ struct target_iovec {
};
/*
+ * sys/ipc.h
+ */
+struct target_ipc_perm {
+ uint32_t cuid; /* creator user id */
+ uint32_t cgid; /* creator group id */
+ uint32_t uid; /* user id */
+ uint32_t gid; /* group id */
+ uint16_t mode; /* r/w permission */
+ uint16_t seq; /* sequence # */
+ abi_long key; /* user specified msg/sem/shm key */
+};
+
+#define TARGET_IPC_RMID 0 /* remove identifier */
+#define TARGET_IPC_SET 1 /* set options */
+#define TARGET_IPC_STAT 2 /* get options */
+
+/*
+ * sys/shm.h
+ */
+struct target_shmid_ds {
+ struct target_ipc_perm shm_perm; /* peration permission structure */
+ abi_ulong shm_segsz; /* size of segment in bytes */
+ int32_t shm_lpid; /* process ID of last shared memory op */
+ int32_t shm_cpid; /* process ID of creator */
+ int32_t shm_nattch; /* number of current attaches */
+ target_time_t shm_atime; /* time of last shmat() */
+ target_time_t shm_dtime; /* time of last shmdt() */
+ target_time_t shm_ctime; /* time of last change by shmctl() */
+};
+
+#define N_BSD_SHM_REGIONS 32
+struct bsd_shm_regions {
+ abi_long start;
+ abi_long size;
+};
+
+/*
* 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 */
@@ -130,11 +169,7 @@ struct target_freebsd_timeval {
/*
* sys/resource.h
*/
-#if defined(__FreeBSD__)
#define TARGET_RLIM_INFINITY RLIM_INFINITY
-#else
-#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
-#endif
#define TARGET_RLIMIT_CPU 0
#define TARGET_RLIMIT_FSIZE 1
@@ -390,6 +425,52 @@ struct target_freebsd_flock {
int32_t l_sysid;
} QEMU_PACKED;
+/* sys/unistd.h */
+/* user: vfork(2) semantics, clear signals */
+#define TARGET_RFSPAWN (1U << 31)
+
+/*
+ * from sys/procctl.h
+ */
+#define TARGET_PROC_SPROTECT 1
+#define TARGET_PROC_REAP_ACQUIRE 2
+#define TARGET_PROC_REAP_RELEASE 3
+#define TARGET_PROC_REAP_STATUS 4
+#define TARGET_PROC_REAP_GETPIDS 5
+#define TARGET_PROC_REAP_KILL 6
+
+struct target_procctl_reaper_status {
+ uint32_t rs_flags;
+ uint32_t rs_children;
+ uint32_t rs_descendants;
+ uint32_t rs_reaper;
+ uint32_t rs_pid;
+ uint32_t rs_pad0[15];
+};
+
+struct target_procctl_reaper_pidinfo {
+ uint32_t pi_pid;
+ uint32_t pi_subtree;
+ uint32_t pi_flags;
+ uint32_t pi_pad0[15];
+};
+
+struct target_procctl_reaper_pids {
+ uint32_t rp_count;
+ uint32_t rp_pad0[15];
+ abi_ulong rp_pids;
+};
+
+struct target_procctl_reaper_kill {
+ int32_t rk_sig;
+ uint32_t rk_flags;
+ uint32_t rk_subtree;
+ uint32_t rk_killed;
+ uint32_t rk_fpid;
+ uint32_t rk_pad0[15];
+};
+
+
#define safe_syscall0(type, name) \
type safe_##name(void) \
{ \
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 4e5deac..cc2f761 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -106,11 +106,27 @@ static void pty_chr_update_read_handler(Chardev *chr)
static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
PtyChardev *s = PTY_CHARDEV(chr);
+ GPollFD pfd;
+ int rc;
- if (!s->connected) {
- return len;
+ if (s->connected) {
+ return io_channel_send(s->ioc, buf, len);
}
- return io_channel_send(s->ioc, buf, len);
+
+ /*
+ * The other side might already be re-connected, but the timer might
+ * not have fired yet. So let's check here whether we can write again:
+ */
+ pfd.fd = QIO_CHANNEL_FILE(s->ioc)->fd;
+ pfd.events = G_IO_OUT;
+ pfd.revents = 0;
+ rc = RETRY_ON_EINTR(g_poll(&pfd, 1, 0));
+ g_assert(rc >= 0);
+ if (!(pfd.revents & G_IO_HUP) && (pfd.revents & G_IO_OUT)) {
+ io_channel_send(s->ioc, buf, len);
+ }
+
+ return len;
}
static GSource *pty_chr_add_watch(Chardev *chr, GIOCondition cond)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index b135d12..281ef0d 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -11,32 +11,22 @@
*/
#include "qemu/osdep.h"
-#include "qemu/option.h"
#include "qemu/accel.h"
#include "sysemu/replay.h"
-#include "qemu/units.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "qapi/error.h"
-#include "qapi/qapi-visit-common.h"
#include "qapi/qapi-visit-machine.h"
-#include "qapi/visitor.h"
#include "qom/object_interfaces.h"
-#include "hw/sysbus.h"
#include "sysemu/cpus.h"
#include "sysemu/sysemu.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
-#include "sysemu/numa.h"
#include "sysemu/xen.h"
-#include "qemu/error-report.h"
#include "sysemu/qtest.h"
-#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
#include "migration/global_state.h"
-#include "migration/vmstate.h"
#include "exec/confidential-guest-support.h"
-#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-net.h"
#include "audio/audio.h"
diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c
index 79b9754..c2b002d 100644
--- a/hw/display/ramfb.c
+++ b/hw/display/ramfb.c
@@ -97,6 +97,7 @@ static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len)
s->width = width;
s->height = height;
+ qemu_free_displaysurface(s->ds);
s->ds = surface;
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 5d399b6..ec01d74 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -24,79 +24,40 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
-#include "hw/i386/x86.h"
#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
-#include "hw/i386/topology.h"
#include "hw/i386/fw_cfg.h"
#include "hw/i386/vmport.h"
#include "sysemu/cpus.h"
-#include "hw/block/fdc.h"
#include "hw/ide/internal.h"
-#include "hw/ide/isa.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci-bridge/pci_expander_bridge.h"
-#include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h"
-#include "hw/firmware/smbios.h"
#include "hw/loader.h"
-#include "elf.h"
-#include "migration/vmstate.h"
-#include "multiboot.h"
#include "hw/rtc/mc146818rtc.h"
#include "hw/intc/i8259.h"
-#include "hw/intc/ioapic.h"
#include "hw/timer/i8254.h"
#include "hw/input/i8042.h"
-#include "hw/irq.h"
#include "hw/audio/pcspk.h"
-#include "hw/pci/msi.h"
-#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
-#include "sysemu/tcg.h"
-#include "sysemu/numa.h"
-#include "sysemu/kvm.h"
#include "sysemu/xen.h"
#include "sysemu/reset.h"
-#include "sysemu/runstate.h"
#include "kvm/kvm_i386.h"
#include "hw/xen/xen.h"
-#include "hw/xen/start_info.h"
-#include "ui/qemu-spice.h"
-#include "exec/memory.h"
-#include "qemu/bitmap.h"
-#include "qemu/config-file.h"
#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include "qemu/cutils.h"
-#include "hw/acpi/acpi.h"
#include "hw/acpi/cpu_hotplug.h"
#include "acpi-build.h"
-#include "hw/mem/pc-dimm.h"
#include "hw/mem/nvdimm.h"
-#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_host.h"
-#include "qapi/error.h"
-#include "qapi/qapi-visit-common.h"
-#include "qapi/qapi-visit-machine.h"
-#include "qapi/visitor.h"
-#include "hw/core/cpu.h"
#include "hw/usb.h"
#include "hw/i386/intel_iommu.h"
#include "hw/net/ne2000-isa.h"
-#include "standard-headers/asm-x86/bootparam.h"
#include "hw/virtio/virtio-iommu.h"
#include "hw/virtio/virtio-md-pci.h"
#include "hw/i386/kvm/xen_overlay.h"
#include "hw/i386/kvm/xen_evtchn.h"
#include "hw/i386/kvm/xen_gnttab.h"
#include "hw/i386/kvm/xen_xenstore.h"
-#include "sysemu/replay.h"
-#include "target/i386/cpu.h"
#include "e820_memory_layout.h"
-#include "fw_cfg.h"
#include "trace.h"
#include CONFIG_DEVICES
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index e4db910..1a31fb7 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -1196,9 +1196,11 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id);
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, JSONWriter *vmdesc);
+int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, JSONWriter *vmdesc, Error **errp);
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, JSONWriter *vmdesc,
- int version_id);
+ int version_id, Error **errp);
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 7f1bbbf..1109482 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -206,4 +206,10 @@
#define QEMU_ANNOTATE(x)
#endif
+#if __has_attribute(used)
+# define QEMU_USED __attribute__((used))
+#else
+# define QEMU_USED
+#endif
+
#endif /* COMPILER_H */
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 18b940d..475a1c6 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -27,6 +27,10 @@
#ifndef QEMU_OSDEP_H
#define QEMU_OSDEP_H
+#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ && defined __linux__
+# define _FORTIFY_SOURCE 2
+#endif
+
#include "config-host.h"
#ifdef NEED_CPU_H
#include CONFIG_TARGET
diff --git a/include/ui/console.h b/include/ui/console.h
index 28882f1..acb61a7 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -422,7 +422,6 @@ bool qemu_console_is_visible(QemuConsole *con);
bool qemu_console_is_graphic(QemuConsole *con);
bool qemu_console_is_fixedsize(QemuConsole *con);
bool qemu_console_is_gl_blocked(QemuConsole *con);
-bool qemu_console_is_multihead(DeviceState *dev);
char *qemu_console_get_label(QemuConsole *con);
int qemu_console_get_index(QemuConsole *con);
uint32_t qemu_console_get_head(QemuConsole *con);
diff --git a/include/ui/input.h b/include/ui/input.h
index c29a730..24d8e45 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -57,7 +57,7 @@ void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
uint32_t button_old, uint32_t button_new);
-bool qemu_input_is_absolute(void);
+bool qemu_input_is_absolute(QemuConsole *con);
int qemu_input_scale_axis(int value,
int min_in, int max_in,
int min_out, int max_out);
diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 51f8709..e587c48 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -32,6 +32,8 @@
# define PIXMAN_LE_r8g8b8 PIXMAN_b8g8r8
# define PIXMAN_LE_a8r8g8b8 PIXMAN_b8g8r8a8
# define PIXMAN_LE_x8r8g8b8 PIXMAN_b8g8r8x8
+# define PIXMAN_LE_a8b8g8r8 PIXMAN_r8g8b8a8
+# define PIXMAN_LE_x8b8g8r8 PIXMAN_r8g8b8x8
#else
# define PIXMAN_BE_r8g8b8 PIXMAN_b8g8r8
# define PIXMAN_BE_x8r8g8b8 PIXMAN_b8g8r8x8
@@ -45,6 +47,8 @@
# define PIXMAN_LE_r8g8b8 PIXMAN_r8g8b8
# define PIXMAN_LE_a8r8g8b8 PIXMAN_a8r8g8b8
# define PIXMAN_LE_x8r8g8b8 PIXMAN_x8r8g8b8
+# define PIXMAN_LE_a8b8g8r8 PIXMAN_a8b8g8r8
+# define PIXMAN_LE_x8b8g8r8 PIXMAN_x8b8g8r8
#endif
#define QEMU_PIXMAN_COLOR(r, g, b) \
diff --git a/meson.build b/meson.build
index b8bb69f..3bb64b5 100644
--- a/meson.build
+++ b/meson.build
@@ -474,16 +474,6 @@ if 'cpp' in all_languages
qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags
endif
-# clang does not support glibc + FORTIFY_SOURCE (is it still true?)
-if get_option('optimization') != '0' and targetos == 'linux'
- if cc.get_id() == 'gcc'
- qemu_cflags += ['-U_FORTIFY_SOURCE', '-D_FORTIFY_SOURCE=2']
- endif
- if 'cpp' in all_languages and cxx.get_id() == 'gcc'
- qemu_cxxflags += ['-U_FORTIFY_SOURCE', '-D_FORTIFY_SOURCE=2']
- endif
-endif
-
add_project_arguments(qemu_cflags, native: false, language: 'c')
add_project_arguments(cc.get_supported_arguments(warn_flags), native: false, language: 'c')
if 'cpp' in all_languages
diff --git a/migration/file.c b/migration/file.c
new file mode 100644
index 0000000..cf5b1bf
--- /dev/null
+++ b/migration/file.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "channel.h"
+#include "file.h"
+#include "migration.h"
+#include "io/channel-file.h"
+#include "io/channel-util.h"
+#include "trace.h"
+
+#define OFFSET_OPTION ",offset="
+
+/* Remove the offset option from @filespec and return it in @offsetp. */
+
+static int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp)
+{
+ char *option = strstr(filespec, OFFSET_OPTION);
+ int ret;
+
+ if (option) {
+ *option = 0;
+ option += sizeof(OFFSET_OPTION) - 1;
+ ret = qemu_strtosz(option, NULL, offsetp);
+ if (ret) {
+ error_setg_errno(errp, -ret, "file URI has bad offset %s", option);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void file_start_outgoing_migration(MigrationState *s, const char *filespec,
+ Error **errp)
+{
+ g_autofree char *filename = g_strdup(filespec);
+ g_autoptr(QIOChannelFile) fioc = NULL;
+ uint64_t offset = 0;
+ QIOChannel *ioc;
+
+ trace_migration_file_outgoing(filename);
+
+ if (file_parse_offset(filename, &offset, errp)) {
+ return;
+ }
+
+ fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY | O_TRUNC,
+ 0600, errp);
+ if (!fioc) {
+ return;
+ }
+
+ ioc = QIO_CHANNEL(fioc);
+ if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) {
+ return;
+ }
+ qio_channel_set_name(ioc, "migration-file-outgoing");
+ migration_channel_connect(s, ioc, NULL, NULL);
+}
+
+static gboolean file_accept_incoming_migration(QIOChannel *ioc,
+ GIOCondition condition,
+ gpointer opaque)
+{
+ migration_channel_process_incoming(ioc);
+ object_unref(OBJECT(ioc));
+ return G_SOURCE_REMOVE;
+}
+
+void file_start_incoming_migration(const char *filespec, Error **errp)
+{
+ g_autofree char *filename = g_strdup(filespec);
+ QIOChannelFile *fioc = NULL;
+ uint64_t offset = 0;
+ QIOChannel *ioc;
+
+ trace_migration_file_incoming(filename);
+
+ if (file_parse_offset(filename, &offset, errp)) {
+ return;
+ }
+
+ fioc = qio_channel_file_new_path(filename, O_RDONLY, 0, errp);
+ if (!fioc) {
+ return;
+ }
+
+ ioc = QIO_CHANNEL(fioc);
+ if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) {
+ return;
+ }
+ qio_channel_set_name(QIO_CHANNEL(ioc), "migration-file-incoming");
+ qio_channel_add_watch_full(ioc, G_IO_IN,
+ file_accept_incoming_migration,
+ NULL, NULL,
+ g_main_context_get_thread_default());
+}
diff --git a/migration/file.h b/migration/file.h
new file mode 100644
index 0000000..90fa484
--- /dev/null
+++ b/migration/file.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_MIGRATION_FILE_H
+#define QEMU_MIGRATION_FILE_H
+void file_start_incoming_migration(const char *filename, Error **errp);
+
+void file_start_outgoing_migration(MigrationState *s, const char *filename,
+ Error **errp);
+#endif
diff --git a/migration/meson.build b/migration/meson.build
index 1ae2852..92b1cc4 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -16,6 +16,7 @@ system_ss.add(files(
'dirtyrate.c',
'exec.c',
'fd.c',
+ 'file.c',
'global_state.c',
'migration-hmp-cmds.c',
'migration.c',
diff --git a/migration/migration.c b/migration/migration.c
index 6d3cf5d..585d3c8 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -20,6 +20,7 @@
#include "migration/blocker.h"
#include "exec.h"
#include "fd.h"
+#include "file.h"
#include "socket.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
@@ -449,6 +450,8 @@ static void qemu_start_incoming_migration(const char *uri, Error **errp)
exec_start_incoming_migration(p, errp);
} else if (strstart(uri, "fd:", &p)) {
fd_start_incoming_migration(p, errp);
+ } else if (strstart(uri, "file:", &p)) {
+ file_start_incoming_migration(p, errp);
} else {
error_setg(errp, "unknown migration protocol: %s", uri);
}
@@ -1702,6 +1705,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
exec_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "fd:", &p)) {
fd_start_outgoing_migration(s, p, &local_err);
+ } else if (strstart(uri, "file:", &p)) {
+ file_start_outgoing_migration(s, p, &local_err);
} else {
error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "uri",
"a valid migration protocol");
diff --git a/migration/rdma.c b/migration/rdma.c
index 7d2726d..cd5e1af 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -2831,7 +2831,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
size_t remaining = iov[i].iov_len;
uint8_t * data = (void *)iov[i].iov_base;
while (remaining) {
- RDMAControlHeader head;
+ RDMAControlHeader head = {};
len = MIN(remaining, RDMA_SEND_INCREMENT);
remaining -= len;
diff --git a/migration/savevm.c b/migration/savevm.c
index bb3e991..60eec7c 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -979,6 +979,8 @@ static void save_section_footer(QEMUFile *f, SaveStateEntry *se)
static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc)
{
int ret;
+ Error *local_err = NULL;
+ MigrationState *s = migrate_get_current();
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
return 0;
@@ -1000,8 +1002,10 @@ static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc)
if (!se->vmsd) {
vmstate_save_old_style(f, se, vmdesc);
} else {
- ret = vmstate_save_state(f, se->vmsd, se->opaque, vmdesc);
+ ret = vmstate_save_state_with_err(f, se->vmsd, se->opaque, vmdesc, &local_err);
if (ret) {
+ migrate_set_error(s, local_err);
+ error_report_err(local_err);
return ret;
}
}
@@ -1068,10 +1072,14 @@ void qemu_savevm_send_open_return_path(QEMUFile *f)
int qemu_savevm_send_packaged(QEMUFile *f, const uint8_t *buf, size_t len)
{
uint32_t tmp;
+ MigrationState *ms = migrate_get_current();
+ Error *local_err = NULL;
if (len > MAX_VM_CMD_PACKAGED_SIZE) {
- error_report("%s: Unreasonably large packaged state: %zu",
+ error_setg(&local_err, "%s: Unreasonably large packaged state: %zu",
__func__, len);
+ migrate_set_error(ms, local_err);
+ error_report_err(local_err);
return -1;
}
@@ -1499,8 +1507,11 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
* bdrv_activate_all() on the other end won't fail. */
ret = bdrv_inactivate_all();
if (ret) {
- error_report("%s: bdrv_inactivate_all() failed (%d)",
- __func__, ret);
+ Error *local_err = NULL;
+ error_setg(&local_err, "%s: bdrv_inactivate_all() failed (%d)",
+ __func__, ret);
+ migrate_set_error(ms, local_err);
+ error_report_err(local_err);
qemu_file_set_error(f, ret);
return ret;
}
diff --git a/migration/trace-events b/migration/trace-events
index 6348373..002abe3 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -66,6 +66,7 @@ vmstate_save_state_loop(const char *name, const char *field, int n_elems) "%s/%s
vmstate_save_state_top(const char *idstr) "%s"
vmstate_subsection_save_loop(const char *name, const char *sub) "%s/%s"
vmstate_subsection_save_top(const char *idstr) "%s"
+vmstate_field_exists(const char *vmsd, const char *name, int field_version, int version, int result) "%s:%s field_version %d version %d result %d"
# vmstate-types.c
get_qtailq(const char *name, int version_id) "%s v%d"
@@ -311,6 +312,10 @@ migration_exec_incoming(const char *cmd) "cmd=%s"
migration_fd_outgoing(int fd) "fd=%d"
migration_fd_incoming(int fd) "fd=%d"
+# file.c
+migration_file_outgoing(const char *filename) "filename=%s"
+migration_file_incoming(const char *filename) "filename=%s"
+
# socket.c
migration_socket_incoming_accepted(void) ""
migration_socket_outgoing_connected(const char *hostname) "hostname=%s"
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 438ea77..1cf9e45 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -14,6 +14,7 @@
#include "migration.h"
#include "migration/vmstate.h"
#include "savevm.h"
+#include "qapi/error.h"
#include "qapi/qmp/json-writer.h"
#include "qemu-file.h"
#include "qemu/bitops.h"
@@ -25,6 +26,30 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
+/* Whether this field should exist for either save or load the VM? */
+static bool
+vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field,
+ void *opaque, int version_id)
+{
+ bool result;
+
+ if (field->field_exists) {
+ /* If there's the function checker, that's the solo truth */
+ result = field->field_exists(opaque, version_id);
+ trace_vmstate_field_exists(vmsd->name, field->name, field->version_id,
+ version_id, result);
+ } else {
+ /*
+ * Otherwise, we only save/load if field version is same or older.
+ * For example, when loading from an old binary with old version,
+ * we ignore new fields with newer version_ids.
+ */
+ result = field->version_id <= version_id;
+ }
+
+ return result;
+}
+
static int vmstate_n_elems(void *opaque, const VMStateField *field)
{
int n_elems = 1;
@@ -104,10 +129,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
}
while (field->name) {
trace_vmstate_load_state_field(vmsd->name, field->name);
- if ((field->field_exists &&
- field->field_exists(opaque, version_id)) ||
- (!field->field_exists &&
- field->version_id <= version_id)) {
+ if (vmstate_field_exists(vmsd, field, opaque, version_id)) {
void *first_elem = opaque + field->offset;
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
@@ -315,11 +337,17 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, JSONWriter *vmdesc_id)
{
- return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id);
+ return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id, NULL);
+}
+
+int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, JSONWriter *vmdesc_id, Error **errp)
+{
+ return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id, errp);
}
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, JSONWriter *vmdesc, int version_id)
+ void *opaque, JSONWriter *vmdesc, int version_id, Error **errp)
{
int ret = 0;
const VMStateField *field = vmsd->fields;
@@ -330,7 +358,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
ret = vmsd->pre_save(opaque);
trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
if (ret) {
- error_report("pre-save failed: %s", vmsd->name);
+ error_setg(errp, "pre-save failed: %s", vmsd->name);
return ret;
}
}
@@ -342,10 +370,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
}
while (field->name) {
- if ((field->field_exists &&
- field->field_exists(opaque, version_id)) ||
- (!field->field_exists &&
- field->version_id <= version_id)) {
+ if (vmstate_field_exists(vmsd, field, opaque, version_id)) {
void *first_elem = opaque + field->offset;
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
@@ -377,14 +402,14 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
} else if (field->flags & VMS_VSTRUCT) {
ret = vmstate_save_state_v(f, field->vmsd, curr_elem,
vmdesc_loop,
- field->struct_version_id);
+ field->struct_version_id, errp);
} else {
ret = field->info->put(f, curr_elem, size, field,
vmdesc_loop);
}
if (ret) {
- error_report("Save of field %s/%s failed",
- vmsd->name, field->name);
+ error_setg(errp, "Save of field %s/%s failed",
+ vmsd->name, field->name);
if (vmsd->post_save) {
vmsd->post_save(opaque);
}
diff --git a/qemu-options.hx b/qemu-options.hx
index 9ce8a5b..840b83d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4706,6 +4706,7 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
" prepare for incoming migration, listen on\n" \
" specified protocol and socket address\n" \
"-incoming fd:fd\n" \
+ "-incoming file:filename[,offset=offset]\n" \
"-incoming exec:cmdline\n" \
" accept incoming migration on given file descriptor\n" \
" or from given external command\n" \
@@ -4722,7 +4723,11 @@ SRST
Prepare for incoming migration, listen on a given unix socket.
``-incoming fd:fd``
- Accept incoming migration from a given filedescriptor.
+ Accept incoming migration from a given file descriptor.
+
+``-incoming file:filename[,offset=offset]``
+ Accept incoming migration from a given file starting at offset.
+ offset allows the common size suffixes, or a 0x prefix, but not both.
``-incoming exec:cmdline``
Accept incoming migration as an output from specified external
diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py
index b82a1b0..0824245 100755
--- a/scripts/analyze-migration.py
+++ b/scripts/analyze-migration.py
@@ -111,6 +111,8 @@ class RamSection(object):
RAM_SAVE_FLAG_CONTINUE = 0x20
RAM_SAVE_FLAG_XBZRLE = 0x40
RAM_SAVE_FLAG_HOOK = 0x80
+ RAM_SAVE_FLAG_COMPRESS_PAGE = 0x100
+ RAM_SAVE_FLAG_MULTIFD_FLUSH = 0x200
def __init__(self, file, version_id, ramargs, section_key):
if version_id != 4:
@@ -205,6 +207,8 @@ class RamSection(object):
raise Exception("XBZRLE RAM compression is not supported yet")
elif flags & self.RAM_SAVE_FLAG_HOOK:
raise Exception("RAM hooks don't make sense with files")
+ if flags & self.RAM_SAVE_FLAG_MULTIFD_FLUSH:
+ continue
# End of RAM section
if flags & self.RAM_SAVE_FLAG_EOS:
diff --git a/tests/migration/i386/a-b-bootblock.S b/tests/migration/i386/a-b-bootblock.S
index 3d464c7..6bb9999 100644
--- a/tests/migration/i386/a-b-bootblock.S
+++ b/tests/migration/i386/a-b-bootblock.S
@@ -34,19 +34,31 @@ start: # at 0x7c00 ?
mov $16,%eax
mov %eax,%ds
+# Start from 1MB
+.set TEST_MEM_START, (1024*1024)
+.set TEST_MEM_END, (100*1024*1024)
+
mov $65,%ax
mov $0x3f8,%dx
outb %al,%dx
# bl keeps a counter so we limit the output speed
mov $0, %bl
+
+pre_zero:
+ mov $TEST_MEM_START,%eax
+do_zero:
+ movb $0, (%eax)
+ add $4096,%eax
+ cmp $TEST_MEM_END,%eax
+ jl do_zero
+
mainloop:
- # Start from 1MB
- mov $(1024*1024),%eax
+ mov $TEST_MEM_START,%eax
innerloop:
incb (%eax)
add $4096,%eax
- cmp $(100*1024*1024),%eax
+ cmp $TEST_MEM_END,%eax
jl innerloop
inc %bl
diff --git a/tests/migration/i386/a-b-bootblock.h b/tests/migration/i386/a-b-bootblock.h
index b7b0fce..5b52391 100644
--- a/tests/migration/i386/a-b-bootblock.h
+++ b/tests/migration/i386/a-b-bootblock.h
@@ -4,18 +4,18 @@
* the header and the assembler differences in your patch submission.
*/
unsigned char x86_bootsect[] = {
- 0xfa, 0x0f, 0x01, 0x16, 0x78, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
+ 0xfa, 0x0f, 0x01, 0x16, 0x8c, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
- 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
- 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8,
- 0x42, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00,
- 0x27, 0x00, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc6, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00,
+ 0x40, 0x06, 0x7c, 0xf1, 0xb8, 0x00, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x05,
+ 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, 0x06, 0x7c, 0xf2, 0xfe,
+ 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8, 0x42, 0x00, 0x66, 0xba,
+ 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x74, 0x7c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/tests/migration/s390x/a-b-bios.c b/tests/migration/s390x/a-b-bios.c
index a0327cd..ff99a3e 100644
--- a/tests/migration/s390x/a-b-bios.c
+++ b/tests/migration/s390x/a-b-bios.c
@@ -27,6 +27,14 @@ void main(void)
sclp_setup();
sclp_print("A");
+ /*
+ * Make sure all of the pages have consistent contents before incrementing
+ * the first byte below.
+ */
+ for (addr = START_ADDRESS; addr < END_ADDRESS; addr += 4096) {
+ *(volatile char *)addr = 0;
+ }
+
while (1) {
for (addr = START_ADDRESS; addr < END_ADDRESS; addr += 4096) {
*(volatile char *)addr += 1; /* Change pages */
diff --git a/tests/migration/s390x/a-b-bios.h b/tests/migration/s390x/a-b-bios.h
index e722dc7..96103da 100644
--- a/tests/migration/s390x/a-b-bios.h
+++ b/tests/migration/s390x/a-b-bios.h
@@ -6,10 +6,10 @@
unsigned char s390x_elf[] = {
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x07, 0x00, 0x40,
- 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00,
@@ -21,140 +21,154 @@ unsigned char s390x_elf[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xac,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xac, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x98, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x18, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x64, 0x74, 0xe5, 0x51,
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x64, 0x74, 0xe5, 0x52, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x36, 0x34, 0x2e, 0x73, 0x6f,
0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xef, 0xf0, 0x70,
- 0x00, 0x24, 0xa7, 0xfb, 0xff, 0x60, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x1f,
- 0xc0, 0x20, 0x00, 0x00, 0x02, 0x64, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x35,
- 0xa5, 0x1e, 0x00, 0x10, 0xa7, 0x29, 0x63, 0x00, 0xe3, 0x30, 0x10, 0x00,
- 0x00, 0x90, 0xa7, 0x3a, 0x00, 0x01, 0x42, 0x30, 0x10, 0x00, 0xa7, 0x1b,
- 0x10, 0x00, 0xa7, 0x27, 0xff, 0xf7, 0xc0, 0x20, 0x00, 0x00, 0x02, 0x50,
- 0xa7, 0xf4, 0xff, 0xeb, 0x07, 0x07, 0x07, 0x07, 0xc0, 0xf0, 0x00, 0x00,
- 0x56, 0xc4, 0xc0, 0x20, 0x00, 0x00, 0x0a, 0xbd, 0xc0, 0x30, 0x00, 0x00,
- 0x56, 0xbe, 0xb9, 0x0b, 0x00, 0x32, 0xb9, 0x02, 0x00, 0x33, 0xa7, 0x84,
- 0x00, 0x19, 0xa7, 0x3b, 0xff, 0xff, 0xeb, 0x43, 0x00, 0x08, 0x00, 0x0c,
- 0xb9, 0x02, 0x00, 0x44, 0xb9, 0x04, 0x00, 0x12, 0xa7, 0x84, 0x00, 0x09,
- 0xd7, 0xff, 0x10, 0x00, 0x10, 0x00, 0x41, 0x10, 0x11, 0x00, 0xa7, 0x47,
- 0xff, 0xfb, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x07, 0x44, 0x30, 0x20, 0x00,
- 0xa7, 0xf4, 0xff, 0xb6, 0xd7, 0x00, 0x10, 0x00, 0x10, 0x00, 0xc0, 0x10,
- 0x00, 0x00, 0x00, 0x29, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00, 0xf0, 0x00,
- 0x00, 0x25, 0x96, 0x02, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x2f,
- 0xc0, 0x10, 0x00, 0x00, 0x00, 0x11, 0xe3, 0x10, 0x01, 0xb8, 0x00, 0x24,
- 0xc0, 0x10, 0x00, 0x00, 0x00, 0x26, 0xd2, 0x07, 0x01, 0xb0, 0x10, 0x00,
- 0xc0, 0x10, 0x00, 0x00, 0x00, 0x18, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xeb, 0xef, 0xf0, 0x70,
+ 0x00, 0x24, 0xa7, 0xfb, 0xff, 0x60, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x5f,
+ 0xc0, 0x20, 0x00, 0x00, 0x02, 0xa8, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x75,
+ 0xa5, 0x2e, 0x00, 0x10, 0xa7, 0x19, 0x63, 0x00, 0x92, 0x00, 0x20, 0x00,
+ 0xa7, 0x2b, 0x10, 0x00, 0xa7, 0x17, 0xff, 0xfc, 0xa5, 0x1e, 0x00, 0x10,
+ 0xa7, 0x29, 0x63, 0x00, 0xe3, 0x30, 0x10, 0x00, 0x00, 0x90, 0xa7, 0x3a,
+ 0x00, 0x01, 0x42, 0x30, 0x10, 0x00, 0xa7, 0x1b, 0x10, 0x00, 0xa7, 0x27,
+ 0xff, 0xf7, 0xc0, 0x20, 0x00, 0x00, 0x02, 0x8a, 0xc0, 0xe5, 0x00, 0x00,
+ 0x01, 0x56, 0xa7, 0xf4, 0xff, 0xeb, 0x07, 0x07, 0xc0, 0xf0, 0x00, 0x00,
+ 0x4e, 0x5c, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x7d, 0xe3, 0x20, 0x20, 0x00,
+ 0x00, 0x04, 0xc0, 0x30, 0x00, 0x00, 0x96, 0xa3, 0xb9, 0x0b, 0x00, 0x32,
+ 0xb9, 0x02, 0x00, 0x33, 0xa7, 0x84, 0x00, 0x19, 0xa7, 0x3b, 0xff, 0xff,
+ 0xeb, 0x43, 0x00, 0x08, 0x00, 0x0c, 0xb9, 0x02, 0x00, 0x44, 0xb9, 0x04,
+ 0x00, 0x12, 0xa7, 0x84, 0x00, 0x09, 0xd7, 0xff, 0x10, 0x00, 0x10, 0x00,
+ 0x41, 0x10, 0x11, 0x00, 0xa7, 0x47, 0xff, 0xfb, 0xc0, 0x20, 0x00, 0x00,
+ 0x00, 0x0d, 0x44, 0x30, 0x20, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x5b,
+ 0xd2, 0x0f, 0x01, 0xd0, 0x20, 0x00, 0xa7, 0xf4, 0xff, 0xa1, 0xd7, 0x00,
+ 0x10, 0x00, 0x10, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x50, 0xb2, 0xb2,
+ 0x10, 0x00, 0xa7, 0xf4, 0x00, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x25,
+ 0x96, 0x02, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x2f, 0xc0, 0x10,
+ 0x00, 0x00, 0x00, 0x2a, 0xe3, 0x10, 0x01, 0xb8, 0x00, 0x24, 0xc0, 0x10,
+ 0x00, 0x00, 0x00, 0x4b, 0xd2, 0x07, 0x01, 0xb0, 0x10, 0x00, 0xc0, 0x10,
+ 0x00, 0x00, 0x00, 0x3d, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x66, 0xf0, 0x00,
+ 0x00, 0x25, 0x96, 0xff, 0xf0, 0x04, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x2f,
+ 0xc0, 0x10, 0x00, 0x00, 0x00, 0x1a, 0xe3, 0x10, 0x01, 0xf8, 0x00, 0x24,
+ 0xc0, 0x10, 0x00, 0x00, 0x00, 0x36, 0xd2, 0x07, 0x01, 0xf0, 0x10, 0x00,
+ 0xc0, 0x10, 0x00, 0x00, 0x00, 0x24, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00,
0xf0, 0x00, 0x00, 0x25, 0x94, 0xfd, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00,
- 0x00, 0x2f, 0x07, 0xfe, 0x07, 0x07, 0x07, 0x07, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x2f, 0x07, 0xfe, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x25, 0x94, 0x00,
+ 0xf0, 0x04, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x2f, 0x07, 0xfe, 0x07, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0x00, 0x02, 0x00, 0x01,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x02, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
- 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0x10, 0x00, 0x00, 0x0e, 0x59,
- 0xa7, 0xfb, 0xff, 0x60, 0xb2, 0x20, 0x00, 0x21, 0xb2, 0x22, 0x00, 0xb0,
- 0x88, 0xb0, 0x00, 0x1c, 0xc0, 0xe5, 0xff, 0xff, 0xff, 0xba, 0xa7, 0xbe,
- 0x00, 0x03, 0xa7, 0x84, 0x00, 0x13, 0xa7, 0xbe, 0x00, 0x02, 0xa7, 0x28,
- 0x00, 0x00, 0xa7, 0x74, 0x00, 0x04, 0xa7, 0x28, 0xff, 0xfe, 0xe3, 0x40,
- 0xf1, 0x10, 0x00, 0x04, 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xbf, 0xf0, 0xf8,
- 0x00, 0x04, 0x07, 0xf4, 0xa7, 0x28, 0xff, 0xff, 0xa7, 0xf4, 0xff, 0xf5,
- 0x07, 0x07, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0,
- 0x00, 0x00, 0x01, 0x21, 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0xb9, 0x00, 0x00,
- 0xa7, 0x19, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x0e, 0x24, 0xa7, 0x3b,
- 0x00, 0x01, 0xa7, 0x37, 0x00, 0x23, 0xc0, 0x20, 0x00, 0x00, 0x0e, 0x1d,
- 0x18, 0x31, 0xa7, 0x1a, 0x00, 0x06, 0x40, 0x10, 0x20, 0x08, 0xa7, 0x3a,
- 0x00, 0x0e, 0xa7, 0x18, 0x1a, 0x00, 0x40, 0x30, 0x20, 0x00, 0x92, 0x00,
- 0x20, 0x02, 0x40, 0x10, 0x20, 0x0a, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04,
- 0xc0, 0xe5, 0xff, 0xff, 0xff, 0xac, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04,
- 0xb9, 0x04, 0x00, 0x2b, 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4,
- 0xb9, 0x04, 0x00, 0x51, 0xa7, 0x5b, 0x00, 0x01, 0xa7, 0x09, 0x0f, 0xf7,
- 0xb9, 0x21, 0x00, 0x50, 0xa7, 0x24, 0xff, 0xd7, 0x41, 0xeb, 0x20, 0x00,
- 0x95, 0x0a, 0xe0, 0x00, 0xa7, 0x74, 0x00, 0x08, 0x41, 0x11, 0x40, 0x0e,
- 0x92, 0x0d, 0x10, 0x00, 0xb9, 0x04, 0x00, 0x15, 0x43, 0x5b, 0x20, 0x00,
- 0x42, 0x51, 0x40, 0x0e, 0xa7, 0xbb, 0x00, 0x01, 0x41, 0x10, 0x10, 0x01,
- 0xa7, 0xf4, 0xff, 0xbf, 0xc0, 0x50, 0x00, 0x00, 0x00, 0xd4, 0xc0, 0x10,
- 0x00, 0x00, 0x0d, 0xd9, 0xa7, 0x48, 0x00, 0x1c, 0x40, 0x40, 0x10, 0x00,
- 0x50, 0x20, 0x10, 0x0c, 0xa7, 0x48, 0x00, 0x04, 0xe3, 0x20, 0x50, 0x00,
- 0x00, 0x04, 0x40, 0x40, 0x10, 0x0a, 0x50, 0x30, 0x10, 0x10, 0xc0, 0xf4,
- 0xff, 0xff, 0xff, 0x6b, 0xa7, 0x39, 0x00, 0x40, 0xa7, 0x29, 0x00, 0x00,
- 0xc0, 0xf4, 0xff, 0xff, 0xff, 0xe4, 0x07, 0x07, 0xb9, 0x04, 0x00, 0x13,
- 0xa7, 0x2a, 0xff, 0xff, 0xb9, 0x04, 0x00, 0x34, 0xa7, 0x48, 0x00, 0x01,
- 0x15, 0x24, 0xa7, 0x24, 0x00, 0x07, 0xb9, 0x04, 0x00, 0x21, 0xc0, 0xf4,
- 0xff, 0xff, 0xff, 0x7f, 0xa7, 0x29, 0xff, 0xff, 0x07, 0xfe, 0x07, 0x07,
- 0xa7, 0x39, 0x00, 0x00, 0x41, 0x13, 0x20, 0x00, 0x95, 0x00, 0x10, 0x00,
- 0xa7, 0x74, 0x00, 0x05, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x70, 0xa7, 0x3b,
- 0x00, 0x01, 0xa7, 0xf4, 0xff, 0xf5, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58,
- 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x91, 0xa7, 0xfb, 0xff, 0x60,
- 0xb9, 0x04, 0x00, 0xb2, 0xa7, 0x19, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x00,
- 0x0d, 0x8c, 0x92, 0x00, 0x20, 0x00, 0xa7, 0x2b, 0x00, 0x01, 0xa7, 0x17,
- 0xff, 0xfc, 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x83, 0xa7, 0x28, 0x00, 0x20,
- 0x40, 0x20, 0x10, 0x00, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5,
- 0xff, 0xff, 0xff, 0x1d, 0x12, 0x22, 0xa7, 0x74, 0x00, 0x17, 0xa7, 0x19,
- 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x75, 0xc0, 0x50, 0x00, 0x00,
- 0x0d, 0x7a, 0xa7, 0x29, 0x00, 0x08, 0xe3, 0x31, 0x50, 0x00, 0x00, 0x90,
- 0x43, 0x33, 0x40, 0x00, 0x42, 0x31, 0xb0, 0x00, 0xa7, 0x1b, 0x00, 0x01,
- 0xa7, 0x27, 0xff, 0xf7, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xeb, 0xbf,
- 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0xeb, 0xaf, 0xf0, 0x50, 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x51,
- 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0x19, 0x0f, 0xf8, 0xb9, 0x21, 0x00, 0x31,
- 0xb9, 0x04, 0x00, 0xa2, 0xa7, 0xc4, 0x00, 0x2d, 0xa7, 0xb9, 0x0f, 0xf8,
- 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x42, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20,
- 0x10, 0x00, 0x92, 0x00, 0x10, 0x02, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04,
- 0xc0, 0xe5, 0xff, 0xff, 0xfe, 0xda, 0xa7, 0xbb, 0x00, 0x01, 0xa7, 0x19,
- 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x0d, 0x2f, 0xa7, 0xb7, 0x00, 0x17,
- 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x2a, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04,
- 0xe3, 0x20, 0x10, 0x08, 0x00, 0x91, 0xa7, 0x2a, 0xff, 0xf9, 0xb9, 0x14,
- 0x00, 0x22, 0xeb, 0xaf, 0xf0, 0xf0, 0x00, 0x04, 0x07, 0xf4, 0xb9, 0x04,
- 0x00, 0xb3, 0xa7, 0xf4, 0xff, 0xd5, 0x43, 0x31, 0x20, 0x0f, 0x42, 0x31,
- 0xa0, 0x00, 0xa7, 0x1b, 0x00, 0x01, 0xa7, 0xf4, 0xff, 0xe3, 0x07, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x78, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xeb, 0xbf, 0xf0, 0x58,
+ 0x00, 0x24, 0xc0, 0x10, 0x00, 0x00, 0x4e, 0x0d, 0xa7, 0xfb, 0xff, 0x60,
+ 0xb2, 0x20, 0x00, 0x21, 0xb2, 0x22, 0x00, 0xb0, 0x88, 0xb0, 0x00, 0x1c,
+ 0xc0, 0xe5, 0xff, 0xff, 0xff, 0x91, 0xa7, 0xbe, 0x00, 0x03, 0xa7, 0x84,
+ 0x00, 0x13, 0xa7, 0xbe, 0x00, 0x02, 0xa7, 0x28, 0x00, 0x00, 0xa7, 0x74,
+ 0x00, 0x04, 0xa7, 0x28, 0xff, 0xfe, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04,
+ 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4,
+ 0xa7, 0x28, 0xff, 0xff, 0xa7, 0xf4, 0xff, 0xf5, 0x07, 0x07, 0x07, 0x07,
+ 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x01, 0x25,
+ 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0xb9, 0x00, 0x00, 0xa7, 0x19, 0x00, 0x00,
+ 0xc0, 0x40, 0x00, 0x00, 0x4d, 0xd8, 0xa7, 0x3b, 0x00, 0x01, 0xa7, 0x37,
+ 0x00, 0x23, 0xc0, 0x20, 0x00, 0x00, 0x4d, 0xd1, 0x18, 0x31, 0xa7, 0x1a,
+ 0x00, 0x06, 0x40, 0x10, 0x20, 0x08, 0xa7, 0x3a, 0x00, 0x0e, 0xa7, 0x18,
+ 0x1a, 0x00, 0x40, 0x30, 0x20, 0x00, 0x92, 0x00, 0x20, 0x02, 0x40, 0x10,
+ 0x20, 0x0a, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff,
+ 0xff, 0xac, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xb9, 0x04, 0x00, 0x2b,
+ 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0xb9, 0x04, 0x00, 0x51,
+ 0xa7, 0x5b, 0x00, 0x01, 0xa7, 0x09, 0x0f, 0xf7, 0xb9, 0x21, 0x00, 0x50,
+ 0xa7, 0x24, 0xff, 0xd7, 0x41, 0xeb, 0x20, 0x00, 0x95, 0x0a, 0xe0, 0x00,
+ 0xa7, 0x74, 0x00, 0x08, 0x41, 0x11, 0x40, 0x0e, 0x92, 0x0d, 0x10, 0x00,
+ 0xb9, 0x04, 0x00, 0x15, 0x43, 0x5b, 0x20, 0x00, 0x42, 0x51, 0x40, 0x0e,
+ 0xa7, 0xbb, 0x00, 0x01, 0x41, 0x10, 0x10, 0x01, 0xa7, 0xf4, 0xff, 0xbf,
+ 0xc0, 0x50, 0x00, 0x00, 0x00, 0xd8, 0xc0, 0x10, 0x00, 0x00, 0x4d, 0x8d,
+ 0xa7, 0x48, 0x00, 0x1c, 0x40, 0x40, 0x10, 0x00, 0x50, 0x20, 0x10, 0x0c,
+ 0xa7, 0x48, 0x00, 0x04, 0xe3, 0x20, 0x50, 0x00, 0x00, 0x04, 0x40, 0x40,
+ 0x10, 0x0a, 0x50, 0x30, 0x10, 0x10, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x6b,
+ 0xa7, 0x39, 0x00, 0x40, 0xa7, 0x29, 0x00, 0x00, 0xc0, 0xf4, 0xff, 0xff,
+ 0xff, 0xe4, 0x07, 0x07, 0xb9, 0x04, 0x00, 0x13, 0xa7, 0x2a, 0xff, 0xff,
+ 0xb9, 0x04, 0x00, 0x34, 0xa7, 0x48, 0x00, 0x01, 0x15, 0x24, 0xa7, 0x24,
+ 0x00, 0x07, 0xb9, 0x04, 0x00, 0x21, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x7f,
+ 0xa7, 0x29, 0xff, 0xff, 0x07, 0xfe, 0x07, 0x07, 0xa7, 0x39, 0x00, 0x00,
+ 0x41, 0x13, 0x20, 0x00, 0x95, 0x00, 0x10, 0x00, 0xa7, 0x74, 0x00, 0x05,
+ 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x70, 0xa7, 0x3b, 0x00, 0x01, 0xa7, 0xf4,
+ 0xff, 0xf5, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0,
+ 0x00, 0x00, 0x00, 0x95, 0xa7, 0xfb, 0xff, 0x60, 0xb9, 0x04, 0x00, 0xb2,
+ 0xa7, 0x19, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x00, 0x4d, 0x40, 0x92, 0x00,
+ 0x20, 0x00, 0xa7, 0x2b, 0x00, 0x01, 0xa7, 0x17, 0xff, 0xfc, 0xc0, 0x10,
+ 0x00, 0x00, 0x4d, 0x37, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20, 0x10, 0x00,
+ 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff, 0xff, 0x1d,
+ 0x12, 0x22, 0xa7, 0x74, 0x00, 0x19, 0xa7, 0x19, 0x00, 0x00, 0xc0, 0x40,
+ 0x00, 0x00, 0x00, 0x79, 0xa7, 0x39, 0x00, 0x08, 0xc0, 0x20, 0x00, 0x00,
+ 0x4d, 0x2c, 0x41, 0x21, 0x20, 0x00, 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90,
+ 0x43, 0x22, 0x40, 0x00, 0x42, 0x21, 0xb0, 0x00, 0xa7, 0x1b, 0x00, 0x01,
+ 0xa7, 0x37, 0xff, 0xf2, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xeb, 0xbf,
+ 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0x07, 0x07, 0xeb, 0xaf, 0xf0, 0x50,
+ 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x55, 0xa7, 0xfb, 0xff, 0x60,
+ 0xa7, 0x19, 0x0f, 0xf8, 0xb9, 0x21, 0x00, 0x31, 0xb9, 0x04, 0x00, 0xa2,
+ 0xa7, 0xc4, 0x00, 0x2a, 0xa7, 0xb9, 0x0f, 0xf8, 0xc0, 0x10, 0x00, 0x00,
+ 0x4c, 0xf6, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20, 0x10, 0x00, 0x92, 0x00,
+ 0x10, 0x02, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff,
+ 0xfe, 0xda, 0xa7, 0xbb, 0x00, 0x01, 0xa7, 0x19, 0x00, 0x00, 0xa7, 0xb7,
+ 0x00, 0x17, 0xc0, 0x10, 0x00, 0x00, 0x4c, 0xe1, 0xe3, 0x40, 0xf1, 0x10,
+ 0x00, 0x04, 0xe3, 0x20, 0x10, 0x08, 0x00, 0x91, 0xa7, 0x2a, 0xff, 0xf9,
+ 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xaf, 0xf0, 0xf0, 0x00, 0x04, 0x07, 0xf4,
+ 0xb9, 0x04, 0x00, 0xb3, 0xa7, 0xf4, 0xff, 0xd8, 0xc0, 0x20, 0x00, 0x00,
+ 0x4c, 0xcc, 0x41, 0x31, 0xa0, 0x00, 0x41, 0x21, 0x20, 0x00, 0xa7, 0x1b,
+ 0x00, 0x01, 0xd2, 0x00, 0x30, 0x00, 0x20, 0x0f, 0xa7, 0xf4, 0xff, 0xdd,
+ 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x05,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x3c, 0x28, 0x2b, 0x7c, 0x26, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x2e, 0x2d, 0x2f, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x60, 0x3a, 0x23,
- 0x40, 0x27, 0x3d, 0x22, 0x2e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x6a, 0x6b, 0x6c,
- 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, 0x26, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x2e,
+ 0x2d, 0x2f, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2c,
+ 0x25, 0x5f, 0x3e, 0x3f, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, 0x2e, 0x61, 0x62, 0x63,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x41, 0x42, 0x43,
- 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x30, 0x31, 0x32, 0x33,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6f, 0xff, 0xfe, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
@@ -163,91 +177,103 @@ unsigned char s390x_elf[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x6f, 0xff, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xff, 0xff, 0xfb,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x6f, 0xff, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x43, 0x43, 0x3a, 0x20, 0x28, 0x47, 0x4e, 0x55, 0x29, 0x20, 0x38,
- 0x2e, 0x32, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x39, 0x30,
- 0x35, 0x20, 0x28, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x38,
- 0x2e, 0x32, 0x2e, 0x31, 0x2d, 0x33, 0x29, 0x00, 0x00, 0x2e, 0x73, 0x68,
- 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x70, 0x00, 0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x68, 0x61, 0x73, 0x68,
- 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x73, 0x79, 0x6d, 0x00, 0x2e, 0x64, 0x79,
- 0x6e, 0x73, 0x74, 0x72, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x2e,
- 0x72, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x61,
- 0x6d, 0x69, 0x63, 0x00, 0x2e, 0x67, 0x6f, 0x74, 0x00, 0x2e, 0x62, 0x73,
- 0x73, 0x00, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00,
+ 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0x43, 0x3a,
+ 0x20, 0x28, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x20, 0x31, 0x31, 0x2e,
+ 0x34, 0x2e, 0x30, 0x2d, 0x31, 0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x31,
+ 0x7e, 0x32, 0x32, 0x2e, 0x30, 0x34, 0x29, 0x20, 0x31, 0x31, 0x2e, 0x34,
+ 0x2e, 0x30, 0x00, 0x00, 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61,
+ 0x62, 0x00, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x00, 0x2e, 0x67,
+ 0x6e, 0x75, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x00, 0x2e, 0x64, 0x79, 0x6e,
+ 0x73, 0x79, 0x6d, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x73, 0x74, 0x72, 0x00,
+ 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x2e, 0x64, 0x79, 0x6e, 0x00, 0x2e, 0x74,
+ 0x65, 0x78, 0x74, 0x00, 0x2e, 0x72, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x00,
+ 0x2e, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x00, 0x2e, 0x67, 0x6f,
+ 0x74, 0x00, 0x2e, 0x62, 0x73, 0x73, 0x00, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x13, 0x6f, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0b,
+ 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6f, 0xff, 0xff, 0xf6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x25,
- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x05, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xe8,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
- 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0,
- 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xe0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x37,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4e,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
diff --git a/ui/cocoa.m b/ui/cocoa.m
index df6d13b..145f42d 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -2001,7 +2001,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl)
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
graphic_hw_update(NULL);
- if (qemu_input_is_absolute()) {
+ if (qemu_input_is_absolute(dcl->con)) {
dispatch_async(dispatch_get_main_queue(), ^{
if (![cocoaView isAbsoluteEnabled]) {
if ([cocoaView isMouseGrabbed]) {
diff --git a/ui/console.c b/ui/console.c
index 4a4f19e..8ee66d1 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1434,25 +1434,23 @@ bool qemu_console_is_gl_blocked(QemuConsole *con)
return con->gl_block;
}
-bool qemu_console_is_multihead(DeviceState *dev)
+static bool qemu_graphic_console_is_multihead(QemuGraphicConsole *c)
{
QemuConsole *con;
- Object *obj;
- uint32_t f = 0xffffffff;
- uint32_t h;
QTAILQ_FOREACH(con, &consoles, next) {
- obj = object_property_get_link(OBJECT(con),
- "device", &error_abort);
- if (DEVICE(obj) != dev) {
+ QemuGraphicConsole *candidate;
+
+ if (!QEMU_IS_GRAPHIC_CONSOLE(con)) {
continue;
}
- h = object_property_get_uint(OBJECT(con),
- "head", &error_abort);
- if (f == 0xffffffff) {
- f = h;
- } else if (h != f) {
+ candidate = QEMU_GRAPHIC_CONSOLE(con);
+ if (candidate->device != c->device) {
+ continue;
+ }
+
+ if (candidate->head != c->head) {
return true;
}
}
@@ -1468,7 +1466,7 @@ char *qemu_console_get_label(QemuConsole *con)
bool multihead;
dev = DEVICE(c->device);
- multihead = qemu_console_is_multihead(dev);
+ multihead = qemu_graphic_console_is_multihead(c);
if (multihead) {
return g_strdup_printf("%s.%d", dev->id ?
dev->id :
diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index 36f7349..49da9cc 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -386,7 +386,7 @@ dbus_mouse_rel_motion(DBusDisplayConsole *ddc,
{
trace_dbus_mouse_rel_motion(dx, dy);
- if (qemu_input_is_absolute()) {
+ if (qemu_input_is_absolute(ddc->dcl.con)) {
g_dbus_method_invocation_return_error(
invocation, DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_INVALID,
@@ -453,7 +453,7 @@ dbus_mouse_set_pos(DBusDisplayConsole *ddc,
trace_dbus_mouse_set_pos(x, y);
- if (!qemu_input_is_absolute()) {
+ if (!qemu_input_is_absolute(ddc->dcl.con)) {
g_dbus_method_invocation_return_error(
invocation, DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_INVALID,
@@ -514,7 +514,7 @@ static void
dbus_mouse_update_is_absolute(DBusDisplayConsole *ddc)
{
g_object_set(ddc->iface_mouse,
- "is-absolute", qemu_input_is_absolute(),
+ "is-absolute", qemu_input_is_absolute(ddc->dcl.con),
NULL);
}
diff --git a/ui/gtk.c b/ui/gtk.c
index 3373427..935de12 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -204,7 +204,7 @@ static void gd_update_cursor(VirtualConsole *vc)
}
window = gtk_widget_get_window(GTK_WIDGET(vc->gfx.drawing_area));
- if (s->full_screen || qemu_input_is_absolute() || s->ptr_owner == vc) {
+ if (s->full_screen || qemu_input_is_absolute(vc->gfx.dcl.con) || s->ptr_owner == vc) {
gdk_window_set_cursor(window, s->null_cursor);
} else {
gdk_window_set_cursor(window, NULL);
@@ -453,7 +453,7 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
gint x_root, y_root;
if (!gtk_widget_get_realized(vc->gfx.drawing_area) ||
- qemu_input_is_absolute()) {
+ qemu_input_is_absolute(dcl->con)) {
return;
}
@@ -689,7 +689,7 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
s = container_of(notify, GtkDisplayState, mouse_mode_notifier);
/* release the grab at switching to absolute mode */
- if (qemu_input_is_absolute() && s->ptr_owner) {
+ if (s->ptr_owner && qemu_input_is_absolute(s->ptr_owner->gfx.dcl.con)) {
if (!s->ptr_owner->window) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
FALSE);
@@ -726,6 +726,10 @@ static void gd_set_ui_refresh_rate(VirtualConsole *vc, int refresh_rate)
{
QemuUIInfo info;
+ if (!dpy_ui_info_supported(vc->gfx.dcl.con)) {
+ return;
+ }
+
info = *dpy_get_ui_info(vc->gfx.dcl.con);
info.refresh_rate = refresh_rate;
dpy_set_ui_info(vc->gfx.dcl.con, &info, true);
@@ -735,6 +739,10 @@ static void gd_set_ui_size(VirtualConsole *vc, gint width, gint height)
{
QemuUIInfo info;
+ if (!dpy_ui_info_supported(vc->gfx.dcl.con)) {
+ return;
+ }
+
info = *dpy_get_ui_info(vc->gfx.dcl.con);
info.width = width;
info.height = height;
@@ -903,7 +911,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
x = (motion->x - mx) / vc->gfx.scale_x * ws;
y = (motion->y - my) / vc->gfx.scale_y * ws;
- if (qemu_input_is_absolute()) {
+ if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
if (x < 0 || y < 0 ||
x >= surface_width(vc->gfx.ds) ||
y >= surface_height(vc->gfx.ds)) {
@@ -923,7 +931,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
s->last_y = y;
s->last_set = TRUE;
- if (!qemu_input_is_absolute() && s->ptr_owner == vc) {
+ if (!qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner == vc) {
GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area);
GdkDisplay *dpy = gtk_widget_get_display(widget);
GdkWindow *win = gtk_widget_get_window(widget);
@@ -965,7 +973,7 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
/* implicitly grab the input at the first click in the relative mode */
if (button->button == 1 && button->type == GDK_BUTTON_PRESS &&
- !qemu_input_is_absolute() && s->ptr_owner != vc) {
+ !qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner != vc) {
if (!vc->window) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
TRUE);
diff --git a/ui/input.c b/ui/input.c
index 1aad64b..cbe8573 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -56,7 +56,7 @@ QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
s->id = id++;
QTAILQ_INSERT_TAIL(&handlers, s, node);
- qemu_input_check_mode_change();
+ notifier_list_notify(&mouse_mode_notifiers, NULL);
return s;
}
@@ -64,21 +64,21 @@ void qemu_input_handler_activate(QemuInputHandlerState *s)
{
QTAILQ_REMOVE(&handlers, s, node);
QTAILQ_INSERT_HEAD(&handlers, s, node);
- qemu_input_check_mode_change();
+ notifier_list_notify(&mouse_mode_notifiers, NULL);
}
void qemu_input_handler_deactivate(QemuInputHandlerState *s)
{
QTAILQ_REMOVE(&handlers, s, node);
QTAILQ_INSERT_TAIL(&handlers, s, node);
- qemu_input_check_mode_change();
+ notifier_list_notify(&mouse_mode_notifiers, NULL);
}
void qemu_input_handler_unregister(QemuInputHandlerState *s)
{
QTAILQ_REMOVE(&handlers, s, node);
g_free(s);
- qemu_input_check_mode_change();
+ notifier_list_notify(&mouse_mode_notifiers, NULL);
}
void qemu_input_handler_bind(QemuInputHandlerState *s,
@@ -494,12 +494,12 @@ void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
}
}
-bool qemu_input_is_absolute(void)
+bool qemu_input_is_absolute(QemuConsole *con)
{
QemuInputHandlerState *s;
s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
- NULL);
+ con);
return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
}
@@ -583,21 +583,6 @@ void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value,
qemu_input_event_send(src, &evt);
}
-void qemu_input_check_mode_change(void)
-{
- static int current_is_absolute;
- int is_absolute;
-
- is_absolute = qemu_input_is_absolute();
-
- if (is_absolute != current_is_absolute) {
- trace_input_mouse_mode(is_absolute);
- notifier_list_notify(&mouse_mode_notifiers, NULL);
- }
-
- current_is_absolute = is_absolute;
-}
-
void qemu_add_mouse_mode_change_notifier(Notifier *notify)
{
notifier_list_add(&mouse_mode_notifiers, notify);
@@ -657,6 +642,6 @@ bool qemu_mouse_set(int index, Error **errp)
}
qemu_input_handler_activate(s);
- qemu_input_check_mode_change();
+ notifier_list_notify(&mouse_mode_notifiers, NULL);
return true;
}
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index be00a96..b43ec38 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -96,7 +96,9 @@ static const struct {
} drm_format_pixman_map[] = {
{ DRM_FORMAT_RGB888, PIXMAN_LE_r8g8b8 },
{ DRM_FORMAT_ARGB8888, PIXMAN_LE_a8r8g8b8 },
- { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 }
+ { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 },
+ { DRM_FORMAT_XBGR8888, PIXMAN_LE_x8b8g8r8 },
+ { DRM_FORMAT_ABGR8888, PIXMAN_LE_a8b8g8r8 },
};
pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format)
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 178cc05..fbfdb64 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -203,7 +203,7 @@ static void sdl_hide_cursor(struct sdl2_console *scon)
SDL_ShowCursor(SDL_DISABLE);
SDL_SetCursor(sdl_cursor_hidden);
- if (!qemu_input_is_absolute()) {
+ if (!qemu_input_is_absolute(scon->dcl.con)) {
SDL_SetRelativeMouseMode(SDL_TRUE);
}
}
@@ -214,12 +214,12 @@ static void sdl_show_cursor(struct sdl2_console *scon)
return;
}
- if (!qemu_input_is_absolute()) {
+ if (!qemu_input_is_absolute(scon->dcl.con)) {
SDL_SetRelativeMouseMode(SDL_FALSE);
}
if (guest_cursor &&
- (gui_grab || qemu_input_is_absolute() || absolute_enabled)) {
+ (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled)) {
SDL_SetCursor(guest_sprite);
} else {
SDL_SetCursor(sdl_cursor_normal);
@@ -245,7 +245,7 @@ static void sdl_grab_start(struct sdl2_console *scon)
}
if (guest_cursor) {
SDL_SetCursor(guest_sprite);
- if (!qemu_input_is_absolute() && !absolute_enabled) {
+ if (!qemu_input_is_absolute(scon->dcl.con) && !absolute_enabled) {
SDL_WarpMouseInWindow(scon->real_window, guest_x, guest_y);
}
} else {
@@ -280,7 +280,7 @@ static void absolute_mouse_grab(struct sdl2_console *scon)
static void sdl_mouse_mode_change(Notifier *notify, void *data)
{
- if (qemu_input_is_absolute()) {
+ if (qemu_input_is_absolute(sdl2_console[0].dcl.con)) {
if (!absolute_enabled) {
absolute_enabled = 1;
SDL_SetRelativeMouseMode(SDL_FALSE);
@@ -311,7 +311,7 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
prev_state = state;
}
- if (qemu_input_is_absolute()) {
+ if (qemu_input_is_absolute(scon->dcl.con)) {
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X,
x, 0, surface_width(scon->surface));
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y,
@@ -497,7 +497,7 @@ static void handle_mousemotion(SDL_Event *ev)
return;
}
- if (qemu_input_is_absolute() || absolute_enabled) {
+ if (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
int scr_w, scr_h;
SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h);
max_x = scr_w - 1;
@@ -513,7 +513,7 @@ static void handle_mousemotion(SDL_Event *ev)
sdl_grab_start(scon);
}
}
- if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
+ if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel,
ev->motion.x, ev->motion.y, ev->motion.state);
}
@@ -530,7 +530,7 @@ static void handle_mousebutton(SDL_Event *ev)
}
bev = &ev->button;
- if (!gui_grab && !qemu_input_is_absolute()) {
+ if (!gui_grab && !qemu_input_is_absolute(scon->dcl.con)) {
if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) {
/* start grabbing all events */
sdl_grab_start(scon);
@@ -603,7 +603,7 @@ static void handle_windowevent(SDL_Event *ev)
}
/* fall through */
case SDL_WINDOWEVENT_ENTER:
- if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) {
+ if (!gui_grab && (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled)) {
absolute_mouse_grab(scon);
}
/* If a new console window opened using a hotkey receives the
@@ -733,9 +733,9 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
if (!guest_cursor) {
sdl_show_cursor(scon);
}
- if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
+ if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
SDL_SetCursor(guest_sprite);
- if (!qemu_input_is_absolute() && !absolute_enabled) {
+ if (!qemu_input_is_absolute(scon->dcl.con) && !absolute_enabled) {
SDL_WarpMouseInWindow(scon->real_window, x, y);
}
}
@@ -773,7 +773,7 @@ static void sdl_mouse_define(DisplayChangeListener *dcl,
return;
}
if (guest_cursor &&
- (gui_grab || qemu_input_is_absolute() || absolute_enabled)) {
+ (gui_grab || qemu_input_is_absolute(dcl->con) || absolute_enabled)) {
SDL_SetCursor(guest_sprite);
}
}
diff --git a/ui/spice-input.c b/ui/spice-input.c
index bbd5025..a5c5d78 100644
--- a/ui/spice-input.c
+++ b/ui/spice-input.c
@@ -224,7 +224,7 @@ static const SpiceTabletInterface tablet_interface = {
static void mouse_mode_notifier(Notifier *notifier, void *data)
{
QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
- bool is_absolute = qemu_input_is_absolute();
+ bool is_absolute = qemu_input_is_absolute(NULL);
if (pointer->absolute == is_absolute) {
return;
diff --git a/ui/trace-events b/ui/trace-events
index 76b19a2..16c35c9 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -92,7 +92,6 @@ input_event_rel(int conidx, const char *axis, int value) "con %d, axis %s, value
input_event_abs(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x"
input_event_mtt(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x"
input_event_sync(void) ""
-input_mouse_mode(int absolute) "absolute %d"
# sdl2-input.c
sdl2_process_key(int sdl_scancode, int qcode, const char *action) "translated SDL scancode %d to QKeyCode %d (%s)"
diff --git a/ui/vnc.c b/ui/vnc.c
index acbb88c..6056028 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1771,7 +1771,7 @@ uint32_t read_u32(uint8_t *data, size_t offset)
static void check_pointer_type_change(Notifier *notifier, void *data)
{
VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
- int absolute = qemu_input_is_absolute();
+ int absolute = qemu_input_is_absolute(vs->vd->dcl.con);
if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
vnc_lock_output(vs);
diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index e2690c5..037d641 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -22,9 +22,9 @@
*/
/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
-#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
-#endif
+#define _FORTIFY_SOURCE 0
+
#include "qemu/osdep.h"
#include <pthread.h>
#include "qemu/coroutine_int.h"
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index ddc98fb..7b304c7 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -19,9 +19,9 @@
*/
/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
-#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
-#endif
+#define _FORTIFY_SOURCE 0
+
#include "qemu/osdep.h"
#include <ucontext.h>
#include "qemu/coroutine_int.h"
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 19a0ea7..55b0189 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -479,7 +479,7 @@ int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
return ret;
}
-EXCEPTION_DISPOSITION
+QEMU_USED EXCEPTION_DISPOSITION
win32_close_exception_handler(struct _EXCEPTION_RECORD *exception_record,
void *registration, struct _CONTEXT *context,
void *dispatcher)