From patchwork Thu Sep 3 07:43:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752573 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2C7C6739 for ; Thu, 3 Sep 2020 07:44:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F08CB2071B for ; Thu, 3 Sep 2020 07:44:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gN6BnqOL" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F08CB2071B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:42416 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjum-0000x2-Ue for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:44:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43278) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuC-00081V-1S for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:36 -0400 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]:34238) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDju8-0003qr-Mn for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:35 -0400 Received: by mail-pg1-x541.google.com with SMTP id u13so1463872pgh.1 for ; Thu, 03 Sep 2020 00:43:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W6KPp+bY7QhvrPjQuzc5G0s+mWhPDfMNCdKRNThSh6I=; b=gN6BnqOLjNMktKCnAFxh/EAMph86YRrSlcF0UsHLYhuNKcZ4beZ+uMelbktCIdXEP+ mbS1fwcH3GjLQjATStmhP+W9+4VHvq1YtoNNU+OF8JWFFko6aCa+aLU8ZK5/vFwu+e0Q PWzkbdKKLJ3EOcP2xc0u26DSis629dfYl9x7BBmFPa2yPJ6UERzPIrE3zMDu6x0pYRzJ oLzqKa43/ucdS0MQqox701TB0PzVv0eHHjp0cTem/nmQ/sCc9zyYsuRy1zQvli3GEjjI 8LEeLYLQpeEeW9vSg7aU9uqon+vDjKgiJT9MNGcODJ2yltr+0L5jjWIl8ydNLBJTqMqy U4Cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W6KPp+bY7QhvrPjQuzc5G0s+mWhPDfMNCdKRNThSh6I=; b=tkA6AT/WX0+sYO7p5mqUnyxf2QlMqOhkU261BPwlVnvs+FLKa78EO3ttvODllbICZE OFIaedHzhdqAh/40ly0RbY8GGtZMRRsb+GJ+yUNOzHEVhA5SNGY9oFuFp20lomUkMCy9 MoTHXy8j5NVj2F0y/l7aPcvjjnV6nt3Ht8qAj49Jshw4/e1AQFnBNg3HagH2IW7EaWcd mVOQ95jxfNpRXkpXpYW8khGqwhfl3Hwo8V2Rk/ChvAEiRIUqvCCR6TVR+TRXs28XqkpJ etXIrr56ARPfCjNqiH/F2Y2ah/E0xMXNpMa6IeQArlMjRQUwXo7z/cOnqOB/JtZQWtyi nhoA== X-Gm-Message-State: AOAM533EWnbUSO7Js6GDWkdHTzPNSSPFWT0i4aRgpN8b27fboWKYQ1ey 0RVOFggkZ8JvHfFN/CIDWL01SCIIgx6KHA== X-Google-Smtp-Source: ABdhPJy82Qlz5C0x0RTpK4Cj9duofmHEA5GbzVt9WkTi0UomsnXi9K0lVrWLo6J0GSZfn+81HBoo+Q== X-Received: by 2002:a62:5fc4:: with SMTP id t187mr2650250pfb.34.1599119010850; Thu, 03 Sep 2020 00:43:30 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:30 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 01/12] configure: fixes dtc not cloned when running msys2 CI Date: Thu, 3 Sep 2020 15:43:02 +0800 Message-Id: <20200903074313.1498-2-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::541; envelope-from=luoyonggang@gmail.com; helo=mail-pg1-x541.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Symlink dtc after git submodule update, because on win32 symlink to non-exist folder are forbidden. Signed-off-by: Yonggang Luo --- configure | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 8a3acef89d..30f8c4db29 100755 --- a/configure +++ b/configure @@ -2053,9 +2053,6 @@ fi if test "$meson" = git; then git_submodules="${git_submodules} meson" fi -if test "$git_update" = yes; then - (cd "${source_path}" && GIT="$git" "./scripts/git-submodule.sh" update "$git_submodules") -fi case "$meson" in git | internal) @@ -4261,9 +4258,6 @@ EOF if test -d "${source_path}/dtc/libfdt" || test -e "${source_path}/.git" ; then fdt=git mkdir -p dtc - if [ "$pwd_is_source_path" != "y" ] ; then - symlink "$source_path/dtc/Makefile" "dtc/Makefile" - fi fdt_cflags="-I${source_path}/dtc/libfdt" fdt_ldflags="-L$PWD/dtc/libfdt" fdt_libs="$fdt_libs" @@ -6593,6 +6587,16 @@ if test "$cpu" = "s390x" ; then fi fi +if test $git_update = 'yes' ; then + (cd "${source_path}" && GIT="$git" "./scripts/git-submodule.sh" update "$git_submodules") + + if test "$fdt" = "git" ; then + if [ "$pwd_is_source_path" != "y" ] ; then + symlink "$source_path/dtc/Makefile" "dtc/Makefile" + fi + fi +fi + # Check that the C++ compiler exists and works with the C compiler. # All the QEMU_CXXFLAGS are based on QEMU_CFLAGS. Keep this at the end to don't miss any other that could be added. if has $cxx; then From patchwork Thu Sep 3 07:43:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752575 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EAEB8739 for ; Thu, 3 Sep 2020 07:44:32 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 749782071B for ; Thu, 3 Sep 2020 07:44:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="in3HYCTD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 749782071B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:44232 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjv5-0001go-GL for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:44:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43314) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuH-0008BV-S3 for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:41 -0400 Received: from mail-pf1-x443.google.com ([2607:f8b0:4864:20::443]:42712) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuD-0003rG-BE for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:41 -0400 Received: by mail-pf1-x443.google.com with SMTP id 17so1602893pfw.9 for ; Thu, 03 Sep 2020 00:43:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3CCQ4/urH9bUSiHO0KVHncurks4pfIdxmYpVvda1T00=; b=in3HYCTDLtkQ6uOZ4r8XoHFP8dZozqr7dHHjjnutCaqDFhrDwN3ZSfVQzRfoH7Kkex dRIwxYWlhsyHIOYxiAW6bAg4Mb7IrnTEXlbICkWUUOW2oFsMcaEWr35KXzv70rnHRf9n +fTFHPFMiScwkBbg/AZ20L1q11r9djaHCR1DSatboPT9dF7rOHRdWq9swzsn7OxP9Kei Ty3VHKD+JptTmuq10clg4PdENo2seu3lCiW2gnOGrzihXIT86m1+oRaTs0pP8R6ifRLH zRk4j2NHkUjzBOWzIT9ib/2TgSTU70TzrOGb/DiCEdj2jOt1xnIwpykW1zQttG1qTvnL YOMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3CCQ4/urH9bUSiHO0KVHncurks4pfIdxmYpVvda1T00=; b=NltQHQG3pE2omndHNZkZgR9Ti908hEiaMzIJfbfdKIJDVTBoy8qrxPDLFTmguSLXvE TMLJv639pr+fzK9GvM1Ona1FWThzhnaHwY7nAfDeDaZ9ZUzlkuwUuPREqWfElbQ+9Suz 4wiGDFn+PkfYOLxruaSw1IyZXMWoRLeTFYS83hJwqO1jGAafeLOQMkjx4/8uLGoy9YQV +/MaAF6jBARXt5Cnet0S52B2JO662LkJuX0Rkb9TFaFFgwHPuyDi5d5GSSiD2i3xzZ68 iarm5dPfhKO6yGw3UPl+y1MtyQW4U4SmWJ1mPsV7kM3MRzHgTkSeXIpdHfKWs0xYS95W kw5Q== X-Gm-Message-State: AOAM531JXVp8N2rjh788Ut9zErN3wGZBZW5E0+A0O7RcABb4oHE/h25+ xDNViZ8oqC0QIavjGg2/7o5SYRaZ2P7lzg== X-Google-Smtp-Source: ABdhPJw+DVCguQD1FEvOh0zIejRP4gx2idYUv3rYWTeuQGTeiK+VL4iO1+7uNW8BfPwCd7IzivxucA== X-Received: by 2002:a62:8c86:: with SMTP id m128mr2610825pfd.111.1599119013754; Thu, 03 Sep 2020 00:43:33 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:32 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 02/12] meson: Convert undefsym.sh to undefsym.py Date: Thu, 3 Sep 2020 15:43:03 +0800 Message-Id: <20200903074313.1498-3-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::443; envelope-from=luoyonggang@gmail.com; helo=mail-pf1-x443.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" undefsym.sh are not msys2 compatible, convert it to python script Signed-off-by: Yonggang Luo --- meson.build | 2994 +++++++++++++++++++++---------------------- scripts/undefsym.py | 57 + scripts/undefsym.sh | 20 - 3 files changed, 1554 insertions(+), 1517 deletions(-) create mode 100644 scripts/undefsym.py delete mode 100755 scripts/undefsym.sh diff --git a/meson.build b/meson.build index 55c7d2318c..c9f5d05664 100644 --- a/meson.build +++ b/meson.build @@ -1,1497 +1,1497 @@ -project('qemu', ['c'], meson_version: '>=0.55.0', - default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', - 'b_lundef=false','b_colorout=auto'], - version: run_command('head', meson.source_root() / 'VERSION').stdout().strip()) - -not_found = dependency('', required: false) -if meson.version().version_compare('>=0.56.0') - keyval = import('keyval') -else - keyval = import('unstable-keyval') -endif -ss = import('sourceset') - -sh = find_program('sh') -cc = meson.get_compiler('c') -config_host = keyval.load(meson.current_build_dir() / 'config-host.mak') -config_all_disas = keyval.load(meson.current_build_dir() / 'config-all-disas.mak') -enable_modules = 'CONFIG_MODULES' in config_host -enable_static = 'CONFIG_STATIC' in config_host -build_docs = 'BUILD_DOCS' in config_host -qemu_datadir = get_option('datadir') / get_option('qemu_suffix') -qemu_docdir = get_option('docdir') / get_option('qemu_suffix') -config_host_data = configuration_data() -genh = [] - -target_dirs = config_host['TARGET_DIRS'].split() -have_user = false -have_system = false -foreach target : target_dirs - have_user = have_user or target.endswith('-user') - have_system = have_system or target.endswith('-softmmu') -endforeach -have_tools = 'CONFIG_TOOLS' in config_host -have_block = have_system or have_tools - -add_project_arguments(config_host['QEMU_CFLAGS'].split(), - native: false, language: ['c', 'objc']) -add_project_arguments(config_host['QEMU_CXXFLAGS'].split(), - native: false, language: 'cpp') -add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(), - native: false, language: ['c', 'cpp', 'objc']) -add_project_arguments(config_host['QEMU_INCLUDES'].split(), - language: ['c', 'cpp', 'objc']) - -python = import('python').find_installation() - -link_language = meson.get_external_property('link_language', 'cpp') -if link_language == 'cpp' - add_languages('cpp', required: true, native: false) -endif -if host_machine.system() == 'darwin' - add_languages('objc', required: false, native: false) -endif - -if 'SPARSE_CFLAGS' in config_host - run_target('sparse', - command: [find_program('scripts/check_sparse.py'), - config_host['SPARSE_CFLAGS'].split(), - 'compile_commands.json']) -endif - -configure_file(input: files('scripts/ninjatool.py'), - output: 'ninjatool', - configuration: config_host) - -supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] -supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64', - 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] - -cpu = host_machine.cpu_family() -targetos = host_machine.system() - -m = cc.find_library('m', required: false) -util = cc.find_library('util', required: false) -winmm = [] -socket = [] -version_res = [] -coref = [] -iokit = [] -cocoa = [] -hvf = [] -if targetos == 'windows' - socket = cc.find_library('ws2_32') - winmm = cc.find_library('winmm') - - win = import('windows') - version_res = win.compile_resources('version.rc', - depend_files: files('pc-bios/qemu-nsis.ico'), - include_directories: include_directories('.')) -elif targetos == 'darwin' - coref = dependency('appleframeworks', modules: 'CoreFoundation') - iokit = dependency('appleframeworks', modules: 'IOKit') - cocoa = dependency('appleframeworks', modules: 'Cocoa') - hvf = dependency('appleframeworks', modules: 'Hypervisor') -elif targetos == 'sunos' - socket = [cc.find_library('socket'), - cc.find_library('nsl'), - cc.find_library('resolv')] -elif targetos == 'haiku' - socket = [cc.find_library('posix_error_mapper'), - cc.find_library('network'), - cc.find_library('bsd')] -endif -glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(), - link_args: config_host['GLIB_LIBS'].split()) -gio = not_found -if 'CONFIG_GIO' in config_host - gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), - link_args: config_host['GIO_LIBS'].split()) -endif -lttng = not_found -if 'CONFIG_TRACE_UST' in config_host - lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split()) -endif -urcubp = not_found -if 'CONFIG_TRACE_UST' in config_host - urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split()) -endif -nettle = not_found -if 'CONFIG_NETTLE' in config_host - nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(), - link_args: config_host['NETTLE_LIBS'].split()) -endif -gnutls = not_found -if 'CONFIG_GNUTLS' in config_host - gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(), - link_args: config_host['GNUTLS_LIBS'].split()) -endif -pixman = not_found -if have_system or have_tools - pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8', - method: 'pkg-config', static: enable_static) -endif -pam = not_found -if 'CONFIG_AUTH_PAM' in config_host - pam = cc.find_library('pam') -endif -libaio = cc.find_library('aio', required: false) -zlib = dependency('zlib', required: true, static: enable_static) -linux_io_uring = not_found -if 'CONFIG_LINUX_IO_URING' in config_host - linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(), - link_args: config_host['LINUX_IO_URING_LIBS'].split()) -endif -libxml2 = not_found -if 'CONFIG_LIBXML2' in config_host - libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(), - link_args: config_host['LIBXML2_LIBS'].split()) -endif -libnfs = not_found -if 'CONFIG_LIBNFS' in config_host - libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split()) -endif -libattr = not_found -if 'CONFIG_ATTR' in config_host - libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split()) -endif -seccomp = not_found -if 'CONFIG_SECCOMP' in config_host - seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(), - link_args: config_host['SECCOMP_LIBS'].split()) -endif -libcap_ng = not_found -if 'CONFIG_LIBCAP_NG' in config_host - libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split()) -endif -if get_option('xkbcommon').auto() and not have_system and not have_tools - xkbcommon = not_found -else - xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'), - method: 'pkg-config', static: enable_static) -endif -slirp = not_found -if config_host.has_key('CONFIG_SLIRP') - slirp = declare_dependency(compile_args: config_host['SLIRP_CFLAGS'].split(), - link_args: config_host['SLIRP_LIBS'].split()) -endif -vde = not_found -if config_host.has_key('CONFIG_VDE') - vde = declare_dependency(link_args: config_host['VDE_LIBS'].split()) -endif -pulse = not_found -if 'CONFIG_LIBPULSE' in config_host - pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(), - link_args: config_host['PULSE_LIBS'].split()) -endif -alsa = not_found -if 'CONFIG_ALSA' in config_host - alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(), - link_args: config_host['ALSA_LIBS'].split()) -endif -jack = not_found -if 'CONFIG_LIBJACK' in config_host - jack = declare_dependency(link_args: config_host['JACK_LIBS'].split()) -endif -spice = not_found -if 'CONFIG_SPICE' in config_host - spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(), - link_args: config_host['SPICE_LIBS'].split()) -endif -rt = cc.find_library('rt', required: false) -libmpathpersist = not_found -if config_host.has_key('CONFIG_MPATH') - libmpathpersist = cc.find_library('mpathpersist') -endif -libiscsi = not_found -if 'CONFIG_LIBISCSI' in config_host - libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(), - link_args: config_host['LIBISCSI_LIBS'].split()) -endif -zstd = not_found -if 'CONFIG_ZSTD' in config_host - zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(), - link_args: config_host['ZSTD_LIBS'].split()) -endif -gbm = not_found -if 'CONFIG_GBM' in config_host - gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(), - link_args: config_host['GBM_LIBS'].split()) -endif -virgl = not_found -if 'CONFIG_VIRGL' in config_host - virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(), - link_args: config_host['VIRGL_LIBS'].split()) -endif -curl = not_found -if 'CONFIG_CURL' in config_host - curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(), - link_args: config_host['CURL_LIBS'].split()) -endif -libudev = not_found -if 'CONFIG_LIBUDEV' in config_host - libudev = declare_dependency(link_args: config_host['LIBUDEV_LIBS'].split()) -endif -brlapi = not_found -if 'CONFIG_BRLAPI' in config_host - brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split()) -endif - -sdl = not_found -if have_system - sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static) - sdl_image = not_found -endif -if sdl.found() - # work around 2.0.8 bug - sdl = declare_dependency(compile_args: '-Wno-undef', - dependencies: sdl) - sdl_image = dependency('SDL2_image', required: get_option('sdl_image'), - method: 'pkg-config', static: enable_static) -else - if get_option('sdl_image').enabled() - error('sdl-image required, but SDL was @0@', - get_option('sdl').disabled() ? 'disabled' : 'not found') - endif - sdl_image = not_found -endif - -rbd = not_found -if 'CONFIG_RBD' in config_host - rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split()) -endif -glusterfs = not_found -if 'CONFIG_GLUSTERFS' in config_host - glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(), - link_args: config_host['GLUSTERFS_LIBS'].split()) -endif -libssh = not_found -if 'CONFIG_LIBSSH' in config_host - libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(), - link_args: config_host['LIBSSH_LIBS'].split()) -endif -libbzip2 = not_found -if 'CONFIG_BZIP2' in config_host - libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split()) -endif -liblzfse = not_found -if 'CONFIG_LZFSE' in config_host - liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split()) -endif -oss = not_found -if 'CONFIG_AUDIO_OSS' in config_host - oss = declare_dependency(link_args: config_host['OSS_LIBS'].split()) -endif -dsound = not_found -if 'CONFIG_AUDIO_DSOUND' in config_host - dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split()) -endif -coreaudio = not_found -if 'CONFIG_AUDIO_COREAUDIO' in config_host - coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split()) -endif -opengl = not_found -if 'CONFIG_OPENGL' in config_host - opengl = declare_dependency(link_args: config_host['OPENGL_LIBS'].split()) -else -endif -gtk = not_found -if 'CONFIG_GTK' in config_host - gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(), - link_args: config_host['GTK_LIBS'].split()) -endif -vte = not_found -if 'CONFIG_VTE' in config_host - vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(), - link_args: config_host['VTE_LIBS'].split()) -endif -x11 = not_found -if 'CONFIG_X11' in config_host - x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(), - link_args: config_host['X11_LIBS'].split()) -endif -curses = not_found -if 'CONFIG_CURSES' in config_host - curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(), - link_args: config_host['CURSES_LIBS'].split()) -endif -iconv = not_found -if 'CONFIG_ICONV' in config_host - iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(), - link_args: config_host['ICONV_LIBS'].split()) -endif -gio = not_found -if 'CONFIG_GIO' in config_host - gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), - link_args: config_host['GIO_LIBS'].split()) -endif -vnc = not_found -png = not_found -jpeg = not_found -sasl = not_found -if get_option('vnc').enabled() - vnc = declare_dependency() # dummy dependency - png = dependency('libpng', required: get_option('vnc_png'), - method: 'pkg-config', static: enable_static) - jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'], - required: get_option('vnc_jpeg'), - static: enable_static) - sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'], - required: get_option('vnc_sasl'), - static: enable_static) - if sasl.found() - sasl = declare_dependency(dependencies: sasl, - compile_args: '-DSTRUCT_IOVEC_DEFINED') - endif -endif -fdt = not_found -if 'CONFIG_FDT' in config_host - fdt = declare_dependency(compile_args: config_host['FDT_CFLAGS'].split(), - link_args: config_host['FDT_LIBS'].split()) -endif -snappy = not_found -if 'CONFIG_SNAPPY' in config_host - snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split()) -endif -lzo = not_found -if 'CONFIG_LZO' in config_host - lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split()) -endif -rdma = not_found -if 'CONFIG_RDMA' in config_host - rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split()) -endif -numa = not_found -if 'CONFIG_NUMA' in config_host - numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split()) -endif -xen = not_found -if 'CONFIG_XEN_BACKEND' in config_host - xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(), - link_args: config_host['XEN_LIBS'].split()) -endif -cacard = not_found -if 'CONFIG_SMARTCARD' in config_host - cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(), - link_args: config_host['SMARTCARD_LIBS'].split()) -endif -u2f = not_found -if have_system - u2f = dependency('u2f-emu', required: get_option('u2f'), - method: 'pkg-config', - static: enable_static) -endif -usbredir = not_found -if 'CONFIG_USB_REDIR' in config_host - usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(), - link_args: config_host['USB_REDIR_LIBS'].split()) -endif -libusb = not_found -if 'CONFIG_USB_LIBUSB' in config_host - libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(), - link_args: config_host['LIBUSB_LIBS'].split()) -endif -capstone = not_found -if 'CONFIG_CAPSTONE' in config_host - capstone = declare_dependency(compile_args: config_host['CAPSTONE_CFLAGS'].split(), - link_args: config_host['CAPSTONE_LIBS'].split()) -endif -libpmem = not_found -if 'CONFIG_LIBPMEM' in config_host - libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(), - link_args: config_host['LIBPMEM_LIBS'].split()) -endif -libdaxctl = not_found -if 'CONFIG_LIBDAXCTL' in config_host - libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split()) -endif - -# Create config-host.h - -config_host_data.set('CONFIG_SDL', sdl.found()) -config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) -config_host_data.set('CONFIG_VNC', vnc.found()) -config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) -config_host_data.set('CONFIG_VNC_PNG', png.found()) -config_host_data.set('CONFIG_VNC_SASL', sasl.found()) -config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found()) -config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version())) -config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0]) -config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) -config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) - -arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] -strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'qemu_confdir', 'qemu_datadir', - 'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir', - 'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath'] -foreach k, v: config_host - if arrays.contains(k) - if v != '' - v = '"' + '", "'.join(v.split()) + '", ' - endif - config_host_data.set(k, v) - elif k == 'ARCH' - config_host_data.set('HOST_' + v.to_upper(), 1) - elif strings.contains(k) - if not k.startswith('CONFIG_') - k = 'CONFIG_' + k.to_upper() - endif - config_host_data.set_quoted(k, v) - elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_') - config_host_data.set(k, v == 'y' ? 1 : v) - endif -endforeach -genh += configure_file(output: 'config-host.h', configuration: config_host_data) - -minikconf = find_program('scripts/minikconf.py') -config_devices_mak_list = [] -config_devices_h = {} -config_target_h = {} -config_target_mak = {} -kconfig_external_symbols = [ - 'CONFIG_KVM', - 'CONFIG_XEN', - 'CONFIG_TPM', - 'CONFIG_SPICE', - 'CONFIG_IVSHMEM', - 'CONFIG_OPENGL', - 'CONFIG_X11', - 'CONFIG_VHOST_USER', - 'CONFIG_VHOST_KERNEL', - 'CONFIG_VIRTFS', - 'CONFIG_LINUX', - 'CONFIG_PVRDMA', -] -ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS'] -foreach target : target_dirs - config_target = keyval.load(meson.current_build_dir() / target / 'config-target.mak') - - config_target_data = configuration_data() - foreach k, v: config_target - if not k.startswith('TARGET_') and not k.startswith('CONFIG_') - # do nothing - elif ignored.contains(k) - # do nothing - elif k == 'TARGET_BASE_ARCH' - config_target_data.set('TARGET_' + v.to_upper(), 1) - elif k == 'TARGET_NAME' - config_target_data.set_quoted(k, v) - elif v == 'y' - config_target_data.set(k, 1) - else - config_target_data.set(k, v) - endif - endforeach - config_target_h += {target: configure_file(output: target + '-config-target.h', - configuration: config_target_data)} - - if target.endswith('-softmmu') - base_kconfig = [] - foreach sym : kconfig_external_symbols - if sym in config_target or sym in config_host - base_kconfig += '@0@=y'.format(sym) - endif - endforeach - - config_devices_mak = target + '-config-devices.mak' - config_devices_mak = configure_file( - input: ['default-configs' / target + '.mak', 'Kconfig'], - output: config_devices_mak, - depfile: config_devices_mak + '.d', - capture: true, - command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'], - config_devices_mak, '@DEPFILE@', '@INPUT@', - base_kconfig]) - - config_devices_data = configuration_data() - config_devices = keyval.load(config_devices_mak) - foreach k, v: config_devices - config_devices_data.set(k, 1) - endforeach - config_devices_mak_list += config_devices_mak - config_devices_h += {target: configure_file(output: target + '-config-devices.h', - configuration: config_devices_data)} - config_target += config_devices - endif - config_target_mak += {target: config_target} -endforeach - -grepy = find_program('scripts/grepy.sh') -# This configuration is used to build files that are shared by -# multiple binaries, and then extracted out of the "common" -# static_library target. -# -# We do not use all_sources()/all_dependencies(), because it would -# build literally all source files, including devices only used by -# targets that are not built for this compilation. The CONFIG_ALL -# pseudo symbol replaces it. - -if have_system - config_all_devices_mak = configure_file( - output: 'config-all-devices.mak', - input: config_devices_mak_list, - capture: true, - command: [grepy, '@INPUT@'], - ) - config_all_devices = keyval.load(config_all_devices_mak) -else - config_all_devices = {} -endif -config_all = config_all_devices -config_all += config_host -config_all += config_all_disas -config_all += { - 'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'), - 'CONFIG_SOFTMMU': have_system, - 'CONFIG_USER_ONLY': have_user, - 'CONFIG_ALL': true, -} - -# Generators - -hxtool = find_program('scripts/hxtool') -shaderinclude = find_program('scripts/shaderinclude.pl') -qapi_gen = find_program('scripts/qapi-gen.py') -qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', - meson.source_root() / 'scripts/qapi/commands.py', - meson.source_root() / 'scripts/qapi/common.py', - meson.source_root() / 'scripts/qapi/doc.py', - meson.source_root() / 'scripts/qapi/error.py', - meson.source_root() / 'scripts/qapi/events.py', - meson.source_root() / 'scripts/qapi/expr.py', - meson.source_root() / 'scripts/qapi/gen.py', - meson.source_root() / 'scripts/qapi/introspect.py', - meson.source_root() / 'scripts/qapi/parser.py', - meson.source_root() / 'scripts/qapi/schema.py', - meson.source_root() / 'scripts/qapi/source.py', - meson.source_root() / 'scripts/qapi/types.py', - meson.source_root() / 'scripts/qapi/visit.py', - meson.source_root() / 'scripts/qapi/common.py', - meson.source_root() / 'scripts/qapi/doc.py', - meson.source_root() / 'scripts/qapi-gen.py' -] - -tracetool = [ - python, files('scripts/tracetool.py'), - '--backend=' + config_host['TRACE_BACKENDS'] -] - -qemu_version_cmd = [find_program('scripts/qemu-version.sh'), - meson.current_source_dir(), - config_host['PKGVERSION'], meson.project_version()] -qemu_version = custom_target('qemu-version.h', - output: 'qemu-version.h', - command: qemu_version_cmd, - capture: true, - build_by_default: true, - build_always_stale: true) -genh += qemu_version - -hxdep = [] -hx_headers = [ - ['qemu-options.hx', 'qemu-options.def'], - ['qemu-img-cmds.hx', 'qemu-img-cmds.h'], -] -if have_system - hx_headers += [ - ['hmp-commands.hx', 'hmp-commands.h'], - ['hmp-commands-info.hx', 'hmp-commands-info.h'], - ] -endif -foreach d : hx_headers - hxdep += custom_target(d[1], - input: files(d[0]), - output: d[1], - capture: true, - build_by_default: true, # to be removed when added to a target - command: [hxtool, '-h', '@INPUT0@']) -endforeach -genh += hxdep - -# Collect sourcesets. - -util_ss = ss.source_set() -stub_ss = ss.source_set() -trace_ss = ss.source_set() -block_ss = ss.source_set() -blockdev_ss = ss.source_set() -qmp_ss = ss.source_set() -common_ss = ss.source_set() -softmmu_ss = ss.source_set() -user_ss = ss.source_set() -bsd_user_ss = ss.source_set() -linux_user_ss = ss.source_set() -specific_ss = ss.source_set() -specific_fuzz_ss = ss.source_set() - -modules = {} -hw_arch = {} -target_arch = {} -target_softmmu_arch = {} - -############### -# Trace files # -############### - -# TODO: add each directory to the subdirs from its own meson.build, once -# we have those -trace_events_subdirs = [ - 'accel/kvm', - 'accel/tcg', - 'crypto', - 'monitor', -] -if have_user - trace_events_subdirs += [ 'linux-user' ] -endif -if have_block - trace_events_subdirs += [ - 'authz', - 'block', - 'io', - 'nbd', - 'scsi', - ] -endif -if have_system - trace_events_subdirs += [ - 'audio', - 'backends', - 'backends/tpm', - 'chardev', - 'hw/9pfs', - 'hw/acpi', - 'hw/alpha', - 'hw/arm', - 'hw/audio', - 'hw/block', - 'hw/block/dataplane', - 'hw/char', - 'hw/display', - 'hw/dma', - 'hw/hppa', - 'hw/hyperv', - 'hw/i2c', - 'hw/i386', - 'hw/i386/xen', - 'hw/ide', - 'hw/input', - 'hw/intc', - 'hw/isa', - 'hw/mem', - 'hw/mips', - 'hw/misc', - 'hw/misc/macio', - 'hw/net', - 'hw/nvram', - 'hw/pci', - 'hw/pci-host', - 'hw/ppc', - 'hw/rdma', - 'hw/rdma/vmw', - 'hw/rtc', - 'hw/s390x', - 'hw/scsi', - 'hw/sd', - 'hw/sparc', - 'hw/sparc64', - 'hw/ssi', - 'hw/timer', - 'hw/tpm', - 'hw/usb', - 'hw/vfio', - 'hw/virtio', - 'hw/watchdog', - 'hw/xen', - 'hw/gpio', - 'hw/riscv', - 'migration', - 'net', - 'ui', - ] -endif -trace_events_subdirs += [ - 'hw/core', - 'qapi', - 'qom', - 'target/arm', - 'target/hppa', - 'target/i386', - 'target/mips', - 'target/ppc', - 'target/riscv', - 'target/s390x', - 'target/sparc', - 'util', -] - -subdir('qapi') -subdir('qobject') -subdir('stubs') -subdir('trace') -subdir('util') -subdir('qom') -subdir('authz') -subdir('crypto') -subdir('ui') - - -if enable_modules - libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') - modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO') -endif - -# Build targets from sourcesets - -stub_ss = stub_ss.apply(config_all, strict: false) - -util_ss.add_all(trace_ss) -util_ss = util_ss.apply(config_all, strict: false) -libqemuutil = static_library('qemuutil', - sources: util_ss.sources() + stub_ss.sources() + genh, - dependencies: [util_ss.dependencies(), m, glib, socket]) -qemuutil = declare_dependency(link_with: libqemuutil, - sources: genh + version_res) - -decodetree = generator(find_program('scripts/decodetree.py'), - output: 'decode-@BASENAME@.c.inc', - arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@']) - -subdir('audio') -subdir('io') -subdir('chardev') -subdir('fsdev') -subdir('libdecnumber') -subdir('target') -subdir('dump') - -block_ss.add(files( - 'block.c', - 'blockjob.c', - 'job.c', - 'qemu-io-cmds.c', -)) -block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c')) - -subdir('nbd') -subdir('scsi') -subdir('block') - -blockdev_ss.add(files( - 'blockdev.c', - 'blockdev-nbd.c', - 'iothread.c', - 'job-qmp.c', -)) - -# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon, -# os-win32.c does not -blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c')) -softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')]) - -softmmu_ss.add_all(blockdev_ss) -softmmu_ss.add(files( - 'bootdevice.c', - 'dma-helpers.c', - 'qdev-monitor.c', -), sdl) - -softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) -softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp]) -softmmu_ss.add(when: ['CONFIG_FDT', fdt], if_true: [files('device_tree.c')]) - -common_ss.add(files('cpus-common.c')) - -subdir('softmmu') - -specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl) -specific_ss.add(files('exec-vary.c')) -specific_ss.add(when: 'CONFIG_TCG', if_true: files( - 'fpu/softfloat.c', - 'tcg/optimize.c', - 'tcg/tcg-common.c', - 'tcg/tcg-op-gvec.c', - 'tcg/tcg-op-vec.c', - 'tcg/tcg-op.c', - 'tcg/tcg.c', -)) -specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c')) - -subdir('backends') -subdir('disas') -subdir('migration') -subdir('monitor') -subdir('net') -subdir('replay') -subdir('hw') -subdir('accel') -subdir('plugins') -subdir('bsd-user') -subdir('linux-user') - -bsd_user_ss.add(files('gdbstub.c')) -specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) - -linux_user_ss.add(files('gdbstub.c', 'thunk.c')) -specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss) - -# needed for fuzzing binaries -subdir('tests/qtest/libqos') -subdir('tests/qtest/fuzz') - -block_mods = [] -softmmu_mods = [] -foreach d, list : modules - foreach m, module_ss : list - if enable_modules and targetos != 'windows' - module_ss = module_ss.apply(config_host, strict: false) - sl = static_library(d + '-' + m, [genh, module_ss.sources()], - dependencies: [modulecommon, module_ss.dependencies()], pic: true) - if d == 'block' - block_mods += sl - else - softmmu_mods += sl - endif - else - if d == 'block' - block_ss.add_all(module_ss) - else - softmmu_ss.add_all(module_ss) - endif - endif - endforeach -endforeach - -nm = find_program('nm') -undefsym = find_program('scripts/undefsym.sh') -block_syms = custom_target('block.syms', output: 'block.syms', - input: [libqemuutil, block_mods], - capture: true, - command: [undefsym, nm, '@INPUT@']) -qemu_syms = custom_target('qemu.syms', output: 'qemu.syms', - input: [libqemuutil, softmmu_mods], - capture: true, - command: [undefsym, nm, '@INPUT@']) - -block_ss = block_ss.apply(config_host, strict: false) -libblock = static_library('block', block_ss.sources() + genh, - dependencies: block_ss.dependencies(), - link_depends: block_syms, - name_suffix: 'fa', - build_by_default: false) - -block = declare_dependency(link_whole: [libblock], - link_args: '@block.syms', - dependencies: [crypto, io]) - -qmp_ss = qmp_ss.apply(config_host, strict: false) -libqmp = static_library('qmp', qmp_ss.sources() + genh, - dependencies: qmp_ss.dependencies(), - name_suffix: 'fa', - build_by_default: false) - -qmp = declare_dependency(link_whole: [libqmp]) - -foreach m : block_mods + softmmu_mods - shared_module(m.name(), - name_prefix: '', - link_whole: m, - install: true, - install_dir: config_host['qemu_moddir']) -endforeach - -softmmu_ss.add(authz, block, chardev, crypto, io, qmp) -common_ss.add(qom, qemuutil) - -common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss]) -common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss) - -common_all = common_ss.apply(config_all, strict: false) -common_all = static_library('common', - build_by_default: false, - sources: common_all.sources() + genh, - dependencies: common_all.dependencies(), - name_suffix: 'fa') - -feature_to_c = find_program('scripts/feature_to_c.sh') - -emulators = [] -foreach target : target_dirs - config_target = config_target_mak[target] - target_name = config_target['TARGET_NAME'] - arch = config_target['TARGET_BASE_ARCH'] - arch_srcs = [config_target_h[target]] - arch_deps = [] - c_args = ['-DNEED_CPU_H', - '-DCONFIG_TARGET="@0@-config-target.h"'.format(target), - '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)] - link_args = [] - - config_target += config_host - target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])] - if targetos == 'linux' - target_inc += include_directories('linux-headers', is_system: true) - endif - if target.endswith('-softmmu') - qemu_target_name = 'qemu-system-' + target_name - target_type='system' - t = target_softmmu_arch[arch].apply(config_target, strict: false) - arch_srcs += t.sources() - arch_deps += t.dependencies() - - hw_dir = target_name == 'sparc64' ? 'sparc64' : arch - hw = hw_arch[hw_dir].apply(config_target, strict: false) - arch_srcs += hw.sources() - arch_deps += hw.dependencies() - - arch_srcs += config_devices_h[target] - link_args += ['@block.syms', '@qemu.syms'] - else - abi = config_target['TARGET_ABI_DIR'] - target_type='user' - qemu_target_name = 'qemu-' + target_name - if 'CONFIG_LINUX_USER' in config_target - base_dir = 'linux-user' - target_inc += include_directories('linux-user/host/' / config_host['ARCH']) - else - base_dir = 'bsd-user' - endif - target_inc += include_directories( - base_dir, - base_dir / abi, - ) - if 'CONFIG_LINUX_USER' in config_target - dir = base_dir / abi - arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c') - if config_target.has_key('TARGET_SYSTBL_ABI') - arch_srcs += \ - syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'], - extra_args : config_target['TARGET_SYSTBL_ABI']) - endif - endif - endif - - if 'TARGET_XML_FILES' in config_target - gdbstub_xml = custom_target(target + '-gdbstub-xml.c', - output: target + '-gdbstub-xml.c', - input: files(config_target['TARGET_XML_FILES'].split()), - command: [feature_to_c, '@INPUT@'], - capture: true) - arch_srcs += gdbstub_xml - endif - - t = target_arch[arch].apply(config_target, strict: false) - arch_srcs += t.sources() - arch_deps += t.dependencies() - - target_common = common_ss.apply(config_target, strict: false) - objects = common_all.extract_objects(target_common.sources()) - deps = target_common.dependencies() - - target_specific = specific_ss.apply(config_target, strict: false) - arch_srcs += target_specific.sources() - arch_deps += target_specific.dependencies() - - lib = static_library('qemu-' + target, - sources: arch_srcs + genh, - dependencies: arch_deps, - objects: objects, - include_directories: target_inc, - c_args: c_args, - build_by_default: false, - name_suffix: 'fa') - - if target.endswith('-softmmu') - execs = [{ - 'name': 'qemu-system-' + target_name, - 'gui': false, - 'sources': files('softmmu/main.c'), - 'dependencies': [] - }] - if targetos == 'windows' and (sdl.found() or gtk.found()) - execs += [{ - 'name': 'qemu-system-' + target_name + 'w', - 'gui': true, - 'sources': files('softmmu/main.c'), - 'dependencies': [] - }] - endif - if config_host.has_key('CONFIG_FUZZ') - specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false) - execs += [{ - 'name': 'qemu-fuzz-' + target_name, - 'gui': false, - 'sources': specific_fuzz.sources(), - 'dependencies': specific_fuzz.dependencies(), - 'link_depends': [files('tests/qtest/fuzz/fork_fuzz.ld')], - }] - endif - else - execs = [{ - 'name': 'qemu-' + target_name, - 'gui': false, - 'sources': [], - 'dependencies': [] - }] - endif - foreach exe: execs - emulators += executable(exe['name'], exe['sources'], - install: true, - c_args: c_args, - dependencies: arch_deps + deps + exe['dependencies'], - objects: lib.extract_all_objects(recursive: true), - link_language: link_language, - link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), - link_args: link_args, - gui_app: exe['gui']) - - if 'CONFIG_TRACE_SYSTEMTAP' in config_host - foreach stp: [ - {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false}, - {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true}, - {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true}, - {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true}, - ] - custom_target(exe['name'] + stp['ext'], - input: trace_events_all, - output: exe['name'] + stp['ext'], - capture: true, - install: stp['install'], - install_dir: qemu_datadir / '../systemtap/tapset', - command: [ - tracetool, '--group=all', '--format=' + stp['fmt'], - '--binary=' + stp['bin'], - '--target-name=' + target_name, - '--target-type=' + target_type, - '--probe-prefix=qemu.' + target_type + '.' + target_name, - '@INPUT@', - ]) - endforeach - endif - endforeach -endforeach - -# Other build targets - -if 'CONFIG_PLUGIN' in config_host - install_headers('include/qemu/qemu-plugin.h') -endif - -if 'CONFIG_GUEST_AGENT' in config_host - subdir('qga') -endif - -# Don't build qemu-keymap if xkbcommon is not explicitly enabled -# when we don't build tools or system -if xkbcommon.found() - # used for the update-keymaps target, so include rules even if !have_tools - qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh, - dependencies: [qemuutil, xkbcommon], install: have_tools) -endif - -qemu_block_tools = [] -if have_tools - qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep], - dependencies: [authz, block, crypto, io, qom, qemuutil], install: true) - qemu_io = executable('qemu-io', files('qemu-io.c'), - dependencies: [block, qemuutil], install: true) - qemu_block_tools += [qemu_img, qemu_io] - if targetos != 'windows' - qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'), - dependencies: [block, qemuutil], install: true) - qemu_block_tools += [qemu_nbd] - endif - - subdir('storage-daemon') - subdir('contrib/rdmacm-mux') - subdir('contrib/elf2dmp') - - executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'), - dependencies: qemuutil, - install: true) - - if 'CONFIG_VHOST_USER' in config_host - subdir('contrib/libvhost-user') - subdir('contrib/vhost-user-blk') - subdir('contrib/vhost-user-gpu') - subdir('contrib/vhost-user-input') - subdir('contrib/vhost-user-scsi') - endif - - if targetos == 'linux' - executable('qemu-bridge-helper', files('qemu-bridge-helper.c'), - dependencies: [qemuutil, libcap_ng], - install: true, - install_dir: get_option('libexecdir')) - - executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'), - dependencies: [authz, crypto, io, qom, qemuutil, - libcap_ng, libudev, libmpathpersist], - install: true) - endif - - if 'CONFIG_IVSHMEM' in config_host - subdir('contrib/ivshmem-client') - subdir('contrib/ivshmem-server') - endif -endif - -subdir('scripts') -subdir('tools') -subdir('pc-bios') -subdir('tests') -subdir('docs') -if 'CONFIG_GTK' in config_host - subdir('po') -endif - -if build_docs - makeinfo = find_program('makeinfo', required: build_docs) - - docs_inc = [ - '-I', meson.current_source_dir(), - '-I', meson.current_build_dir() / 'docs', - '-I', '@OUTDIR@', - ] - - version_texi = configure_file(output: 'version.texi', - input: 'version.texi.in', - configuration: {'VERSION': meson.project_version(), - 'qemu_confdir': config_host['qemu_confdir']}) - - texi = { - 'qemu-qmp-ref': ['docs/interop/qemu-qmp-ref.texi', qapi_doc_texi, version_texi], - } - if 'CONFIG_GUEST_AGENT' in config_host - texi += {'qemu-ga-ref': ['docs/interop/qemu-ga-ref.texi', qga_qapi_doc_texi, version_texi]} - endif - - if makeinfo.found() - cmd = [ - 'env', 'LC_ALL=C', makeinfo, '--no-split', '--number-sections', docs_inc, - '@INPUT0@', '-o', '@OUTPUT@', - ] - foreach ext, args: { - 'info': [], - 'html': ['--no-headers', '--html'], - 'txt': ['--no-headers', '--plaintext'], - } - t = [] - foreach doc, input: texi - output = doc + '.' + ext - t += custom_target(output, - input: input, - output: output, - install: true, - install_dir: qemu_docdir / 'interop', - command: cmd + args) - endforeach - alias_target(ext, t) - endforeach - endif - - texi2pdf = find_program('texi2pdf', required: false) - - if texi2pdf.found() - pdfs = [] - foreach doc, input: texi - output = doc + '.pdf' - pdfs += custom_target(output, - input: input, - output: output, - command: [texi2pdf, '-q', docs_inc, '@INPUT0@', '-o', '@OUTPUT@'], - build_by_default: false) - endforeach - alias_target('pdf', pdfs) - endif - - texi2pod = find_program('scripts/texi2pod.pl') - pod2man = find_program('pod2man', required: build_docs) - - if pod2man.found() - foreach doc, input: texi - man = doc + '.7' - pod = custom_target(man + '.pod', - input: input, - output: man + '.pod', - command: [texi2pod, - '-DVERSION="' + meson.project_version() + '"', - '-DCONFDIR="' + config_host['qemu_confdir'] + '"', - '@INPUT0@', '@OUTPUT@']) - man = custom_target(man, - input: pod, - output: man, - capture: true, - install: true, - install_dir: get_option('mandir') / 'man7', - command: [pod2man, '--utf8', '--section=7', '--center=" "', - '--release=" "', '@INPUT@']) - endforeach - endif -endif - -if host_machine.system() == 'windows' - nsis_cmd = [ - find_program('scripts/nsis.py'), - '@OUTPUT@', - get_option('prefix'), - meson.current_source_dir(), - host_machine.cpu_family(), - '--', - '-DDISPLAYVERSION=' + meson.project_version(), - ] - if build_docs - nsis_cmd += '-DCONFIG_DOCUMENTATION=y' - endif - if 'CONFIG_GTK' in config_host - nsis_cmd += '-DCONFIG_GTK=y' - endif - - nsis = custom_target('nsis', - output: 'qemu-setup-' + meson.project_version() + '.exe', - input: files('qemu.nsi'), - build_always_stale: true, - command: nsis_cmd + ['@INPUT@']) - alias_target('installer', nsis) -endif - -summary_info = {} -summary_info += {'Install prefix': config_host['prefix']} -summary_info += {'BIOS directory': config_host['qemu_datadir']} -summary_info += {'firmware path': config_host['qemu_firmwarepath']} -summary_info += {'binary directory': config_host['bindir']} -summary_info += {'library directory': config_host['libdir']} -summary_info += {'module directory': config_host['qemu_moddir']} -summary_info += {'libexec directory': config_host['libexecdir']} -summary_info += {'include directory': config_host['includedir']} -summary_info += {'config directory': config_host['sysconfdir']} -if targetos != 'windows' - summary_info += {'local state directory': config_host['qemu_localstatedir']} - summary_info += {'Manual directory': get_option('mandir')} -else - summary_info += {'local state directory': 'queried at runtime'} -endif -summary_info += {'Doc directory': get_option('docdir')} -summary_info += {'Build directory': meson.current_build_dir()} -summary_info += {'Source path': meson.current_source_dir()} -summary_info += {'GIT binary': config_host['GIT']} -summary_info += {'GIT submodules': config_host['GIT_SUBMODULES']} -summary_info += {'C compiler': meson.get_compiler('c').cmd_array()[0]} -summary_info += {'Host C compiler': meson.get_compiler('c', native: true).cmd_array()[0]} -if link_language == 'cpp' - summary_info += {'C++ compiler': meson.get_compiler('cpp').cmd_array()[0]} -else - summary_info += {'C++ compiler': false} -endif -if targetos == 'darwin' - summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]} -endif -summary_info += {'ARFLAGS': config_host['ARFLAGS']} -summary_info += {'CFLAGS': config_host['CFLAGS']} -summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} -summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} -summary_info += {'make': config_host['MAKE']} -summary_info += {'install': config_host['INSTALL']} -summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())} -summary_info += {'sphinx-build': config_host['SPHINX_BUILD']} -summary_info += {'genisoimage': config_host['GENISOIMAGE']} -# TODO: add back version -summary_info += {'slirp support': config_host.has_key('CONFIG_SLIRP')} -if config_host.has_key('CONFIG_SLIRP') - summary_info += {'smbd': config_host['CONFIG_SMBD_COMMAND']} -endif -summary_info += {'module support': config_host.has_key('CONFIG_MODULES')} -if config_host.has_key('CONFIG_MODULES') - summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')} -endif -summary_info += {'host CPU': cpu} -summary_info += {'host endianness': build_machine.endian()} -summary_info += {'target list': config_host['TARGET_DIRS']} -summary_info += {'gprof enabled': config_host.has_key('CONFIG_GPROF')} -summary_info += {'sparse enabled': meson.get_compiler('c').cmd_array().contains('cgcc')} -summary_info += {'strip binaries': get_option('strip')} -summary_info += {'profiler': config_host.has_key('CONFIG_PROFILER')} -summary_info += {'static build': config_host.has_key('CONFIG_TOOLS')} -if targetos == 'darwin' - summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')} -endif -# TODO: add back version -summary_info += {'SDL support': sdl.found()} -summary_info += {'SDL image support': sdl_image.found()} -# TODO: add back version -summary_info += {'GTK support': config_host.has_key('CONFIG_GTK')} -summary_info += {'GTK GL support': config_host.has_key('CONFIG_GTK_GL')} -summary_info += {'pixman': pixman.found()} -# TODO: add back version -summary_info += {'VTE support': config_host.has_key('CONFIG_VTE')} -summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']} -summary_info += {'GNUTLS support': config_host.has_key('CONFIG_GNUTLS')} -# TODO: add back version -summary_info += {'libgcrypt': config_host.has_key('CONFIG_GCRYPT')} -if config_host.has_key('CONFIG_GCRYPT') - summary_info += {' hmac': config_host.has_key('CONFIG_GCRYPT_HMAC')} - summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} -endif -# TODO: add back version -summary_info += {'nettle': config_host.has_key('CONFIG_NETTLE')} -if config_host.has_key('CONFIG_NETTLE') - summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} -endif -summary_info += {'libtasn1': config_host.has_key('CONFIG_TASN1')} -summary_info += {'PAM': config_host.has_key('CONFIG_AUTH_PAM')} -summary_info += {'iconv support': config_host.has_key('CONFIG_ICONV')} -summary_info += {'curses support': config_host.has_key('CONFIG_CURSES')} -# TODO: add back version -summary_info += {'virgl support': config_host.has_key('CONFIG_VIRGL')} -summary_info += {'curl support': config_host.has_key('CONFIG_CURL')} -summary_info += {'mingw32 support': targetos == 'windows'} -summary_info += {'Audio drivers': config_host['CONFIG_AUDIO_DRIVERS']} -summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']} -summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']} -summary_info += {'VirtFS support': config_host.has_key('CONFIG_VIRTFS')} -summary_info += {'Multipath support': config_host.has_key('CONFIG_MPATH')} -summary_info += {'VNC support': vnc.found()} -if vnc.found() - summary_info += {'VNC SASL support': sasl.found()} - summary_info += {'VNC JPEG support': jpeg.found()} - summary_info += {'VNC PNG support': png.found()} -endif -summary_info += {'xen support': config_host.has_key('CONFIG_XEN_BACKEND')} -if config_host.has_key('CONFIG_XEN_BACKEND') - summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']} -endif -summary_info += {'brlapi support': config_host.has_key('CONFIG_BRLAPI')} -summary_info += {'Documentation': config_host.has_key('BUILD_DOCS')} -summary_info += {'PIE': get_option('b_pie')} -summary_info += {'vde support': config_host.has_key('CONFIG_VDE')} -summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')} -summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')} -summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')} -summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')} -summary_info += {'Install blobs': config_host.has_key('INSTALL_BLOBS')} -# TODO: add back KVM/HAX/HVF/WHPX/TCG -#summary_info += {'KVM support': have_kvm'} -#summary_info += {'HAX support': have_hax'} -#summary_info += {'HVF support': have_hvf'} -#summary_info += {'WHPX support': have_whpx'} -#summary_info += {'TCG support': have_tcg'} -#if get_option('tcg') -# summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')} -# summary_info += {'TCG interpreter': config_host.has_key('CONFIG_TCG_INTERPRETER')} -#endif -summary_info += {'malloc trim support': config_host.has_key('CONFIG_MALLOC_TRIM')} -summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')} -summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')} -summary_info += {'fdt support': config_host.has_key('CONFIG_FDT')} -summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')} -summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')} -summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')} -summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')} -summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')} -summary_info += {'posix_memalign': config_host.has_key('CONFIG_POSIX_MEMALIGN')} -summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')} -summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')} -summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')} -summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')} -summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')} -summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')} -summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')} -summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')} -summary_info += {'Trace backends': config_host['TRACE_BACKENDS']} -if config_host['TRACE_BACKENDS'].split().contains('simple') - summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-'} -endif -# TODO: add back protocol and server version -summary_info += {'spice support': config_host.has_key('CONFIG_SPICE')} -summary_info += {'rbd support': config_host.has_key('CONFIG_RBD')} -summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')} -summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')} -summary_info += {'U2F support': u2f.found()} -summary_info += {'libusb': config_host.has_key('CONFIG_USB_LIBUSB')} -summary_info += {'usb net redir': config_host.has_key('CONFIG_USB_REDIR')} -summary_info += {'OpenGL support': config_host.has_key('CONFIG_OPENGL')} -summary_info += {'OpenGL dmabufs': config_host.has_key('CONFIG_OPENGL_DMABUF')} -summary_info += {'libiscsi support': config_host.has_key('CONFIG_LIBISCSI')} -summary_info += {'libnfs support': config_host.has_key('CONFIG_LIBNFS')} -summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')} -if targetos == 'windows' - if 'WIN_SDK' in config_host - summary_info += {'Windows SDK': config_host['WIN_SDK']} - endif - summary_info += {'QGA VSS support': config_host.has_key('CONFIG_QGA_VSS')} - summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')} - summary_info += {'QGA MSI support': config_host.has_key('CONFIG_QGA_MSI_ENABLED')} -endif -summary_info += {'seccomp support': config_host.has_key('CONFIG_SECCOMP')} -summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']} -summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1'} -summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')} -summary_info += {'mutex debugging': config_host.has_key('CONFIG_DEBUG_MUTEX')} -summary_info += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} -summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')} -summary_info += {'gcov': get_option('b_coverage')} -summary_info += {'TPM support': config_host.has_key('CONFIG_TPM')} -summary_info += {'libssh support': config_host.has_key('CONFIG_LIBSSH')} -summary_info += {'QOM debugging': config_host.has_key('CONFIG_QOM_CAST_DEBUG')} -summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')} -summary_info += {'lzo support': config_host.has_key('CONFIG_LZO')} -summary_info += {'snappy support': config_host.has_key('CONFIG_SNAPPY')} -summary_info += {'bzip2 support': config_host.has_key('CONFIG_BZIP2')} -summary_info += {'lzfse support': config_host.has_key('CONFIG_LZFSE')} -summary_info += {'zstd support': config_host.has_key('CONFIG_ZSTD')} -summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} -summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} -summary_info += {'tcmalloc support': config_host.has_key('CONFIG_TCMALLOC')} -summary_info += {'jemalloc support': config_host.has_key('CONFIG_JEMALLOC')} -summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')} -summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')} -summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')} -summary_info += {'bochs support': config_host.has_key('CONFIG_BOCHS')} -summary_info += {'cloop support': config_host.has_key('CONFIG_CLOOP')} -summary_info += {'dmg support': config_host.has_key('CONFIG_DMG')} -summary_info += {'qcow v1 support': config_host.has_key('CONFIG_QCOW1')} -summary_info += {'vdi support': config_host.has_key('CONFIG_VDI')} -summary_info += {'vvfat support': config_host.has_key('CONFIG_VVFAT')} -summary_info += {'qed support': config_host.has_key('CONFIG_QED')} -summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')} -summary_info += {'sheepdog support': config_host.has_key('CONFIG_SHEEPDOG')} -summary_info += {'capstone': config_host.has_key('CONFIG_CAPSTONE')} -summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} -summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} -summary_info += {'libudev': config_host.has_key('CONFIG_LIBUDEV')} -summary_info += {'default devices': config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'} -summary_info += {'plugin support': config_host.has_key('CONFIG_PLUGIN')} -summary_info += {'fuzzing support': config_host.has_key('CONFIG_FUZZ')} -if config_host.has_key('HAVE_GDB_BIN') - summary_info += {'gdb': config_host['HAVE_GDB_BIN']} -endif -summary_info += {'thread sanitizer': config_host.has_key('CONFIG_TSAN')} -summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} -summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} -summary(summary_info, bool_yn: true) - -if not supported_cpus.contains(cpu) - message() - warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!') - message() - message('CPU host architecture ' + cpu + ' support is not currently maintained.') - message('The QEMU project intends to remove support for this host CPU in') - message('a future release if nobody volunteers to maintain it and to') - message('provide a build host for our continuous integration setup.') - message('configure has succeeded and you can continue to build, but') - message('if you care about QEMU on this platform you should contact') - message('us upstream at qemu-devel@nongnu.org.') -endif - -if not supported_oses.contains(targetos) - message() - warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!') - message() - message('Host OS ' + targetos + 'support is not currently maintained.') - message('The QEMU project intends to remove support for this host OS in') - message('a future release if nobody volunteers to maintain it and to') - message('provide a build host for our continuous integration setup.') - message('configure has succeeded and you can continue to build, but') - message('if you care about QEMU on this platform you should contact') - message('us upstream at qemu-devel@nongnu.org.') -endif +project('qemu', ['c'], meson_version: '>=0.55.0', + default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', + 'b_lundef=false','b_colorout=auto'], + version: run_command('head', meson.source_root() / 'VERSION').stdout().strip()) + +not_found = dependency('', required: false) +if meson.version().version_compare('>=0.56.0') + keyval = import('keyval') +else + keyval = import('unstable-keyval') +endif +ss = import('sourceset') + +sh = find_program('sh') +cc = meson.get_compiler('c') +config_host = keyval.load(meson.current_build_dir() / 'config-host.mak') +config_all_disas = keyval.load(meson.current_build_dir() / 'config-all-disas.mak') +enable_modules = 'CONFIG_MODULES' in config_host +enable_static = 'CONFIG_STATIC' in config_host +build_docs = 'BUILD_DOCS' in config_host +qemu_datadir = get_option('datadir') / get_option('qemu_suffix') +qemu_docdir = get_option('docdir') / get_option('qemu_suffix') +config_host_data = configuration_data() +genh = [] + +target_dirs = config_host['TARGET_DIRS'].split() +have_user = false +have_system = false +foreach target : target_dirs + have_user = have_user or target.endswith('-user') + have_system = have_system or target.endswith('-softmmu') +endforeach +have_tools = 'CONFIG_TOOLS' in config_host +have_block = have_system or have_tools + +add_project_arguments(config_host['QEMU_CFLAGS'].split(), + native: false, language: ['c', 'objc']) +add_project_arguments(config_host['QEMU_CXXFLAGS'].split(), + native: false, language: 'cpp') +add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(), + native: false, language: ['c', 'cpp', 'objc']) +add_project_arguments(config_host['QEMU_INCLUDES'].split(), + language: ['c', 'cpp', 'objc']) + +python = import('python').find_installation() + +link_language = meson.get_external_property('link_language', 'cpp') +if link_language == 'cpp' + add_languages('cpp', required: true, native: false) +endif +if host_machine.system() == 'darwin' + add_languages('objc', required: false, native: false) +endif + +if 'SPARSE_CFLAGS' in config_host + run_target('sparse', + command: [find_program('scripts/check_sparse.py'), + config_host['SPARSE_CFLAGS'].split(), + 'compile_commands.json']) +endif + +configure_file(input: files('scripts/ninjatool.py'), + output: 'ninjatool', + configuration: config_host) + +supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] +supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64', + 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + +cpu = host_machine.cpu_family() +targetos = host_machine.system() + +m = cc.find_library('m', required: false) +util = cc.find_library('util', required: false) +winmm = [] +socket = [] +version_res = [] +coref = [] +iokit = [] +cocoa = [] +hvf = [] +if targetos == 'windows' + socket = cc.find_library('ws2_32') + winmm = cc.find_library('winmm') + + win = import('windows') + version_res = win.compile_resources('version.rc', + depend_files: files('pc-bios/qemu-nsis.ico'), + include_directories: include_directories('.')) +elif targetos == 'darwin' + coref = dependency('appleframeworks', modules: 'CoreFoundation') + iokit = dependency('appleframeworks', modules: 'IOKit') + cocoa = dependency('appleframeworks', modules: 'Cocoa') + hvf = dependency('appleframeworks', modules: 'Hypervisor') +elif targetos == 'sunos' + socket = [cc.find_library('socket'), + cc.find_library('nsl'), + cc.find_library('resolv')] +elif targetos == 'haiku' + socket = [cc.find_library('posix_error_mapper'), + cc.find_library('network'), + cc.find_library('bsd')] +endif +glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(), + link_args: config_host['GLIB_LIBS'].split()) +gio = not_found +if 'CONFIG_GIO' in config_host + gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), + link_args: config_host['GIO_LIBS'].split()) +endif +lttng = not_found +if 'CONFIG_TRACE_UST' in config_host + lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split()) +endif +urcubp = not_found +if 'CONFIG_TRACE_UST' in config_host + urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split()) +endif +nettle = not_found +if 'CONFIG_NETTLE' in config_host + nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(), + link_args: config_host['NETTLE_LIBS'].split()) +endif +gnutls = not_found +if 'CONFIG_GNUTLS' in config_host + gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(), + link_args: config_host['GNUTLS_LIBS'].split()) +endif +pixman = not_found +if have_system or have_tools + pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8', + method: 'pkg-config', static: enable_static) +endif +pam = not_found +if 'CONFIG_AUTH_PAM' in config_host + pam = cc.find_library('pam') +endif +libaio = cc.find_library('aio', required: false) +zlib = dependency('zlib', required: true, static: enable_static) +linux_io_uring = not_found +if 'CONFIG_LINUX_IO_URING' in config_host + linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(), + link_args: config_host['LINUX_IO_URING_LIBS'].split()) +endif +libxml2 = not_found +if 'CONFIG_LIBXML2' in config_host + libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(), + link_args: config_host['LIBXML2_LIBS'].split()) +endif +libnfs = not_found +if 'CONFIG_LIBNFS' in config_host + libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split()) +endif +libattr = not_found +if 'CONFIG_ATTR' in config_host + libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split()) +endif +seccomp = not_found +if 'CONFIG_SECCOMP' in config_host + seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(), + link_args: config_host['SECCOMP_LIBS'].split()) +endif +libcap_ng = not_found +if 'CONFIG_LIBCAP_NG' in config_host + libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split()) +endif +if get_option('xkbcommon').auto() and not have_system and not have_tools + xkbcommon = not_found +else + xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'), + method: 'pkg-config', static: enable_static) +endif +slirp = not_found +if config_host.has_key('CONFIG_SLIRP') + slirp = declare_dependency(compile_args: config_host['SLIRP_CFLAGS'].split(), + link_args: config_host['SLIRP_LIBS'].split()) +endif +vde = not_found +if config_host.has_key('CONFIG_VDE') + vde = declare_dependency(link_args: config_host['VDE_LIBS'].split()) +endif +pulse = not_found +if 'CONFIG_LIBPULSE' in config_host + pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(), + link_args: config_host['PULSE_LIBS'].split()) +endif +alsa = not_found +if 'CONFIG_ALSA' in config_host + alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(), + link_args: config_host['ALSA_LIBS'].split()) +endif +jack = not_found +if 'CONFIG_LIBJACK' in config_host + jack = declare_dependency(link_args: config_host['JACK_LIBS'].split()) +endif +spice = not_found +if 'CONFIG_SPICE' in config_host + spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(), + link_args: config_host['SPICE_LIBS'].split()) +endif +rt = cc.find_library('rt', required: false) +libmpathpersist = not_found +if config_host.has_key('CONFIG_MPATH') + libmpathpersist = cc.find_library('mpathpersist') +endif +libiscsi = not_found +if 'CONFIG_LIBISCSI' in config_host + libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(), + link_args: config_host['LIBISCSI_LIBS'].split()) +endif +zstd = not_found +if 'CONFIG_ZSTD' in config_host + zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(), + link_args: config_host['ZSTD_LIBS'].split()) +endif +gbm = not_found +if 'CONFIG_GBM' in config_host + gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(), + link_args: config_host['GBM_LIBS'].split()) +endif +virgl = not_found +if 'CONFIG_VIRGL' in config_host + virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(), + link_args: config_host['VIRGL_LIBS'].split()) +endif +curl = not_found +if 'CONFIG_CURL' in config_host + curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(), + link_args: config_host['CURL_LIBS'].split()) +endif +libudev = not_found +if 'CONFIG_LIBUDEV' in config_host + libudev = declare_dependency(link_args: config_host['LIBUDEV_LIBS'].split()) +endif +brlapi = not_found +if 'CONFIG_BRLAPI' in config_host + brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split()) +endif + +sdl = not_found +if have_system + sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static) + sdl_image = not_found +endif +if sdl.found() + # work around 2.0.8 bug + sdl = declare_dependency(compile_args: '-Wno-undef', + dependencies: sdl) + sdl_image = dependency('SDL2_image', required: get_option('sdl_image'), + method: 'pkg-config', static: enable_static) +else + if get_option('sdl_image').enabled() + error('sdl-image required, but SDL was @0@', + get_option('sdl').disabled() ? 'disabled' : 'not found') + endif + sdl_image = not_found +endif + +rbd = not_found +if 'CONFIG_RBD' in config_host + rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split()) +endif +glusterfs = not_found +if 'CONFIG_GLUSTERFS' in config_host + glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(), + link_args: config_host['GLUSTERFS_LIBS'].split()) +endif +libssh = not_found +if 'CONFIG_LIBSSH' in config_host + libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(), + link_args: config_host['LIBSSH_LIBS'].split()) +endif +libbzip2 = not_found +if 'CONFIG_BZIP2' in config_host + libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split()) +endif +liblzfse = not_found +if 'CONFIG_LZFSE' in config_host + liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split()) +endif +oss = not_found +if 'CONFIG_AUDIO_OSS' in config_host + oss = declare_dependency(link_args: config_host['OSS_LIBS'].split()) +endif +dsound = not_found +if 'CONFIG_AUDIO_DSOUND' in config_host + dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split()) +endif +coreaudio = not_found +if 'CONFIG_AUDIO_COREAUDIO' in config_host + coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split()) +endif +opengl = not_found +if 'CONFIG_OPENGL' in config_host + opengl = declare_dependency(link_args: config_host['OPENGL_LIBS'].split()) +else +endif +gtk = not_found +if 'CONFIG_GTK' in config_host + gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(), + link_args: config_host['GTK_LIBS'].split()) +endif +vte = not_found +if 'CONFIG_VTE' in config_host + vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(), + link_args: config_host['VTE_LIBS'].split()) +endif +x11 = not_found +if 'CONFIG_X11' in config_host + x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(), + link_args: config_host['X11_LIBS'].split()) +endif +curses = not_found +if 'CONFIG_CURSES' in config_host + curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(), + link_args: config_host['CURSES_LIBS'].split()) +endif +iconv = not_found +if 'CONFIG_ICONV' in config_host + iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(), + link_args: config_host['ICONV_LIBS'].split()) +endif +gio = not_found +if 'CONFIG_GIO' in config_host + gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), + link_args: config_host['GIO_LIBS'].split()) +endif +vnc = not_found +png = not_found +jpeg = not_found +sasl = not_found +if get_option('vnc').enabled() + vnc = declare_dependency() # dummy dependency + png = dependency('libpng', required: get_option('vnc_png'), + method: 'pkg-config', static: enable_static) + jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'], + required: get_option('vnc_jpeg'), + static: enable_static) + sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'], + required: get_option('vnc_sasl'), + static: enable_static) + if sasl.found() + sasl = declare_dependency(dependencies: sasl, + compile_args: '-DSTRUCT_IOVEC_DEFINED') + endif +endif +fdt = not_found +if 'CONFIG_FDT' in config_host + fdt = declare_dependency(compile_args: config_host['FDT_CFLAGS'].split(), + link_args: config_host['FDT_LIBS'].split()) +endif +snappy = not_found +if 'CONFIG_SNAPPY' in config_host + snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split()) +endif +lzo = not_found +if 'CONFIG_LZO' in config_host + lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split()) +endif +rdma = not_found +if 'CONFIG_RDMA' in config_host + rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split()) +endif +numa = not_found +if 'CONFIG_NUMA' in config_host + numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split()) +endif +xen = not_found +if 'CONFIG_XEN_BACKEND' in config_host + xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(), + link_args: config_host['XEN_LIBS'].split()) +endif +cacard = not_found +if 'CONFIG_SMARTCARD' in config_host + cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(), + link_args: config_host['SMARTCARD_LIBS'].split()) +endif +u2f = not_found +if have_system + u2f = dependency('u2f-emu', required: get_option('u2f'), + method: 'pkg-config', + static: enable_static) +endif +usbredir = not_found +if 'CONFIG_USB_REDIR' in config_host + usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(), + link_args: config_host['USB_REDIR_LIBS'].split()) +endif +libusb = not_found +if 'CONFIG_USB_LIBUSB' in config_host + libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(), + link_args: config_host['LIBUSB_LIBS'].split()) +endif +capstone = not_found +if 'CONFIG_CAPSTONE' in config_host + capstone = declare_dependency(compile_args: config_host['CAPSTONE_CFLAGS'].split(), + link_args: config_host['CAPSTONE_LIBS'].split()) +endif +libpmem = not_found +if 'CONFIG_LIBPMEM' in config_host + libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(), + link_args: config_host['LIBPMEM_LIBS'].split()) +endif +libdaxctl = not_found +if 'CONFIG_LIBDAXCTL' in config_host + libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split()) +endif + +# Create config-host.h + +config_host_data.set('CONFIG_SDL', sdl.found()) +config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) +config_host_data.set('CONFIG_VNC', vnc.found()) +config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) +config_host_data.set('CONFIG_VNC_PNG', png.found()) +config_host_data.set('CONFIG_VNC_SASL', sasl.found()) +config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found()) +config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version())) +config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0]) +config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) +config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) + +arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] +strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'qemu_confdir', 'qemu_datadir', + 'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir', + 'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath'] +foreach k, v: config_host + if arrays.contains(k) + if v != '' + v = '"' + '", "'.join(v.split()) + '", ' + endif + config_host_data.set(k, v) + elif k == 'ARCH' + config_host_data.set('HOST_' + v.to_upper(), 1) + elif strings.contains(k) + if not k.startswith('CONFIG_') + k = 'CONFIG_' + k.to_upper() + endif + config_host_data.set_quoted(k, v) + elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_') + config_host_data.set(k, v == 'y' ? 1 : v) + endif +endforeach +genh += configure_file(output: 'config-host.h', configuration: config_host_data) + +minikconf = find_program('scripts/minikconf.py') +config_devices_mak_list = [] +config_devices_h = {} +config_target_h = {} +config_target_mak = {} +kconfig_external_symbols = [ + 'CONFIG_KVM', + 'CONFIG_XEN', + 'CONFIG_TPM', + 'CONFIG_SPICE', + 'CONFIG_IVSHMEM', + 'CONFIG_OPENGL', + 'CONFIG_X11', + 'CONFIG_VHOST_USER', + 'CONFIG_VHOST_KERNEL', + 'CONFIG_VIRTFS', + 'CONFIG_LINUX', + 'CONFIG_PVRDMA', +] +ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS'] +foreach target : target_dirs + config_target = keyval.load(meson.current_build_dir() / target / 'config-target.mak') + + config_target_data = configuration_data() + foreach k, v: config_target + if not k.startswith('TARGET_') and not k.startswith('CONFIG_') + # do nothing + elif ignored.contains(k) + # do nothing + elif k == 'TARGET_BASE_ARCH' + config_target_data.set('TARGET_' + v.to_upper(), 1) + elif k == 'TARGET_NAME' + config_target_data.set_quoted(k, v) + elif v == 'y' + config_target_data.set(k, 1) + else + config_target_data.set(k, v) + endif + endforeach + config_target_h += {target: configure_file(output: target + '-config-target.h', + configuration: config_target_data)} + + if target.endswith('-softmmu') + base_kconfig = [] + foreach sym : kconfig_external_symbols + if sym in config_target or sym in config_host + base_kconfig += '@0@=y'.format(sym) + endif + endforeach + + config_devices_mak = target + '-config-devices.mak' + config_devices_mak = configure_file( + input: ['default-configs' / target + '.mak', 'Kconfig'], + output: config_devices_mak, + depfile: config_devices_mak + '.d', + capture: true, + command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'], + config_devices_mak, '@DEPFILE@', '@INPUT@', + base_kconfig]) + + config_devices_data = configuration_data() + config_devices = keyval.load(config_devices_mak) + foreach k, v: config_devices + config_devices_data.set(k, 1) + endforeach + config_devices_mak_list += config_devices_mak + config_devices_h += {target: configure_file(output: target + '-config-devices.h', + configuration: config_devices_data)} + config_target += config_devices + endif + config_target_mak += {target: config_target} +endforeach + +grepy = find_program('scripts/grepy.sh') +# This configuration is used to build files that are shared by +# multiple binaries, and then extracted out of the "common" +# static_library target. +# +# We do not use all_sources()/all_dependencies(), because it would +# build literally all source files, including devices only used by +# targets that are not built for this compilation. The CONFIG_ALL +# pseudo symbol replaces it. + +if have_system + config_all_devices_mak = configure_file( + output: 'config-all-devices.mak', + input: config_devices_mak_list, + capture: true, + command: [grepy, '@INPUT@'], + ) + config_all_devices = keyval.load(config_all_devices_mak) +else + config_all_devices = {} +endif +config_all = config_all_devices +config_all += config_host +config_all += config_all_disas +config_all += { + 'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'), + 'CONFIG_SOFTMMU': have_system, + 'CONFIG_USER_ONLY': have_user, + 'CONFIG_ALL': true, +} + +# Generators + +hxtool = find_program('scripts/hxtool') +shaderinclude = find_program('scripts/shaderinclude.pl') +qapi_gen = find_program('scripts/qapi-gen.py') +qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', + meson.source_root() / 'scripts/qapi/commands.py', + meson.source_root() / 'scripts/qapi/common.py', + meson.source_root() / 'scripts/qapi/doc.py', + meson.source_root() / 'scripts/qapi/error.py', + meson.source_root() / 'scripts/qapi/events.py', + meson.source_root() / 'scripts/qapi/expr.py', + meson.source_root() / 'scripts/qapi/gen.py', + meson.source_root() / 'scripts/qapi/introspect.py', + meson.source_root() / 'scripts/qapi/parser.py', + meson.source_root() / 'scripts/qapi/schema.py', + meson.source_root() / 'scripts/qapi/source.py', + meson.source_root() / 'scripts/qapi/types.py', + meson.source_root() / 'scripts/qapi/visit.py', + meson.source_root() / 'scripts/qapi/common.py', + meson.source_root() / 'scripts/qapi/doc.py', + meson.source_root() / 'scripts/qapi-gen.py' +] + +tracetool = [ + python, files('scripts/tracetool.py'), + '--backend=' + config_host['TRACE_BACKENDS'] +] + +qemu_version_cmd = [find_program('scripts/qemu-version.sh'), + meson.current_source_dir(), + config_host['PKGVERSION'], meson.project_version()] +qemu_version = custom_target('qemu-version.h', + output: 'qemu-version.h', + command: qemu_version_cmd, + capture: true, + build_by_default: true, + build_always_stale: true) +genh += qemu_version + +hxdep = [] +hx_headers = [ + ['qemu-options.hx', 'qemu-options.def'], + ['qemu-img-cmds.hx', 'qemu-img-cmds.h'], +] +if have_system + hx_headers += [ + ['hmp-commands.hx', 'hmp-commands.h'], + ['hmp-commands-info.hx', 'hmp-commands-info.h'], + ] +endif +foreach d : hx_headers + hxdep += custom_target(d[1], + input: files(d[0]), + output: d[1], + capture: true, + build_by_default: true, # to be removed when added to a target + command: [hxtool, '-h', '@INPUT0@']) +endforeach +genh += hxdep + +# Collect sourcesets. + +util_ss = ss.source_set() +stub_ss = ss.source_set() +trace_ss = ss.source_set() +block_ss = ss.source_set() +blockdev_ss = ss.source_set() +qmp_ss = ss.source_set() +common_ss = ss.source_set() +softmmu_ss = ss.source_set() +user_ss = ss.source_set() +bsd_user_ss = ss.source_set() +linux_user_ss = ss.source_set() +specific_ss = ss.source_set() +specific_fuzz_ss = ss.source_set() + +modules = {} +hw_arch = {} +target_arch = {} +target_softmmu_arch = {} + +############### +# Trace files # +############### + +# TODO: add each directory to the subdirs from its own meson.build, once +# we have those +trace_events_subdirs = [ + 'accel/kvm', + 'accel/tcg', + 'crypto', + 'monitor', +] +if have_user + trace_events_subdirs += [ 'linux-user' ] +endif +if have_block + trace_events_subdirs += [ + 'authz', + 'block', + 'io', + 'nbd', + 'scsi', + ] +endif +if have_system + trace_events_subdirs += [ + 'audio', + 'backends', + 'backends/tpm', + 'chardev', + 'hw/9pfs', + 'hw/acpi', + 'hw/alpha', + 'hw/arm', + 'hw/audio', + 'hw/block', + 'hw/block/dataplane', + 'hw/char', + 'hw/display', + 'hw/dma', + 'hw/hppa', + 'hw/hyperv', + 'hw/i2c', + 'hw/i386', + 'hw/i386/xen', + 'hw/ide', + 'hw/input', + 'hw/intc', + 'hw/isa', + 'hw/mem', + 'hw/mips', + 'hw/misc', + 'hw/misc/macio', + 'hw/net', + 'hw/nvram', + 'hw/pci', + 'hw/pci-host', + 'hw/ppc', + 'hw/rdma', + 'hw/rdma/vmw', + 'hw/rtc', + 'hw/s390x', + 'hw/scsi', + 'hw/sd', + 'hw/sparc', + 'hw/sparc64', + 'hw/ssi', + 'hw/timer', + 'hw/tpm', + 'hw/usb', + 'hw/vfio', + 'hw/virtio', + 'hw/watchdog', + 'hw/xen', + 'hw/gpio', + 'hw/riscv', + 'migration', + 'net', + 'ui', + ] +endif +trace_events_subdirs += [ + 'hw/core', + 'qapi', + 'qom', + 'target/arm', + 'target/hppa', + 'target/i386', + 'target/mips', + 'target/ppc', + 'target/riscv', + 'target/s390x', + 'target/sparc', + 'util', +] + +subdir('qapi') +subdir('qobject') +subdir('stubs') +subdir('trace') +subdir('util') +subdir('qom') +subdir('authz') +subdir('crypto') +subdir('ui') + + +if enable_modules + libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') + modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO') +endif + +# Build targets from sourcesets + +stub_ss = stub_ss.apply(config_all, strict: false) + +util_ss.add_all(trace_ss) +util_ss = util_ss.apply(config_all, strict: false) +libqemuutil = static_library('qemuutil', + sources: util_ss.sources() + stub_ss.sources() + genh, + dependencies: [util_ss.dependencies(), m, glib, socket]) +qemuutil = declare_dependency(link_with: libqemuutil, + sources: genh + version_res) + +decodetree = generator(find_program('scripts/decodetree.py'), + output: 'decode-@BASENAME@.c.inc', + arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@']) + +subdir('audio') +subdir('io') +subdir('chardev') +subdir('fsdev') +subdir('libdecnumber') +subdir('target') +subdir('dump') + +block_ss.add(files( + 'block.c', + 'blockjob.c', + 'job.c', + 'qemu-io-cmds.c', +)) +block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c')) + +subdir('nbd') +subdir('scsi') +subdir('block') + +blockdev_ss.add(files( + 'blockdev.c', + 'blockdev-nbd.c', + 'iothread.c', + 'job-qmp.c', +)) + +# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon, +# os-win32.c does not +blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c')) +softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')]) + +softmmu_ss.add_all(blockdev_ss) +softmmu_ss.add(files( + 'bootdevice.c', + 'dma-helpers.c', + 'qdev-monitor.c', +), sdl) + +softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) +softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp]) +softmmu_ss.add(when: ['CONFIG_FDT', fdt], if_true: [files('device_tree.c')]) + +common_ss.add(files('cpus-common.c')) + +subdir('softmmu') + +specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl) +specific_ss.add(files('exec-vary.c')) +specific_ss.add(when: 'CONFIG_TCG', if_true: files( + 'fpu/softfloat.c', + 'tcg/optimize.c', + 'tcg/tcg-common.c', + 'tcg/tcg-op-gvec.c', + 'tcg/tcg-op-vec.c', + 'tcg/tcg-op.c', + 'tcg/tcg.c', +)) +specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c')) + +subdir('backends') +subdir('disas') +subdir('migration') +subdir('monitor') +subdir('net') +subdir('replay') +subdir('hw') +subdir('accel') +subdir('plugins') +subdir('bsd-user') +subdir('linux-user') + +bsd_user_ss.add(files('gdbstub.c')) +specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) + +linux_user_ss.add(files('gdbstub.c', 'thunk.c')) +specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss) + +# needed for fuzzing binaries +subdir('tests/qtest/libqos') +subdir('tests/qtest/fuzz') + +block_mods = [] +softmmu_mods = [] +foreach d, list : modules + foreach m, module_ss : list + if enable_modules and targetos != 'windows' + module_ss = module_ss.apply(config_host, strict: false) + sl = static_library(d + '-' + m, [genh, module_ss.sources()], + dependencies: [modulecommon, module_ss.dependencies()], pic: true) + if d == 'block' + block_mods += sl + else + softmmu_mods += sl + endif + else + if d == 'block' + block_ss.add_all(module_ss) + else + softmmu_ss.add_all(module_ss) + endif + endif + endforeach +endforeach + +nm = find_program('nm') +undefsym = find_program('scripts/undefsym.py') +block_syms = custom_target('block.syms', output: 'block.syms', + input: [libqemuutil, block_mods], + capture: true, + command: [undefsym, nm, '@INPUT@']) +qemu_syms = custom_target('qemu.syms', output: 'qemu.syms', + input: [libqemuutil, softmmu_mods], + capture: true, + command: [undefsym, nm, '@INPUT@']) + +block_ss = block_ss.apply(config_host, strict: false) +libblock = static_library('block', block_ss.sources() + genh, + dependencies: block_ss.dependencies(), + link_depends: block_syms, + name_suffix: 'fa', + build_by_default: false) + +block = declare_dependency(link_whole: [libblock], + link_args: '@block.syms', + dependencies: [crypto, io]) + +qmp_ss = qmp_ss.apply(config_host, strict: false) +libqmp = static_library('qmp', qmp_ss.sources() + genh, + dependencies: qmp_ss.dependencies(), + name_suffix: 'fa', + build_by_default: false) + +qmp = declare_dependency(link_whole: [libqmp]) + +foreach m : block_mods + softmmu_mods + shared_module(m.name(), + name_prefix: '', + link_whole: m, + install: true, + install_dir: config_host['qemu_moddir']) +endforeach + +softmmu_ss.add(authz, block, chardev, crypto, io, qmp) +common_ss.add(qom, qemuutil) + +common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss]) +common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss) + +common_all = common_ss.apply(config_all, strict: false) +common_all = static_library('common', + build_by_default: false, + sources: common_all.sources() + genh, + dependencies: common_all.dependencies(), + name_suffix: 'fa') + +feature_to_c = find_program('scripts/feature_to_c.sh') + +emulators = [] +foreach target : target_dirs + config_target = config_target_mak[target] + target_name = config_target['TARGET_NAME'] + arch = config_target['TARGET_BASE_ARCH'] + arch_srcs = [config_target_h[target]] + arch_deps = [] + c_args = ['-DNEED_CPU_H', + '-DCONFIG_TARGET="@0@-config-target.h"'.format(target), + '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)] + link_args = [] + + config_target += config_host + target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])] + if targetos == 'linux' + target_inc += include_directories('linux-headers', is_system: true) + endif + if target.endswith('-softmmu') + qemu_target_name = 'qemu-system-' + target_name + target_type='system' + t = target_softmmu_arch[arch].apply(config_target, strict: false) + arch_srcs += t.sources() + arch_deps += t.dependencies() + + hw_dir = target_name == 'sparc64' ? 'sparc64' : arch + hw = hw_arch[hw_dir].apply(config_target, strict: false) + arch_srcs += hw.sources() + arch_deps += hw.dependencies() + + arch_srcs += config_devices_h[target] + link_args += ['@block.syms', '@qemu.syms'] + else + abi = config_target['TARGET_ABI_DIR'] + target_type='user' + qemu_target_name = 'qemu-' + target_name + if 'CONFIG_LINUX_USER' in config_target + base_dir = 'linux-user' + target_inc += include_directories('linux-user/host/' / config_host['ARCH']) + else + base_dir = 'bsd-user' + endif + target_inc += include_directories( + base_dir, + base_dir / abi, + ) + if 'CONFIG_LINUX_USER' in config_target + dir = base_dir / abi + arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c') + if config_target.has_key('TARGET_SYSTBL_ABI') + arch_srcs += \ + syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'], + extra_args : config_target['TARGET_SYSTBL_ABI']) + endif + endif + endif + + if 'TARGET_XML_FILES' in config_target + gdbstub_xml = custom_target(target + '-gdbstub-xml.c', + output: target + '-gdbstub-xml.c', + input: files(config_target['TARGET_XML_FILES'].split()), + command: [feature_to_c, '@INPUT@'], + capture: true) + arch_srcs += gdbstub_xml + endif + + t = target_arch[arch].apply(config_target, strict: false) + arch_srcs += t.sources() + arch_deps += t.dependencies() + + target_common = common_ss.apply(config_target, strict: false) + objects = common_all.extract_objects(target_common.sources()) + deps = target_common.dependencies() + + target_specific = specific_ss.apply(config_target, strict: false) + arch_srcs += target_specific.sources() + arch_deps += target_specific.dependencies() + + lib = static_library('qemu-' + target, + sources: arch_srcs + genh, + dependencies: arch_deps, + objects: objects, + include_directories: target_inc, + c_args: c_args, + build_by_default: false, + name_suffix: 'fa') + + if target.endswith('-softmmu') + execs = [{ + 'name': 'qemu-system-' + target_name, + 'gui': false, + 'sources': files('softmmu/main.c'), + 'dependencies': [] + }] + if targetos == 'windows' and (sdl.found() or gtk.found()) + execs += [{ + 'name': 'qemu-system-' + target_name + 'w', + 'gui': true, + 'sources': files('softmmu/main.c'), + 'dependencies': [] + }] + endif + if config_host.has_key('CONFIG_FUZZ') + specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false) + execs += [{ + 'name': 'qemu-fuzz-' + target_name, + 'gui': false, + 'sources': specific_fuzz.sources(), + 'dependencies': specific_fuzz.dependencies(), + 'link_depends': [files('tests/qtest/fuzz/fork_fuzz.ld')], + }] + endif + else + execs = [{ + 'name': 'qemu-' + target_name, + 'gui': false, + 'sources': [], + 'dependencies': [] + }] + endif + foreach exe: execs + emulators += executable(exe['name'], exe['sources'], + install: true, + c_args: c_args, + dependencies: arch_deps + deps + exe['dependencies'], + objects: lib.extract_all_objects(recursive: true), + link_language: link_language, + link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), + link_args: link_args, + gui_app: exe['gui']) + + if 'CONFIG_TRACE_SYSTEMTAP' in config_host + foreach stp: [ + {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false}, + {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true}, + {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true}, + {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true}, + ] + custom_target(exe['name'] + stp['ext'], + input: trace_events_all, + output: exe['name'] + stp['ext'], + capture: true, + install: stp['install'], + install_dir: qemu_datadir / '../systemtap/tapset', + command: [ + tracetool, '--group=all', '--format=' + stp['fmt'], + '--binary=' + stp['bin'], + '--target-name=' + target_name, + '--target-type=' + target_type, + '--probe-prefix=qemu.' + target_type + '.' + target_name, + '@INPUT@', + ]) + endforeach + endif + endforeach +endforeach + +# Other build targets + +if 'CONFIG_PLUGIN' in config_host + install_headers('include/qemu/qemu-plugin.h') +endif + +if 'CONFIG_GUEST_AGENT' in config_host + subdir('qga') +endif + +# Don't build qemu-keymap if xkbcommon is not explicitly enabled +# when we don't build tools or system +if xkbcommon.found() + # used for the update-keymaps target, so include rules even if !have_tools + qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh, + dependencies: [qemuutil, xkbcommon], install: have_tools) +endif + +qemu_block_tools = [] +if have_tools + qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep], + dependencies: [authz, block, crypto, io, qom, qemuutil], install: true) + qemu_io = executable('qemu-io', files('qemu-io.c'), + dependencies: [block, qemuutil], install: true) + qemu_block_tools += [qemu_img, qemu_io] + if targetos != 'windows' + qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'), + dependencies: [block, qemuutil], install: true) + qemu_block_tools += [qemu_nbd] + endif + + subdir('storage-daemon') + subdir('contrib/rdmacm-mux') + subdir('contrib/elf2dmp') + + executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'), + dependencies: qemuutil, + install: true) + + if 'CONFIG_VHOST_USER' in config_host + subdir('contrib/libvhost-user') + subdir('contrib/vhost-user-blk') + subdir('contrib/vhost-user-gpu') + subdir('contrib/vhost-user-input') + subdir('contrib/vhost-user-scsi') + endif + + if targetos == 'linux' + executable('qemu-bridge-helper', files('qemu-bridge-helper.c'), + dependencies: [qemuutil, libcap_ng], + install: true, + install_dir: get_option('libexecdir')) + + executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'), + dependencies: [authz, crypto, io, qom, qemuutil, + libcap_ng, libudev, libmpathpersist], + install: true) + endif + + if 'CONFIG_IVSHMEM' in config_host + subdir('contrib/ivshmem-client') + subdir('contrib/ivshmem-server') + endif +endif + +subdir('scripts') +subdir('tools') +subdir('pc-bios') +subdir('tests') +subdir('docs') +if 'CONFIG_GTK' in config_host + subdir('po') +endif + +if build_docs + makeinfo = find_program('makeinfo', required: build_docs) + + docs_inc = [ + '-I', meson.current_source_dir(), + '-I', meson.current_build_dir() / 'docs', + '-I', '@OUTDIR@', + ] + + version_texi = configure_file(output: 'version.texi', + input: 'version.texi.in', + configuration: {'VERSION': meson.project_version(), + 'qemu_confdir': config_host['qemu_confdir']}) + + texi = { + 'qemu-qmp-ref': ['docs/interop/qemu-qmp-ref.texi', qapi_doc_texi, version_texi], + } + if 'CONFIG_GUEST_AGENT' in config_host + texi += {'qemu-ga-ref': ['docs/interop/qemu-ga-ref.texi', qga_qapi_doc_texi, version_texi]} + endif + + if makeinfo.found() + cmd = [ + 'env', 'LC_ALL=C', makeinfo, '--no-split', '--number-sections', docs_inc, + '@INPUT0@', '-o', '@OUTPUT@', + ] + foreach ext, args: { + 'info': [], + 'html': ['--no-headers', '--html'], + 'txt': ['--no-headers', '--plaintext'], + } + t = [] + foreach doc, input: texi + output = doc + '.' + ext + t += custom_target(output, + input: input, + output: output, + install: true, + install_dir: qemu_docdir / 'interop', + command: cmd + args) + endforeach + alias_target(ext, t) + endforeach + endif + + texi2pdf = find_program('texi2pdf', required: false) + + if texi2pdf.found() + pdfs = [] + foreach doc, input: texi + output = doc + '.pdf' + pdfs += custom_target(output, + input: input, + output: output, + command: [texi2pdf, '-q', docs_inc, '@INPUT0@', '-o', '@OUTPUT@'], + build_by_default: false) + endforeach + alias_target('pdf', pdfs) + endif + + texi2pod = find_program('scripts/texi2pod.pl') + pod2man = find_program('pod2man', required: build_docs) + + if pod2man.found() + foreach doc, input: texi + man = doc + '.7' + pod = custom_target(man + '.pod', + input: input, + output: man + '.pod', + command: [texi2pod, + '-DVERSION="' + meson.project_version() + '"', + '-DCONFDIR="' + config_host['qemu_confdir'] + '"', + '@INPUT0@', '@OUTPUT@']) + man = custom_target(man, + input: pod, + output: man, + capture: true, + install: true, + install_dir: get_option('mandir') / 'man7', + command: [pod2man, '--utf8', '--section=7', '--center=" "', + '--release=" "', '@INPUT@']) + endforeach + endif +endif + +if host_machine.system() == 'windows' + nsis_cmd = [ + find_program('scripts/nsis.py'), + '@OUTPUT@', + get_option('prefix'), + meson.current_source_dir(), + host_machine.cpu_family(), + '--', + '-DDISPLAYVERSION=' + meson.project_version(), + ] + if build_docs + nsis_cmd += '-DCONFIG_DOCUMENTATION=y' + endif + if 'CONFIG_GTK' in config_host + nsis_cmd += '-DCONFIG_GTK=y' + endif + + nsis = custom_target('nsis', + output: 'qemu-setup-' + meson.project_version() + '.exe', + input: files('qemu.nsi'), + build_always_stale: true, + command: nsis_cmd + ['@INPUT@']) + alias_target('installer', nsis) +endif + +summary_info = {} +summary_info += {'Install prefix': config_host['prefix']} +summary_info += {'BIOS directory': config_host['qemu_datadir']} +summary_info += {'firmware path': config_host['qemu_firmwarepath']} +summary_info += {'binary directory': config_host['bindir']} +summary_info += {'library directory': config_host['libdir']} +summary_info += {'module directory': config_host['qemu_moddir']} +summary_info += {'libexec directory': config_host['libexecdir']} +summary_info += {'include directory': config_host['includedir']} +summary_info += {'config directory': config_host['sysconfdir']} +if targetos != 'windows' + summary_info += {'local state directory': config_host['qemu_localstatedir']} + summary_info += {'Manual directory': get_option('mandir')} +else + summary_info += {'local state directory': 'queried at runtime'} +endif +summary_info += {'Doc directory': get_option('docdir')} +summary_info += {'Build directory': meson.current_build_dir()} +summary_info += {'Source path': meson.current_source_dir()} +summary_info += {'GIT binary': config_host['GIT']} +summary_info += {'GIT submodules': config_host['GIT_SUBMODULES']} +summary_info += {'C compiler': meson.get_compiler('c').cmd_array()[0]} +summary_info += {'Host C compiler': meson.get_compiler('c', native: true).cmd_array()[0]} +if link_language == 'cpp' + summary_info += {'C++ compiler': meson.get_compiler('cpp').cmd_array()[0]} +else + summary_info += {'C++ compiler': false} +endif +if targetos == 'darwin' + summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]} +endif +summary_info += {'ARFLAGS': config_host['ARFLAGS']} +summary_info += {'CFLAGS': config_host['CFLAGS']} +summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} +summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} +summary_info += {'make': config_host['MAKE']} +summary_info += {'install': config_host['INSTALL']} +summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())} +summary_info += {'sphinx-build': config_host['SPHINX_BUILD']} +summary_info += {'genisoimage': config_host['GENISOIMAGE']} +# TODO: add back version +summary_info += {'slirp support': config_host.has_key('CONFIG_SLIRP')} +if config_host.has_key('CONFIG_SLIRP') + summary_info += {'smbd': config_host['CONFIG_SMBD_COMMAND']} +endif +summary_info += {'module support': config_host.has_key('CONFIG_MODULES')} +if config_host.has_key('CONFIG_MODULES') + summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')} +endif +summary_info += {'host CPU': cpu} +summary_info += {'host endianness': build_machine.endian()} +summary_info += {'target list': config_host['TARGET_DIRS']} +summary_info += {'gprof enabled': config_host.has_key('CONFIG_GPROF')} +summary_info += {'sparse enabled': meson.get_compiler('c').cmd_array().contains('cgcc')} +summary_info += {'strip binaries': get_option('strip')} +summary_info += {'profiler': config_host.has_key('CONFIG_PROFILER')} +summary_info += {'static build': config_host.has_key('CONFIG_TOOLS')} +if targetos == 'darwin' + summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')} +endif +# TODO: add back version +summary_info += {'SDL support': sdl.found()} +summary_info += {'SDL image support': sdl_image.found()} +# TODO: add back version +summary_info += {'GTK support': config_host.has_key('CONFIG_GTK')} +summary_info += {'GTK GL support': config_host.has_key('CONFIG_GTK_GL')} +summary_info += {'pixman': pixman.found()} +# TODO: add back version +summary_info += {'VTE support': config_host.has_key('CONFIG_VTE')} +summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']} +summary_info += {'GNUTLS support': config_host.has_key('CONFIG_GNUTLS')} +# TODO: add back version +summary_info += {'libgcrypt': config_host.has_key('CONFIG_GCRYPT')} +if config_host.has_key('CONFIG_GCRYPT') + summary_info += {' hmac': config_host.has_key('CONFIG_GCRYPT_HMAC')} + summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} +endif +# TODO: add back version +summary_info += {'nettle': config_host.has_key('CONFIG_NETTLE')} +if config_host.has_key('CONFIG_NETTLE') + summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} +endif +summary_info += {'libtasn1': config_host.has_key('CONFIG_TASN1')} +summary_info += {'PAM': config_host.has_key('CONFIG_AUTH_PAM')} +summary_info += {'iconv support': config_host.has_key('CONFIG_ICONV')} +summary_info += {'curses support': config_host.has_key('CONFIG_CURSES')} +# TODO: add back version +summary_info += {'virgl support': config_host.has_key('CONFIG_VIRGL')} +summary_info += {'curl support': config_host.has_key('CONFIG_CURL')} +summary_info += {'mingw32 support': targetos == 'windows'} +summary_info += {'Audio drivers': config_host['CONFIG_AUDIO_DRIVERS']} +summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']} +summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']} +summary_info += {'VirtFS support': config_host.has_key('CONFIG_VIRTFS')} +summary_info += {'Multipath support': config_host.has_key('CONFIG_MPATH')} +summary_info += {'VNC support': vnc.found()} +if vnc.found() + summary_info += {'VNC SASL support': sasl.found()} + summary_info += {'VNC JPEG support': jpeg.found()} + summary_info += {'VNC PNG support': png.found()} +endif +summary_info += {'xen support': config_host.has_key('CONFIG_XEN_BACKEND')} +if config_host.has_key('CONFIG_XEN_BACKEND') + summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']} +endif +summary_info += {'brlapi support': config_host.has_key('CONFIG_BRLAPI')} +summary_info += {'Documentation': config_host.has_key('BUILD_DOCS')} +summary_info += {'PIE': get_option('b_pie')} +summary_info += {'vde support': config_host.has_key('CONFIG_VDE')} +summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')} +summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')} +summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')} +summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')} +summary_info += {'Install blobs': config_host.has_key('INSTALL_BLOBS')} +# TODO: add back KVM/HAX/HVF/WHPX/TCG +#summary_info += {'KVM support': have_kvm'} +#summary_info += {'HAX support': have_hax'} +#summary_info += {'HVF support': have_hvf'} +#summary_info += {'WHPX support': have_whpx'} +#summary_info += {'TCG support': have_tcg'} +#if get_option('tcg') +# summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')} +# summary_info += {'TCG interpreter': config_host.has_key('CONFIG_TCG_INTERPRETER')} +#endif +summary_info += {'malloc trim support': config_host.has_key('CONFIG_MALLOC_TRIM')} +summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')} +summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')} +summary_info += {'fdt support': config_host.has_key('CONFIG_FDT')} +summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')} +summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')} +summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')} +summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')} +summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')} +summary_info += {'posix_memalign': config_host.has_key('CONFIG_POSIX_MEMALIGN')} +summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')} +summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')} +summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')} +summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')} +summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')} +summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')} +summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')} +summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')} +summary_info += {'Trace backends': config_host['TRACE_BACKENDS']} +if config_host['TRACE_BACKENDS'].split().contains('simple') + summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-'} +endif +# TODO: add back protocol and server version +summary_info += {'spice support': config_host.has_key('CONFIG_SPICE')} +summary_info += {'rbd support': config_host.has_key('CONFIG_RBD')} +summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')} +summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')} +summary_info += {'U2F support': u2f.found()} +summary_info += {'libusb': config_host.has_key('CONFIG_USB_LIBUSB')} +summary_info += {'usb net redir': config_host.has_key('CONFIG_USB_REDIR')} +summary_info += {'OpenGL support': config_host.has_key('CONFIG_OPENGL')} +summary_info += {'OpenGL dmabufs': config_host.has_key('CONFIG_OPENGL_DMABUF')} +summary_info += {'libiscsi support': config_host.has_key('CONFIG_LIBISCSI')} +summary_info += {'libnfs support': config_host.has_key('CONFIG_LIBNFS')} +summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')} +if targetos == 'windows' + if 'WIN_SDK' in config_host + summary_info += {'Windows SDK': config_host['WIN_SDK']} + endif + summary_info += {'QGA VSS support': config_host.has_key('CONFIG_QGA_VSS')} + summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')} + summary_info += {'QGA MSI support': config_host.has_key('CONFIG_QGA_MSI_ENABLED')} +endif +summary_info += {'seccomp support': config_host.has_key('CONFIG_SECCOMP')} +summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']} +summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1'} +summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')} +summary_info += {'mutex debugging': config_host.has_key('CONFIG_DEBUG_MUTEX')} +summary_info += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} +summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')} +summary_info += {'gcov': get_option('b_coverage')} +summary_info += {'TPM support': config_host.has_key('CONFIG_TPM')} +summary_info += {'libssh support': config_host.has_key('CONFIG_LIBSSH')} +summary_info += {'QOM debugging': config_host.has_key('CONFIG_QOM_CAST_DEBUG')} +summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')} +summary_info += {'lzo support': config_host.has_key('CONFIG_LZO')} +summary_info += {'snappy support': config_host.has_key('CONFIG_SNAPPY')} +summary_info += {'bzip2 support': config_host.has_key('CONFIG_BZIP2')} +summary_info += {'lzfse support': config_host.has_key('CONFIG_LZFSE')} +summary_info += {'zstd support': config_host.has_key('CONFIG_ZSTD')} +summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} +summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} +summary_info += {'tcmalloc support': config_host.has_key('CONFIG_TCMALLOC')} +summary_info += {'jemalloc support': config_host.has_key('CONFIG_JEMALLOC')} +summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')} +summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')} +summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')} +summary_info += {'bochs support': config_host.has_key('CONFIG_BOCHS')} +summary_info += {'cloop support': config_host.has_key('CONFIG_CLOOP')} +summary_info += {'dmg support': config_host.has_key('CONFIG_DMG')} +summary_info += {'qcow v1 support': config_host.has_key('CONFIG_QCOW1')} +summary_info += {'vdi support': config_host.has_key('CONFIG_VDI')} +summary_info += {'vvfat support': config_host.has_key('CONFIG_VVFAT')} +summary_info += {'qed support': config_host.has_key('CONFIG_QED')} +summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')} +summary_info += {'sheepdog support': config_host.has_key('CONFIG_SHEEPDOG')} +summary_info += {'capstone': config_host.has_key('CONFIG_CAPSTONE')} +summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} +summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} +summary_info += {'libudev': config_host.has_key('CONFIG_LIBUDEV')} +summary_info += {'default devices': config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'} +summary_info += {'plugin support': config_host.has_key('CONFIG_PLUGIN')} +summary_info += {'fuzzing support': config_host.has_key('CONFIG_FUZZ')} +if config_host.has_key('HAVE_GDB_BIN') + summary_info += {'gdb': config_host['HAVE_GDB_BIN']} +endif +summary_info += {'thread sanitizer': config_host.has_key('CONFIG_TSAN')} +summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} +summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} +summary(summary_info, bool_yn: true) + +if not supported_cpus.contains(cpu) + message() + warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!') + message() + message('CPU host architecture ' + cpu + ' support is not currently maintained.') + message('The QEMU project intends to remove support for this host CPU in') + message('a future release if nobody volunteers to maintain it and to') + message('provide a build host for our continuous integration setup.') + message('configure has succeeded and you can continue to build, but') + message('if you care about QEMU on this platform you should contact') + message('us upstream at qemu-devel@nongnu.org.') +endif + +if not supported_oses.contains(targetos) + message() + warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!') + message() + message('Host OS ' + targetos + 'support is not currently maintained.') + message('The QEMU project intends to remove support for this host OS in') + message('a future release if nobody volunteers to maintain it and to') + message('provide a build host for our continuous integration setup.') + message('configure has succeeded and you can continue to build, but') + message('if you care about QEMU on this platform you should contact') + message('us upstream at qemu-devel@nongnu.org.') +endif diff --git a/scripts/undefsym.py b/scripts/undefsym.py new file mode 100644 index 0000000000..c690f88c7a --- /dev/null +++ b/scripts/undefsym.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Before a shared module's DSO is produced, a static library is built for it +# and passed to this script. The script generates -Wl,-u options to force +# the inclusion of symbol from libqemuutil.a if the shared modules need them, +# This is necessary because the modules may use functions not needed by the +# executable itself, which would cause the function to not be linked in. +# Then the DSO loading would fail because of the missing symbol. + + +""" +Compare the static library with the shared module for compute the symbol duplication +""" + +import sys +import subprocess + +def filter_lines_set(stdout, is_static = True): + linesSet = set() + for line in stdout.splitlines(): + tokens = line.split(b' ') + if len(tokens) >= 1: + if len(tokens) > 1: + if is_static and tokens[1] == b'U': + continue + if not is_static and tokens[1] != b'U': + continue + new_line = b'-Wl,-u,' + tokens[0] + if not new_line in linesSet: + linesSet.add(new_line) + return linesSet + +def main(args): + if len(args) <= 3: + sys.exit(0) + + nm = args[1] + staticlib = args[2] + pc = subprocess.run([nm, "-P", "-g", staticlib], stdout=subprocess.PIPE) + if pc.returncode != 0: + sys.exit(-1) + lines_set_left = filter_lines_set(pc.stdout) + + shared_modules = args[3:] + pc = subprocess.run([nm, "-P", "-g"] + shared_modules, stdout=subprocess.PIPE) + if pc.returncode != 0: + sys.exit(-1) + lines_set_right = filter_lines_set(pc.stdout, False) + lines = [] + for line in sorted(list(lines_set_right)): + if line in lines_set_left: + lines.append(line) + sys.stdout.write(b'\n'.join(lines).decode()) + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/undefsym.sh b/scripts/undefsym.sh deleted file mode 100755 index b9ec332e95..0000000000 --- a/scripts/undefsym.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env bash - -# Before a shared module's DSO is produced, a static library is built for it -# and passed to this script. The script generates -Wl,-u options to force -# the inclusion of symbol from libqemuutil.a if the shared modules need them, -# This is necessary because the modules may use functions not needed by the -# executable itself, which would cause the function to not be linked in. -# Then the DSO loading would fail because of the missing symbol. - -if test $# -le 2; then - exit 0 -fi - -NM=$1 -staticlib=$2 -shift 2 -# Find symbols defined in static libraries and undefined in shared modules -comm -12 \ - <( $NM -P -g $staticlib | awk '$2!="U"{print "-Wl,-u," $1}' | sort -u) \ - <( $NM -P -g "$@" | awk '$2=="U"{print "-Wl,-u," $1}' | sort -u) From patchwork Thu Sep 3 07:43:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752585 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6C81739 for ; Thu, 3 Sep 2020 07:46:57 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 29ED820716 for ; Thu, 3 Sep 2020 07:46:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ivrr+fZ2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 29ED820716 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:54654 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjxQ-00061t-8z for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:46:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43374) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuO-0008PN-JO for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:48 -0400 Received: from mail-pj1-x1033.google.com ([2607:f8b0:4864:20::1033]:40888) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuI-0003rU-7H for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:48 -0400 Received: by mail-pj1-x1033.google.com with SMTP id gf14so1055423pjb.5 for ; Thu, 03 Sep 2020 00:43:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=C/EyLnqbTRYUDf3q8ozzHANSrPdMQW7zxrYW8UbFQvQ=; b=ivrr+fZ2f+4fPFHHGondaB90DGboNLqXX4Be5PpDJsGMK14P60XYtRUYfyCx9jEbNe QYq8JyR4yR0HxSEgOFVnfzuiXFd/c2o1ih9Mn6Kd8GMeDwVovXnpAW2i2v6i3HIvH67p m+0q6azpf59oCCpbhNVnN49p+XSnJ0yrFMTskUl4N3ydkNS7Vb7kPU8jNDhvHQ5glt9/ NqMcI6huLo84OHzuzaik9VEqAhmZ2RcMrNJiVzZTbbTrVGhR//s5iaayGnSbPQoLbW2d r/E72ytO+MthE9uOl8z9CxqAUBiNHVtbII2e8Qw4iWxP0aXT1hZV4CJCzmncVHUUJxDq QCDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=C/EyLnqbTRYUDf3q8ozzHANSrPdMQW7zxrYW8UbFQvQ=; b=qspne+HaCqrGD7lGc10uCX63k0bzD+Hq0wAnTTA0pEgBW7fAqzD0HAriOFHp1/w91W fO5HhDhG8DYK9+H6aZqcyPB5gDqEInYVZJd0gCkDiIh06qfKuvxNVqiep2X3iw7wyTsh b3Lba0CrBWinCQjpdfJvjYp0IA3zBJhol+hW8V/dBZXcF0r2SG9LVcatmJoeixX9o0fn 2FQupA2P45LFNsoe6x8jVT4KXTqOm3uTajwM5SHOZ6EIbeQoCB0pgg99AId0nObSfLP4 enyxX+uzUnslGRXtNjwqIscNdFffLTP6x44kvzT5DeFYxQaSRe0r4xLTbyNy1vYJbbFq 42rQ== X-Gm-Message-State: AOAM532XAYo9mK6Af9mzX5cyH9nBCwNyrV28pEo+UG9KmEmtuFTUUQVh RVN7zD2lt4QbWxaeW1h+sWOa6sJmKIwag/D/ X-Google-Smtp-Source: ABdhPJx9PZ1Q+kOTkcya6yOSGVTMrMpo7vZZKlji2d2EGEIF6a6cAa83H2VObwu49YSlYCBahmvP0Q== X-Received: by 2002:a17:90a:a60c:: with SMTP id c12mr1933617pjq.1.1599119017281; Thu, 03 Sep 2020 00:43:37 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:36 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 03/12] tcg: Fixes dup_const link error Date: Thu, 3 Sep 2020 15:43:04 +0800 Message-Id: <20200903074313.1498-4-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1033; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1033.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Rename function dup_const to dup_const_eval for avoid confliction with macro dup_const The link error on msys2 Linking target qemu-system-alpha.exe C:/CI-Tools/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: libqemu-alpha-softmmu.fa.p/tcg_optimize.c.obj: in function `tcg_optimize': E:\CI-Cor-Ready\xemu\qemu-build/../qemu.org/tcg/optimize.c:1106: undefined reference to `dup_const' C:/CI-Tools/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: libqemu-alpha-softmmu.fa.p/tcg_tcg-op-vec.c.obj: in function `tcg_gen_dupi_vec': E:\CI-Cor-Ready\xemu\qemu-build/../qemu.org/tcg/tcg-op-vec.c:283: undefined reference to `dup_const' collect2.exe: error: ld returned 1 exit status Signed-off-by: Yonggang Luo --- include/tcg/tcg.h | 2898 +++++++++---------- tcg/tcg-op-gvec.c | 7012 ++++++++++++++++++++++----------------------- 2 files changed, 4955 insertions(+), 4955 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 53ce94c2c5..7f6fe8454b 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -1,1449 +1,1449 @@ -/* - * Tiny Code Generator for QEMU - * - * Copyright (c) 2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TCG_H -#define TCG_H - -#include "cpu.h" -#include "exec/memop.h" -#include "exec/tb-context.h" -#include "qemu/bitops.h" -#include "qemu/plugin.h" -#include "qemu/queue.h" -#include "tcg/tcg-mo.h" -#include "tcg-target.h" -#include "qemu/int128.h" - -/* XXX: make safe guess about sizes */ -#define MAX_OP_PER_INSTR 266 - -#if HOST_LONG_BITS == 32 -#define MAX_OPC_PARAM_PER_ARG 2 -#else -#define MAX_OPC_PARAM_PER_ARG 1 -#endif -#define MAX_OPC_PARAM_IARGS 6 -#define MAX_OPC_PARAM_OARGS 1 -#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS) - -/* A Call op needs up to 4 + 2N parameters on 32-bit archs, - * and up to 4 + N parameters on 64-bit archs - * (N = number of input arguments + output arguments). */ -#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS)) - -#define CPU_TEMP_BUF_NLONGS 128 - -/* Default target word size to pointer size. */ -#ifndef TCG_TARGET_REG_BITS -# if UINTPTR_MAX == UINT32_MAX -# define TCG_TARGET_REG_BITS 32 -# elif UINTPTR_MAX == UINT64_MAX -# define TCG_TARGET_REG_BITS 64 -# else -# error Unknown pointer size for tcg target -# endif -#endif - -#if TCG_TARGET_REG_BITS == 32 -typedef int32_t tcg_target_long; -typedef uint32_t tcg_target_ulong; -#define TCG_PRIlx PRIx32 -#define TCG_PRIld PRId32 -#elif TCG_TARGET_REG_BITS == 64 -typedef int64_t tcg_target_long; -typedef uint64_t tcg_target_ulong; -#define TCG_PRIlx PRIx64 -#define TCG_PRIld PRId64 -#else -#error unsupported -#endif - -/* Oversized TCG guests make things like MTTCG hard - * as we can't use atomics for cputlb updates. - */ -#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS -#define TCG_OVERSIZED_GUEST 1 -#else -#define TCG_OVERSIZED_GUEST 0 -#endif - -#if TCG_TARGET_NB_REGS <= 32 -typedef uint32_t TCGRegSet; -#elif TCG_TARGET_NB_REGS <= 64 -typedef uint64_t TCGRegSet; -#else -#error unsupported -#endif - -#if TCG_TARGET_REG_BITS == 32 -/* Turn some undef macros into false macros. */ -#define TCG_TARGET_HAS_extrl_i64_i32 0 -#define TCG_TARGET_HAS_extrh_i64_i32 0 -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 -#define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 0 -#define TCG_TARGET_HAS_ext8s_i64 0 -#define TCG_TARGET_HAS_ext16s_i64 0 -#define TCG_TARGET_HAS_ext32s_i64 0 -#define TCG_TARGET_HAS_ext8u_i64 0 -#define TCG_TARGET_HAS_ext16u_i64 0 -#define TCG_TARGET_HAS_ext32u_i64 0 -#define TCG_TARGET_HAS_bswap16_i64 0 -#define TCG_TARGET_HAS_bswap32_i64 0 -#define TCG_TARGET_HAS_bswap64_i64 0 -#define TCG_TARGET_HAS_neg_i64 0 -#define TCG_TARGET_HAS_not_i64 0 -#define TCG_TARGET_HAS_andc_i64 0 -#define TCG_TARGET_HAS_orc_i64 0 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 0 -#define TCG_TARGET_HAS_ctz_i64 0 -#define TCG_TARGET_HAS_ctpop_i64 0 -#define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_movcond_i64 0 -#define TCG_TARGET_HAS_add2_i64 0 -#define TCG_TARGET_HAS_sub2_i64 0 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 -/* Turn some undef macros into true macros. */ -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#endif - -#ifndef TCG_TARGET_deposit_i32_valid -#define TCG_TARGET_deposit_i32_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_deposit_i64_valid -#define TCG_TARGET_deposit_i64_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_extract_i32_valid -#define TCG_TARGET_extract_i32_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_extract_i64_valid -#define TCG_TARGET_extract_i64_valid(ofs, len) 1 -#endif - -/* Only one of DIV or DIV2 should be defined. */ -#if defined(TCG_TARGET_HAS_div_i32) -#define TCG_TARGET_HAS_div2_i32 0 -#elif defined(TCG_TARGET_HAS_div2_i32) -#define TCG_TARGET_HAS_div_i32 0 -#define TCG_TARGET_HAS_rem_i32 0 -#endif -#if defined(TCG_TARGET_HAS_div_i64) -#define TCG_TARGET_HAS_div2_i64 0 -#elif defined(TCG_TARGET_HAS_div2_i64) -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 -#endif - -/* For 32-bit targets, some sort of unsigned widening multiply is required. */ -#if TCG_TARGET_REG_BITS == 32 \ - && !(defined(TCG_TARGET_HAS_mulu2_i32) \ - || defined(TCG_TARGET_HAS_muluh_i32)) -# error "Missing unsigned widening multiply" -#endif - -#if !defined(TCG_TARGET_HAS_v64) \ - && !defined(TCG_TARGET_HAS_v128) \ - && !defined(TCG_TARGET_HAS_v256) -#define TCG_TARGET_MAYBE_vec 0 -#define TCG_TARGET_HAS_abs_vec 0 -#define TCG_TARGET_HAS_neg_vec 0 -#define TCG_TARGET_HAS_not_vec 0 -#define TCG_TARGET_HAS_andc_vec 0 -#define TCG_TARGET_HAS_orc_vec 0 -#define TCG_TARGET_HAS_roti_vec 0 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 0 -#define TCG_TARGET_HAS_shi_vec 0 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 0 -#define TCG_TARGET_HAS_mul_vec 0 -#define TCG_TARGET_HAS_sat_vec 0 -#define TCG_TARGET_HAS_minmax_vec 0 -#define TCG_TARGET_HAS_bitsel_vec 0 -#define TCG_TARGET_HAS_cmpsel_vec 0 -#else -#define TCG_TARGET_MAYBE_vec 1 -#endif -#ifndef TCG_TARGET_HAS_v64 -#define TCG_TARGET_HAS_v64 0 -#endif -#ifndef TCG_TARGET_HAS_v128 -#define TCG_TARGET_HAS_v128 0 -#endif -#ifndef TCG_TARGET_HAS_v256 -#define TCG_TARGET_HAS_v256 0 -#endif - -#ifndef TARGET_INSN_START_EXTRA_WORDS -# define TARGET_INSN_START_WORDS 1 -#else -# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS) -#endif - -typedef enum TCGOpcode { -#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name, -#include "tcg/tcg-opc.h" -#undef DEF - NB_OPS, -} TCGOpcode; - -#define tcg_regset_set_reg(d, r) ((d) |= (TCGRegSet)1 << (r)) -#define tcg_regset_reset_reg(d, r) ((d) &= ~((TCGRegSet)1 << (r))) -#define tcg_regset_test_reg(d, r) (((d) >> (r)) & 1) - -#ifndef TCG_TARGET_INSN_UNIT_SIZE -# error "Missing TCG_TARGET_INSN_UNIT_SIZE" -#elif TCG_TARGET_INSN_UNIT_SIZE == 1 -typedef uint8_t tcg_insn_unit; -#elif TCG_TARGET_INSN_UNIT_SIZE == 2 -typedef uint16_t tcg_insn_unit; -#elif TCG_TARGET_INSN_UNIT_SIZE == 4 -typedef uint32_t tcg_insn_unit; -#elif TCG_TARGET_INSN_UNIT_SIZE == 8 -typedef uint64_t tcg_insn_unit; -#else -/* The port better have done this. */ -#endif - - -#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS -# define tcg_debug_assert(X) do { assert(X); } while (0) -#else -# define tcg_debug_assert(X) \ - do { if (!(X)) { __builtin_unreachable(); } } while (0) -#endif - -typedef struct TCGRelocation TCGRelocation; -struct TCGRelocation { - QSIMPLEQ_ENTRY(TCGRelocation) next; - tcg_insn_unit *ptr; - intptr_t addend; - int type; -}; - -typedef struct TCGLabel TCGLabel; -struct TCGLabel { - unsigned present : 1; - unsigned has_value : 1; - unsigned id : 14; - unsigned refs : 16; - union { - uintptr_t value; - tcg_insn_unit *value_ptr; - } u; - QSIMPLEQ_HEAD(, TCGRelocation) relocs; - QSIMPLEQ_ENTRY(TCGLabel) next; -}; - -typedef struct TCGPool { - struct TCGPool *next; - int size; - uint8_t data[] __attribute__ ((aligned)); -} TCGPool; - -#define TCG_POOL_CHUNK_SIZE 32768 - -#define TCG_MAX_TEMPS 512 -#define TCG_MAX_INSNS 512 - -/* when the size of the arguments of a called function is smaller than - this value, they are statically allocated in the TB stack frame */ -#define TCG_STATIC_CALL_ARGS_SIZE 128 - -typedef enum TCGType { - TCG_TYPE_I32, - TCG_TYPE_I64, - - TCG_TYPE_V64, - TCG_TYPE_V128, - TCG_TYPE_V256, - - TCG_TYPE_COUNT, /* number of different types */ - - /* An alias for the size of the host register. */ -#if TCG_TARGET_REG_BITS == 32 - TCG_TYPE_REG = TCG_TYPE_I32, -#else - TCG_TYPE_REG = TCG_TYPE_I64, -#endif - - /* An alias for the size of the native pointer. */ -#if UINTPTR_MAX == UINT32_MAX - TCG_TYPE_PTR = TCG_TYPE_I32, -#else - TCG_TYPE_PTR = TCG_TYPE_I64, -#endif - - /* An alias for the size of the target "long", aka register. */ -#if TARGET_LONG_BITS == 64 - TCG_TYPE_TL = TCG_TYPE_I64, -#else - TCG_TYPE_TL = TCG_TYPE_I32, -#endif -} TCGType; - -/** - * get_alignment_bits - * @memop: MemOp value - * - * Extract the alignment size from the memop. - */ -static inline unsigned get_alignment_bits(MemOp memop) -{ - unsigned a = memop & MO_AMASK; - - if (a == MO_UNALN) { - /* No alignment required. */ - a = 0; - } else if (a == MO_ALIGN) { - /* A natural alignment requirement. */ - a = memop & MO_SIZE; - } else { - /* A specific alignment requirement. */ - a = a >> MO_ASHIFT; - } -#if defined(CONFIG_SOFTMMU) - /* The requested alignment cannot overlap the TLB flags. */ - tcg_debug_assert((TLB_FLAGS_MASK & ((1 << a) - 1)) == 0); -#endif - return a; -} - -typedef tcg_target_ulong TCGArg; - -/* Define type and accessor macros for TCG variables. - - TCG variables are the inputs and outputs of TCG ops, as described - in tcg/README. Target CPU front-end code uses these types to deal - with TCG variables as it emits TCG code via the tcg_gen_* functions. - They come in several flavours: - * TCGv_i32 : 32 bit integer type - * TCGv_i64 : 64 bit integer type - * TCGv_ptr : a host pointer type - * TCGv_vec : a host vector type; the exact size is not exposed - to the CPU front-end code. - * TCGv : an integer type the same size as target_ulong - (an alias for either TCGv_i32 or TCGv_i64) - The compiler's type checking will complain if you mix them - up and pass the wrong sized TCGv to a function. - - Users of tcg_gen_* don't need to know about any of the internal - details of these, and should treat them as opaque types. - You won't be able to look inside them in a debugger either. - - Internal implementation details follow: - - Note that there is no definition of the structs TCGv_i32_d etc anywhere. - This is deliberate, because the values we store in variables of type - TCGv_i32 are not really pointers-to-structures. They're just small - integers, but keeping them in pointer types like this means that the - compiler will complain if you accidentally pass a TCGv_i32 to a - function which takes a TCGv_i64, and so on. Only the internals of - TCG need to care about the actual contents of the types. */ - -typedef struct TCGv_i32_d *TCGv_i32; -typedef struct TCGv_i64_d *TCGv_i64; -typedef struct TCGv_ptr_d *TCGv_ptr; -typedef struct TCGv_vec_d *TCGv_vec; -typedef TCGv_ptr TCGv_env; -#if TARGET_LONG_BITS == 32 -#define TCGv TCGv_i32 -#elif TARGET_LONG_BITS == 64 -#define TCGv TCGv_i64 -#else -#error Unhandled TARGET_LONG_BITS value -#endif - -/* call flags */ -/* Helper does not read globals (either directly or through an exception). It - implies TCG_CALL_NO_WRITE_GLOBALS. */ -#define TCG_CALL_NO_READ_GLOBALS 0x0001 -/* Helper does not write globals */ -#define TCG_CALL_NO_WRITE_GLOBALS 0x0002 -/* Helper can be safely suppressed if the return value is not used. */ -#define TCG_CALL_NO_SIDE_EFFECTS 0x0004 -/* Helper is QEMU_NORETURN. */ -#define TCG_CALL_NO_RETURN 0x0008 - -/* convenience version of most used call flags */ -#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS -#define TCG_CALL_NO_WG TCG_CALL_NO_WRITE_GLOBALS -#define TCG_CALL_NO_SE TCG_CALL_NO_SIDE_EFFECTS -#define TCG_CALL_NO_RWG_SE (TCG_CALL_NO_RWG | TCG_CALL_NO_SE) -#define TCG_CALL_NO_WG_SE (TCG_CALL_NO_WG | TCG_CALL_NO_SE) - -/* Used to align parameters. See the comment before tcgv_i32_temp. */ -#define TCG_CALL_DUMMY_ARG ((TCGArg)0) - -/* Conditions. Note that these are laid out for easy manipulation by - the functions below: - bit 0 is used for inverting; - bit 1 is signed, - bit 2 is unsigned, - bit 3 is used with bit 0 for swapping signed/unsigned. */ -typedef enum { - /* non-signed */ - TCG_COND_NEVER = 0 | 0 | 0 | 0, - TCG_COND_ALWAYS = 0 | 0 | 0 | 1, - TCG_COND_EQ = 8 | 0 | 0 | 0, - TCG_COND_NE = 8 | 0 | 0 | 1, - /* signed */ - TCG_COND_LT = 0 | 0 | 2 | 0, - TCG_COND_GE = 0 | 0 | 2 | 1, - TCG_COND_LE = 8 | 0 | 2 | 0, - TCG_COND_GT = 8 | 0 | 2 | 1, - /* unsigned */ - TCG_COND_LTU = 0 | 4 | 0 | 0, - TCG_COND_GEU = 0 | 4 | 0 | 1, - TCG_COND_LEU = 8 | 4 | 0 | 0, - TCG_COND_GTU = 8 | 4 | 0 | 1, -} TCGCond; - -/* Invert the sense of the comparison. */ -static inline TCGCond tcg_invert_cond(TCGCond c) -{ - return (TCGCond)(c ^ 1); -} - -/* Swap the operands in a comparison. */ -static inline TCGCond tcg_swap_cond(TCGCond c) -{ - return c & 6 ? (TCGCond)(c ^ 9) : c; -} - -/* Create an "unsigned" version of a "signed" comparison. */ -static inline TCGCond tcg_unsigned_cond(TCGCond c) -{ - return c & 2 ? (TCGCond)(c ^ 6) : c; -} - -/* Create a "signed" version of an "unsigned" comparison. */ -static inline TCGCond tcg_signed_cond(TCGCond c) -{ - return c & 4 ? (TCGCond)(c ^ 6) : c; -} - -/* Must a comparison be considered unsigned? */ -static inline bool is_unsigned_cond(TCGCond c) -{ - return (c & 4) != 0; -} - -/* Create a "high" version of a double-word comparison. - This removes equality from a LTE or GTE comparison. */ -static inline TCGCond tcg_high_cond(TCGCond c) -{ - switch (c) { - case TCG_COND_GE: - case TCG_COND_LE: - case TCG_COND_GEU: - case TCG_COND_LEU: - return (TCGCond)(c ^ 8); - default: - return c; - } -} - -typedef enum TCGTempVal { - TEMP_VAL_DEAD, - TEMP_VAL_REG, - TEMP_VAL_MEM, - TEMP_VAL_CONST, -} TCGTempVal; - -typedef struct TCGTemp { - TCGReg reg:8; - TCGTempVal val_type:8; - TCGType base_type:8; - TCGType type:8; - unsigned int fixed_reg:1; - unsigned int indirect_reg:1; - unsigned int indirect_base:1; - unsigned int mem_coherent:1; - unsigned int mem_allocated:1; - /* If true, the temp is saved across both basic blocks and - translation blocks. */ - unsigned int temp_global:1; - /* If true, the temp is saved across basic blocks but dead - at the end of translation blocks. If false, the temp is - dead at the end of basic blocks. */ - unsigned int temp_local:1; - unsigned int temp_allocated:1; - - tcg_target_long val; - struct TCGTemp *mem_base; - intptr_t mem_offset; - const char *name; - - /* Pass-specific information that can be stored for a temporary. - One word worth of integer data, and one pointer to data - allocated separately. */ - uintptr_t state; - void *state_ptr; -} TCGTemp; - -typedef struct TCGContext TCGContext; - -typedef struct TCGTempSet { - unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)]; -} TCGTempSet; - -/* While we limit helpers to 6 arguments, for 32-bit hosts, with padding, - this imples a max of 6*2 (64-bit in) + 2 (64-bit out) = 14 operands. - There are never more than 2 outputs, which means that we can store all - dead + sync data within 16 bits. */ -#define DEAD_ARG 4 -#define SYNC_ARG 1 -typedef uint16_t TCGLifeData; - -/* The layout here is designed to avoid a bitfield crossing of - a 32-bit boundary, which would cause GCC to add extra padding. */ -typedef struct TCGOp { - TCGOpcode opc : 8; /* 8 */ - - /* Parameters for this opcode. See below. */ - unsigned param1 : 4; /* 12 */ - unsigned param2 : 4; /* 16 */ - - /* Lifetime data of the operands. */ - unsigned life : 16; /* 32 */ - - /* Next and previous opcodes. */ - QTAILQ_ENTRY(TCGOp) link; -#ifdef CONFIG_PLUGIN - QSIMPLEQ_ENTRY(TCGOp) plugin_link; -#endif - - /* Arguments for the opcode. */ - TCGArg args[MAX_OPC_PARAM]; - - /* Register preferences for the output(s). */ - TCGRegSet output_pref[2]; -} TCGOp; - -#define TCGOP_CALLI(X) (X)->param1 -#define TCGOP_CALLO(X) (X)->param2 - -#define TCGOP_VECL(X) (X)->param1 -#define TCGOP_VECE(X) (X)->param2 - -/* Make sure operands fit in the bitfields above. */ -QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8)); - -typedef struct TCGProfile { - int64_t cpu_exec_time; - int64_t tb_count1; - int64_t tb_count; - int64_t op_count; /* total insn count */ - int op_count_max; /* max insn per TB */ - int temp_count_max; - int64_t temp_count; - int64_t del_op_count; - int64_t code_in_len; - int64_t code_out_len; - int64_t search_out_len; - int64_t interm_time; - int64_t code_time; - int64_t la_time; - int64_t opt_time; - int64_t restore_count; - int64_t restore_time; - int64_t table_op_count[NB_OPS]; -} TCGProfile; - -struct TCGContext { - uint8_t *pool_cur, *pool_end; - TCGPool *pool_first, *pool_current, *pool_first_large; - int nb_labels; - int nb_globals; - int nb_temps; - int nb_indirects; - int nb_ops; - - /* goto_tb support */ - tcg_insn_unit *code_buf; - uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */ - uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */ - uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */ - - TCGRegSet reserved_regs; - uint32_t tb_cflags; /* cflags of the current TB */ - intptr_t current_frame_offset; - intptr_t frame_start; - intptr_t frame_end; - TCGTemp *frame_temp; - - tcg_insn_unit *code_ptr; - -#ifdef CONFIG_PROFILER - TCGProfile prof; -#endif - -#ifdef CONFIG_DEBUG_TCG - int temps_in_use; - int goto_tb_issue_mask; - const TCGOpcode *vecop_list; -#endif - - /* Code generation. Note that we specifically do not use tcg_insn_unit - here, because there's too much arithmetic throughout that relies - on addition and subtraction working on bytes. Rely on the GCC - extension that allows arithmetic on void*. */ - void *code_gen_prologue; - void *code_gen_epilogue; - void *code_gen_buffer; - size_t code_gen_buffer_size; - void *code_gen_ptr; - void *data_gen_ptr; - - /* Threshold to flush the translated code buffer. */ - void *code_gen_highwater; - - size_t tb_phys_invalidate_count; - - /* Track which vCPU triggers events */ - CPUState *cpu; /* *_trans */ - - /* These structures are private to tcg-target.c.inc. */ -#ifdef TCG_TARGET_NEED_LDST_LABELS - QSIMPLEQ_HEAD(, TCGLabelQemuLdst) ldst_labels; -#endif -#ifdef TCG_TARGET_NEED_POOL_LABELS - struct TCGLabelPoolData *pool_labels; -#endif - - TCGLabel *exitreq_label; - -#ifdef CONFIG_PLUGIN - /* - * We keep one plugin_tb struct per TCGContext. Note that on every TB - * translation we clear but do not free its contents; this way we - * avoid a lot of malloc/free churn, since after a few TB's it's - * unlikely that we'll need to allocate either more instructions or more - * space for instructions (for variable-instruction-length ISAs). - */ - struct qemu_plugin_tb *plugin_tb; - - /* descriptor of the instruction being translated */ - struct qemu_plugin_insn *plugin_insn; - - /* list to quickly access the injected ops */ - QSIMPLEQ_HEAD(, TCGOp) plugin_ops; -#endif - - TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; - TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ - - QTAILQ_HEAD(, TCGOp) ops, free_ops; - QSIMPLEQ_HEAD(, TCGLabel) labels; - - /* Tells which temporary holds a given register. - It does not take into account fixed registers */ - TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS]; - - uint16_t gen_insn_end_off[TCG_MAX_INSNS]; - target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; -}; - -extern TCGContext tcg_init_ctx; -extern __thread TCGContext *tcg_ctx; -extern TCGv_env cpu_env; - -static inline size_t temp_idx(TCGTemp *ts) -{ - ptrdiff_t n = ts - tcg_ctx->temps; - tcg_debug_assert(n >= 0 && n < tcg_ctx->nb_temps); - return n; -} - -static inline TCGArg temp_arg(TCGTemp *ts) -{ - return (uintptr_t)ts; -} - -static inline TCGTemp *arg_temp(TCGArg a) -{ - return (TCGTemp *)(uintptr_t)a; -} - -/* Using the offset of a temporary, relative to TCGContext, rather than - its index means that we don't use 0. That leaves offset 0 free for - a NULL representation without having to leave index 0 unused. */ -static inline TCGTemp *tcgv_i32_temp(TCGv_i32 v) -{ - uintptr_t o = (uintptr_t)v; - TCGTemp *t = (void *)tcg_ctx + o; - tcg_debug_assert(offsetof(TCGContext, temps[temp_idx(t)]) == o); - return t; -} - -static inline TCGTemp *tcgv_i64_temp(TCGv_i64 v) -{ - return tcgv_i32_temp((TCGv_i32)v); -} - -static inline TCGTemp *tcgv_ptr_temp(TCGv_ptr v) -{ - return tcgv_i32_temp((TCGv_i32)v); -} - -static inline TCGTemp *tcgv_vec_temp(TCGv_vec v) -{ - return tcgv_i32_temp((TCGv_i32)v); -} - -static inline TCGArg tcgv_i32_arg(TCGv_i32 v) -{ - return temp_arg(tcgv_i32_temp(v)); -} - -static inline TCGArg tcgv_i64_arg(TCGv_i64 v) -{ - return temp_arg(tcgv_i64_temp(v)); -} - -static inline TCGArg tcgv_ptr_arg(TCGv_ptr v) -{ - return temp_arg(tcgv_ptr_temp(v)); -} - -static inline TCGArg tcgv_vec_arg(TCGv_vec v) -{ - return temp_arg(tcgv_vec_temp(v)); -} - -static inline TCGv_i32 temp_tcgv_i32(TCGTemp *t) -{ - (void)temp_idx(t); /* trigger embedded assert */ - return (TCGv_i32)((void *)t - (void *)tcg_ctx); -} - -static inline TCGv_i64 temp_tcgv_i64(TCGTemp *t) -{ - return (TCGv_i64)temp_tcgv_i32(t); -} - -static inline TCGv_ptr temp_tcgv_ptr(TCGTemp *t) -{ - return (TCGv_ptr)temp_tcgv_i32(t); -} - -static inline TCGv_vec temp_tcgv_vec(TCGTemp *t) -{ - return (TCGv_vec)temp_tcgv_i32(t); -} - -#if TCG_TARGET_REG_BITS == 32 -static inline TCGv_i32 TCGV_LOW(TCGv_i64 t) -{ - return temp_tcgv_i32(tcgv_i64_temp(t)); -} - -static inline TCGv_i32 TCGV_HIGH(TCGv_i64 t) -{ - return temp_tcgv_i32(tcgv_i64_temp(t) + 1); -} -#endif - -static inline TCGArg tcg_get_insn_param(TCGOp *op, int arg) -{ - return op->args[arg]; -} - -static inline void tcg_set_insn_param(TCGOp *op, int arg, TCGArg v) -{ - op->args[arg] = v; -} - -static inline target_ulong tcg_get_insn_start_param(TCGOp *op, int arg) -{ -#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS - return tcg_get_insn_param(op, arg); -#else - return tcg_get_insn_param(op, arg * 2) | - ((uint64_t)tcg_get_insn_param(op, arg * 2 + 1) << 32); -#endif -} - -static inline void tcg_set_insn_start_param(TCGOp *op, int arg, target_ulong v) -{ -#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS - tcg_set_insn_param(op, arg, v); -#else - tcg_set_insn_param(op, arg * 2, v); - tcg_set_insn_param(op, arg * 2 + 1, v >> 32); -#endif -} - -/* The last op that was emitted. */ -static inline TCGOp *tcg_last_op(void) -{ - return QTAILQ_LAST(&tcg_ctx->ops); -} - -/* Test for whether to terminate the TB for using too many opcodes. */ -static inline bool tcg_op_buf_full(void) -{ - /* This is not a hard limit, it merely stops translation when - * we have produced "enough" opcodes. We want to limit TB size - * such that a RISC host can reasonably use a 16-bit signed - * branch within the TB. We also need to be mindful of the - * 16-bit unsigned offsets, TranslationBlock.jmp_reset_offset[] - * and TCGContext.gen_insn_end_off[]. - */ - return tcg_ctx->nb_ops >= 4000; -} - -/* pool based memory allocation */ - -/* user-mode: mmap_lock must be held for tcg_malloc_internal. */ -void *tcg_malloc_internal(TCGContext *s, int size); -void tcg_pool_reset(TCGContext *s); -TranslationBlock *tcg_tb_alloc(TCGContext *s); - -void tcg_region_init(void); -void tb_destroy(TranslationBlock *tb); -void tcg_region_reset_all(void); - -size_t tcg_code_size(void); -size_t tcg_code_capacity(void); - -void tcg_tb_insert(TranslationBlock *tb); -void tcg_tb_remove(TranslationBlock *tb); -size_t tcg_tb_phys_invalidate_count(void); -TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); -void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); -size_t tcg_nb_tbs(void); - -/* user-mode: Called with mmap_lock held. */ -static inline void *tcg_malloc(int size) -{ - TCGContext *s = tcg_ctx; - uint8_t *ptr, *ptr_end; - - /* ??? This is a weak placeholder for minimum malloc alignment. */ - size = QEMU_ALIGN_UP(size, 8); - - ptr = s->pool_cur; - ptr_end = ptr + size; - if (unlikely(ptr_end > s->pool_end)) { - return tcg_malloc_internal(tcg_ctx, size); - } else { - s->pool_cur = ptr_end; - return ptr; - } -} - -void tcg_context_init(TCGContext *s); -void tcg_register_thread(void); -void tcg_prologue_init(TCGContext *s); -void tcg_func_start(TCGContext *s); - -int tcg_gen_code(TCGContext *s, TranslationBlock *tb); - -void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size); - -TCGTemp *tcg_global_mem_new_internal(TCGType, TCGv_ptr, - intptr_t, const char *); -TCGTemp *tcg_temp_new_internal(TCGType, bool); -void tcg_temp_free_internal(TCGTemp *); -TCGv_vec tcg_temp_new_vec(TCGType type); -TCGv_vec tcg_temp_new_vec_matching(TCGv_vec match); - -static inline void tcg_temp_free_i32(TCGv_i32 arg) -{ - tcg_temp_free_internal(tcgv_i32_temp(arg)); -} - -static inline void tcg_temp_free_i64(TCGv_i64 arg) -{ - tcg_temp_free_internal(tcgv_i64_temp(arg)); -} - -static inline void tcg_temp_free_ptr(TCGv_ptr arg) -{ - tcg_temp_free_internal(tcgv_ptr_temp(arg)); -} - -static inline void tcg_temp_free_vec(TCGv_vec arg) -{ - tcg_temp_free_internal(tcgv_vec_temp(arg)); -} - -static inline TCGv_i32 tcg_global_mem_new_i32(TCGv_ptr reg, intptr_t offset, - const char *name) -{ - TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); - return temp_tcgv_i32(t); -} - -static inline TCGv_i32 tcg_temp_new_i32(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, false); - return temp_tcgv_i32(t); -} - -static inline TCGv_i32 tcg_temp_local_new_i32(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, true); - return temp_tcgv_i32(t); -} - -static inline TCGv_i64 tcg_global_mem_new_i64(TCGv_ptr reg, intptr_t offset, - const char *name) -{ - TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); - return temp_tcgv_i64(t); -} - -static inline TCGv_i64 tcg_temp_new_i64(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, false); - return temp_tcgv_i64(t); -} - -static inline TCGv_i64 tcg_temp_local_new_i64(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, true); - return temp_tcgv_i64(t); -} - -static inline TCGv_ptr tcg_global_mem_new_ptr(TCGv_ptr reg, intptr_t offset, - const char *name) -{ - TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_PTR, reg, offset, name); - return temp_tcgv_ptr(t); -} - -static inline TCGv_ptr tcg_temp_new_ptr(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_PTR, false); - return temp_tcgv_ptr(t); -} - -static inline TCGv_ptr tcg_temp_local_new_ptr(void) -{ - TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_PTR, true); - return temp_tcgv_ptr(t); -} - -#if defined(CONFIG_DEBUG_TCG) -/* If you call tcg_clear_temp_count() at the start of a section of - * code which is not supposed to leak any TCG temporaries, then - * calling tcg_check_temp_count() at the end of the section will - * return 1 if the section did in fact leak a temporary. - */ -void tcg_clear_temp_count(void); -int tcg_check_temp_count(void); -#else -#define tcg_clear_temp_count() do { } while (0) -#define tcg_check_temp_count() 0 -#endif - -int64_t tcg_cpu_exec_time(void); -void tcg_dump_info(void); -void tcg_dump_op_count(void); - -#define TCG_CT_ALIAS 0x80 -#define TCG_CT_IALIAS 0x40 -#define TCG_CT_NEWREG 0x20 /* output requires a new register */ -#define TCG_CT_REG 0x01 -#define TCG_CT_CONST 0x02 /* any constant of register size */ - -typedef struct TCGArgConstraint { - uint16_t ct; - uint8_t alias_index; - union { - TCGRegSet regs; - } u; -} TCGArgConstraint; - -#define TCG_MAX_OP_ARGS 16 - -/* Bits for TCGOpDef->flags, 8 bits available. */ -enum { - /* Instruction exits the translation block. */ - TCG_OPF_BB_EXIT = 0x01, - /* Instruction defines the end of a basic block. */ - TCG_OPF_BB_END = 0x02, - /* Instruction clobbers call registers and potentially update globals. */ - TCG_OPF_CALL_CLOBBER = 0x04, - /* Instruction has side effects: it cannot be removed if its outputs - are not used, and might trigger exceptions. */ - TCG_OPF_SIDE_EFFECTS = 0x08, - /* Instruction operands are 64-bits (otherwise 32-bits). */ - TCG_OPF_64BIT = 0x10, - /* Instruction is optional and not implemented by the host, or insn - is generic and should not be implemened by the host. */ - TCG_OPF_NOT_PRESENT = 0x20, - /* Instruction operands are vectors. */ - TCG_OPF_VECTOR = 0x40, -}; - -typedef struct TCGOpDef { - const char *name; - uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args; - uint8_t flags; - TCGArgConstraint *args_ct; - int *sorted_args; -#if defined(CONFIG_DEBUG_TCG) - int used; -#endif -} TCGOpDef; - -extern TCGOpDef tcg_op_defs[]; -extern const size_t tcg_op_defs_max; - -typedef struct TCGTargetOpDef { - TCGOpcode op; - const char *args_ct_str[TCG_MAX_OP_ARGS]; -} TCGTargetOpDef; - -#define tcg_abort() \ -do {\ - fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\ - abort();\ -} while (0) - -bool tcg_op_supported(TCGOpcode op); - -void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args); - -TCGOp *tcg_emit_op(TCGOpcode opc); -void tcg_op_remove(TCGContext *s, TCGOp *op); -TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, TCGOpcode opc); -TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc); - -void tcg_optimize(TCGContext *s); - -TCGv_i32 tcg_const_i32(int32_t val); -TCGv_i64 tcg_const_i64(int64_t val); -TCGv_i32 tcg_const_local_i32(int32_t val); -TCGv_i64 tcg_const_local_i64(int64_t val); -TCGv_vec tcg_const_zeros_vec(TCGType); -TCGv_vec tcg_const_ones_vec(TCGType); -TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec); -TCGv_vec tcg_const_ones_vec_matching(TCGv_vec); - -#if UINTPTR_MAX == UINT32_MAX -# define tcg_const_ptr(x) ((TCGv_ptr)tcg_const_i32((intptr_t)(x))) -# define tcg_const_local_ptr(x) ((TCGv_ptr)tcg_const_local_i32((intptr_t)(x))) -#else -# define tcg_const_ptr(x) ((TCGv_ptr)tcg_const_i64((intptr_t)(x))) -# define tcg_const_local_ptr(x) ((TCGv_ptr)tcg_const_local_i64((intptr_t)(x))) -#endif - -TCGLabel *gen_new_label(void); - -/** - * label_arg - * @l: label - * - * Encode a label for storage in the TCG opcode stream. - */ - -static inline TCGArg label_arg(TCGLabel *l) -{ - return (uintptr_t)l; -} - -/** - * arg_label - * @i: value - * - * The opposite of label_arg. Retrieve a label from the - * encoding of the TCG opcode stream. - */ - -static inline TCGLabel *arg_label(TCGArg i) -{ - return (TCGLabel *)(uintptr_t)i; -} - -/** - * tcg_ptr_byte_diff - * @a, @b: addresses to be differenced - * - * There are many places within the TCG backends where we need a byte - * difference between two pointers. While this can be accomplished - * with local casting, it's easy to get wrong -- especially if one is - * concerned with the signedness of the result. - * - * This version relies on GCC's void pointer arithmetic to get the - * correct result. - */ - -static inline ptrdiff_t tcg_ptr_byte_diff(void *a, void *b) -{ - return a - b; -} - -/** - * tcg_pcrel_diff - * @s: the tcg context - * @target: address of the target - * - * Produce a pc-relative difference, from the current code_ptr - * to the destination address. - */ - -static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, void *target) -{ - return tcg_ptr_byte_diff(target, s->code_ptr); -} - -/** - * tcg_current_code_size - * @s: the tcg context - * - * Compute the current code size within the translation block. - * This is used to fill in qemu's data structures for goto_tb. - */ - -static inline size_t tcg_current_code_size(TCGContext *s) -{ - return tcg_ptr_byte_diff(s->code_ptr, s->code_buf); -} - -/* Combine the MemOp and mmu_idx parameters into a single value. */ -typedef uint32_t TCGMemOpIdx; - -/** - * make_memop_idx - * @op: memory operation - * @idx: mmu index - * - * Encode these values into a single parameter. - */ -static inline TCGMemOpIdx make_memop_idx(MemOp op, unsigned idx) -{ - tcg_debug_assert(idx <= 15); - return (op << 4) | idx; -} - -/** - * get_memop - * @oi: combined op/idx parameter - * - * Extract the memory operation from the combined value. - */ -static inline MemOp get_memop(TCGMemOpIdx oi) -{ - return oi >> 4; -} - -/** - * get_mmuidx - * @oi: combined op/idx parameter - * - * Extract the mmu index from the combined value. - */ -static inline unsigned get_mmuidx(TCGMemOpIdx oi) -{ - return oi & 15; -} - -/** - * tcg_qemu_tb_exec: - * @env: pointer to CPUArchState for the CPU - * @tb_ptr: address of generated code for the TB to execute - * - * Start executing code from a given translation block. - * Where translation blocks have been linked, execution - * may proceed from the given TB into successive ones. - * Control eventually returns only when some action is needed - * from the top-level loop: either control must pass to a TB - * which has not yet been directly linked, or an asynchronous - * event such as an interrupt needs handling. - * - * Return: The return value is the value passed to the corresponding - * tcg_gen_exit_tb() at translation time of the last TB attempted to execute. - * The value is either zero or a 4-byte aligned pointer to that TB combined - * with additional information in its two least significant bits. The - * additional information is encoded as follows: - * 0, 1: the link between this TB and the next is via the specified - * TB index (0 or 1). That is, we left the TB via (the equivalent - * of) "goto_tb ". The main loop uses this to determine - * how to link the TB just executed to the next. - * 2: we are using instruction counting code generation, and we - * did not start executing this TB because the instruction counter - * would hit zero midway through it. In this case the pointer - * returned is the TB we were about to execute, and the caller must - * arrange to execute the remaining count of instructions. - * 3: we stopped because the CPU's exit_request flag was set - * (usually meaning that there is an interrupt that needs to be - * handled). The pointer returned is the TB we were about to execute - * when we noticed the pending exit request. - * - * If the bottom two bits indicate an exit-via-index then the CPU - * state is correctly synchronised and ready for execution of the next - * TB (and in particular the guest PC is the address to execute next). - * Otherwise, we gave up on execution of this TB before it started, and - * the caller must fix up the CPU state by calling the CPU's - * synchronize_from_tb() method with the TB pointer we return (falling - * back to calling the CPU's set_pc method with tb->pb if no - * synchronize_from_tb() method exists). - * - * Note that TCG targets may use a different definition of tcg_qemu_tb_exec - * to this default (which just calls the prologue.code emitted by - * tcg_target_qemu_prologue()). - */ -#define TB_EXIT_MASK 3 -#define TB_EXIT_IDX0 0 -#define TB_EXIT_IDX1 1 -#define TB_EXIT_IDXMAX 1 -#define TB_EXIT_REQUESTED 3 - -#ifdef HAVE_TCG_QEMU_TB_EXEC -uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr); -#else -# define tcg_qemu_tb_exec(env, tb_ptr) \ - ((uintptr_t (*)(void *, void *))tcg_ctx->code_gen_prologue)(env, tb_ptr) -#endif - -void tcg_register_jit(void *buf, size_t buf_size); - -#if TCG_TARGET_MAYBE_vec -/* Return zero if the tuple (opc, type, vece) is unsupportable; - return > 0 if it is directly supportable; - return < 0 if we must call tcg_expand_vec_op. */ -int tcg_can_emit_vec_op(TCGOpcode, TCGType, unsigned); -#else -static inline int tcg_can_emit_vec_op(TCGOpcode o, TCGType t, unsigned ve) -{ - return 0; -} -#endif - -/* Expand the tuple (opc, type, vece) on the given arguments. */ -void tcg_expand_vec_op(TCGOpcode, TCGType, unsigned, TCGArg, ...); - -/* Replicate a constant C accoring to the log2 of the element size. */ -uint64_t dup_const(unsigned vece, uint64_t c); - -#define dup_const(VECE, C) \ - (__builtin_constant_p(VECE) \ - ? ( (VECE) == MO_8 ? 0x0101010101010101ull * (uint8_t)(C) \ - : (VECE) == MO_16 ? 0x0001000100010001ull * (uint16_t)(C) \ - : (VECE) == MO_32 ? 0x0000000100000001ull * (uint32_t)(C) \ - : dup_const(VECE, C)) \ - : dup_const(VECE, C)) - - -/* - * Memory helpers that will be used by TCG generated code. - */ -#ifdef CONFIG_SOFTMMU -/* Value zero-extended to tcg register size. */ -tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); - -/* Value sign-extended to tcg register size. */ -tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); - -void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, - TCGMemOpIdx oi, uintptr_t retaddr); - -/* Temporary aliases until backends are converted. */ -#ifdef TARGET_WORDS_BIGENDIAN -# define helper_ret_ldsw_mmu helper_be_ldsw_mmu -# define helper_ret_lduw_mmu helper_be_lduw_mmu -# define helper_ret_ldsl_mmu helper_be_ldsl_mmu -# define helper_ret_ldul_mmu helper_be_ldul_mmu -# define helper_ret_ldl_mmu helper_be_ldul_mmu -# define helper_ret_ldq_mmu helper_be_ldq_mmu -# define helper_ret_stw_mmu helper_be_stw_mmu -# define helper_ret_stl_mmu helper_be_stl_mmu -# define helper_ret_stq_mmu helper_be_stq_mmu -#else -# define helper_ret_ldsw_mmu helper_le_ldsw_mmu -# define helper_ret_lduw_mmu helper_le_lduw_mmu -# define helper_ret_ldsl_mmu helper_le_ldsl_mmu -# define helper_ret_ldul_mmu helper_le_ldul_mmu -# define helper_ret_ldl_mmu helper_le_ldul_mmu -# define helper_ret_ldq_mmu helper_le_ldq_mmu -# define helper_ret_stw_mmu helper_le_stw_mmu -# define helper_ret_stl_mmu helper_le_stl_mmu -# define helper_ret_stq_mmu helper_le_stq_mmu -#endif - -uint32_t helper_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr, - uint32_t cmpv, uint32_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint32_t helper_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr, - uint32_t cmpv, uint32_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint32_t helper_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr, - uint32_t cmpv, uint32_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint64_t helper_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr, - uint64_t cmpv, uint64_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint32_t helper_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr, - uint32_t cmpv, uint32_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint32_t helper_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr, - uint32_t cmpv, uint32_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); -uint64_t helper_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr, - uint64_t cmpv, uint64_t newv, - TCGMemOpIdx oi, uintptr_t retaddr); - -#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \ -TYPE helper_atomic_ ## NAME ## SUFFIX ## _mmu \ - (CPUArchState *env, target_ulong addr, TYPE val, \ - TCGMemOpIdx oi, uintptr_t retaddr); - -#ifdef CONFIG_ATOMIC64 -#define GEN_ATOMIC_HELPER_ALL(NAME) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, b) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) \ - GEN_ATOMIC_HELPER(NAME, uint64_t, q_le) \ - GEN_ATOMIC_HELPER(NAME, uint64_t, q_be) -#else -#define GEN_ATOMIC_HELPER_ALL(NAME) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, b) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \ - GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) -#endif - -GEN_ATOMIC_HELPER_ALL(fetch_add) -GEN_ATOMIC_HELPER_ALL(fetch_sub) -GEN_ATOMIC_HELPER_ALL(fetch_and) -GEN_ATOMIC_HELPER_ALL(fetch_or) -GEN_ATOMIC_HELPER_ALL(fetch_xor) -GEN_ATOMIC_HELPER_ALL(fetch_smin) -GEN_ATOMIC_HELPER_ALL(fetch_umin) -GEN_ATOMIC_HELPER_ALL(fetch_smax) -GEN_ATOMIC_HELPER_ALL(fetch_umax) - -GEN_ATOMIC_HELPER_ALL(add_fetch) -GEN_ATOMIC_HELPER_ALL(sub_fetch) -GEN_ATOMIC_HELPER_ALL(and_fetch) -GEN_ATOMIC_HELPER_ALL(or_fetch) -GEN_ATOMIC_HELPER_ALL(xor_fetch) -GEN_ATOMIC_HELPER_ALL(smin_fetch) -GEN_ATOMIC_HELPER_ALL(umin_fetch) -GEN_ATOMIC_HELPER_ALL(smax_fetch) -GEN_ATOMIC_HELPER_ALL(umax_fetch) - -GEN_ATOMIC_HELPER_ALL(xchg) - -#undef GEN_ATOMIC_HELPER_ALL -#undef GEN_ATOMIC_HELPER -#endif /* CONFIG_SOFTMMU */ - -/* - * These aren't really a "proper" helpers because TCG cannot manage Int128. - * However, use the same format as the others, for use by the backends. - * - * The cmpxchg functions are only defined if HAVE_CMPXCHG128; - * the ld/st functions are only defined if HAVE_ATOMIC128, - * as defined by . - */ -Int128 helper_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr, - Int128 cmpv, Int128 newv, - TCGMemOpIdx oi, uintptr_t retaddr); -Int128 helper_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr, - Int128 cmpv, Int128 newv, - TCGMemOpIdx oi, uintptr_t retaddr); - -Int128 helper_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -Int128 helper_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val, - TCGMemOpIdx oi, uintptr_t retaddr); -void helper_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val, - TCGMemOpIdx oi, uintptr_t retaddr); - -#ifdef CONFIG_DEBUG_TCG -void tcg_assert_listed_vecop(TCGOpcode); -#else -static inline void tcg_assert_listed_vecop(TCGOpcode op) { } -#endif - -static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n) -{ -#ifdef CONFIG_DEBUG_TCG - const TCGOpcode *o = tcg_ctx->vecop_list; - tcg_ctx->vecop_list = n; - return o; -#else - return NULL; -#endif -} - -bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned); - -#endif /* TCG_H */ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TCG_H +#define TCG_H + +#include "cpu.h" +#include "exec/memop.h" +#include "exec/tb-context.h" +#include "qemu/bitops.h" +#include "qemu/plugin.h" +#include "qemu/queue.h" +#include "tcg/tcg-mo.h" +#include "tcg-target.h" +#include "qemu/int128.h" + +/* XXX: make safe guess about sizes */ +#define MAX_OP_PER_INSTR 266 + +#if HOST_LONG_BITS == 32 +#define MAX_OPC_PARAM_PER_ARG 2 +#else +#define MAX_OPC_PARAM_PER_ARG 1 +#endif +#define MAX_OPC_PARAM_IARGS 6 +#define MAX_OPC_PARAM_OARGS 1 +#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS) + +/* A Call op needs up to 4 + 2N parameters on 32-bit archs, + * and up to 4 + N parameters on 64-bit archs + * (N = number of input arguments + output arguments). */ +#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS)) + +#define CPU_TEMP_BUF_NLONGS 128 + +/* Default target word size to pointer size. */ +#ifndef TCG_TARGET_REG_BITS +# if UINTPTR_MAX == UINT32_MAX +# define TCG_TARGET_REG_BITS 32 +# elif UINTPTR_MAX == UINT64_MAX +# define TCG_TARGET_REG_BITS 64 +# else +# error Unknown pointer size for tcg target +# endif +#endif + +#if TCG_TARGET_REG_BITS == 32 +typedef int32_t tcg_target_long; +typedef uint32_t tcg_target_ulong; +#define TCG_PRIlx PRIx32 +#define TCG_PRIld PRId32 +#elif TCG_TARGET_REG_BITS == 64 +typedef int64_t tcg_target_long; +typedef uint64_t tcg_target_ulong; +#define TCG_PRIlx PRIx64 +#define TCG_PRIld PRId64 +#else +#error unsupported +#endif + +/* Oversized TCG guests make things like MTTCG hard + * as we can't use atomics for cputlb updates. + */ +#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS +#define TCG_OVERSIZED_GUEST 1 +#else +#define TCG_OVERSIZED_GUEST 0 +#endif + +#if TCG_TARGET_NB_REGS <= 32 +typedef uint32_t TCGRegSet; +#elif TCG_TARGET_NB_REGS <= 64 +typedef uint64_t TCGRegSet; +#else +#error unsupported +#endif + +#if TCG_TARGET_REG_BITS == 32 +/* Turn some undef macros into false macros. */ +#define TCG_TARGET_HAS_extrl_i64_i32 0 +#define TCG_TARGET_HAS_extrh_i64_i32 0 +#define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_ext8s_i64 0 +#define TCG_TARGET_HAS_ext16s_i64 0 +#define TCG_TARGET_HAS_ext32s_i64 0 +#define TCG_TARGET_HAS_ext8u_i64 0 +#define TCG_TARGET_HAS_ext16u_i64 0 +#define TCG_TARGET_HAS_ext32u_i64 0 +#define TCG_TARGET_HAS_bswap16_i64 0 +#define TCG_TARGET_HAS_bswap32_i64 0 +#define TCG_TARGET_HAS_bswap64_i64 0 +#define TCG_TARGET_HAS_neg_i64 0 +#define TCG_TARGET_HAS_not_i64 0 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i64 0 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 +/* Turn some undef macros into true macros. */ +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#endif + +#ifndef TCG_TARGET_deposit_i32_valid +#define TCG_TARGET_deposit_i32_valid(ofs, len) 1 +#endif +#ifndef TCG_TARGET_deposit_i64_valid +#define TCG_TARGET_deposit_i64_valid(ofs, len) 1 +#endif +#ifndef TCG_TARGET_extract_i32_valid +#define TCG_TARGET_extract_i32_valid(ofs, len) 1 +#endif +#ifndef TCG_TARGET_extract_i64_valid +#define TCG_TARGET_extract_i64_valid(ofs, len) 1 +#endif + +/* Only one of DIV or DIV2 should be defined. */ +#if defined(TCG_TARGET_HAS_div_i32) +#define TCG_TARGET_HAS_div2_i32 0 +#elif defined(TCG_TARGET_HAS_div2_i32) +#define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 +#endif +#if defined(TCG_TARGET_HAS_div_i64) +#define TCG_TARGET_HAS_div2_i64 0 +#elif defined(TCG_TARGET_HAS_div2_i64) +#define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 +#endif + +/* For 32-bit targets, some sort of unsigned widening multiply is required. */ +#if TCG_TARGET_REG_BITS == 32 \ + && !(defined(TCG_TARGET_HAS_mulu2_i32) \ + || defined(TCG_TARGET_HAS_muluh_i32)) +# error "Missing unsigned widening multiply" +#endif + +#if !defined(TCG_TARGET_HAS_v64) \ + && !defined(TCG_TARGET_HAS_v128) \ + && !defined(TCG_TARGET_HAS_v256) +#define TCG_TARGET_MAYBE_vec 0 +#define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_neg_vec 0 +#define TCG_TARGET_HAS_not_vec 0 +#define TCG_TARGET_HAS_andc_vec 0 +#define TCG_TARGET_HAS_orc_vec 0 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 +#define TCG_TARGET_HAS_shi_vec 0 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 0 +#define TCG_TARGET_HAS_mul_vec 0 +#define TCG_TARGET_HAS_sat_vec 0 +#define TCG_TARGET_HAS_minmax_vec 0 +#define TCG_TARGET_HAS_bitsel_vec 0 +#define TCG_TARGET_HAS_cmpsel_vec 0 +#else +#define TCG_TARGET_MAYBE_vec 1 +#endif +#ifndef TCG_TARGET_HAS_v64 +#define TCG_TARGET_HAS_v64 0 +#endif +#ifndef TCG_TARGET_HAS_v128 +#define TCG_TARGET_HAS_v128 0 +#endif +#ifndef TCG_TARGET_HAS_v256 +#define TCG_TARGET_HAS_v256 0 +#endif + +#ifndef TARGET_INSN_START_EXTRA_WORDS +# define TARGET_INSN_START_WORDS 1 +#else +# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS) +#endif + +typedef enum TCGOpcode { +#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name, +#include "tcg/tcg-opc.h" +#undef DEF + NB_OPS, +} TCGOpcode; + +#define tcg_regset_set_reg(d, r) ((d) |= (TCGRegSet)1 << (r)) +#define tcg_regset_reset_reg(d, r) ((d) &= ~((TCGRegSet)1 << (r))) +#define tcg_regset_test_reg(d, r) (((d) >> (r)) & 1) + +#ifndef TCG_TARGET_INSN_UNIT_SIZE +# error "Missing TCG_TARGET_INSN_UNIT_SIZE" +#elif TCG_TARGET_INSN_UNIT_SIZE == 1 +typedef uint8_t tcg_insn_unit; +#elif TCG_TARGET_INSN_UNIT_SIZE == 2 +typedef uint16_t tcg_insn_unit; +#elif TCG_TARGET_INSN_UNIT_SIZE == 4 +typedef uint32_t tcg_insn_unit; +#elif TCG_TARGET_INSN_UNIT_SIZE == 8 +typedef uint64_t tcg_insn_unit; +#else +/* The port better have done this. */ +#endif + + +#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS +# define tcg_debug_assert(X) do { assert(X); } while (0) +#else +# define tcg_debug_assert(X) \ + do { if (!(X)) { __builtin_unreachable(); } } while (0) +#endif + +typedef struct TCGRelocation TCGRelocation; +struct TCGRelocation { + QSIMPLEQ_ENTRY(TCGRelocation) next; + tcg_insn_unit *ptr; + intptr_t addend; + int type; +}; + +typedef struct TCGLabel TCGLabel; +struct TCGLabel { + unsigned present : 1; + unsigned has_value : 1; + unsigned id : 14; + unsigned refs : 16; + union { + uintptr_t value; + tcg_insn_unit *value_ptr; + } u; + QSIMPLEQ_HEAD(, TCGRelocation) relocs; + QSIMPLEQ_ENTRY(TCGLabel) next; +}; + +typedef struct TCGPool { + struct TCGPool *next; + int size; + uint8_t data[] __attribute__ ((aligned)); +} TCGPool; + +#define TCG_POOL_CHUNK_SIZE 32768 + +#define TCG_MAX_TEMPS 512 +#define TCG_MAX_INSNS 512 + +/* when the size of the arguments of a called function is smaller than + this value, they are statically allocated in the TB stack frame */ +#define TCG_STATIC_CALL_ARGS_SIZE 128 + +typedef enum TCGType { + TCG_TYPE_I32, + TCG_TYPE_I64, + + TCG_TYPE_V64, + TCG_TYPE_V128, + TCG_TYPE_V256, + + TCG_TYPE_COUNT, /* number of different types */ + + /* An alias for the size of the host register. */ +#if TCG_TARGET_REG_BITS == 32 + TCG_TYPE_REG = TCG_TYPE_I32, +#else + TCG_TYPE_REG = TCG_TYPE_I64, +#endif + + /* An alias for the size of the native pointer. */ +#if UINTPTR_MAX == UINT32_MAX + TCG_TYPE_PTR = TCG_TYPE_I32, +#else + TCG_TYPE_PTR = TCG_TYPE_I64, +#endif + + /* An alias for the size of the target "long", aka register. */ +#if TARGET_LONG_BITS == 64 + TCG_TYPE_TL = TCG_TYPE_I64, +#else + TCG_TYPE_TL = TCG_TYPE_I32, +#endif +} TCGType; + +/** + * get_alignment_bits + * @memop: MemOp value + * + * Extract the alignment size from the memop. + */ +static inline unsigned get_alignment_bits(MemOp memop) +{ + unsigned a = memop & MO_AMASK; + + if (a == MO_UNALN) { + /* No alignment required. */ + a = 0; + } else if (a == MO_ALIGN) { + /* A natural alignment requirement. */ + a = memop & MO_SIZE; + } else { + /* A specific alignment requirement. */ + a = a >> MO_ASHIFT; + } +#if defined(CONFIG_SOFTMMU) + /* The requested alignment cannot overlap the TLB flags. */ + tcg_debug_assert((TLB_FLAGS_MASK & ((1 << a) - 1)) == 0); +#endif + return a; +} + +typedef tcg_target_ulong TCGArg; + +/* Define type and accessor macros for TCG variables. + + TCG variables are the inputs and outputs of TCG ops, as described + in tcg/README. Target CPU front-end code uses these types to deal + with TCG variables as it emits TCG code via the tcg_gen_* functions. + They come in several flavours: + * TCGv_i32 : 32 bit integer type + * TCGv_i64 : 64 bit integer type + * TCGv_ptr : a host pointer type + * TCGv_vec : a host vector type; the exact size is not exposed + to the CPU front-end code. + * TCGv : an integer type the same size as target_ulong + (an alias for either TCGv_i32 or TCGv_i64) + The compiler's type checking will complain if you mix them + up and pass the wrong sized TCGv to a function. + + Users of tcg_gen_* don't need to know about any of the internal + details of these, and should treat them as opaque types. + You won't be able to look inside them in a debugger either. + + Internal implementation details follow: + + Note that there is no definition of the structs TCGv_i32_d etc anywhere. + This is deliberate, because the values we store in variables of type + TCGv_i32 are not really pointers-to-structures. They're just small + integers, but keeping them in pointer types like this means that the + compiler will complain if you accidentally pass a TCGv_i32 to a + function which takes a TCGv_i64, and so on. Only the internals of + TCG need to care about the actual contents of the types. */ + +typedef struct TCGv_i32_d *TCGv_i32; +typedef struct TCGv_i64_d *TCGv_i64; +typedef struct TCGv_ptr_d *TCGv_ptr; +typedef struct TCGv_vec_d *TCGv_vec; +typedef TCGv_ptr TCGv_env; +#if TARGET_LONG_BITS == 32 +#define TCGv TCGv_i32 +#elif TARGET_LONG_BITS == 64 +#define TCGv TCGv_i64 +#else +#error Unhandled TARGET_LONG_BITS value +#endif + +/* call flags */ +/* Helper does not read globals (either directly or through an exception). It + implies TCG_CALL_NO_WRITE_GLOBALS. */ +#define TCG_CALL_NO_READ_GLOBALS 0x0001 +/* Helper does not write globals */ +#define TCG_CALL_NO_WRITE_GLOBALS 0x0002 +/* Helper can be safely suppressed if the return value is not used. */ +#define TCG_CALL_NO_SIDE_EFFECTS 0x0004 +/* Helper is QEMU_NORETURN. */ +#define TCG_CALL_NO_RETURN 0x0008 + +/* convenience version of most used call flags */ +#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS +#define TCG_CALL_NO_WG TCG_CALL_NO_WRITE_GLOBALS +#define TCG_CALL_NO_SE TCG_CALL_NO_SIDE_EFFECTS +#define TCG_CALL_NO_RWG_SE (TCG_CALL_NO_RWG | TCG_CALL_NO_SE) +#define TCG_CALL_NO_WG_SE (TCG_CALL_NO_WG | TCG_CALL_NO_SE) + +/* Used to align parameters. See the comment before tcgv_i32_temp. */ +#define TCG_CALL_DUMMY_ARG ((TCGArg)0) + +/* Conditions. Note that these are laid out for easy manipulation by + the functions below: + bit 0 is used for inverting; + bit 1 is signed, + bit 2 is unsigned, + bit 3 is used with bit 0 for swapping signed/unsigned. */ +typedef enum { + /* non-signed */ + TCG_COND_NEVER = 0 | 0 | 0 | 0, + TCG_COND_ALWAYS = 0 | 0 | 0 | 1, + TCG_COND_EQ = 8 | 0 | 0 | 0, + TCG_COND_NE = 8 | 0 | 0 | 1, + /* signed */ + TCG_COND_LT = 0 | 0 | 2 | 0, + TCG_COND_GE = 0 | 0 | 2 | 1, + TCG_COND_LE = 8 | 0 | 2 | 0, + TCG_COND_GT = 8 | 0 | 2 | 1, + /* unsigned */ + TCG_COND_LTU = 0 | 4 | 0 | 0, + TCG_COND_GEU = 0 | 4 | 0 | 1, + TCG_COND_LEU = 8 | 4 | 0 | 0, + TCG_COND_GTU = 8 | 4 | 0 | 1, +} TCGCond; + +/* Invert the sense of the comparison. */ +static inline TCGCond tcg_invert_cond(TCGCond c) +{ + return (TCGCond)(c ^ 1); +} + +/* Swap the operands in a comparison. */ +static inline TCGCond tcg_swap_cond(TCGCond c) +{ + return c & 6 ? (TCGCond)(c ^ 9) : c; +} + +/* Create an "unsigned" version of a "signed" comparison. */ +static inline TCGCond tcg_unsigned_cond(TCGCond c) +{ + return c & 2 ? (TCGCond)(c ^ 6) : c; +} + +/* Create a "signed" version of an "unsigned" comparison. */ +static inline TCGCond tcg_signed_cond(TCGCond c) +{ + return c & 4 ? (TCGCond)(c ^ 6) : c; +} + +/* Must a comparison be considered unsigned? */ +static inline bool is_unsigned_cond(TCGCond c) +{ + return (c & 4) != 0; +} + +/* Create a "high" version of a double-word comparison. + This removes equality from a LTE or GTE comparison. */ +static inline TCGCond tcg_high_cond(TCGCond c) +{ + switch (c) { + case TCG_COND_GE: + case TCG_COND_LE: + case TCG_COND_GEU: + case TCG_COND_LEU: + return (TCGCond)(c ^ 8); + default: + return c; + } +} + +typedef enum TCGTempVal { + TEMP_VAL_DEAD, + TEMP_VAL_REG, + TEMP_VAL_MEM, + TEMP_VAL_CONST, +} TCGTempVal; + +typedef struct TCGTemp { + TCGReg reg:8; + TCGTempVal val_type:8; + TCGType base_type:8; + TCGType type:8; + unsigned int fixed_reg:1; + unsigned int indirect_reg:1; + unsigned int indirect_base:1; + unsigned int mem_coherent:1; + unsigned int mem_allocated:1; + /* If true, the temp is saved across both basic blocks and + translation blocks. */ + unsigned int temp_global:1; + /* If true, the temp is saved across basic blocks but dead + at the end of translation blocks. If false, the temp is + dead at the end of basic blocks. */ + unsigned int temp_local:1; + unsigned int temp_allocated:1; + + tcg_target_long val; + struct TCGTemp *mem_base; + intptr_t mem_offset; + const char *name; + + /* Pass-specific information that can be stored for a temporary. + One word worth of integer data, and one pointer to data + allocated separately. */ + uintptr_t state; + void *state_ptr; +} TCGTemp; + +typedef struct TCGContext TCGContext; + +typedef struct TCGTempSet { + unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)]; +} TCGTempSet; + +/* While we limit helpers to 6 arguments, for 32-bit hosts, with padding, + this imples a max of 6*2 (64-bit in) + 2 (64-bit out) = 14 operands. + There are never more than 2 outputs, which means that we can store all + dead + sync data within 16 bits. */ +#define DEAD_ARG 4 +#define SYNC_ARG 1 +typedef uint16_t TCGLifeData; + +/* The layout here is designed to avoid a bitfield crossing of + a 32-bit boundary, which would cause GCC to add extra padding. */ +typedef struct TCGOp { + TCGOpcode opc : 8; /* 8 */ + + /* Parameters for this opcode. See below. */ + unsigned param1 : 4; /* 12 */ + unsigned param2 : 4; /* 16 */ + + /* Lifetime data of the operands. */ + unsigned life : 16; /* 32 */ + + /* Next and previous opcodes. */ + QTAILQ_ENTRY(TCGOp) link; +#ifdef CONFIG_PLUGIN + QSIMPLEQ_ENTRY(TCGOp) plugin_link; +#endif + + /* Arguments for the opcode. */ + TCGArg args[MAX_OPC_PARAM]; + + /* Register preferences for the output(s). */ + TCGRegSet output_pref[2]; +} TCGOp; + +#define TCGOP_CALLI(X) (X)->param1 +#define TCGOP_CALLO(X) (X)->param2 + +#define TCGOP_VECL(X) (X)->param1 +#define TCGOP_VECE(X) (X)->param2 + +/* Make sure operands fit in the bitfields above. */ +QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8)); + +typedef struct TCGProfile { + int64_t cpu_exec_time; + int64_t tb_count1; + int64_t tb_count; + int64_t op_count; /* total insn count */ + int op_count_max; /* max insn per TB */ + int temp_count_max; + int64_t temp_count; + int64_t del_op_count; + int64_t code_in_len; + int64_t code_out_len; + int64_t search_out_len; + int64_t interm_time; + int64_t code_time; + int64_t la_time; + int64_t opt_time; + int64_t restore_count; + int64_t restore_time; + int64_t table_op_count[NB_OPS]; +} TCGProfile; + +struct TCGContext { + uint8_t *pool_cur, *pool_end; + TCGPool *pool_first, *pool_current, *pool_first_large; + int nb_labels; + int nb_globals; + int nb_temps; + int nb_indirects; + int nb_ops; + + /* goto_tb support */ + tcg_insn_unit *code_buf; + uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */ + uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */ + uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */ + + TCGRegSet reserved_regs; + uint32_t tb_cflags; /* cflags of the current TB */ + intptr_t current_frame_offset; + intptr_t frame_start; + intptr_t frame_end; + TCGTemp *frame_temp; + + tcg_insn_unit *code_ptr; + +#ifdef CONFIG_PROFILER + TCGProfile prof; +#endif + +#ifdef CONFIG_DEBUG_TCG + int temps_in_use; + int goto_tb_issue_mask; + const TCGOpcode *vecop_list; +#endif + + /* Code generation. Note that we specifically do not use tcg_insn_unit + here, because there's too much arithmetic throughout that relies + on addition and subtraction working on bytes. Rely on the GCC + extension that allows arithmetic on void*. */ + void *code_gen_prologue; + void *code_gen_epilogue; + void *code_gen_buffer; + size_t code_gen_buffer_size; + void *code_gen_ptr; + void *data_gen_ptr; + + /* Threshold to flush the translated code buffer. */ + void *code_gen_highwater; + + size_t tb_phys_invalidate_count; + + /* Track which vCPU triggers events */ + CPUState *cpu; /* *_trans */ + + /* These structures are private to tcg-target.c.inc. */ +#ifdef TCG_TARGET_NEED_LDST_LABELS + QSIMPLEQ_HEAD(, TCGLabelQemuLdst) ldst_labels; +#endif +#ifdef TCG_TARGET_NEED_POOL_LABELS + struct TCGLabelPoolData *pool_labels; +#endif + + TCGLabel *exitreq_label; + +#ifdef CONFIG_PLUGIN + /* + * We keep one plugin_tb struct per TCGContext. Note that on every TB + * translation we clear but do not free its contents; this way we + * avoid a lot of malloc/free churn, since after a few TB's it's + * unlikely that we'll need to allocate either more instructions or more + * space for instructions (for variable-instruction-length ISAs). + */ + struct qemu_plugin_tb *plugin_tb; + + /* descriptor of the instruction being translated */ + struct qemu_plugin_insn *plugin_insn; + + /* list to quickly access the injected ops */ + QSIMPLEQ_HEAD(, TCGOp) plugin_ops; +#endif + + TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; + TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ + + QTAILQ_HEAD(, TCGOp) ops, free_ops; + QSIMPLEQ_HEAD(, TCGLabel) labels; + + /* Tells which temporary holds a given register. + It does not take into account fixed registers */ + TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS]; + + uint16_t gen_insn_end_off[TCG_MAX_INSNS]; + target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; +}; + +extern TCGContext tcg_init_ctx; +extern __thread TCGContext *tcg_ctx; +extern TCGv_env cpu_env; + +static inline size_t temp_idx(TCGTemp *ts) +{ + ptrdiff_t n = ts - tcg_ctx->temps; + tcg_debug_assert(n >= 0 && n < tcg_ctx->nb_temps); + return n; +} + +static inline TCGArg temp_arg(TCGTemp *ts) +{ + return (uintptr_t)ts; +} + +static inline TCGTemp *arg_temp(TCGArg a) +{ + return (TCGTemp *)(uintptr_t)a; +} + +/* Using the offset of a temporary, relative to TCGContext, rather than + its index means that we don't use 0. That leaves offset 0 free for + a NULL representation without having to leave index 0 unused. */ +static inline TCGTemp *tcgv_i32_temp(TCGv_i32 v) +{ + uintptr_t o = (uintptr_t)v; + TCGTemp *t = (void *)tcg_ctx + o; + tcg_debug_assert(offsetof(TCGContext, temps[temp_idx(t)]) == o); + return t; +} + +static inline TCGTemp *tcgv_i64_temp(TCGv_i64 v) +{ + return tcgv_i32_temp((TCGv_i32)v); +} + +static inline TCGTemp *tcgv_ptr_temp(TCGv_ptr v) +{ + return tcgv_i32_temp((TCGv_i32)v); +} + +static inline TCGTemp *tcgv_vec_temp(TCGv_vec v) +{ + return tcgv_i32_temp((TCGv_i32)v); +} + +static inline TCGArg tcgv_i32_arg(TCGv_i32 v) +{ + return temp_arg(tcgv_i32_temp(v)); +} + +static inline TCGArg tcgv_i64_arg(TCGv_i64 v) +{ + return temp_arg(tcgv_i64_temp(v)); +} + +static inline TCGArg tcgv_ptr_arg(TCGv_ptr v) +{ + return temp_arg(tcgv_ptr_temp(v)); +} + +static inline TCGArg tcgv_vec_arg(TCGv_vec v) +{ + return temp_arg(tcgv_vec_temp(v)); +} + +static inline TCGv_i32 temp_tcgv_i32(TCGTemp *t) +{ + (void)temp_idx(t); /* trigger embedded assert */ + return (TCGv_i32)((void *)t - (void *)tcg_ctx); +} + +static inline TCGv_i64 temp_tcgv_i64(TCGTemp *t) +{ + return (TCGv_i64)temp_tcgv_i32(t); +} + +static inline TCGv_ptr temp_tcgv_ptr(TCGTemp *t) +{ + return (TCGv_ptr)temp_tcgv_i32(t); +} + +static inline TCGv_vec temp_tcgv_vec(TCGTemp *t) +{ + return (TCGv_vec)temp_tcgv_i32(t); +} + +#if TCG_TARGET_REG_BITS == 32 +static inline TCGv_i32 TCGV_LOW(TCGv_i64 t) +{ + return temp_tcgv_i32(tcgv_i64_temp(t)); +} + +static inline TCGv_i32 TCGV_HIGH(TCGv_i64 t) +{ + return temp_tcgv_i32(tcgv_i64_temp(t) + 1); +} +#endif + +static inline TCGArg tcg_get_insn_param(TCGOp *op, int arg) +{ + return op->args[arg]; +} + +static inline void tcg_set_insn_param(TCGOp *op, int arg, TCGArg v) +{ + op->args[arg] = v; +} + +static inline target_ulong tcg_get_insn_start_param(TCGOp *op, int arg) +{ +#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS + return tcg_get_insn_param(op, arg); +#else + return tcg_get_insn_param(op, arg * 2) | + ((uint64_t)tcg_get_insn_param(op, arg * 2 + 1) << 32); +#endif +} + +static inline void tcg_set_insn_start_param(TCGOp *op, int arg, target_ulong v) +{ +#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS + tcg_set_insn_param(op, arg, v); +#else + tcg_set_insn_param(op, arg * 2, v); + tcg_set_insn_param(op, arg * 2 + 1, v >> 32); +#endif +} + +/* The last op that was emitted. */ +static inline TCGOp *tcg_last_op(void) +{ + return QTAILQ_LAST(&tcg_ctx->ops); +} + +/* Test for whether to terminate the TB for using too many opcodes. */ +static inline bool tcg_op_buf_full(void) +{ + /* This is not a hard limit, it merely stops translation when + * we have produced "enough" opcodes. We want to limit TB size + * such that a RISC host can reasonably use a 16-bit signed + * branch within the TB. We also need to be mindful of the + * 16-bit unsigned offsets, TranslationBlock.jmp_reset_offset[] + * and TCGContext.gen_insn_end_off[]. + */ + return tcg_ctx->nb_ops >= 4000; +} + +/* pool based memory allocation */ + +/* user-mode: mmap_lock must be held for tcg_malloc_internal. */ +void *tcg_malloc_internal(TCGContext *s, int size); +void tcg_pool_reset(TCGContext *s); +TranslationBlock *tcg_tb_alloc(TCGContext *s); + +void tcg_region_init(void); +void tb_destroy(TranslationBlock *tb); +void tcg_region_reset_all(void); + +size_t tcg_code_size(void); +size_t tcg_code_capacity(void); + +void tcg_tb_insert(TranslationBlock *tb); +void tcg_tb_remove(TranslationBlock *tb); +size_t tcg_tb_phys_invalidate_count(void); +TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); +void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); +size_t tcg_nb_tbs(void); + +/* user-mode: Called with mmap_lock held. */ +static inline void *tcg_malloc(int size) +{ + TCGContext *s = tcg_ctx; + uint8_t *ptr, *ptr_end; + + /* ??? This is a weak placeholder for minimum malloc alignment. */ + size = QEMU_ALIGN_UP(size, 8); + + ptr = s->pool_cur; + ptr_end = ptr + size; + if (unlikely(ptr_end > s->pool_end)) { + return tcg_malloc_internal(tcg_ctx, size); + } else { + s->pool_cur = ptr_end; + return ptr; + } +} + +void tcg_context_init(TCGContext *s); +void tcg_register_thread(void); +void tcg_prologue_init(TCGContext *s); +void tcg_func_start(TCGContext *s); + +int tcg_gen_code(TCGContext *s, TranslationBlock *tb); + +void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size); + +TCGTemp *tcg_global_mem_new_internal(TCGType, TCGv_ptr, + intptr_t, const char *); +TCGTemp *tcg_temp_new_internal(TCGType, bool); +void tcg_temp_free_internal(TCGTemp *); +TCGv_vec tcg_temp_new_vec(TCGType type); +TCGv_vec tcg_temp_new_vec_matching(TCGv_vec match); + +static inline void tcg_temp_free_i32(TCGv_i32 arg) +{ + tcg_temp_free_internal(tcgv_i32_temp(arg)); +} + +static inline void tcg_temp_free_i64(TCGv_i64 arg) +{ + tcg_temp_free_internal(tcgv_i64_temp(arg)); +} + +static inline void tcg_temp_free_ptr(TCGv_ptr arg) +{ + tcg_temp_free_internal(tcgv_ptr_temp(arg)); +} + +static inline void tcg_temp_free_vec(TCGv_vec arg) +{ + tcg_temp_free_internal(tcgv_vec_temp(arg)); +} + +static inline TCGv_i32 tcg_global_mem_new_i32(TCGv_ptr reg, intptr_t offset, + const char *name) +{ + TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); + return temp_tcgv_i32(t); +} + +static inline TCGv_i32 tcg_temp_new_i32(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, false); + return temp_tcgv_i32(t); +} + +static inline TCGv_i32 tcg_temp_local_new_i32(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, true); + return temp_tcgv_i32(t); +} + +static inline TCGv_i64 tcg_global_mem_new_i64(TCGv_ptr reg, intptr_t offset, + const char *name) +{ + TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); + return temp_tcgv_i64(t); +} + +static inline TCGv_i64 tcg_temp_new_i64(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, false); + return temp_tcgv_i64(t); +} + +static inline TCGv_i64 tcg_temp_local_new_i64(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, true); + return temp_tcgv_i64(t); +} + +static inline TCGv_ptr tcg_global_mem_new_ptr(TCGv_ptr reg, intptr_t offset, + const char *name) +{ + TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_PTR, reg, offset, name); + return temp_tcgv_ptr(t); +} + +static inline TCGv_ptr tcg_temp_new_ptr(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_PTR, false); + return temp_tcgv_ptr(t); +} + +static inline TCGv_ptr tcg_temp_local_new_ptr(void) +{ + TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_PTR, true); + return temp_tcgv_ptr(t); +} + +#if defined(CONFIG_DEBUG_TCG) +/* If you call tcg_clear_temp_count() at the start of a section of + * code which is not supposed to leak any TCG temporaries, then + * calling tcg_check_temp_count() at the end of the section will + * return 1 if the section did in fact leak a temporary. + */ +void tcg_clear_temp_count(void); +int tcg_check_temp_count(void); +#else +#define tcg_clear_temp_count() do { } while (0) +#define tcg_check_temp_count() 0 +#endif + +int64_t tcg_cpu_exec_time(void); +void tcg_dump_info(void); +void tcg_dump_op_count(void); + +#define TCG_CT_ALIAS 0x80 +#define TCG_CT_IALIAS 0x40 +#define TCG_CT_NEWREG 0x20 /* output requires a new register */ +#define TCG_CT_REG 0x01 +#define TCG_CT_CONST 0x02 /* any constant of register size */ + +typedef struct TCGArgConstraint { + uint16_t ct; + uint8_t alias_index; + union { + TCGRegSet regs; + } u; +} TCGArgConstraint; + +#define TCG_MAX_OP_ARGS 16 + +/* Bits for TCGOpDef->flags, 8 bits available. */ +enum { + /* Instruction exits the translation block. */ + TCG_OPF_BB_EXIT = 0x01, + /* Instruction defines the end of a basic block. */ + TCG_OPF_BB_END = 0x02, + /* Instruction clobbers call registers and potentially update globals. */ + TCG_OPF_CALL_CLOBBER = 0x04, + /* Instruction has side effects: it cannot be removed if its outputs + are not used, and might trigger exceptions. */ + TCG_OPF_SIDE_EFFECTS = 0x08, + /* Instruction operands are 64-bits (otherwise 32-bits). */ + TCG_OPF_64BIT = 0x10, + /* Instruction is optional and not implemented by the host, or insn + is generic and should not be implemened by the host. */ + TCG_OPF_NOT_PRESENT = 0x20, + /* Instruction operands are vectors. */ + TCG_OPF_VECTOR = 0x40, +}; + +typedef struct TCGOpDef { + const char *name; + uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args; + uint8_t flags; + TCGArgConstraint *args_ct; + int *sorted_args; +#if defined(CONFIG_DEBUG_TCG) + int used; +#endif +} TCGOpDef; + +extern TCGOpDef tcg_op_defs[]; +extern const size_t tcg_op_defs_max; + +typedef struct TCGTargetOpDef { + TCGOpcode op; + const char *args_ct_str[TCG_MAX_OP_ARGS]; +} TCGTargetOpDef; + +#define tcg_abort() \ +do {\ + fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\ + abort();\ +} while (0) + +bool tcg_op_supported(TCGOpcode op); + +void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args); + +TCGOp *tcg_emit_op(TCGOpcode opc); +void tcg_op_remove(TCGContext *s, TCGOp *op); +TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, TCGOpcode opc); +TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc); + +void tcg_optimize(TCGContext *s); + +TCGv_i32 tcg_const_i32(int32_t val); +TCGv_i64 tcg_const_i64(int64_t val); +TCGv_i32 tcg_const_local_i32(int32_t val); +TCGv_i64 tcg_const_local_i64(int64_t val); +TCGv_vec tcg_const_zeros_vec(TCGType); +TCGv_vec tcg_const_ones_vec(TCGType); +TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec); +TCGv_vec tcg_const_ones_vec_matching(TCGv_vec); + +#if UINTPTR_MAX == UINT32_MAX +# define tcg_const_ptr(x) ((TCGv_ptr)tcg_const_i32((intptr_t)(x))) +# define tcg_const_local_ptr(x) ((TCGv_ptr)tcg_const_local_i32((intptr_t)(x))) +#else +# define tcg_const_ptr(x) ((TCGv_ptr)tcg_const_i64((intptr_t)(x))) +# define tcg_const_local_ptr(x) ((TCGv_ptr)tcg_const_local_i64((intptr_t)(x))) +#endif + +TCGLabel *gen_new_label(void); + +/** + * label_arg + * @l: label + * + * Encode a label for storage in the TCG opcode stream. + */ + +static inline TCGArg label_arg(TCGLabel *l) +{ + return (uintptr_t)l; +} + +/** + * arg_label + * @i: value + * + * The opposite of label_arg. Retrieve a label from the + * encoding of the TCG opcode stream. + */ + +static inline TCGLabel *arg_label(TCGArg i) +{ + return (TCGLabel *)(uintptr_t)i; +} + +/** + * tcg_ptr_byte_diff + * @a, @b: addresses to be differenced + * + * There are many places within the TCG backends where we need a byte + * difference between two pointers. While this can be accomplished + * with local casting, it's easy to get wrong -- especially if one is + * concerned with the signedness of the result. + * + * This version relies on GCC's void pointer arithmetic to get the + * correct result. + */ + +static inline ptrdiff_t tcg_ptr_byte_diff(void *a, void *b) +{ + return a - b; +} + +/** + * tcg_pcrel_diff + * @s: the tcg context + * @target: address of the target + * + * Produce a pc-relative difference, from the current code_ptr + * to the destination address. + */ + +static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, void *target) +{ + return tcg_ptr_byte_diff(target, s->code_ptr); +} + +/** + * tcg_current_code_size + * @s: the tcg context + * + * Compute the current code size within the translation block. + * This is used to fill in qemu's data structures for goto_tb. + */ + +static inline size_t tcg_current_code_size(TCGContext *s) +{ + return tcg_ptr_byte_diff(s->code_ptr, s->code_buf); +} + +/* Combine the MemOp and mmu_idx parameters into a single value. */ +typedef uint32_t TCGMemOpIdx; + +/** + * make_memop_idx + * @op: memory operation + * @idx: mmu index + * + * Encode these values into a single parameter. + */ +static inline TCGMemOpIdx make_memop_idx(MemOp op, unsigned idx) +{ + tcg_debug_assert(idx <= 15); + return (op << 4) | idx; +} + +/** + * get_memop + * @oi: combined op/idx parameter + * + * Extract the memory operation from the combined value. + */ +static inline MemOp get_memop(TCGMemOpIdx oi) +{ + return oi >> 4; +} + +/** + * get_mmuidx + * @oi: combined op/idx parameter + * + * Extract the mmu index from the combined value. + */ +static inline unsigned get_mmuidx(TCGMemOpIdx oi) +{ + return oi & 15; +} + +/** + * tcg_qemu_tb_exec: + * @env: pointer to CPUArchState for the CPU + * @tb_ptr: address of generated code for the TB to execute + * + * Start executing code from a given translation block. + * Where translation blocks have been linked, execution + * may proceed from the given TB into successive ones. + * Control eventually returns only when some action is needed + * from the top-level loop: either control must pass to a TB + * which has not yet been directly linked, or an asynchronous + * event such as an interrupt needs handling. + * + * Return: The return value is the value passed to the corresponding + * tcg_gen_exit_tb() at translation time of the last TB attempted to execute. + * The value is either zero or a 4-byte aligned pointer to that TB combined + * with additional information in its two least significant bits. The + * additional information is encoded as follows: + * 0, 1: the link between this TB and the next is via the specified + * TB index (0 or 1). That is, we left the TB via (the equivalent + * of) "goto_tb ". The main loop uses this to determine + * how to link the TB just executed to the next. + * 2: we are using instruction counting code generation, and we + * did not start executing this TB because the instruction counter + * would hit zero midway through it. In this case the pointer + * returned is the TB we were about to execute, and the caller must + * arrange to execute the remaining count of instructions. + * 3: we stopped because the CPU's exit_request flag was set + * (usually meaning that there is an interrupt that needs to be + * handled). The pointer returned is the TB we were about to execute + * when we noticed the pending exit request. + * + * If the bottom two bits indicate an exit-via-index then the CPU + * state is correctly synchronised and ready for execution of the next + * TB (and in particular the guest PC is the address to execute next). + * Otherwise, we gave up on execution of this TB before it started, and + * the caller must fix up the CPU state by calling the CPU's + * synchronize_from_tb() method with the TB pointer we return (falling + * back to calling the CPU's set_pc method with tb->pb if no + * synchronize_from_tb() method exists). + * + * Note that TCG targets may use a different definition of tcg_qemu_tb_exec + * to this default (which just calls the prologue.code emitted by + * tcg_target_qemu_prologue()). + */ +#define TB_EXIT_MASK 3 +#define TB_EXIT_IDX0 0 +#define TB_EXIT_IDX1 1 +#define TB_EXIT_IDXMAX 1 +#define TB_EXIT_REQUESTED 3 + +#ifdef HAVE_TCG_QEMU_TB_EXEC +uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr); +#else +# define tcg_qemu_tb_exec(env, tb_ptr) \ + ((uintptr_t (*)(void *, void *))tcg_ctx->code_gen_prologue)(env, tb_ptr) +#endif + +void tcg_register_jit(void *buf, size_t buf_size); + +#if TCG_TARGET_MAYBE_vec +/* Return zero if the tuple (opc, type, vece) is unsupportable; + return > 0 if it is directly supportable; + return < 0 if we must call tcg_expand_vec_op. */ +int tcg_can_emit_vec_op(TCGOpcode, TCGType, unsigned); +#else +static inline int tcg_can_emit_vec_op(TCGOpcode o, TCGType t, unsigned ve) +{ + return 0; +} +#endif + +/* Expand the tuple (opc, type, vece) on the given arguments. */ +void tcg_expand_vec_op(TCGOpcode, TCGType, unsigned, TCGArg, ...); + +/* Replicate a constant C accoring to the log2 of the element size. */ +uint64_t dup_const_eval(unsigned vece, uint64_t c); + +#define dup_const(VECE, C) \ + (__builtin_constant_p(VECE) \ + ? ( (VECE) == MO_8 ? 0x0101010101010101ull * (uint8_t)(C) \ + : (VECE) == MO_16 ? 0x0001000100010001ull * (uint16_t)(C) \ + : (VECE) == MO_32 ? 0x0000000100000001ull * (uint32_t)(C) \ + : dup_const_eval(VECE, C)) \ + : dup_const_eval(VECE, C)) + + +/* + * Memory helpers that will be used by TCG generated code. + */ +#ifdef CONFIG_SOFTMMU +/* Value zero-extended to tcg register size. */ +tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); + +/* Value sign-extended to tcg register size. */ +tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); + +void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, + TCGMemOpIdx oi, uintptr_t retaddr); + +/* Temporary aliases until backends are converted. */ +#ifdef TARGET_WORDS_BIGENDIAN +# define helper_ret_ldsw_mmu helper_be_ldsw_mmu +# define helper_ret_lduw_mmu helper_be_lduw_mmu +# define helper_ret_ldsl_mmu helper_be_ldsl_mmu +# define helper_ret_ldul_mmu helper_be_ldul_mmu +# define helper_ret_ldl_mmu helper_be_ldul_mmu +# define helper_ret_ldq_mmu helper_be_ldq_mmu +# define helper_ret_stw_mmu helper_be_stw_mmu +# define helper_ret_stl_mmu helper_be_stl_mmu +# define helper_ret_stq_mmu helper_be_stq_mmu +#else +# define helper_ret_ldsw_mmu helper_le_ldsw_mmu +# define helper_ret_lduw_mmu helper_le_lduw_mmu +# define helper_ret_ldsl_mmu helper_le_ldsl_mmu +# define helper_ret_ldul_mmu helper_le_ldul_mmu +# define helper_ret_ldl_mmu helper_le_ldul_mmu +# define helper_ret_ldq_mmu helper_le_ldq_mmu +# define helper_ret_stw_mmu helper_le_stw_mmu +# define helper_ret_stl_mmu helper_le_stl_mmu +# define helper_ret_stq_mmu helper_le_stq_mmu +#endif + +uint32_t helper_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr, + uint32_t cmpv, uint32_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint32_t helper_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr, + uint32_t cmpv, uint32_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint32_t helper_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr, + uint32_t cmpv, uint32_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint64_t helper_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr, + uint64_t cmpv, uint64_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint32_t helper_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr, + uint32_t cmpv, uint32_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint32_t helper_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr, + uint32_t cmpv, uint32_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); +uint64_t helper_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr, + uint64_t cmpv, uint64_t newv, + TCGMemOpIdx oi, uintptr_t retaddr); + +#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \ +TYPE helper_atomic_ ## NAME ## SUFFIX ## _mmu \ + (CPUArchState *env, target_ulong addr, TYPE val, \ + TCGMemOpIdx oi, uintptr_t retaddr); + +#ifdef CONFIG_ATOMIC64 +#define GEN_ATOMIC_HELPER_ALL(NAME) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, b) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) \ + GEN_ATOMIC_HELPER(NAME, uint64_t, q_le) \ + GEN_ATOMIC_HELPER(NAME, uint64_t, q_be) +#else +#define GEN_ATOMIC_HELPER_ALL(NAME) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, b) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \ + GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) +#endif + +GEN_ATOMIC_HELPER_ALL(fetch_add) +GEN_ATOMIC_HELPER_ALL(fetch_sub) +GEN_ATOMIC_HELPER_ALL(fetch_and) +GEN_ATOMIC_HELPER_ALL(fetch_or) +GEN_ATOMIC_HELPER_ALL(fetch_xor) +GEN_ATOMIC_HELPER_ALL(fetch_smin) +GEN_ATOMIC_HELPER_ALL(fetch_umin) +GEN_ATOMIC_HELPER_ALL(fetch_smax) +GEN_ATOMIC_HELPER_ALL(fetch_umax) + +GEN_ATOMIC_HELPER_ALL(add_fetch) +GEN_ATOMIC_HELPER_ALL(sub_fetch) +GEN_ATOMIC_HELPER_ALL(and_fetch) +GEN_ATOMIC_HELPER_ALL(or_fetch) +GEN_ATOMIC_HELPER_ALL(xor_fetch) +GEN_ATOMIC_HELPER_ALL(smin_fetch) +GEN_ATOMIC_HELPER_ALL(umin_fetch) +GEN_ATOMIC_HELPER_ALL(smax_fetch) +GEN_ATOMIC_HELPER_ALL(umax_fetch) + +GEN_ATOMIC_HELPER_ALL(xchg) + +#undef GEN_ATOMIC_HELPER_ALL +#undef GEN_ATOMIC_HELPER +#endif /* CONFIG_SOFTMMU */ + +/* + * These aren't really a "proper" helpers because TCG cannot manage Int128. + * However, use the same format as the others, for use by the backends. + * + * The cmpxchg functions are only defined if HAVE_CMPXCHG128; + * the ld/st functions are only defined if HAVE_ATOMIC128, + * as defined by . + */ +Int128 helper_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr, + Int128 cmpv, Int128 newv, + TCGMemOpIdx oi, uintptr_t retaddr); +Int128 helper_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr, + Int128 cmpv, Int128 newv, + TCGMemOpIdx oi, uintptr_t retaddr); + +Int128 helper_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +Int128 helper_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val, + TCGMemOpIdx oi, uintptr_t retaddr); +void helper_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val, + TCGMemOpIdx oi, uintptr_t retaddr); + +#ifdef CONFIG_DEBUG_TCG +void tcg_assert_listed_vecop(TCGOpcode); +#else +static inline void tcg_assert_listed_vecop(TCGOpcode op) { } +#endif + +static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n) +{ +#ifdef CONFIG_DEBUG_TCG + const TCGOpcode *o = tcg_ctx->vecop_list; + tcg_ctx->vecop_list = n; + return o; +#else + return NULL; +#endif +} + +bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned); + +#endif /* TCG_H */ diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c index 3707c0effb..cbb6cd04bc 100644 --- a/tcg/tcg-op-gvec.c +++ b/tcg/tcg-op-gvec.c @@ -1,3506 +1,3506 @@ -/* - * Generic vector operation expansion - * - * Copyright (c) 2018 Linaro - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include "qemu/osdep.h" -#include "tcg/tcg.h" -#include "tcg/tcg-op.h" -#include "tcg/tcg-op-gvec.h" -#include "qemu/main-loop.h" -#include "tcg/tcg-gvec-desc.h" - -#define MAX_UNROLL 4 - -#ifdef CONFIG_DEBUG_TCG -static const TCGOpcode vecop_list_empty[1] = { 0 }; -#else -#define vecop_list_empty NULL -#endif - - -/* Verify vector size and alignment rules. OFS should be the OR of all - of the operand offsets so that we can check them all at once. */ -static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs) -{ - uint32_t opr_align = oprsz >= 16 ? 15 : 7; - uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7; - tcg_debug_assert(oprsz > 0); - tcg_debug_assert(oprsz <= maxsz); - tcg_debug_assert((oprsz & opr_align) == 0); - tcg_debug_assert((maxsz & max_align) == 0); - tcg_debug_assert((ofs & max_align) == 0); -} - -/* Verify vector overlap rules for two operands. */ -static void check_overlap_2(uint32_t d, uint32_t a, uint32_t s) -{ - tcg_debug_assert(d == a || d + s <= a || a + s <= d); -} - -/* Verify vector overlap rules for three operands. */ -static void check_overlap_3(uint32_t d, uint32_t a, uint32_t b, uint32_t s) -{ - check_overlap_2(d, a, s); - check_overlap_2(d, b, s); - check_overlap_2(a, b, s); -} - -/* Verify vector overlap rules for four operands. */ -static void check_overlap_4(uint32_t d, uint32_t a, uint32_t b, - uint32_t c, uint32_t s) -{ - check_overlap_2(d, a, s); - check_overlap_2(d, b, s); - check_overlap_2(d, c, s); - check_overlap_2(a, b, s); - check_overlap_2(a, c, s); - check_overlap_2(b, c, s); -} - -/* Create a descriptor from components. */ -uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data) -{ - uint32_t desc = 0; - - assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS)); - assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS)); - assert(data == sextract32(data, 0, SIMD_DATA_BITS)); - - oprsz = (oprsz / 8) - 1; - maxsz = (maxsz / 8) - 1; - desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz); - desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz); - desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data); - - return desc; -} - -/* Generate a call to a gvec-style helper with two vector operands. */ -void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz, int32_t data, - gen_helper_gvec_2 *fn) -{ - TCGv_ptr a0, a1; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - - fn(a0, a1, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with two vector operands - and one scalar operand. */ -void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c, - uint32_t oprsz, uint32_t maxsz, int32_t data, - gen_helper_gvec_2i *fn) -{ - TCGv_ptr a0, a1; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - - fn(a0, a1, c, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with three vector operands. */ -void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, uint32_t maxsz, int32_t data, - gen_helper_gvec_3 *fn) -{ - TCGv_ptr a0, a1, a2; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - - fn(a0, a1, a2, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with four vector operands. */ -void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, uint32_t oprsz, uint32_t maxsz, - int32_t data, gen_helper_gvec_4 *fn) -{ - TCGv_ptr a0, a1, a2, a3; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - a3 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - tcg_gen_addi_ptr(a3, cpu_env, cofs); - - fn(a0, a1, a2, a3, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_ptr(a3); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with five vector operands. */ -void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, uint32_t xofs, uint32_t oprsz, - uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn) -{ - TCGv_ptr a0, a1, a2, a3, a4; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - a3 = tcg_temp_new_ptr(); - a4 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - tcg_gen_addi_ptr(a3, cpu_env, cofs); - tcg_gen_addi_ptr(a4, cpu_env, xofs); - - fn(a0, a1, a2, a3, a4, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_ptr(a3); - tcg_temp_free_ptr(a4); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with three vector operands - and an extra pointer operand. */ -void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs, - TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, - int32_t data, gen_helper_gvec_2_ptr *fn) -{ - TCGv_ptr a0, a1; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - - fn(a0, a1, ptr, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with three vector operands - and an extra pointer operand. */ -void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, - TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, - int32_t data, gen_helper_gvec_3_ptr *fn) -{ - TCGv_ptr a0, a1, a2; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - - fn(a0, a1, a2, ptr, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with four vector operands - and an extra pointer operand. */ -void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz, - uint32_t maxsz, int32_t data, - gen_helper_gvec_4_ptr *fn) -{ - TCGv_ptr a0, a1, a2, a3; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - a3 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - tcg_gen_addi_ptr(a3, cpu_env, cofs); - - fn(a0, a1, a2, a3, ptr, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_ptr(a3); - tcg_temp_free_i32(desc); -} - -/* Generate a call to a gvec-style helper with five vector operands - and an extra pointer operand. */ -void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, uint32_t eofs, TCGv_ptr ptr, - uint32_t oprsz, uint32_t maxsz, int32_t data, - gen_helper_gvec_5_ptr *fn) -{ - TCGv_ptr a0, a1, a2, a3, a4; - TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); - - a0 = tcg_temp_new_ptr(); - a1 = tcg_temp_new_ptr(); - a2 = tcg_temp_new_ptr(); - a3 = tcg_temp_new_ptr(); - a4 = tcg_temp_new_ptr(); - - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - tcg_gen_addi_ptr(a2, cpu_env, bofs); - tcg_gen_addi_ptr(a3, cpu_env, cofs); - tcg_gen_addi_ptr(a4, cpu_env, eofs); - - fn(a0, a1, a2, a3, a4, ptr, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_ptr(a2); - tcg_temp_free_ptr(a3); - tcg_temp_free_ptr(a4); - tcg_temp_free_i32(desc); -} - -/* Return true if we want to implement something of OPRSZ bytes - in units of LNSZ. This limits the expansion of inline code. */ -static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz) -{ - uint32_t q, r; - - if (oprsz < lnsz) { - return false; - } - - q = oprsz / lnsz; - r = oprsz % lnsz; - tcg_debug_assert((r & 7) == 0); - - if (lnsz < 16) { - /* For sizes below 16, accept no remainder. */ - if (r != 0) { - return false; - } - } else { - /* - * Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - * In addition, expand_clr needs to handle a multiple of 8. - * Thus we can handle the tail with one more operation per - * diminishing power of 2. - */ - q += ctpop32(r); - } - - return q <= MAX_UNROLL; -} - -static void expand_clr(uint32_t dofs, uint32_t maxsz); - -/* Duplicate C as per VECE. */ -uint64_t (dup_const)(unsigned vece, uint64_t c) -{ - switch (vece) { - case MO_8: - return 0x0101010101010101ull * (uint8_t)c; - case MO_16: - return 0x0001000100010001ull * (uint16_t)c; - case MO_32: - return 0x0000000100000001ull * (uint32_t)c; - case MO_64: - return c; - default: - g_assert_not_reached(); - } -} - -/* Duplicate IN into OUT as per VECE. */ -static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in) -{ - switch (vece) { - case MO_8: - tcg_gen_ext8u_i32(out, in); - tcg_gen_muli_i32(out, out, 0x01010101); - break; - case MO_16: - tcg_gen_deposit_i32(out, in, in, 16, 16); - break; - case MO_32: - tcg_gen_mov_i32(out, in); - break; - default: - g_assert_not_reached(); - } -} - -static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in) -{ - switch (vece) { - case MO_8: - tcg_gen_ext8u_i64(out, in); - tcg_gen_muli_i64(out, out, 0x0101010101010101ull); - break; - case MO_16: - tcg_gen_ext16u_i64(out, in); - tcg_gen_muli_i64(out, out, 0x0001000100010001ull); - break; - case MO_32: - tcg_gen_deposit_i64(out, in, in, 32, 32); - break; - case MO_64: - tcg_gen_mov_i64(out, in); - break; - default: - g_assert_not_reached(); - } -} - -/* Select a supported vector type for implementing an operation on SIZE - * bytes. If OP is 0, assume that the real operation to be performed is - * required by all backends. Otherwise, make sure than OP can be performed - * on elements of size VECE in the selected type. Do not select V64 if - * PREFER_I64 is true. Return 0 if no vector type is selected. - */ -static TCGType choose_vector_type(const TCGOpcode *list, unsigned vece, - uint32_t size, bool prefer_i64) -{ - /* - * Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - * It is hard to imagine a case in which v256 is supported - * but v128 is not, but check anyway. - * In addition, expand_clr needs to handle a multiple of 8. - */ - if (TCG_TARGET_HAS_v256 && - check_size_impl(size, 32) && - tcg_can_emit_vecop_list(list, TCG_TYPE_V256, vece) && - (!(size & 16) || - (TCG_TARGET_HAS_v128 && - tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece))) && - (!(size & 8) || - (TCG_TARGET_HAS_v64 && - tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { - return TCG_TYPE_V256; - } - if (TCG_TARGET_HAS_v128 && - check_size_impl(size, 16) && - tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece) && - (!(size & 8) || - (TCG_TARGET_HAS_v64 && - tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { - return TCG_TYPE_V128; - } - if (TCG_TARGET_HAS_v64 && !prefer_i64 && check_size_impl(size, 8) - && tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)) { - return TCG_TYPE_V64; - } - return 0; -} - -static void do_dup_store(TCGType type, uint32_t dofs, uint32_t oprsz, - uint32_t maxsz, TCGv_vec t_vec) -{ - uint32_t i = 0; - - tcg_debug_assert(oprsz >= 8); - - /* - * This may be expand_clr for the tail of an operation, e.g. - * oprsz == 8 && maxsz == 64. The first 8 bytes of this store - * are misaligned wrt the maximum vector size, so do that first. - */ - if (dofs & 8) { - tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64); - i += 8; - } - - switch (type) { - case TCG_TYPE_V256: - /* - * Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - for (; i + 32 <= oprsz; i += 32) { - tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V256); - } - /* fallthru */ - case TCG_TYPE_V128: - for (; i + 16 <= oprsz; i += 16) { - tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V128); - } - break; - case TCG_TYPE_V64: - for (; i < oprsz; i += 8) { - tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64); - } - break; - default: - g_assert_not_reached(); - } - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Set OPRSZ bytes at DOFS to replications of IN_32, IN_64 or IN_C. - * Only one of IN_32 or IN_64 may be set; - * IN_C is used if IN_32 and IN_64 are unset. - */ -static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz, - uint32_t maxsz, TCGv_i32 in_32, TCGv_i64 in_64, - uint64_t in_c) -{ - TCGType type; - TCGv_i64 t_64; - TCGv_i32 t_32, t_desc; - TCGv_ptr t_ptr; - uint32_t i; - - assert(vece <= (in_32 ? MO_32 : MO_64)); - assert(in_32 == NULL || in_64 == NULL); - - /* If we're storing 0, expand oprsz to maxsz. */ - if (in_32 == NULL && in_64 == NULL) { - in_c = dup_const(vece, in_c); - if (in_c == 0) { - oprsz = maxsz; - } - } - - /* Implement inline with a vector type, if possible. - * Prefer integer when 64-bit host and no variable dup. - */ - type = choose_vector_type(NULL, vece, oprsz, - (TCG_TARGET_REG_BITS == 64 && in_32 == NULL - && (in_64 == NULL || vece == MO_64))); - if (type != 0) { - TCGv_vec t_vec = tcg_temp_new_vec(type); - - if (in_32) { - tcg_gen_dup_i32_vec(vece, t_vec, in_32); - } else if (in_64) { - tcg_gen_dup_i64_vec(vece, t_vec, in_64); - } else { - tcg_gen_dupi_vec(vece, t_vec, in_c); - } - do_dup_store(type, dofs, oprsz, maxsz, t_vec); - tcg_temp_free_vec(t_vec); - return; - } - - /* Otherwise, inline with an integer type, unless "large". */ - if (check_size_impl(oprsz, TCG_TARGET_REG_BITS / 8)) { - t_64 = NULL; - t_32 = NULL; - - if (in_32) { - /* We are given a 32-bit variable input. For a 64-bit host, - use a 64-bit operation unless the 32-bit operation would - be simple enough. */ - if (TCG_TARGET_REG_BITS == 64 - && (vece != MO_32 || !check_size_impl(oprsz, 4))) { - t_64 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(t_64, in_32); - gen_dup_i64(vece, t_64, t_64); - } else { - t_32 = tcg_temp_new_i32(); - gen_dup_i32(vece, t_32, in_32); - } - } else if (in_64) { - /* We are given a 64-bit variable input. */ - t_64 = tcg_temp_new_i64(); - gen_dup_i64(vece, t_64, in_64); - } else { - /* We are given a constant input. */ - /* For 64-bit hosts, use 64-bit constants for "simple" constants - or when we'd need too many 32-bit stores, or when a 64-bit - constant is really required. */ - if (vece == MO_64 - || (TCG_TARGET_REG_BITS == 64 - && (in_c == 0 || in_c == -1 - || !check_size_impl(oprsz, 4)))) { - t_64 = tcg_const_i64(in_c); - } else { - t_32 = tcg_const_i32(in_c); - } - } - - /* Implement inline if we picked an implementation size above. */ - if (t_32) { - for (i = 0; i < oprsz; i += 4) { - tcg_gen_st_i32(t_32, cpu_env, dofs + i); - } - tcg_temp_free_i32(t_32); - goto done; - } - if (t_64) { - for (i = 0; i < oprsz; i += 8) { - tcg_gen_st_i64(t_64, cpu_env, dofs + i); - } - tcg_temp_free_i64(t_64); - goto done; - } - } - - /* Otherwise implement out of line. */ - t_ptr = tcg_temp_new_ptr(); - tcg_gen_addi_ptr(t_ptr, cpu_env, dofs); - t_desc = tcg_const_i32(simd_desc(oprsz, maxsz, 0)); - - if (vece == MO_64) { - if (in_64) { - gen_helper_gvec_dup64(t_ptr, t_desc, in_64); - } else { - t_64 = tcg_const_i64(in_c); - gen_helper_gvec_dup64(t_ptr, t_desc, t_64); - tcg_temp_free_i64(t_64); - } - } else { - typedef void dup_fn(TCGv_ptr, TCGv_i32, TCGv_i32); - static dup_fn * const fns[3] = { - gen_helper_gvec_dup8, - gen_helper_gvec_dup16, - gen_helper_gvec_dup32 - }; - - if (in_32) { - fns[vece](t_ptr, t_desc, in_32); - } else { - t_32 = tcg_temp_new_i32(); - if (in_64) { - tcg_gen_extrl_i64_i32(t_32, in_64); - } else if (vece == MO_8) { - tcg_gen_movi_i32(t_32, in_c & 0xff); - } else if (vece == MO_16) { - tcg_gen_movi_i32(t_32, in_c & 0xffff); - } else { - tcg_gen_movi_i32(t_32, in_c); - } - fns[vece](t_ptr, t_desc, t_32); - tcg_temp_free_i32(t_32); - } - } - - tcg_temp_free_ptr(t_ptr); - tcg_temp_free_i32(t_desc); - return; - - done: - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Likewise, but with zero. */ -static void expand_clr(uint32_t dofs, uint32_t maxsz) -{ - do_dup(MO_8, dofs, maxsz, maxsz, NULL, NULL, 0); -} - -/* Expand OPSZ bytes worth of two-operand operations using i32 elements. */ -static void expand_2_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - bool load_dest, void (*fni)(TCGv_i32, TCGv_i32)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_i32(t1, cpu_env, dofs + i); - } - fni(t1, t0); - tcg_gen_st_i32(t1, cpu_env, dofs + i); - } - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); -} - -static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - int32_t c, bool load_dest, - void (*fni)(TCGv_i32, TCGv_i32, int32_t)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_i32(t1, cpu_env, dofs + i); - } - fni(t1, t0, c); - tcg_gen_st_i32(t1, cpu_env, dofs + i); - } - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); -} - -static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - TCGv_i32 c, bool scalar_first, - void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - if (scalar_first) { - fni(t1, c, t0); - } else { - fni(t1, t0, c); - } - tcg_gen_st_i32(t1, cpu_env, dofs + i); - } - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); -} - -/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ -static void expand_3_i32(uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, bool load_dest, - void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - tcg_gen_ld_i32(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_i32(t2, cpu_env, dofs + i); - } - fni(t2, t0, t1); - tcg_gen_st_i32(t2, cpu_env, dofs + i); - } - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -static void expand_3i_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, int32_t c, bool load_dest, - void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, int32_t)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - tcg_gen_ld_i32(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_i32(t2, cpu_env, dofs + i); - } - fni(t2, t0, t1, c); - tcg_gen_st_i32(t2, cpu_env, dofs + i); - } - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); -} - -/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ -static void expand_4_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, uint32_t oprsz, bool write_aofs, - void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t1, cpu_env, aofs + i); - tcg_gen_ld_i32(t2, cpu_env, bofs + i); - tcg_gen_ld_i32(t3, cpu_env, cofs + i); - fni(t0, t1, t2, t3); - tcg_gen_st_i32(t0, cpu_env, dofs + i); - if (write_aofs) { - tcg_gen_st_i32(t1, cpu_env, aofs + i); - } - } - tcg_temp_free_i32(t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -/* Expand OPSZ bytes worth of two-operand operations using i64 elements. */ -static void expand_2_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - bool load_dest, void (*fni)(TCGv_i64, TCGv_i64)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_i64(t1, cpu_env, dofs + i); - } - fni(t1, t0); - tcg_gen_st_i64(t1, cpu_env, dofs + i); - } - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} - -static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - int64_t c, bool load_dest, - void (*fni)(TCGv_i64, TCGv_i64, int64_t)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_i64(t1, cpu_env, dofs + i); - } - fni(t1, t0, c); - tcg_gen_st_i64(t1, cpu_env, dofs + i); - } - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} - -static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - TCGv_i64 c, bool scalar_first, - void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - if (scalar_first) { - fni(t1, c, t0); - } else { - fni(t1, t0, c); - } - tcg_gen_st_i64(t1, cpu_env, dofs + i); - } - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} - -/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ -static void expand_3_i64(uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, bool load_dest, - void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - tcg_gen_ld_i64(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_i64(t2, cpu_env, dofs + i); - } - fni(t2, t0, t1); - tcg_gen_st_i64(t2, cpu_env, dofs + i); - } - tcg_temp_free_i64(t2); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t0); -} - -static void expand_3i_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, int64_t c, bool load_dest, - void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, int64_t)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - tcg_gen_ld_i64(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_i64(t2, cpu_env, dofs + i); - } - fni(t2, t0, t1, c); - tcg_gen_st_i64(t2, cpu_env, dofs + i); - } - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); -} - -/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ -static void expand_4_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t cofs, uint32_t oprsz, bool write_aofs, - void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t1, cpu_env, aofs + i); - tcg_gen_ld_i64(t2, cpu_env, bofs + i); - tcg_gen_ld_i64(t3, cpu_env, cofs + i); - fni(t0, t1, t2, t3); - tcg_gen_st_i64(t0, cpu_env, dofs + i); - if (write_aofs) { - tcg_gen_st_i64(t1, cpu_env, aofs + i); - } - } - tcg_temp_free_i64(t3); - tcg_temp_free_i64(t2); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t0); -} - -/* Expand OPSZ bytes worth of two-operand operations using host vectors. */ -static void expand_2_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t tysz, TCGType type, - bool load_dest, - void (*fni)(unsigned, TCGv_vec, TCGv_vec)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_vec(t1, cpu_env, dofs + i); - } - fni(vece, t1, t0); - tcg_gen_st_vec(t1, cpu_env, dofs + i); - } - tcg_temp_free_vec(t0); - tcg_temp_free_vec(t1); -} - -/* Expand OPSZ bytes worth of two-vector operands and an immediate operand - using host vectors. */ -static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t tysz, TCGType type, - int64_t c, bool load_dest, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, int64_t)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - if (load_dest) { - tcg_gen_ld_vec(t1, cpu_env, dofs + i); - } - fni(vece, t1, t0, c); - tcg_gen_st_vec(t1, cpu_env, dofs + i); - } - tcg_temp_free_vec(t0); - tcg_temp_free_vec(t1); -} - -static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t tysz, TCGType type, - TCGv_vec c, bool scalar_first, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - if (scalar_first) { - fni(vece, t1, c, t0); - } else { - fni(vece, t1, t0, c); - } - tcg_gen_st_vec(t1, cpu_env, dofs + i); - } - tcg_temp_free_vec(t0); - tcg_temp_free_vec(t1); -} - -/* Expand OPSZ bytes worth of three-operand operations using host vectors. */ -static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, - uint32_t tysz, TCGType type, bool load_dest, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - TCGv_vec t2 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - tcg_gen_ld_vec(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_vec(t2, cpu_env, dofs + i); - } - fni(vece, t2, t0, t1); - tcg_gen_st_vec(t2, cpu_env, dofs + i); - } - tcg_temp_free_vec(t2); - tcg_temp_free_vec(t1); - tcg_temp_free_vec(t0); -} - -/* - * Expand OPSZ bytes worth of three-vector operands and an immediate operand - * using host vectors. - */ -static void expand_3i_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t tysz, - TCGType type, int64_t c, bool load_dest, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, - int64_t)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - TCGv_vec t2 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - tcg_gen_ld_vec(t1, cpu_env, bofs + i); - if (load_dest) { - tcg_gen_ld_vec(t2, cpu_env, dofs + i); - } - fni(vece, t2, t0, t1, c); - tcg_gen_st_vec(t2, cpu_env, dofs + i); - } - tcg_temp_free_vec(t0); - tcg_temp_free_vec(t1); - tcg_temp_free_vec(t2); -} - -/* Expand OPSZ bytes worth of four-operand operations using host vectors. */ -static void expand_4_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t cofs, uint32_t oprsz, - uint32_t tysz, TCGType type, bool write_aofs, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, - TCGv_vec, TCGv_vec)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - TCGv_vec t2 = tcg_temp_new_vec(type); - TCGv_vec t3 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t1, cpu_env, aofs + i); - tcg_gen_ld_vec(t2, cpu_env, bofs + i); - tcg_gen_ld_vec(t3, cpu_env, cofs + i); - fni(vece, t0, t1, t2, t3); - tcg_gen_st_vec(t0, cpu_env, dofs + i); - if (write_aofs) { - tcg_gen_st_vec(t1, cpu_env, aofs + i); - } - } - tcg_temp_free_vec(t3); - tcg_temp_free_vec(t2); - tcg_temp_free_vec(t1); - tcg_temp_free_vec(t0); -} - -/* Expand a vector two-operand operation. */ -void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz, const GVecGen2 *g) -{ - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs); - check_overlap_2(dofs, aofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_2_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, - g->load_dest, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_2_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, - g->load_dest, g->fniv); - break; - case TCG_TYPE_V64: - expand_2_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, - g->load_dest, g->fniv); - break; - - case 0: - if (g->fni8 && check_size_impl(oprsz, 8)) { - expand_2_i64(dofs, aofs, oprsz, g->load_dest, g->fni8); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - expand_2_i32(dofs, aofs, oprsz, g->load_dest, g->fni4); - } else { - assert(g->fno != NULL); - tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, g->data, g->fno); - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Expand a vector operation with two vectors and an immediate. */ -void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - uint32_t maxsz, int64_t c, const GVecGen2i *g) -{ - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs); - check_overlap_2(dofs, aofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_2i_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, - c, g->load_dest, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_2i_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, - c, g->load_dest, g->fniv); - break; - case TCG_TYPE_V64: - expand_2i_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, - c, g->load_dest, g->fniv); - break; - - case 0: - if (g->fni8 && check_size_impl(oprsz, 8)) { - expand_2i_i64(dofs, aofs, oprsz, c, g->load_dest, g->fni8); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - expand_2i_i32(dofs, aofs, oprsz, c, g->load_dest, g->fni4); - } else { - if (g->fno) { - tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno); - } else { - TCGv_i64 tcg_c = tcg_const_i64(c); - tcg_gen_gvec_2i_ool(dofs, aofs, tcg_c, oprsz, - maxsz, c, g->fnoi); - tcg_temp_free_i64(tcg_c); - } - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Expand a vector operation with two vectors and a scalar. */ -void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g) -{ - TCGType type; - - check_size_align(oprsz, maxsz, dofs | aofs); - check_overlap_2(dofs, aofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - if (type != 0) { - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGv_vec t_vec = tcg_temp_new_vec(type); - uint32_t some; - - tcg_gen_dup_i64_vec(g->vece, t_vec, c); - - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_2s_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, - t_vec, g->scalar_first, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - - case TCG_TYPE_V128: - expand_2s_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, - t_vec, g->scalar_first, g->fniv); - break; - - case TCG_TYPE_V64: - expand_2s_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, - t_vec, g->scalar_first, g->fniv); - break; - - default: - g_assert_not_reached(); - } - tcg_temp_free_vec(t_vec); - tcg_swap_vecop_list(hold_list); - } else if (g->fni8 && check_size_impl(oprsz, 8)) { - TCGv_i64 t64 = tcg_temp_new_i64(); - - gen_dup_i64(g->vece, t64, c); - expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8); - tcg_temp_free_i64(t64); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - TCGv_i32 t32 = tcg_temp_new_i32(); - - tcg_gen_extrl_i64_i32(t32, c); - gen_dup_i32(g->vece, t32, t32); - expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4); - tcg_temp_free_i32(t32); - } else { - tcg_gen_gvec_2i_ool(dofs, aofs, c, oprsz, maxsz, 0, g->fno); - return; - } - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Expand a vector three-operand operation. */ -void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g) -{ - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs | bofs); - check_overlap_3(dofs, aofs, bofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_3_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, - g->load_dest, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - bofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, - g->load_dest, g->fniv); - break; - case TCG_TYPE_V64: - expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, - g->load_dest, g->fniv); - break; - - case 0: - if (g->fni8 && check_size_impl(oprsz, 8)) { - expand_3_i64(dofs, aofs, bofs, oprsz, g->load_dest, g->fni8); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - expand_3_i32(dofs, aofs, bofs, oprsz, g->load_dest, g->fni4); - } else { - assert(g->fno != NULL); - tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, - maxsz, g->data, g->fno); - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Expand a vector operation with three vectors and an immediate. */ -void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, uint32_t maxsz, int64_t c, - const GVecGen3i *g) -{ - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs | bofs); - check_overlap_3(dofs, aofs, bofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - switch (type) { - case TCG_TYPE_V256: - /* - * Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_3i_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, - c, g->load_dest, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - bofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, - c, g->load_dest, g->fniv); - break; - case TCG_TYPE_V64: - expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, - c, g->load_dest, g->fniv); - break; - - case 0: - if (g->fni8 && check_size_impl(oprsz, 8)) { - expand_3i_i64(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni8); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - expand_3i_i32(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni4); - } else { - assert(g->fno != NULL); - tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, c, g->fno); - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* Expand a vector four-operand operation. */ -void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, - uint32_t oprsz, uint32_t maxsz, const GVecGen4 *g) -{ - const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; - const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs | bofs | cofs); - check_overlap_4(dofs, aofs, bofs, cofs, maxsz); - - type = 0; - if (g->fniv) { - type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); - } - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_4_vec(g->vece, dofs, aofs, bofs, cofs, some, - 32, TCG_TYPE_V256, g->write_aofs, g->fniv); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - bofs += some; - cofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz, - 16, TCG_TYPE_V128, g->write_aofs, g->fniv); - break; - case TCG_TYPE_V64: - expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz, - 8, TCG_TYPE_V64, g->write_aofs, g->fniv); - break; - - case 0: - if (g->fni8 && check_size_impl(oprsz, 8)) { - expand_4_i64(dofs, aofs, bofs, cofs, oprsz, - g->write_aofs, g->fni8); - } else if (g->fni4 && check_size_impl(oprsz, 4)) { - expand_4_i32(dofs, aofs, bofs, cofs, oprsz, - g->write_aofs, g->fni4); - } else { - assert(g->fno != NULL); - tcg_gen_gvec_4_ool(dofs, aofs, bofs, cofs, - oprsz, maxsz, g->data, g->fno); - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -/* - * Expand specific vector operations. - */ - -static void vec_mov2(unsigned vece, TCGv_vec a, TCGv_vec b) -{ - tcg_gen_mov_vec(a, b); -} - -void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2 g = { - .fni8 = tcg_gen_mov_i64, - .fniv = vec_mov2, - .fno = gen_helper_gvec_mov, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - if (dofs != aofs) { - tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g); - } else { - check_size_align(oprsz, maxsz, dofs); - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } - } -} - -void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t oprsz, - uint32_t maxsz, TCGv_i32 in) -{ - check_size_align(oprsz, maxsz, dofs); - tcg_debug_assert(vece <= MO_32); - do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0); -} - -void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t oprsz, - uint32_t maxsz, TCGv_i64 in) -{ - check_size_align(oprsz, maxsz, dofs); - tcg_debug_assert(vece <= MO_64); - do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0); -} - -void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz) -{ - check_size_align(oprsz, maxsz, dofs); - if (vece <= MO_64) { - TCGType type = choose_vector_type(NULL, vece, oprsz, 0); - if (type != 0) { - TCGv_vec t_vec = tcg_temp_new_vec(type); - tcg_gen_dup_mem_vec(vece, t_vec, cpu_env, aofs); - do_dup_store(type, dofs, oprsz, maxsz, t_vec); - tcg_temp_free_vec(t_vec); - } else if (vece <= MO_32) { - TCGv_i32 in = tcg_temp_new_i32(); - switch (vece) { - case MO_8: - tcg_gen_ld8u_i32(in, cpu_env, aofs); - break; - case MO_16: - tcg_gen_ld16u_i32(in, cpu_env, aofs); - break; - default: - tcg_gen_ld_i32(in, cpu_env, aofs); - break; - } - do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0); - tcg_temp_free_i32(in); - } else { - TCGv_i64 in = tcg_temp_new_i64(); - tcg_gen_ld_i64(in, cpu_env, aofs); - do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0); - tcg_temp_free_i64(in); - } - } else { - /* 128-bit duplicate. */ - /* ??? Dup to 256-bit vector. */ - int i; - - tcg_debug_assert(vece == 4); - tcg_debug_assert(oprsz >= 16); - if (TCG_TARGET_HAS_v128) { - TCGv_vec in = tcg_temp_new_vec(TCG_TYPE_V128); - - tcg_gen_ld_vec(in, cpu_env, aofs); - for (i = 0; i < oprsz; i += 16) { - tcg_gen_st_vec(in, cpu_env, dofs + i); - } - tcg_temp_free_vec(in); - } else { - TCGv_i64 in0 = tcg_temp_new_i64(); - TCGv_i64 in1 = tcg_temp_new_i64(); - - tcg_gen_ld_i64(in0, cpu_env, aofs); - tcg_gen_ld_i64(in1, cpu_env, aofs + 8); - for (i = 0; i < oprsz; i += 16) { - tcg_gen_st_i64(in0, cpu_env, dofs + i); - tcg_gen_st_i64(in1, cpu_env, dofs + i + 8); - } - tcg_temp_free_i64(in0); - tcg_temp_free_i64(in1); - } - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } - } -} - -void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz, - uint32_t maxsz, uint64_t x) -{ - check_size_align(oprsz, maxsz, dofs); - do_dup(vece, dofs, oprsz, maxsz, NULL, NULL, x); -} - -void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2 g = { - .fni8 = tcg_gen_not_i64, - .fniv = tcg_gen_not_vec, - .fno = gen_helper_gvec_not, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g); -} - -/* Perform a vector addition using normal addition and a mask. The mask - should be the sign bit of each lane. This 6-operation form is more - efficient than separate additions when there are 4 or more lanes in - the 64-bit operation. */ -static void gen_addv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m) -{ - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - tcg_gen_andc_i64(t1, a, m); - tcg_gen_andc_i64(t2, b, m); - tcg_gen_xor_i64(t3, a, b); - tcg_gen_add_i64(d, t1, t2); - tcg_gen_and_i64(t3, t3, m); - tcg_gen_xor_i64(d, d, t3); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - tcg_temp_free_i64(t3); -} - -void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); - gen_addv_mask(d, a, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); - gen_addv_mask(d, a, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t1, a, ~0xffffffffull); - tcg_gen_add_i64(t2, a, b); - tcg_gen_add_i64(t1, t1, b); - tcg_gen_deposit_i64(d, t1, t2, 0, 32); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); -} - -static const TCGOpcode vecop_list_add[] = { INDEX_op_add_vec, 0 }; - -void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g[4] = { - { .fni8 = tcg_gen_vec_add8_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_add8, - .opt_opc = vecop_list_add, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_add16_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_add16, - .opt_opc = vecop_list_add, - .vece = MO_16 }, - { .fni4 = tcg_gen_add_i32, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_add32, - .opt_opc = vecop_list_add, - .vece = MO_32 }, - { .fni8 = tcg_gen_add_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_add64, - .opt_opc = vecop_list_add, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2s g[4] = { - { .fni8 = tcg_gen_vec_add8_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_adds8, - .opt_opc = vecop_list_add, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_add16_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_adds16, - .opt_opc = vecop_list_add, - .vece = MO_16 }, - { .fni4 = tcg_gen_add_i32, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_adds32, - .opt_opc = vecop_list_add, - .vece = MO_32 }, - { .fni8 = tcg_gen_add_i64, - .fniv = tcg_gen_add_vec, - .fno = gen_helper_gvec_adds64, - .opt_opc = vecop_list_add, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); -} - -void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_const_i64(c); - tcg_gen_gvec_adds(vece, dofs, aofs, tmp, oprsz, maxsz); - tcg_temp_free_i64(tmp); -} - -static const TCGOpcode vecop_list_sub[] = { INDEX_op_sub_vec, 0 }; - -void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2s g[4] = { - { .fni8 = tcg_gen_vec_sub8_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_subs8, - .opt_opc = vecop_list_sub, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_sub16_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_subs16, - .opt_opc = vecop_list_sub, - .vece = MO_16 }, - { .fni4 = tcg_gen_sub_i32, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_subs32, - .opt_opc = vecop_list_sub, - .vece = MO_32 }, - { .fni8 = tcg_gen_sub_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_subs64, - .opt_opc = vecop_list_sub, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); -} - -/* Perform a vector subtraction using normal subtraction and a mask. - Compare gen_addv_mask above. */ -static void gen_subv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m) -{ - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - tcg_gen_or_i64(t1, a, m); - tcg_gen_andc_i64(t2, b, m); - tcg_gen_eqv_i64(t3, a, b); - tcg_gen_sub_i64(d, t1, t2); - tcg_gen_and_i64(t3, t3, m); - tcg_gen_xor_i64(d, d, t3); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - tcg_temp_free_i64(t3); -} - -void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); - gen_subv_mask(d, a, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); - gen_subv_mask(d, a, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t1, b, ~0xffffffffull); - tcg_gen_sub_i64(t2, a, b); - tcg_gen_sub_i64(t1, a, t1); - tcg_gen_deposit_i64(d, t1, t2, 0, 32); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); -} - -void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g[4] = { - { .fni8 = tcg_gen_vec_sub8_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_sub8, - .opt_opc = vecop_list_sub, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_sub16_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_sub16, - .opt_opc = vecop_list_sub, - .vece = MO_16 }, - { .fni4 = tcg_gen_sub_i32, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_sub32, - .opt_opc = vecop_list_sub, - .vece = MO_32 }, - { .fni8 = tcg_gen_sub_i64, - .fniv = tcg_gen_sub_vec, - .fno = gen_helper_gvec_sub64, - .opt_opc = vecop_list_sub, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -static const TCGOpcode vecop_list_mul[] = { INDEX_op_mul_vec, 0 }; - -void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_mul8, - .opt_opc = vecop_list_mul, - .vece = MO_8 }, - { .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_mul16, - .opt_opc = vecop_list_mul, - .vece = MO_16 }, - { .fni4 = tcg_gen_mul_i32, - .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_mul32, - .opt_opc = vecop_list_mul, - .vece = MO_32 }, - { .fni8 = tcg_gen_mul_i64, - .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_mul64, - .opt_opc = vecop_list_mul, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2s g[4] = { - { .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_muls8, - .opt_opc = vecop_list_mul, - .vece = MO_8 }, - { .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_muls16, - .opt_opc = vecop_list_mul, - .vece = MO_16 }, - { .fni4 = tcg_gen_mul_i32, - .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_muls32, - .opt_opc = vecop_list_mul, - .vece = MO_32 }, - { .fni8 = tcg_gen_mul_i64, - .fniv = tcg_gen_mul_vec, - .fno = gen_helper_gvec_muls64, - .opt_opc = vecop_list_mul, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); -} - -void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_const_i64(c); - tcg_gen_gvec_muls(vece, dofs, aofs, tmp, oprsz, maxsz); - tcg_temp_free_i64(tmp); -} - -void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_ssadd_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_ssadd_vec, - .fno = gen_helper_gvec_ssadd8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_ssadd_vec, - .fno = gen_helper_gvec_ssadd16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fniv = tcg_gen_ssadd_vec, - .fno = gen_helper_gvec_ssadd32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fniv = tcg_gen_ssadd_vec, - .fno = gen_helper_gvec_ssadd64, - .opt_opc = vecop_list, - .vece = MO_64 }, - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_sssub_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_sssub_vec, - .fno = gen_helper_gvec_sssub8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_sssub_vec, - .fno = gen_helper_gvec_sssub16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fniv = tcg_gen_sssub_vec, - .fno = gen_helper_gvec_sssub32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fniv = tcg_gen_sssub_vec, - .fno = gen_helper_gvec_sssub64, - .opt_opc = vecop_list, - .vece = MO_64 }, - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -static void tcg_gen_usadd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 max = tcg_const_i32(-1); - tcg_gen_add_i32(d, a, b); - tcg_gen_movcond_i32(TCG_COND_LTU, d, d, a, max, d); - tcg_temp_free_i32(max); -} - -static void tcg_gen_usadd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 max = tcg_const_i64(-1); - tcg_gen_add_i64(d, a, b); - tcg_gen_movcond_i64(TCG_COND_LTU, d, d, a, max, d); - tcg_temp_free_i64(max); -} - -void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_usadd_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_usadd_vec, - .fno = gen_helper_gvec_usadd8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_usadd_vec, - .fno = gen_helper_gvec_usadd16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_usadd_i32, - .fniv = tcg_gen_usadd_vec, - .fno = gen_helper_gvec_usadd32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_usadd_i64, - .fniv = tcg_gen_usadd_vec, - .fno = gen_helper_gvec_usadd64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -static void tcg_gen_ussub_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 min = tcg_const_i32(0); - tcg_gen_sub_i32(d, a, b); - tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, min, d); - tcg_temp_free_i32(min); -} - -static void tcg_gen_ussub_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 min = tcg_const_i64(0); - tcg_gen_sub_i64(d, a, b); - tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, min, d); - tcg_temp_free_i64(min); -} - -void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_ussub_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_ussub_vec, - .fno = gen_helper_gvec_ussub8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_ussub_vec, - .fno = gen_helper_gvec_ussub16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_ussub_i32, - .fniv = tcg_gen_ussub_vec, - .fno = gen_helper_gvec_ussub32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_ussub_i64, - .fniv = tcg_gen_ussub_vec, - .fno = gen_helper_gvec_ussub64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_smin_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_smin_vec, - .fno = gen_helper_gvec_smin8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_smin_vec, - .fno = gen_helper_gvec_smin16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_smin_i32, - .fniv = tcg_gen_smin_vec, - .fno = gen_helper_gvec_smin32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_smin_i64, - .fniv = tcg_gen_smin_vec, - .fno = gen_helper_gvec_smin64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_umin_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_umin_vec, - .fno = gen_helper_gvec_umin8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_umin_vec, - .fno = gen_helper_gvec_umin16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_umin_i32, - .fniv = tcg_gen_umin_vec, - .fno = gen_helper_gvec_umin32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_umin_i64, - .fniv = tcg_gen_umin_vec, - .fno = gen_helper_gvec_umin64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_smax_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_smax_vec, - .fno = gen_helper_gvec_smax8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_smax_vec, - .fno = gen_helper_gvec_smax16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_smax_i32, - .fniv = tcg_gen_smax_vec, - .fno = gen_helper_gvec_smax32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_smax_i64, - .fniv = tcg_gen_smax_vec, - .fno = gen_helper_gvec_smax64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_umax_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_umax_vec, - .fno = gen_helper_gvec_umax8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_umax_vec, - .fno = gen_helper_gvec_umax16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_umax_i32, - .fniv = tcg_gen_umax_vec, - .fno = gen_helper_gvec_umax32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_umax_i64, - .fniv = tcg_gen_umax_vec, - .fno = gen_helper_gvec_umax64, - .opt_opc = vecop_list, - .vece = MO_64 } - }; - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -/* Perform a vector negation using normal negation and a mask. - Compare gen_subv_mask above. */ -static void gen_negv_mask(TCGv_i64 d, TCGv_i64 b, TCGv_i64 m) -{ - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - tcg_gen_andc_i64(t3, m, b); - tcg_gen_andc_i64(t2, b, m); - tcg_gen_sub_i64(d, m, t2); - tcg_gen_xor_i64(d, d, t3); - - tcg_temp_free_i64(t2); - tcg_temp_free_i64(t3); -} - -void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); - gen_negv_mask(d, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 b) -{ - TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); - gen_negv_mask(d, b, m); - tcg_temp_free_i64(m); -} - -void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 b) -{ - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t1, b, ~0xffffffffull); - tcg_gen_neg_i64(t2, b); - tcg_gen_neg_i64(t1, t1); - tcg_gen_deposit_i64(d, t1, t2, 0, 32); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); -} - -void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_neg_vec, 0 }; - static const GVecGen2 g[4] = { - { .fni8 = tcg_gen_vec_neg8_i64, - .fniv = tcg_gen_neg_vec, - .fno = gen_helper_gvec_neg8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_neg16_i64, - .fniv = tcg_gen_neg_vec, - .fno = gen_helper_gvec_neg16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_neg_i32, - .fniv = tcg_gen_neg_vec, - .fno = gen_helper_gvec_neg32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_neg_i64, - .fniv = tcg_gen_neg_vec, - .fno = gen_helper_gvec_neg64, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]); -} - -static void gen_absv_mask(TCGv_i64 d, TCGv_i64 b, unsigned vece) -{ - TCGv_i64 t = tcg_temp_new_i64(); - int nbit = 8 << vece; - - /* Create -1 for each negative element. */ - tcg_gen_shri_i64(t, b, nbit - 1); - tcg_gen_andi_i64(t, t, dup_const(vece, 1)); - tcg_gen_muli_i64(t, t, (1 << nbit) - 1); - - /* - * Invert (via xor -1) and add one (via sub -1). - * Because of the ordering the msb is cleared, - * so we never have carry into the next element. - */ - tcg_gen_xor_i64(d, b, t); - tcg_gen_sub_i64(d, d, t); - - tcg_temp_free_i64(t); -} - -static void tcg_gen_vec_abs8_i64(TCGv_i64 d, TCGv_i64 b) -{ - gen_absv_mask(d, b, MO_8); -} - -static void tcg_gen_vec_abs16_i64(TCGv_i64 d, TCGv_i64 b) -{ - gen_absv_mask(d, b, MO_16); -} - -void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_abs_vec, 0 }; - static const GVecGen2 g[4] = { - { .fni8 = tcg_gen_vec_abs8_i64, - .fniv = tcg_gen_abs_vec, - .fno = gen_helper_gvec_abs8, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_abs16_i64, - .fniv = tcg_gen_abs_vec, - .fno = gen_helper_gvec_abs16, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_abs_i32, - .fniv = tcg_gen_abs_vec, - .fno = gen_helper_gvec_abs32, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_abs_i64, - .fniv = tcg_gen_abs_vec, - .fno = gen_helper_gvec_abs64, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]); -} - -void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_and_i64, - .fniv = tcg_gen_and_vec, - .fno = gen_helper_gvec_and, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_or_i64, - .fniv = tcg_gen_or_vec, - .fno = gen_helper_gvec_or, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_xor_i64, - .fniv = tcg_gen_xor_vec, - .fno = gen_helper_gvec_xor, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_andc_i64, - .fniv = tcg_gen_andc_vec, - .fno = gen_helper_gvec_andc, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_orc_i64, - .fniv = tcg_gen_orc_vec, - .fno = gen_helper_gvec_orc, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_nand_i64, - .fniv = tcg_gen_nand_vec, - .fno = gen_helper_gvec_nand, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_nor_i64, - .fniv = tcg_gen_nor_vec, - .fno = gen_helper_gvec_nor, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 g = { - .fni8 = tcg_gen_eqv_i64, - .fniv = tcg_gen_eqv_vec, - .fno = gen_helper_gvec_eqv, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - if (aofs == bofs) { - tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); - } else { - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); - } -} - -static const GVecGen2s gop_ands = { - .fni8 = tcg_gen_and_i64, - .fniv = tcg_gen_and_vec, - .fno = gen_helper_gvec_ands, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 -}; - -void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands); - tcg_temp_free_i64(tmp); -} - -void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands); - tcg_temp_free_i64(tmp); -} - -static const GVecGen2s gop_xors = { - .fni8 = tcg_gen_xor_i64, - .fniv = tcg_gen_xor_vec, - .fno = gen_helper_gvec_xors, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 -}; - -void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors); - tcg_temp_free_i64(tmp); -} - -void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors); - tcg_temp_free_i64(tmp); -} - -static const GVecGen2s gop_ors = { - .fni8 = tcg_gen_or_i64, - .fniv = tcg_gen_or_vec, - .fno = gen_helper_gvec_ors, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 -}; - -void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors); - tcg_temp_free_i64(tmp); -} - -void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t c, uint32_t oprsz, uint32_t maxsz) -{ - TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); - tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors); - tcg_temp_free_i64(tmp); -} - -void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_8, 0xff << c); - tcg_gen_shli_i64(d, a, c); - tcg_gen_andi_i64(d, d, mask); -} - -void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_16, 0xffff << c); - tcg_gen_shli_i64(d, a, c); - tcg_gen_andi_i64(d, d, mask); -} - -void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t shift, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 }; - static const GVecGen2i g[4] = { - { .fni8 = tcg_gen_vec_shl8i_i64, - .fniv = tcg_gen_shli_vec, - .fno = gen_helper_gvec_shl8i, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_shl16i_i64, - .fniv = tcg_gen_shli_vec, - .fno = gen_helper_gvec_shl16i, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_shli_i32, - .fniv = tcg_gen_shli_vec, - .fno = gen_helper_gvec_shl32i, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_shli_i64, - .fniv = tcg_gen_shli_vec, - .fno = gen_helper_gvec_shl64i, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_debug_assert(shift >= 0 && shift < (8 << vece)); - if (shift == 0) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); - } -} - -void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_8, 0xff >> c); - tcg_gen_shri_i64(d, a, c); - tcg_gen_andi_i64(d, d, mask); -} - -void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_16, 0xffff >> c); - tcg_gen_shri_i64(d, a, c); - tcg_gen_andi_i64(d, d, mask); -} - -void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t shift, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 }; - static const GVecGen2i g[4] = { - { .fni8 = tcg_gen_vec_shr8i_i64, - .fniv = tcg_gen_shri_vec, - .fno = gen_helper_gvec_shr8i, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_shr16i_i64, - .fniv = tcg_gen_shri_vec, - .fno = gen_helper_gvec_shr16i, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_shri_i32, - .fniv = tcg_gen_shri_vec, - .fno = gen_helper_gvec_shr32i, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_shri_i64, - .fniv = tcg_gen_shri_vec, - .fno = gen_helper_gvec_shr64i, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_debug_assert(shift >= 0 && shift < (8 << vece)); - if (shift == 0) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); - } -} - -void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t s_mask = dup_const(MO_8, 0x80 >> c); - uint64_t c_mask = dup_const(MO_8, 0xff >> c); - TCGv_i64 s = tcg_temp_new_i64(); - - tcg_gen_shri_i64(d, a, c); - tcg_gen_andi_i64(s, d, s_mask); /* isolate (shifted) sign bit */ - tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */ - tcg_gen_andi_i64(d, d, c_mask); /* clear out bits above sign */ - tcg_gen_or_i64(d, d, s); /* include sign extension */ - tcg_temp_free_i64(s); -} - -void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t s_mask = dup_const(MO_16, 0x8000 >> c); - uint64_t c_mask = dup_const(MO_16, 0xffff >> c); - TCGv_i64 s = tcg_temp_new_i64(); - - tcg_gen_shri_i64(d, a, c); - tcg_gen_andi_i64(s, d, s_mask); /* isolate (shifted) sign bit */ - tcg_gen_andi_i64(d, d, c_mask); /* clear out bits above sign */ - tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */ - tcg_gen_or_i64(d, d, s); /* include sign extension */ - tcg_temp_free_i64(s); -} - -void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t shift, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_sari_vec, 0 }; - static const GVecGen2i g[4] = { - { .fni8 = tcg_gen_vec_sar8i_i64, - .fniv = tcg_gen_sari_vec, - .fno = gen_helper_gvec_sar8i, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_sar16i_i64, - .fniv = tcg_gen_sari_vec, - .fno = gen_helper_gvec_sar16i, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_sari_i32, - .fniv = tcg_gen_sari_vec, - .fno = gen_helper_gvec_sar32i, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_sari_i64, - .fniv = tcg_gen_sari_vec, - .fno = gen_helper_gvec_sar64i, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_debug_assert(shift >= 0 && shift < (8 << vece)); - if (shift == 0) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); - } -} - -void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_8, 0xff << c); - - tcg_gen_shli_i64(d, a, c); - tcg_gen_shri_i64(a, a, 8 - c); - tcg_gen_andi_i64(d, d, mask); - tcg_gen_andi_i64(a, a, ~mask); - tcg_gen_or_i64(d, d, a); -} - -void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) -{ - uint64_t mask = dup_const(MO_16, 0xffff << c); - - tcg_gen_shli_i64(d, a, c); - tcg_gen_shri_i64(a, a, 16 - c); - tcg_gen_andi_i64(d, d, mask); - tcg_gen_andi_i64(a, a, ~mask); - tcg_gen_or_i64(d, d, a); -} - -void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t shift, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 }; - static const GVecGen2i g[4] = { - { .fni8 = tcg_gen_vec_rotl8i_i64, - .fniv = tcg_gen_rotli_vec, - .fno = gen_helper_gvec_rotl8i, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fni8 = tcg_gen_vec_rotl16i_i64, - .fniv = tcg_gen_rotli_vec, - .fno = gen_helper_gvec_rotl16i, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_rotli_i32, - .fniv = tcg_gen_rotli_vec, - .fno = gen_helper_gvec_rotl32i, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_rotli_i64, - .fniv = tcg_gen_rotli_vec, - .fno = gen_helper_gvec_rotl64i, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_debug_assert(shift >= 0 && shift < (8 << vece)); - if (shift == 0) { - tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); - } else { - tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); - } -} - -void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs, - int64_t shift, uint32_t oprsz, uint32_t maxsz) -{ - tcg_debug_assert(vece <= MO_64); - tcg_debug_assert(shift >= 0 && shift < (8 << vece)); - tcg_gen_gvec_rotli(vece, dofs, aofs, -shift & ((8 << vece) - 1), - oprsz, maxsz); -} - -/* - * Specialized generation vector shifts by a non-constant scalar. - */ - -typedef struct { - void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32); - void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64); - void (*fniv_s)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32); - void (*fniv_v)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec); - gen_helper_gvec_2 *fno[4]; - TCGOpcode s_list[2]; - TCGOpcode v_list[2]; -} GVecGen2sh; - -static void expand_2sh_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t tysz, TCGType type, - TCGv_i32 shift, - void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32)) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - fni(vece, t0, t0, shift); - tcg_gen_st_vec(t0, cpu_env, dofs + i); - } - tcg_temp_free_vec(t0); -} - -static void -do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift, - uint32_t oprsz, uint32_t maxsz, const GVecGen2sh *g) -{ - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs); - check_overlap_2(dofs, aofs, maxsz); - - /* If the backend has a scalar expansion, great. */ - type = choose_vector_type(g->s_list, vece, oprsz, vece == MO_64); - if (type) { - const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); - switch (type) { - case TCG_TYPE_V256: - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_2sh_vec(vece, dofs, aofs, some, 32, - TCG_TYPE_V256, shift, g->fniv_s); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_2sh_vec(vece, dofs, aofs, oprsz, 16, - TCG_TYPE_V128, shift, g->fniv_s); - break; - case TCG_TYPE_V64: - expand_2sh_vec(vece, dofs, aofs, oprsz, 8, - TCG_TYPE_V64, shift, g->fniv_s); - break; - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - goto clear_tail; - } - - /* If the backend supports variable vector shifts, also cool. */ - type = choose_vector_type(g->v_list, vece, oprsz, vece == MO_64); - if (type) { - const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); - TCGv_vec v_shift = tcg_temp_new_vec(type); - - if (vece == MO_64) { - TCGv_i64 sh64 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(sh64, shift); - tcg_gen_dup_i64_vec(MO_64, v_shift, sh64); - tcg_temp_free_i64(sh64); - } else { - tcg_gen_dup_i32_vec(vece, v_shift, shift); - } - - switch (type) { - case TCG_TYPE_V256: - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_2s_vec(vece, dofs, aofs, some, 32, TCG_TYPE_V256, - v_shift, false, g->fniv_v); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_2s_vec(vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, - v_shift, false, g->fniv_v); - break; - case TCG_TYPE_V64: - expand_2s_vec(vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, - v_shift, false, g->fniv_v); - break; - default: - g_assert_not_reached(); - } - tcg_temp_free_vec(v_shift); - tcg_swap_vecop_list(hold_list); - goto clear_tail; - } - - /* Otherwise fall back to integral... */ - if (vece == MO_32 && check_size_impl(oprsz, 4)) { - expand_2s_i32(dofs, aofs, oprsz, shift, false, g->fni4); - } else if (vece == MO_64 && check_size_impl(oprsz, 8)) { - TCGv_i64 sh64 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(sh64, shift); - expand_2s_i64(dofs, aofs, oprsz, sh64, false, g->fni8); - tcg_temp_free_i64(sh64); - } else { - TCGv_ptr a0 = tcg_temp_new_ptr(); - TCGv_ptr a1 = tcg_temp_new_ptr(); - TCGv_i32 desc = tcg_temp_new_i32(); - - tcg_gen_shli_i32(desc, shift, SIMD_DATA_SHIFT); - tcg_gen_ori_i32(desc, desc, simd_desc(oprsz, maxsz, 0)); - tcg_gen_addi_ptr(a0, cpu_env, dofs); - tcg_gen_addi_ptr(a1, cpu_env, aofs); - - g->fno[vece](a0, a1, desc); - - tcg_temp_free_ptr(a0); - tcg_temp_free_ptr(a1); - tcg_temp_free_i32(desc); - return; - } - - clear_tail: - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2sh g = { - .fni4 = tcg_gen_shl_i32, - .fni8 = tcg_gen_shl_i64, - .fniv_s = tcg_gen_shls_vec, - .fniv_v = tcg_gen_shlv_vec, - .fno = { - gen_helper_gvec_shl8i, - gen_helper_gvec_shl16i, - gen_helper_gvec_shl32i, - gen_helper_gvec_shl64i, - }, - .s_list = { INDEX_op_shls_vec, 0 }, - .v_list = { INDEX_op_shlv_vec, 0 }, - }; - - tcg_debug_assert(vece <= MO_64); - do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); -} - -void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2sh g = { - .fni4 = tcg_gen_shr_i32, - .fni8 = tcg_gen_shr_i64, - .fniv_s = tcg_gen_shrs_vec, - .fniv_v = tcg_gen_shrv_vec, - .fno = { - gen_helper_gvec_shr8i, - gen_helper_gvec_shr16i, - gen_helper_gvec_shr32i, - gen_helper_gvec_shr64i, - }, - .s_list = { INDEX_op_shrs_vec, 0 }, - .v_list = { INDEX_op_shrv_vec, 0 }, - }; - - tcg_debug_assert(vece <= MO_64); - do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); -} - -void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2sh g = { - .fni4 = tcg_gen_sar_i32, - .fni8 = tcg_gen_sar_i64, - .fniv_s = tcg_gen_sars_vec, - .fniv_v = tcg_gen_sarv_vec, - .fno = { - gen_helper_gvec_sar8i, - gen_helper_gvec_sar16i, - gen_helper_gvec_sar32i, - gen_helper_gvec_sar64i, - }, - .s_list = { INDEX_op_sars_vec, 0 }, - .v_list = { INDEX_op_sarv_vec, 0 }, - }; - - tcg_debug_assert(vece <= MO_64); - do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); -} - -void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs, - TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen2sh g = { - .fni4 = tcg_gen_rotl_i32, - .fni8 = tcg_gen_rotl_i64, - .fniv_s = tcg_gen_rotls_vec, - .fniv_v = tcg_gen_rotlv_vec, - .fno = { - gen_helper_gvec_rotl8i, - gen_helper_gvec_rotl16i, - gen_helper_gvec_rotl32i, - gen_helper_gvec_rotl64i, - }, - .s_list = { INDEX_op_rotls_vec, 0 }, - .v_list = { INDEX_op_rotlv_vec, 0 }, - }; - - tcg_debug_assert(vece <= MO_64); - do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); -} - -/* - * Expand D = A << (B % element bits) - * - * Unlike scalar shifts, where it is easy for the target front end - * to include the modulo as part of the expansion. If the target - * naturally includes the modulo as part of the operation, great! - * If the target has some other behaviour from out-of-range shifts, - * then it could not use this function anyway, and would need to - * do it's own expansion with custom functions. - */ -static void tcg_gen_shlv_mod_vec(unsigned vece, TCGv_vec d, - TCGv_vec a, TCGv_vec b) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); - tcg_gen_and_vec(vece, t, t, b); - tcg_gen_shlv_vec(vece, d, a, t); - tcg_temp_free_vec(t); -} - -static void tcg_gen_shl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t, b, 31); - tcg_gen_shl_i32(d, a, t); - tcg_temp_free_i32(t); -} - -static void tcg_gen_shl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t, b, 63); - tcg_gen_shl_i64(d, a, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_shlv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_shlv_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_shlv_mod_vec, - .fno = gen_helper_gvec_shl8v, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_shlv_mod_vec, - .fno = gen_helper_gvec_shl16v, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_shl_mod_i32, - .fniv = tcg_gen_shlv_mod_vec, - .fno = gen_helper_gvec_shl32v, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_shl_mod_i64, - .fniv = tcg_gen_shlv_mod_vec, - .fno = gen_helper_gvec_shl64v, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -/* - * Similarly for logical right shifts. - */ - -static void tcg_gen_shrv_mod_vec(unsigned vece, TCGv_vec d, - TCGv_vec a, TCGv_vec b) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); - tcg_gen_and_vec(vece, t, t, b); - tcg_gen_shrv_vec(vece, d, a, t); - tcg_temp_free_vec(t); -} - -static void tcg_gen_shr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t, b, 31); - tcg_gen_shr_i32(d, a, t); - tcg_temp_free_i32(t); -} - -static void tcg_gen_shr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t, b, 63); - tcg_gen_shr_i64(d, a, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_shrv_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_shrv_mod_vec, - .fno = gen_helper_gvec_shr8v, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_shrv_mod_vec, - .fno = gen_helper_gvec_shr16v, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_shr_mod_i32, - .fniv = tcg_gen_shrv_mod_vec, - .fno = gen_helper_gvec_shr32v, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_shr_mod_i64, - .fniv = tcg_gen_shrv_mod_vec, - .fno = gen_helper_gvec_shr64v, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -/* - * Similarly for arithmetic right shifts. - */ - -static void tcg_gen_sarv_mod_vec(unsigned vece, TCGv_vec d, - TCGv_vec a, TCGv_vec b) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); - tcg_gen_and_vec(vece, t, t, b); - tcg_gen_sarv_vec(vece, d, a, t); - tcg_temp_free_vec(t); -} - -static void tcg_gen_sar_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t, b, 31); - tcg_gen_sar_i32(d, a, t); - tcg_temp_free_i32(t); -} - -static void tcg_gen_sar_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t, b, 63); - tcg_gen_sar_i64(d, a, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_sarv_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_sarv_mod_vec, - .fno = gen_helper_gvec_sar8v, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_sarv_mod_vec, - .fno = gen_helper_gvec_sar16v, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_sar_mod_i32, - .fniv = tcg_gen_sarv_mod_vec, - .fno = gen_helper_gvec_sar32v, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_sar_mod_i64, - .fniv = tcg_gen_sarv_mod_vec, - .fno = gen_helper_gvec_sar64v, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -/* - * Similarly for rotates. - */ - -static void tcg_gen_rotlv_mod_vec(unsigned vece, TCGv_vec d, - TCGv_vec a, TCGv_vec b) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); - tcg_gen_and_vec(vece, t, t, b); - tcg_gen_rotlv_vec(vece, d, a, t); - tcg_temp_free_vec(t); -} - -static void tcg_gen_rotl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t, b, 31); - tcg_gen_rotl_i32(d, a, t); - tcg_temp_free_i32(t); -} - -static void tcg_gen_rotl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t, b, 63); - tcg_gen_rotl_i64(d, a, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_rotlv_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_rotlv_mod_vec, - .fno = gen_helper_gvec_rotl8v, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_rotlv_mod_vec, - .fno = gen_helper_gvec_rotl16v, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_rotl_mod_i32, - .fniv = tcg_gen_rotlv_mod_vec, - .fno = gen_helper_gvec_rotl32v, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_rotl_mod_i64, - .fniv = tcg_gen_rotlv_mod_vec, - .fno = gen_helper_gvec_rotl64v, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -static void tcg_gen_rotrv_mod_vec(unsigned vece, TCGv_vec d, - TCGv_vec a, TCGv_vec b) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); - tcg_gen_and_vec(vece, t, t, b); - tcg_gen_rotrv_vec(vece, d, a, t); - tcg_temp_free_vec(t); -} - -static void tcg_gen_rotr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t, b, 31); - tcg_gen_rotr_i32(d, a, t); - tcg_temp_free_i32(t); -} - -static void tcg_gen_rotr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t, b, 63); - tcg_gen_rotr_i64(d, a, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode vecop_list[] = { INDEX_op_rotrv_vec, 0 }; - static const GVecGen3 g[4] = { - { .fniv = tcg_gen_rotrv_mod_vec, - .fno = gen_helper_gvec_rotr8v, - .opt_opc = vecop_list, - .vece = MO_8 }, - { .fniv = tcg_gen_rotrv_mod_vec, - .fno = gen_helper_gvec_rotr16v, - .opt_opc = vecop_list, - .vece = MO_16 }, - { .fni4 = tcg_gen_rotr_mod_i32, - .fniv = tcg_gen_rotrv_mod_vec, - .fno = gen_helper_gvec_rotr32v, - .opt_opc = vecop_list, - .vece = MO_32 }, - { .fni8 = tcg_gen_rotr_mod_i64, - .fniv = tcg_gen_rotrv_mod_vec, - .fno = gen_helper_gvec_rotr64v, - .opt_opc = vecop_list, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .vece = MO_64 }, - }; - - tcg_debug_assert(vece <= MO_64); - tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); -} - -/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ -static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, TCGCond cond) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - uint32_t i; - - for (i = 0; i < oprsz; i += 4) { - tcg_gen_ld_i32(t0, cpu_env, aofs + i); - tcg_gen_ld_i32(t1, cpu_env, bofs + i); - tcg_gen_setcond_i32(cond, t0, t0, t1); - tcg_gen_neg_i32(t0, t0); - tcg_gen_st_i32(t0, cpu_env, dofs + i); - } - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, TCGCond cond) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - uint32_t i; - - for (i = 0; i < oprsz; i += 8) { - tcg_gen_ld_i64(t0, cpu_env, aofs + i); - tcg_gen_ld_i64(t1, cpu_env, bofs + i); - tcg_gen_setcond_i64(cond, t0, t0, t1); - tcg_gen_neg_i64(t0, t0); - tcg_gen_st_i64(t0, cpu_env, dofs + i); - } - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t0); -} - -static void expand_cmp_vec(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t oprsz, uint32_t tysz, - TCGType type, TCGCond cond) -{ - TCGv_vec t0 = tcg_temp_new_vec(type); - TCGv_vec t1 = tcg_temp_new_vec(type); - uint32_t i; - - for (i = 0; i < oprsz; i += tysz) { - tcg_gen_ld_vec(t0, cpu_env, aofs + i); - tcg_gen_ld_vec(t1, cpu_env, bofs + i); - tcg_gen_cmp_vec(cond, vece, t0, t0, t1); - tcg_gen_st_vec(t0, cpu_env, dofs + i); - } - tcg_temp_free_vec(t1); - tcg_temp_free_vec(t0); -} - -void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs, - uint32_t aofs, uint32_t bofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const TCGOpcode cmp_list[] = { INDEX_op_cmp_vec, 0 }; - static gen_helper_gvec_3 * const eq_fn[4] = { - gen_helper_gvec_eq8, gen_helper_gvec_eq16, - gen_helper_gvec_eq32, gen_helper_gvec_eq64 - }; - static gen_helper_gvec_3 * const ne_fn[4] = { - gen_helper_gvec_ne8, gen_helper_gvec_ne16, - gen_helper_gvec_ne32, gen_helper_gvec_ne64 - }; - static gen_helper_gvec_3 * const lt_fn[4] = { - gen_helper_gvec_lt8, gen_helper_gvec_lt16, - gen_helper_gvec_lt32, gen_helper_gvec_lt64 - }; - static gen_helper_gvec_3 * const le_fn[4] = { - gen_helper_gvec_le8, gen_helper_gvec_le16, - gen_helper_gvec_le32, gen_helper_gvec_le64 - }; - static gen_helper_gvec_3 * const ltu_fn[4] = { - gen_helper_gvec_ltu8, gen_helper_gvec_ltu16, - gen_helper_gvec_ltu32, gen_helper_gvec_ltu64 - }; - static gen_helper_gvec_3 * const leu_fn[4] = { - gen_helper_gvec_leu8, gen_helper_gvec_leu16, - gen_helper_gvec_leu32, gen_helper_gvec_leu64 - }; - static gen_helper_gvec_3 * const * const fns[16] = { - [TCG_COND_EQ] = eq_fn, - [TCG_COND_NE] = ne_fn, - [TCG_COND_LT] = lt_fn, - [TCG_COND_LE] = le_fn, - [TCG_COND_LTU] = ltu_fn, - [TCG_COND_LEU] = leu_fn, - }; - - const TCGOpcode *hold_list; - TCGType type; - uint32_t some; - - check_size_align(oprsz, maxsz, dofs | aofs | bofs); - check_overlap_3(dofs, aofs, bofs, maxsz); - - if (cond == TCG_COND_NEVER || cond == TCG_COND_ALWAYS) { - do_dup(MO_8, dofs, oprsz, maxsz, - NULL, NULL, -(cond == TCG_COND_ALWAYS)); - return; - } - - /* - * Implement inline with a vector type, if possible. - * Prefer integer when 64-bit host and 64-bit comparison. - */ - hold_list = tcg_swap_vecop_list(cmp_list); - type = choose_vector_type(cmp_list, vece, oprsz, - TCG_TARGET_REG_BITS == 64 && vece == MO_64); - switch (type) { - case TCG_TYPE_V256: - /* Recall that ARM SVE allows vector sizes that are not a - * power of 2, but always a multiple of 16. The intent is - * that e.g. size == 80 would be expanded with 2x32 + 1x16. - */ - some = QEMU_ALIGN_DOWN(oprsz, 32); - expand_cmp_vec(vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, cond); - if (some == oprsz) { - break; - } - dofs += some; - aofs += some; - bofs += some; - oprsz -= some; - maxsz -= some; - /* fallthru */ - case TCG_TYPE_V128: - expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, cond); - break; - case TCG_TYPE_V64: - expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, cond); - break; - - case 0: - if (vece == MO_64 && check_size_impl(oprsz, 8)) { - expand_cmp_i64(dofs, aofs, bofs, oprsz, cond); - } else if (vece == MO_32 && check_size_impl(oprsz, 4)) { - expand_cmp_i32(dofs, aofs, bofs, oprsz, cond); - } else { - gen_helper_gvec_3 * const *fn = fns[cond]; - - if (fn == NULL) { - uint32_t tmp; - tmp = aofs, aofs = bofs, bofs = tmp; - cond = tcg_swap_cond(cond); - fn = fns[cond]; - assert(fn != NULL); - } - tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, 0, fn[vece]); - oprsz = maxsz; - } - break; - - default: - g_assert_not_reached(); - } - tcg_swap_vecop_list(hold_list); - - if (oprsz < maxsz) { - expand_clr(dofs + oprsz, maxsz - oprsz); - } -} - -static void tcg_gen_bitsel_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - tcg_gen_and_i64(t, b, a); - tcg_gen_andc_i64(d, c, a); - tcg_gen_or_i64(d, d, t); - tcg_temp_free_i64(t); -} - -void tcg_gen_gvec_bitsel(unsigned vece, uint32_t dofs, uint32_t aofs, - uint32_t bofs, uint32_t cofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen4 g = { - .fni8 = tcg_gen_bitsel_i64, - .fniv = tcg_gen_bitsel_vec, - .fno = gen_helper_gvec_bitsel, - }; - - tcg_gen_gvec_4(dofs, aofs, bofs, cofs, oprsz, maxsz, &g); -} +/* + * Generic vector operation expansion + * + * Copyright (c) 2018 Linaro + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "tcg/tcg.h" +#include "tcg/tcg-op.h" +#include "tcg/tcg-op-gvec.h" +#include "qemu/main-loop.h" +#include "tcg/tcg-gvec-desc.h" + +#define MAX_UNROLL 4 + +#ifdef CONFIG_DEBUG_TCG +static const TCGOpcode vecop_list_empty[1] = { 0 }; +#else +#define vecop_list_empty NULL +#endif + + +/* Verify vector size and alignment rules. OFS should be the OR of all + of the operand offsets so that we can check them all at once. */ +static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs) +{ + uint32_t opr_align = oprsz >= 16 ? 15 : 7; + uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7; + tcg_debug_assert(oprsz > 0); + tcg_debug_assert(oprsz <= maxsz); + tcg_debug_assert((oprsz & opr_align) == 0); + tcg_debug_assert((maxsz & max_align) == 0); + tcg_debug_assert((ofs & max_align) == 0); +} + +/* Verify vector overlap rules for two operands. */ +static void check_overlap_2(uint32_t d, uint32_t a, uint32_t s) +{ + tcg_debug_assert(d == a || d + s <= a || a + s <= d); +} + +/* Verify vector overlap rules for three operands. */ +static void check_overlap_3(uint32_t d, uint32_t a, uint32_t b, uint32_t s) +{ + check_overlap_2(d, a, s); + check_overlap_2(d, b, s); + check_overlap_2(a, b, s); +} + +/* Verify vector overlap rules for four operands. */ +static void check_overlap_4(uint32_t d, uint32_t a, uint32_t b, + uint32_t c, uint32_t s) +{ + check_overlap_2(d, a, s); + check_overlap_2(d, b, s); + check_overlap_2(d, c, s); + check_overlap_2(a, b, s); + check_overlap_2(a, c, s); + check_overlap_2(b, c, s); +} + +/* Create a descriptor from components. */ +uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data) +{ + uint32_t desc = 0; + + assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS)); + assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS)); + assert(data == sextract32(data, 0, SIMD_DATA_BITS)); + + oprsz = (oprsz / 8) - 1; + maxsz = (maxsz / 8) - 1; + desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz); + desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz); + desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data); + + return desc; +} + +/* Generate a call to a gvec-style helper with two vector operands. */ +void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz, int32_t data, + gen_helper_gvec_2 *fn) +{ + TCGv_ptr a0, a1; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + + fn(a0, a1, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with two vector operands + and one scalar operand. */ +void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c, + uint32_t oprsz, uint32_t maxsz, int32_t data, + gen_helper_gvec_2i *fn) +{ + TCGv_ptr a0, a1; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + + fn(a0, a1, c, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with three vector operands. */ +void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz, int32_t data, + gen_helper_gvec_3 *fn) +{ + TCGv_ptr a0, a1, a2; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + + fn(a0, a1, a2, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with four vector operands. */ +void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, uint32_t oprsz, uint32_t maxsz, + int32_t data, gen_helper_gvec_4 *fn) +{ + TCGv_ptr a0, a1, a2, a3; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + a3 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + tcg_gen_addi_ptr(a3, cpu_env, cofs); + + fn(a0, a1, a2, a3, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_ptr(a3); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with five vector operands. */ +void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, uint32_t xofs, uint32_t oprsz, + uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn) +{ + TCGv_ptr a0, a1, a2, a3, a4; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + a3 = tcg_temp_new_ptr(); + a4 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + tcg_gen_addi_ptr(a3, cpu_env, cofs); + tcg_gen_addi_ptr(a4, cpu_env, xofs); + + fn(a0, a1, a2, a3, a4, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_ptr(a3); + tcg_temp_free_ptr(a4); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with three vector operands + and an extra pointer operand. */ +void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs, + TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, + int32_t data, gen_helper_gvec_2_ptr *fn) +{ + TCGv_ptr a0, a1; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + + fn(a0, a1, ptr, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with three vector operands + and an extra pointer operand. */ +void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, + TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, + int32_t data, gen_helper_gvec_3_ptr *fn) +{ + TCGv_ptr a0, a1, a2; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + + fn(a0, a1, a2, ptr, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with four vector operands + and an extra pointer operand. */ +void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz, + uint32_t maxsz, int32_t data, + gen_helper_gvec_4_ptr *fn) +{ + TCGv_ptr a0, a1, a2, a3; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + a3 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + tcg_gen_addi_ptr(a3, cpu_env, cofs); + + fn(a0, a1, a2, a3, ptr, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_ptr(a3); + tcg_temp_free_i32(desc); +} + +/* Generate a call to a gvec-style helper with five vector operands + and an extra pointer operand. */ +void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, uint32_t eofs, TCGv_ptr ptr, + uint32_t oprsz, uint32_t maxsz, int32_t data, + gen_helper_gvec_5_ptr *fn) +{ + TCGv_ptr a0, a1, a2, a3, a4; + TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data)); + + a0 = tcg_temp_new_ptr(); + a1 = tcg_temp_new_ptr(); + a2 = tcg_temp_new_ptr(); + a3 = tcg_temp_new_ptr(); + a4 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + tcg_gen_addi_ptr(a2, cpu_env, bofs); + tcg_gen_addi_ptr(a3, cpu_env, cofs); + tcg_gen_addi_ptr(a4, cpu_env, eofs); + + fn(a0, a1, a2, a3, a4, ptr, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_ptr(a2); + tcg_temp_free_ptr(a3); + tcg_temp_free_ptr(a4); + tcg_temp_free_i32(desc); +} + +/* Return true if we want to implement something of OPRSZ bytes + in units of LNSZ. This limits the expansion of inline code. */ +static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz) +{ + uint32_t q, r; + + if (oprsz < lnsz) { + return false; + } + + q = oprsz / lnsz; + r = oprsz % lnsz; + tcg_debug_assert((r & 7) == 0); + + if (lnsz < 16) { + /* For sizes below 16, accept no remainder. */ + if (r != 0) { + return false; + } + } else { + /* + * Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + * In addition, expand_clr needs to handle a multiple of 8. + * Thus we can handle the tail with one more operation per + * diminishing power of 2. + */ + q += ctpop32(r); + } + + return q <= MAX_UNROLL; +} + +static void expand_clr(uint32_t dofs, uint32_t maxsz); + +/* Duplicate C as per VECE. */ +uint64_t dup_const_eval(unsigned vece, uint64_t c) +{ + switch (vece) { + case MO_8: + return 0x0101010101010101ull * (uint8_t)c; + case MO_16: + return 0x0001000100010001ull * (uint16_t)c; + case MO_32: + return 0x0000000100000001ull * (uint32_t)c; + case MO_64: + return c; + default: + g_assert_not_reached(); + } +} + +/* Duplicate IN into OUT as per VECE. */ +static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in) +{ + switch (vece) { + case MO_8: + tcg_gen_ext8u_i32(out, in); + tcg_gen_muli_i32(out, out, 0x01010101); + break; + case MO_16: + tcg_gen_deposit_i32(out, in, in, 16, 16); + break; + case MO_32: + tcg_gen_mov_i32(out, in); + break; + default: + g_assert_not_reached(); + } +} + +static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in) +{ + switch (vece) { + case MO_8: + tcg_gen_ext8u_i64(out, in); + tcg_gen_muli_i64(out, out, 0x0101010101010101ull); + break; + case MO_16: + tcg_gen_ext16u_i64(out, in); + tcg_gen_muli_i64(out, out, 0x0001000100010001ull); + break; + case MO_32: + tcg_gen_deposit_i64(out, in, in, 32, 32); + break; + case MO_64: + tcg_gen_mov_i64(out, in); + break; + default: + g_assert_not_reached(); + } +} + +/* Select a supported vector type for implementing an operation on SIZE + * bytes. If OP is 0, assume that the real operation to be performed is + * required by all backends. Otherwise, make sure than OP can be performed + * on elements of size VECE in the selected type. Do not select V64 if + * PREFER_I64 is true. Return 0 if no vector type is selected. + */ +static TCGType choose_vector_type(const TCGOpcode *list, unsigned vece, + uint32_t size, bool prefer_i64) +{ + /* + * Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + * It is hard to imagine a case in which v256 is supported + * but v128 is not, but check anyway. + * In addition, expand_clr needs to handle a multiple of 8. + */ + if (TCG_TARGET_HAS_v256 && + check_size_impl(size, 32) && + tcg_can_emit_vecop_list(list, TCG_TYPE_V256, vece) && + (!(size & 16) || + (TCG_TARGET_HAS_v128 && + tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece))) && + (!(size & 8) || + (TCG_TARGET_HAS_v64 && + tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { + return TCG_TYPE_V256; + } + if (TCG_TARGET_HAS_v128 && + check_size_impl(size, 16) && + tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece) && + (!(size & 8) || + (TCG_TARGET_HAS_v64 && + tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { + return TCG_TYPE_V128; + } + if (TCG_TARGET_HAS_v64 && !prefer_i64 && check_size_impl(size, 8) + && tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)) { + return TCG_TYPE_V64; + } + return 0; +} + +static void do_dup_store(TCGType type, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, TCGv_vec t_vec) +{ + uint32_t i = 0; + + tcg_debug_assert(oprsz >= 8); + + /* + * This may be expand_clr for the tail of an operation, e.g. + * oprsz == 8 && maxsz == 64. The first 8 bytes of this store + * are misaligned wrt the maximum vector size, so do that first. + */ + if (dofs & 8) { + tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64); + i += 8; + } + + switch (type) { + case TCG_TYPE_V256: + /* + * Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + for (; i + 32 <= oprsz; i += 32) { + tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V256); + } + /* fallthru */ + case TCG_TYPE_V128: + for (; i + 16 <= oprsz; i += 16) { + tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V128); + } + break; + case TCG_TYPE_V64: + for (; i < oprsz; i += 8) { + tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64); + } + break; + default: + g_assert_not_reached(); + } + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Set OPRSZ bytes at DOFS to replications of IN_32, IN_64 or IN_C. + * Only one of IN_32 or IN_64 may be set; + * IN_C is used if IN_32 and IN_64 are unset. + */ +static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, TCGv_i32 in_32, TCGv_i64 in_64, + uint64_t in_c) +{ + TCGType type; + TCGv_i64 t_64; + TCGv_i32 t_32, t_desc; + TCGv_ptr t_ptr; + uint32_t i; + + assert(vece <= (in_32 ? MO_32 : MO_64)); + assert(in_32 == NULL || in_64 == NULL); + + /* If we're storing 0, expand oprsz to maxsz. */ + if (in_32 == NULL && in_64 == NULL) { + in_c = dup_const(vece, in_c); + if (in_c == 0) { + oprsz = maxsz; + } + } + + /* Implement inline with a vector type, if possible. + * Prefer integer when 64-bit host and no variable dup. + */ + type = choose_vector_type(NULL, vece, oprsz, + (TCG_TARGET_REG_BITS == 64 && in_32 == NULL + && (in_64 == NULL || vece == MO_64))); + if (type != 0) { + TCGv_vec t_vec = tcg_temp_new_vec(type); + + if (in_32) { + tcg_gen_dup_i32_vec(vece, t_vec, in_32); + } else if (in_64) { + tcg_gen_dup_i64_vec(vece, t_vec, in_64); + } else { + tcg_gen_dupi_vec(vece, t_vec, in_c); + } + do_dup_store(type, dofs, oprsz, maxsz, t_vec); + tcg_temp_free_vec(t_vec); + return; + } + + /* Otherwise, inline with an integer type, unless "large". */ + if (check_size_impl(oprsz, TCG_TARGET_REG_BITS / 8)) { + t_64 = NULL; + t_32 = NULL; + + if (in_32) { + /* We are given a 32-bit variable input. For a 64-bit host, + use a 64-bit operation unless the 32-bit operation would + be simple enough. */ + if (TCG_TARGET_REG_BITS == 64 + && (vece != MO_32 || !check_size_impl(oprsz, 4))) { + t_64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t_64, in_32); + gen_dup_i64(vece, t_64, t_64); + } else { + t_32 = tcg_temp_new_i32(); + gen_dup_i32(vece, t_32, in_32); + } + } else if (in_64) { + /* We are given a 64-bit variable input. */ + t_64 = tcg_temp_new_i64(); + gen_dup_i64(vece, t_64, in_64); + } else { + /* We are given a constant input. */ + /* For 64-bit hosts, use 64-bit constants for "simple" constants + or when we'd need too many 32-bit stores, or when a 64-bit + constant is really required. */ + if (vece == MO_64 + || (TCG_TARGET_REG_BITS == 64 + && (in_c == 0 || in_c == -1 + || !check_size_impl(oprsz, 4)))) { + t_64 = tcg_const_i64(in_c); + } else { + t_32 = tcg_const_i32(in_c); + } + } + + /* Implement inline if we picked an implementation size above. */ + if (t_32) { + for (i = 0; i < oprsz; i += 4) { + tcg_gen_st_i32(t_32, cpu_env, dofs + i); + } + tcg_temp_free_i32(t_32); + goto done; + } + if (t_64) { + for (i = 0; i < oprsz; i += 8) { + tcg_gen_st_i64(t_64, cpu_env, dofs + i); + } + tcg_temp_free_i64(t_64); + goto done; + } + } + + /* Otherwise implement out of line. */ + t_ptr = tcg_temp_new_ptr(); + tcg_gen_addi_ptr(t_ptr, cpu_env, dofs); + t_desc = tcg_const_i32(simd_desc(oprsz, maxsz, 0)); + + if (vece == MO_64) { + if (in_64) { + gen_helper_gvec_dup64(t_ptr, t_desc, in_64); + } else { + t_64 = tcg_const_i64(in_c); + gen_helper_gvec_dup64(t_ptr, t_desc, t_64); + tcg_temp_free_i64(t_64); + } + } else { + typedef void dup_fn(TCGv_ptr, TCGv_i32, TCGv_i32); + static dup_fn * const fns[3] = { + gen_helper_gvec_dup8, + gen_helper_gvec_dup16, + gen_helper_gvec_dup32 + }; + + if (in_32) { + fns[vece](t_ptr, t_desc, in_32); + } else { + t_32 = tcg_temp_new_i32(); + if (in_64) { + tcg_gen_extrl_i64_i32(t_32, in_64); + } else if (vece == MO_8) { + tcg_gen_movi_i32(t_32, in_c & 0xff); + } else if (vece == MO_16) { + tcg_gen_movi_i32(t_32, in_c & 0xffff); + } else { + tcg_gen_movi_i32(t_32, in_c); + } + fns[vece](t_ptr, t_desc, t_32); + tcg_temp_free_i32(t_32); + } + } + + tcg_temp_free_ptr(t_ptr); + tcg_temp_free_i32(t_desc); + return; + + done: + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Likewise, but with zero. */ +static void expand_clr(uint32_t dofs, uint32_t maxsz) +{ + do_dup(MO_8, dofs, maxsz, maxsz, NULL, NULL, 0); +} + +/* Expand OPSZ bytes worth of two-operand operations using i32 elements. */ +static void expand_2_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + bool load_dest, void (*fni)(TCGv_i32, TCGv_i32)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_i32(t1, cpu_env, dofs + i); + } + fni(t1, t0); + tcg_gen_st_i32(t1, cpu_env, dofs + i); + } + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); +} + +static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + int32_t c, bool load_dest, + void (*fni)(TCGv_i32, TCGv_i32, int32_t)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_i32(t1, cpu_env, dofs + i); + } + fni(t1, t0, c); + tcg_gen_st_i32(t1, cpu_env, dofs + i); + } + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); +} + +static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + TCGv_i32 c, bool scalar_first, + void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + if (scalar_first) { + fni(t1, c, t0); + } else { + fni(t1, t0, c); + } + tcg_gen_st_i32(t1, cpu_env, dofs + i); + } + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); +} + +/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ +static void expand_3_i32(uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, bool load_dest, + void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + tcg_gen_ld_i32(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_i32(t2, cpu_env, dofs + i); + } + fni(t2, t0, t1); + tcg_gen_st_i32(t2, cpu_env, dofs + i); + } + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static void expand_3i_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, int32_t c, bool load_dest, + void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, int32_t)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + tcg_gen_ld_i32(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_i32(t2, cpu_env, dofs + i); + } + fni(t2, t0, t1, c); + tcg_gen_st_i32(t2, cpu_env, dofs + i); + } + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + +/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ +static void expand_4_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, uint32_t oprsz, bool write_aofs, + void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t1, cpu_env, aofs + i); + tcg_gen_ld_i32(t2, cpu_env, bofs + i); + tcg_gen_ld_i32(t3, cpu_env, cofs + i); + fni(t0, t1, t2, t3); + tcg_gen_st_i32(t0, cpu_env, dofs + i); + if (write_aofs) { + tcg_gen_st_i32(t1, cpu_env, aofs + i); + } + } + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +/* Expand OPSZ bytes worth of two-operand operations using i64 elements. */ +static void expand_2_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + bool load_dest, void (*fni)(TCGv_i64, TCGv_i64)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_i64(t1, cpu_env, dofs + i); + } + fni(t1, t0); + tcg_gen_st_i64(t1, cpu_env, dofs + i); + } + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + +static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + int64_t c, bool load_dest, + void (*fni)(TCGv_i64, TCGv_i64, int64_t)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_i64(t1, cpu_env, dofs + i); + } + fni(t1, t0, c); + tcg_gen_st_i64(t1, cpu_env, dofs + i); + } + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + +static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + TCGv_i64 c, bool scalar_first, + void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + if (scalar_first) { + fni(t1, c, t0); + } else { + fni(t1, t0, c); + } + tcg_gen_st_i64(t1, cpu_env, dofs + i); + } + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + +/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ +static void expand_3_i64(uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, bool load_dest, + void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + tcg_gen_ld_i64(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_i64(t2, cpu_env, dofs + i); + } + fni(t2, t0, t1); + tcg_gen_st_i64(t2, cpu_env, dofs + i); + } + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static void expand_3i_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, int64_t c, bool load_dest, + void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, int64_t)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + tcg_gen_ld_i64(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_i64(t2, cpu_env, dofs + i); + } + fni(t2, t0, t1, c); + tcg_gen_st_i64(t2, cpu_env, dofs + i); + } + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + +/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ +static void expand_4_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t cofs, uint32_t oprsz, bool write_aofs, + void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t1, cpu_env, aofs + i); + tcg_gen_ld_i64(t2, cpu_env, bofs + i); + tcg_gen_ld_i64(t3, cpu_env, cofs + i); + fni(t0, t1, t2, t3); + tcg_gen_st_i64(t0, cpu_env, dofs + i); + if (write_aofs) { + tcg_gen_st_i64(t1, cpu_env, aofs + i); + } + } + tcg_temp_free_i64(t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +/* Expand OPSZ bytes worth of two-operand operations using host vectors. */ +static void expand_2_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t tysz, TCGType type, + bool load_dest, + void (*fni)(unsigned, TCGv_vec, TCGv_vec)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_vec(t1, cpu_env, dofs + i); + } + fni(vece, t1, t0); + tcg_gen_st_vec(t1, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); + tcg_temp_free_vec(t1); +} + +/* Expand OPSZ bytes worth of two-vector operands and an immediate operand + using host vectors. */ +static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t tysz, TCGType type, + int64_t c, bool load_dest, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, int64_t)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + if (load_dest) { + tcg_gen_ld_vec(t1, cpu_env, dofs + i); + } + fni(vece, t1, t0, c); + tcg_gen_st_vec(t1, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); + tcg_temp_free_vec(t1); +} + +static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t tysz, TCGType type, + TCGv_vec c, bool scalar_first, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + if (scalar_first) { + fni(vece, t1, c, t0); + } else { + fni(vece, t1, t0, c); + } + tcg_gen_st_vec(t1, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); + tcg_temp_free_vec(t1); +} + +/* Expand OPSZ bytes worth of three-operand operations using host vectors. */ +static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, + uint32_t tysz, TCGType type, bool load_dest, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + TCGv_vec t2 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + tcg_gen_ld_vec(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_vec(t2, cpu_env, dofs + i); + } + fni(vece, t2, t0, t1); + tcg_gen_st_vec(t2, cpu_env, dofs + i); + } + tcg_temp_free_vec(t2); + tcg_temp_free_vec(t1); + tcg_temp_free_vec(t0); +} + +/* + * Expand OPSZ bytes worth of three-vector operands and an immediate operand + * using host vectors. + */ +static void expand_3i_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t tysz, + TCGType type, int64_t c, bool load_dest, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, + int64_t)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + TCGv_vec t2 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + tcg_gen_ld_vec(t1, cpu_env, bofs + i); + if (load_dest) { + tcg_gen_ld_vec(t2, cpu_env, dofs + i); + } + fni(vece, t2, t0, t1, c); + tcg_gen_st_vec(t2, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); + tcg_temp_free_vec(t1); + tcg_temp_free_vec(t2); +} + +/* Expand OPSZ bytes worth of four-operand operations using host vectors. */ +static void expand_4_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t cofs, uint32_t oprsz, + uint32_t tysz, TCGType type, bool write_aofs, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, + TCGv_vec, TCGv_vec)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + TCGv_vec t2 = tcg_temp_new_vec(type); + TCGv_vec t3 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t1, cpu_env, aofs + i); + tcg_gen_ld_vec(t2, cpu_env, bofs + i); + tcg_gen_ld_vec(t3, cpu_env, cofs + i); + fni(vece, t0, t1, t2, t3); + tcg_gen_st_vec(t0, cpu_env, dofs + i); + if (write_aofs) { + tcg_gen_st_vec(t1, cpu_env, aofs + i); + } + } + tcg_temp_free_vec(t3); + tcg_temp_free_vec(t2); + tcg_temp_free_vec(t1); + tcg_temp_free_vec(t0); +} + +/* Expand a vector two-operand operation. */ +void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz, const GVecGen2 *g) +{ + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs); + check_overlap_2(dofs, aofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_2_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, + g->load_dest, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_2_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, + g->load_dest, g->fniv); + break; + case TCG_TYPE_V64: + expand_2_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, + g->load_dest, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { + expand_2_i64(dofs, aofs, oprsz, g->load_dest, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + expand_2_i32(dofs, aofs, oprsz, g->load_dest, g->fni4); + } else { + assert(g->fno != NULL); + tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, g->data, g->fno); + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Expand a vector operation with two vectors and an immediate. */ +void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + uint32_t maxsz, int64_t c, const GVecGen2i *g) +{ + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs); + check_overlap_2(dofs, aofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_2i_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, + c, g->load_dest, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_2i_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, + c, g->load_dest, g->fniv); + break; + case TCG_TYPE_V64: + expand_2i_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, + c, g->load_dest, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { + expand_2i_i64(dofs, aofs, oprsz, c, g->load_dest, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + expand_2i_i32(dofs, aofs, oprsz, c, g->load_dest, g->fni4); + } else { + if (g->fno) { + tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno); + } else { + TCGv_i64 tcg_c = tcg_const_i64(c); + tcg_gen_gvec_2i_ool(dofs, aofs, tcg_c, oprsz, + maxsz, c, g->fnoi); + tcg_temp_free_i64(tcg_c); + } + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Expand a vector operation with two vectors and a scalar. */ +void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, + uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g) +{ + TCGType type; + + check_size_align(oprsz, maxsz, dofs | aofs); + check_overlap_2(dofs, aofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + if (type != 0) { + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGv_vec t_vec = tcg_temp_new_vec(type); + uint32_t some; + + tcg_gen_dup_i64_vec(g->vece, t_vec, c); + + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_2s_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, + t_vec, g->scalar_first, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + + case TCG_TYPE_V128: + expand_2s_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, + t_vec, g->scalar_first, g->fniv); + break; + + case TCG_TYPE_V64: + expand_2s_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, + t_vec, g->scalar_first, g->fniv); + break; + + default: + g_assert_not_reached(); + } + tcg_temp_free_vec(t_vec); + tcg_swap_vecop_list(hold_list); + } else if (g->fni8 && check_size_impl(oprsz, 8)) { + TCGv_i64 t64 = tcg_temp_new_i64(); + + gen_dup_i64(g->vece, t64, c); + expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8); + tcg_temp_free_i64(t64); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + TCGv_i32 t32 = tcg_temp_new_i32(); + + tcg_gen_extrl_i64_i32(t32, c); + gen_dup_i32(g->vece, t32, t32); + expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4); + tcg_temp_free_i32(t32); + } else { + tcg_gen_gvec_2i_ool(dofs, aofs, c, oprsz, maxsz, 0, g->fno); + return; + } + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Expand a vector three-operand operation. */ +void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g) +{ + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs | bofs); + check_overlap_3(dofs, aofs, bofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_3_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, + g->load_dest, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + bofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, + g->load_dest, g->fniv); + break; + case TCG_TYPE_V64: + expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, + g->load_dest, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { + expand_3_i64(dofs, aofs, bofs, oprsz, g->load_dest, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + expand_3_i32(dofs, aofs, bofs, oprsz, g->load_dest, g->fni4); + } else { + assert(g->fno != NULL); + tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, + maxsz, g->data, g->fno); + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Expand a vector operation with three vectors and an immediate. */ +void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz, int64_t c, + const GVecGen3i *g) +{ + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs | bofs); + check_overlap_3(dofs, aofs, bofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + switch (type) { + case TCG_TYPE_V256: + /* + * Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_3i_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, + c, g->load_dest, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + bofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, + c, g->load_dest, g->fniv); + break; + case TCG_TYPE_V64: + expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, + c, g->load_dest, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { + expand_3i_i64(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + expand_3i_i32(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni4); + } else { + assert(g->fno != NULL); + tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, c, g->fno); + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* Expand a vector four-operand operation. */ +void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, + uint32_t oprsz, uint32_t maxsz, const GVecGen4 *g) +{ + const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; + const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list); + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs | bofs | cofs); + check_overlap_4(dofs, aofs, bofs, cofs, maxsz); + + type = 0; + if (g->fniv) { + type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64); + } + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_4_vec(g->vece, dofs, aofs, bofs, cofs, some, + 32, TCG_TYPE_V256, g->write_aofs, g->fniv); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + bofs += some; + cofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz, + 16, TCG_TYPE_V128, g->write_aofs, g->fniv); + break; + case TCG_TYPE_V64: + expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz, + 8, TCG_TYPE_V64, g->write_aofs, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { + expand_4_i64(dofs, aofs, bofs, cofs, oprsz, + g->write_aofs, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { + expand_4_i32(dofs, aofs, bofs, cofs, oprsz, + g->write_aofs, g->fni4); + } else { + assert(g->fno != NULL); + tcg_gen_gvec_4_ool(dofs, aofs, bofs, cofs, + oprsz, maxsz, g->data, g->fno); + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +/* + * Expand specific vector operations. + */ + +static void vec_mov2(unsigned vece, TCGv_vec a, TCGv_vec b) +{ + tcg_gen_mov_vec(a, b); +} + +void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2 g = { + .fni8 = tcg_gen_mov_i64, + .fniv = vec_mov2, + .fno = gen_helper_gvec_mov, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + if (dofs != aofs) { + tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g); + } else { + check_size_align(oprsz, maxsz, dofs); + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } + } +} + +void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, TCGv_i32 in) +{ + check_size_align(oprsz, maxsz, dofs); + tcg_debug_assert(vece <= MO_32); + do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0); +} + +void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, TCGv_i64 in) +{ + check_size_align(oprsz, maxsz, dofs); + tcg_debug_assert(vece <= MO_64); + do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0); +} + +void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) +{ + check_size_align(oprsz, maxsz, dofs); + if (vece <= MO_64) { + TCGType type = choose_vector_type(NULL, vece, oprsz, 0); + if (type != 0) { + TCGv_vec t_vec = tcg_temp_new_vec(type); + tcg_gen_dup_mem_vec(vece, t_vec, cpu_env, aofs); + do_dup_store(type, dofs, oprsz, maxsz, t_vec); + tcg_temp_free_vec(t_vec); + } else if (vece <= MO_32) { + TCGv_i32 in = tcg_temp_new_i32(); + switch (vece) { + case MO_8: + tcg_gen_ld8u_i32(in, cpu_env, aofs); + break; + case MO_16: + tcg_gen_ld16u_i32(in, cpu_env, aofs); + break; + default: + tcg_gen_ld_i32(in, cpu_env, aofs); + break; + } + do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0); + tcg_temp_free_i32(in); + } else { + TCGv_i64 in = tcg_temp_new_i64(); + tcg_gen_ld_i64(in, cpu_env, aofs); + do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0); + tcg_temp_free_i64(in); + } + } else { + /* 128-bit duplicate. */ + /* ??? Dup to 256-bit vector. */ + int i; + + tcg_debug_assert(vece == 4); + tcg_debug_assert(oprsz >= 16); + if (TCG_TARGET_HAS_v128) { + TCGv_vec in = tcg_temp_new_vec(TCG_TYPE_V128); + + tcg_gen_ld_vec(in, cpu_env, aofs); + for (i = 0; i < oprsz; i += 16) { + tcg_gen_st_vec(in, cpu_env, dofs + i); + } + tcg_temp_free_vec(in); + } else { + TCGv_i64 in0 = tcg_temp_new_i64(); + TCGv_i64 in1 = tcg_temp_new_i64(); + + tcg_gen_ld_i64(in0, cpu_env, aofs); + tcg_gen_ld_i64(in1, cpu_env, aofs + 8); + for (i = 0; i < oprsz; i += 16) { + tcg_gen_st_i64(in0, cpu_env, dofs + i); + tcg_gen_st_i64(in1, cpu_env, dofs + i + 8); + } + tcg_temp_free_i64(in0); + tcg_temp_free_i64(in1); + } + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } + } +} + +void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, uint64_t x) +{ + check_size_align(oprsz, maxsz, dofs); + do_dup(vece, dofs, oprsz, maxsz, NULL, NULL, x); +} + +void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2 g = { + .fni8 = tcg_gen_not_i64, + .fniv = tcg_gen_not_vec, + .fno = gen_helper_gvec_not, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g); +} + +/* Perform a vector addition using normal addition and a mask. The mask + should be the sign bit of each lane. This 6-operation form is more + efficient than separate additions when there are 4 or more lanes in + the 64-bit operation. */ +static void gen_addv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_andc_i64(t1, a, m); + tcg_gen_andc_i64(t2, b, m); + tcg_gen_xor_i64(t3, a, b); + tcg_gen_add_i64(d, t1, t2); + tcg_gen_and_i64(t3, t3, m); + tcg_gen_xor_i64(d, d, t3); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); + gen_addv_mask(d, a, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); + gen_addv_mask(d, a, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t1, a, ~0xffffffffull); + tcg_gen_add_i64(t2, a, b); + tcg_gen_add_i64(t1, t1, b); + tcg_gen_deposit_i64(d, t1, t2, 0, 32); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + +static const TCGOpcode vecop_list_add[] = { INDEX_op_add_vec, 0 }; + +void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g[4] = { + { .fni8 = tcg_gen_vec_add8_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_add8, + .opt_opc = vecop_list_add, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_add16_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_add16, + .opt_opc = vecop_list_add, + .vece = MO_16 }, + { .fni4 = tcg_gen_add_i32, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_add32, + .opt_opc = vecop_list_add, + .vece = MO_32 }, + { .fni8 = tcg_gen_add_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_add64, + .opt_opc = vecop_list_add, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2s g[4] = { + { .fni8 = tcg_gen_vec_add8_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_adds8, + .opt_opc = vecop_list_add, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_add16_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_adds16, + .opt_opc = vecop_list_add, + .vece = MO_16 }, + { .fni4 = tcg_gen_add_i32, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_adds32, + .opt_opc = vecop_list_add, + .vece = MO_32 }, + { .fni8 = tcg_gen_add_i64, + .fniv = tcg_gen_add_vec, + .fno = gen_helper_gvec_adds64, + .opt_opc = vecop_list_add, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); +} + +void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(c); + tcg_gen_gvec_adds(vece, dofs, aofs, tmp, oprsz, maxsz); + tcg_temp_free_i64(tmp); +} + +static const TCGOpcode vecop_list_sub[] = { INDEX_op_sub_vec, 0 }; + +void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2s g[4] = { + { .fni8 = tcg_gen_vec_sub8_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_subs8, + .opt_opc = vecop_list_sub, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_sub16_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_subs16, + .opt_opc = vecop_list_sub, + .vece = MO_16 }, + { .fni4 = tcg_gen_sub_i32, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_subs32, + .opt_opc = vecop_list_sub, + .vece = MO_32 }, + { .fni8 = tcg_gen_sub_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_subs64, + .opt_opc = vecop_list_sub, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); +} + +/* Perform a vector subtraction using normal subtraction and a mask. + Compare gen_addv_mask above. */ +static void gen_subv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_or_i64(t1, a, m); + tcg_gen_andc_i64(t2, b, m); + tcg_gen_eqv_i64(t3, a, b); + tcg_gen_sub_i64(d, t1, t2); + tcg_gen_and_i64(t3, t3, m); + tcg_gen_xor_i64(d, d, t3); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); + gen_subv_mask(d, a, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); + gen_subv_mask(d, a, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t1, b, ~0xffffffffull); + tcg_gen_sub_i64(t2, a, b); + tcg_gen_sub_i64(t1, a, t1); + tcg_gen_deposit_i64(d, t1, t2, 0, 32); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + +void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g[4] = { + { .fni8 = tcg_gen_vec_sub8_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_sub8, + .opt_opc = vecop_list_sub, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_sub16_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_sub16, + .opt_opc = vecop_list_sub, + .vece = MO_16 }, + { .fni4 = tcg_gen_sub_i32, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_sub32, + .opt_opc = vecop_list_sub, + .vece = MO_32 }, + { .fni8 = tcg_gen_sub_i64, + .fniv = tcg_gen_sub_vec, + .fno = gen_helper_gvec_sub64, + .opt_opc = vecop_list_sub, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +static const TCGOpcode vecop_list_mul[] = { INDEX_op_mul_vec, 0 }; + +void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_mul8, + .opt_opc = vecop_list_mul, + .vece = MO_8 }, + { .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_mul16, + .opt_opc = vecop_list_mul, + .vece = MO_16 }, + { .fni4 = tcg_gen_mul_i32, + .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_mul32, + .opt_opc = vecop_list_mul, + .vece = MO_32 }, + { .fni8 = tcg_gen_mul_i64, + .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_mul64, + .opt_opc = vecop_list_mul, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2s g[4] = { + { .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_muls8, + .opt_opc = vecop_list_mul, + .vece = MO_8 }, + { .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_muls16, + .opt_opc = vecop_list_mul, + .vece = MO_16 }, + { .fni4 = tcg_gen_mul_i32, + .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_muls32, + .opt_opc = vecop_list_mul, + .vece = MO_32 }, + { .fni8 = tcg_gen_mul_i64, + .fniv = tcg_gen_mul_vec, + .fno = gen_helper_gvec_muls64, + .opt_opc = vecop_list_mul, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]); +} + +void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(c); + tcg_gen_gvec_muls(vece, dofs, aofs, tmp, oprsz, maxsz); + tcg_temp_free_i64(tmp); +} + +void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_ssadd_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_ssadd_vec, + .fno = gen_helper_gvec_ssadd8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_ssadd_vec, + .fno = gen_helper_gvec_ssadd16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fniv = tcg_gen_ssadd_vec, + .fno = gen_helper_gvec_ssadd32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fniv = tcg_gen_ssadd_vec, + .fno = gen_helper_gvec_ssadd64, + .opt_opc = vecop_list, + .vece = MO_64 }, + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_sssub_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_sssub_vec, + .fno = gen_helper_gvec_sssub8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_sssub_vec, + .fno = gen_helper_gvec_sssub16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fniv = tcg_gen_sssub_vec, + .fno = gen_helper_gvec_sssub32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fniv = tcg_gen_sssub_vec, + .fno = gen_helper_gvec_sssub64, + .opt_opc = vecop_list, + .vece = MO_64 }, + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +static void tcg_gen_usadd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 max = tcg_const_i32(-1); + tcg_gen_add_i32(d, a, b); + tcg_gen_movcond_i32(TCG_COND_LTU, d, d, a, max, d); + tcg_temp_free_i32(max); +} + +static void tcg_gen_usadd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 max = tcg_const_i64(-1); + tcg_gen_add_i64(d, a, b); + tcg_gen_movcond_i64(TCG_COND_LTU, d, d, a, max, d); + tcg_temp_free_i64(max); +} + +void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_usadd_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_usadd_vec, + .fno = gen_helper_gvec_usadd8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_usadd_vec, + .fno = gen_helper_gvec_usadd16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_usadd_i32, + .fniv = tcg_gen_usadd_vec, + .fno = gen_helper_gvec_usadd32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_usadd_i64, + .fniv = tcg_gen_usadd_vec, + .fno = gen_helper_gvec_usadd64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +static void tcg_gen_ussub_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 min = tcg_const_i32(0); + tcg_gen_sub_i32(d, a, b); + tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, min, d); + tcg_temp_free_i32(min); +} + +static void tcg_gen_ussub_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 min = tcg_const_i64(0); + tcg_gen_sub_i64(d, a, b); + tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, min, d); + tcg_temp_free_i64(min); +} + +void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_ussub_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_ussub_vec, + .fno = gen_helper_gvec_ussub8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_ussub_vec, + .fno = gen_helper_gvec_ussub16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_ussub_i32, + .fniv = tcg_gen_ussub_vec, + .fno = gen_helper_gvec_ussub32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_ussub_i64, + .fniv = tcg_gen_ussub_vec, + .fno = gen_helper_gvec_ussub64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_smin_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_smin_vec, + .fno = gen_helper_gvec_smin8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_smin_vec, + .fno = gen_helper_gvec_smin16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_smin_i32, + .fniv = tcg_gen_smin_vec, + .fno = gen_helper_gvec_smin32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_smin_i64, + .fniv = tcg_gen_smin_vec, + .fno = gen_helper_gvec_smin64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_umin_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_umin_vec, + .fno = gen_helper_gvec_umin8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_umin_vec, + .fno = gen_helper_gvec_umin16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_umin_i32, + .fniv = tcg_gen_umin_vec, + .fno = gen_helper_gvec_umin32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_umin_i64, + .fniv = tcg_gen_umin_vec, + .fno = gen_helper_gvec_umin64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_smax_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_smax_vec, + .fno = gen_helper_gvec_smax8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_smax_vec, + .fno = gen_helper_gvec_smax16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_smax_i32, + .fniv = tcg_gen_smax_vec, + .fno = gen_helper_gvec_smax32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_smax_i64, + .fniv = tcg_gen_smax_vec, + .fno = gen_helper_gvec_smax64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_umax_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_umax_vec, + .fno = gen_helper_gvec_umax8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_umax_vec, + .fno = gen_helper_gvec_umax16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_umax_i32, + .fniv = tcg_gen_umax_vec, + .fno = gen_helper_gvec_umax32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_umax_i64, + .fniv = tcg_gen_umax_vec, + .fno = gen_helper_gvec_umax64, + .opt_opc = vecop_list, + .vece = MO_64 } + }; + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +/* Perform a vector negation using normal negation and a mask. + Compare gen_subv_mask above. */ +static void gen_negv_mask(TCGv_i64 d, TCGv_i64 b, TCGv_i64 m) +{ + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_andc_i64(t3, m, b); + tcg_gen_andc_i64(t2, b, m); + tcg_gen_sub_i64(d, m, t2); + tcg_gen_xor_i64(d, d, t3); + + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80)); + gen_negv_mask(d, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 b) +{ + TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000)); + gen_negv_mask(d, b, m); + tcg_temp_free_i64(m); +} + +void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 b) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t1, b, ~0xffffffffull); + tcg_gen_neg_i64(t2, b); + tcg_gen_neg_i64(t1, t1); + tcg_gen_deposit_i64(d, t1, t2, 0, 32); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + +void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_neg_vec, 0 }; + static const GVecGen2 g[4] = { + { .fni8 = tcg_gen_vec_neg8_i64, + .fniv = tcg_gen_neg_vec, + .fno = gen_helper_gvec_neg8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_neg16_i64, + .fniv = tcg_gen_neg_vec, + .fno = gen_helper_gvec_neg16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_neg_i32, + .fniv = tcg_gen_neg_vec, + .fno = gen_helper_gvec_neg32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_neg_i64, + .fniv = tcg_gen_neg_vec, + .fno = gen_helper_gvec_neg64, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]); +} + +static void gen_absv_mask(TCGv_i64 d, TCGv_i64 b, unsigned vece) +{ + TCGv_i64 t = tcg_temp_new_i64(); + int nbit = 8 << vece; + + /* Create -1 for each negative element. */ + tcg_gen_shri_i64(t, b, nbit - 1); + tcg_gen_andi_i64(t, t, dup_const(vece, 1)); + tcg_gen_muli_i64(t, t, (1 << nbit) - 1); + + /* + * Invert (via xor -1) and add one (via sub -1). + * Because of the ordering the msb is cleared, + * so we never have carry into the next element. + */ + tcg_gen_xor_i64(d, b, t); + tcg_gen_sub_i64(d, d, t); + + tcg_temp_free_i64(t); +} + +static void tcg_gen_vec_abs8_i64(TCGv_i64 d, TCGv_i64 b) +{ + gen_absv_mask(d, b, MO_8); +} + +static void tcg_gen_vec_abs16_i64(TCGv_i64 d, TCGv_i64 b) +{ + gen_absv_mask(d, b, MO_16); +} + +void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_abs_vec, 0 }; + static const GVecGen2 g[4] = { + { .fni8 = tcg_gen_vec_abs8_i64, + .fniv = tcg_gen_abs_vec, + .fno = gen_helper_gvec_abs8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_abs16_i64, + .fniv = tcg_gen_abs_vec, + .fno = gen_helper_gvec_abs16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_abs_i32, + .fniv = tcg_gen_abs_vec, + .fno = gen_helper_gvec_abs32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_abs_i64, + .fniv = tcg_gen_abs_vec, + .fno = gen_helper_gvec_abs64, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]); +} + +void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_and_i64, + .fniv = tcg_gen_and_vec, + .fno = gen_helper_gvec_and, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_or_i64, + .fniv = tcg_gen_or_vec, + .fno = gen_helper_gvec_or, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_xor_i64, + .fniv = tcg_gen_xor_vec, + .fno = gen_helper_gvec_xor, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_andc_i64, + .fniv = tcg_gen_andc_vec, + .fno = gen_helper_gvec_andc, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_orc_i64, + .fniv = tcg_gen_orc_vec, + .fno = gen_helper_gvec_orc, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_nand_i64, + .fniv = tcg_gen_nand_vec, + .fno = gen_helper_gvec_nand, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_nor_i64, + .fniv = tcg_gen_nor_vec, + .fno = gen_helper_gvec_nor, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen3 g = { + .fni8 = tcg_gen_eqv_i64, + .fniv = tcg_gen_eqv_vec, + .fno = gen_helper_gvec_eqv, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + }; + + if (aofs == bofs) { + tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +} + +static const GVecGen2s gop_ands = { + .fni8 = tcg_gen_and_i64, + .fniv = tcg_gen_and_vec, + .fno = gen_helper_gvec_ands, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 +}; + +void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + gen_dup_i64(vece, tmp, c); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands); + tcg_temp_free_i64(tmp); +} + +void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands); + tcg_temp_free_i64(tmp); +} + +static const GVecGen2s gop_xors = { + .fni8 = tcg_gen_xor_i64, + .fniv = tcg_gen_xor_vec, + .fno = gen_helper_gvec_xors, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 +}; + +void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + gen_dup_i64(vece, tmp, c); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors); + tcg_temp_free_i64(tmp); +} + +void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors); + tcg_temp_free_i64(tmp); +} + +static const GVecGen2s gop_ors = { + .fni8 = tcg_gen_or_i64, + .fniv = tcg_gen_or_vec, + .fno = gen_helper_gvec_ors, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 +}; + +void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + gen_dup_i64(vece, tmp, c); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors); + tcg_temp_free_i64(tmp); +} + +void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c)); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors); + tcg_temp_free_i64(tmp); +} + +void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_8, 0xff << c); + tcg_gen_shli_i64(d, a, c); + tcg_gen_andi_i64(d, d, mask); +} + +void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_16, 0xffff << c); + tcg_gen_shli_i64(d, a, c); + tcg_gen_andi_i64(d, d, mask); +} + +void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 }; + static const GVecGen2i g[4] = { + { .fni8 = tcg_gen_vec_shl8i_i64, + .fniv = tcg_gen_shli_vec, + .fno = gen_helper_gvec_shl8i, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_shl16i_i64, + .fniv = tcg_gen_shli_vec, + .fno = gen_helper_gvec_shl16i, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_shli_i32, + .fniv = tcg_gen_shli_vec, + .fno = gen_helper_gvec_shl32i, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_shli_i64, + .fniv = tcg_gen_shli_vec, + .fno = gen_helper_gvec_shl64i, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + if (shift == 0) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); + } +} + +void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_8, 0xff >> c); + tcg_gen_shri_i64(d, a, c); + tcg_gen_andi_i64(d, d, mask); +} + +void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_16, 0xffff >> c); + tcg_gen_shri_i64(d, a, c); + tcg_gen_andi_i64(d, d, mask); +} + +void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 }; + static const GVecGen2i g[4] = { + { .fni8 = tcg_gen_vec_shr8i_i64, + .fniv = tcg_gen_shri_vec, + .fno = gen_helper_gvec_shr8i, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_shr16i_i64, + .fniv = tcg_gen_shri_vec, + .fno = gen_helper_gvec_shr16i, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_shri_i32, + .fniv = tcg_gen_shri_vec, + .fno = gen_helper_gvec_shr32i, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_shri_i64, + .fniv = tcg_gen_shri_vec, + .fno = gen_helper_gvec_shr64i, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + if (shift == 0) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); + } +} + +void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t s_mask = dup_const(MO_8, 0x80 >> c); + uint64_t c_mask = dup_const(MO_8, 0xff >> c); + TCGv_i64 s = tcg_temp_new_i64(); + + tcg_gen_shri_i64(d, a, c); + tcg_gen_andi_i64(s, d, s_mask); /* isolate (shifted) sign bit */ + tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */ + tcg_gen_andi_i64(d, d, c_mask); /* clear out bits above sign */ + tcg_gen_or_i64(d, d, s); /* include sign extension */ + tcg_temp_free_i64(s); +} + +void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t s_mask = dup_const(MO_16, 0x8000 >> c); + uint64_t c_mask = dup_const(MO_16, 0xffff >> c); + TCGv_i64 s = tcg_temp_new_i64(); + + tcg_gen_shri_i64(d, a, c); + tcg_gen_andi_i64(s, d, s_mask); /* isolate (shifted) sign bit */ + tcg_gen_andi_i64(d, d, c_mask); /* clear out bits above sign */ + tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */ + tcg_gen_or_i64(d, d, s); /* include sign extension */ + tcg_temp_free_i64(s); +} + +void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_sari_vec, 0 }; + static const GVecGen2i g[4] = { + { .fni8 = tcg_gen_vec_sar8i_i64, + .fniv = tcg_gen_sari_vec, + .fno = gen_helper_gvec_sar8i, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_sar16i_i64, + .fniv = tcg_gen_sari_vec, + .fno = gen_helper_gvec_sar16i, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_sari_i32, + .fniv = tcg_gen_sari_vec, + .fno = gen_helper_gvec_sar32i, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_sari_i64, + .fniv = tcg_gen_sari_vec, + .fno = gen_helper_gvec_sar64i, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + if (shift == 0) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); + } +} + +void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_8, 0xff << c); + + tcg_gen_shli_i64(d, a, c); + tcg_gen_shri_i64(a, a, 8 - c); + tcg_gen_andi_i64(d, d, mask); + tcg_gen_andi_i64(a, a, ~mask); + tcg_gen_or_i64(d, d, a); +} + +void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_16, 0xffff << c); + + tcg_gen_shli_i64(d, a, c); + tcg_gen_shri_i64(a, a, 16 - c); + tcg_gen_andi_i64(d, d, mask); + tcg_gen_andi_i64(a, a, ~mask); + tcg_gen_or_i64(d, d, a); +} + +void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 }; + static const GVecGen2i g[4] = { + { .fni8 = tcg_gen_vec_rotl8i_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl8i, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_rotl16i_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl16i, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotli_i32, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl32i, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotli_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl64i, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + if (shift == 0) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); + } +} + +void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + tcg_gen_gvec_rotli(vece, dofs, aofs, -shift & ((8 << vece) - 1), + oprsz, maxsz); +} + +/* + * Specialized generation vector shifts by a non-constant scalar. + */ + +typedef struct { + void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32); + void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64); + void (*fniv_s)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32); + void (*fniv_v)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec); + gen_helper_gvec_2 *fno[4]; + TCGOpcode s_list[2]; + TCGOpcode v_list[2]; +} GVecGen2sh; + +static void expand_2sh_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t tysz, TCGType type, + TCGv_i32 shift, + void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32)) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + fni(vece, t0, t0, shift); + tcg_gen_st_vec(t0, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); +} + +static void +do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift, + uint32_t oprsz, uint32_t maxsz, const GVecGen2sh *g) +{ + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs); + check_overlap_2(dofs, aofs, maxsz); + + /* If the backend has a scalar expansion, great. */ + type = choose_vector_type(g->s_list, vece, oprsz, vece == MO_64); + if (type) { + const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); + switch (type) { + case TCG_TYPE_V256: + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_2sh_vec(vece, dofs, aofs, some, 32, + TCG_TYPE_V256, shift, g->fniv_s); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_2sh_vec(vece, dofs, aofs, oprsz, 16, + TCG_TYPE_V128, shift, g->fniv_s); + break; + case TCG_TYPE_V64: + expand_2sh_vec(vece, dofs, aofs, oprsz, 8, + TCG_TYPE_V64, shift, g->fniv_s); + break; + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + goto clear_tail; + } + + /* If the backend supports variable vector shifts, also cool. */ + type = choose_vector_type(g->v_list, vece, oprsz, vece == MO_64); + if (type) { + const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); + TCGv_vec v_shift = tcg_temp_new_vec(type); + + if (vece == MO_64) { + TCGv_i64 sh64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(sh64, shift); + tcg_gen_dup_i64_vec(MO_64, v_shift, sh64); + tcg_temp_free_i64(sh64); + } else { + tcg_gen_dup_i32_vec(vece, v_shift, shift); + } + + switch (type) { + case TCG_TYPE_V256: + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_2s_vec(vece, dofs, aofs, some, 32, TCG_TYPE_V256, + v_shift, false, g->fniv_v); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_2s_vec(vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, + v_shift, false, g->fniv_v); + break; + case TCG_TYPE_V64: + expand_2s_vec(vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, + v_shift, false, g->fniv_v); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free_vec(v_shift); + tcg_swap_vecop_list(hold_list); + goto clear_tail; + } + + /* Otherwise fall back to integral... */ + if (vece == MO_32 && check_size_impl(oprsz, 4)) { + expand_2s_i32(dofs, aofs, oprsz, shift, false, g->fni4); + } else if (vece == MO_64 && check_size_impl(oprsz, 8)) { + TCGv_i64 sh64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(sh64, shift); + expand_2s_i64(dofs, aofs, oprsz, sh64, false, g->fni8); + tcg_temp_free_i64(sh64); + } else { + TCGv_ptr a0 = tcg_temp_new_ptr(); + TCGv_ptr a1 = tcg_temp_new_ptr(); + TCGv_i32 desc = tcg_temp_new_i32(); + + tcg_gen_shli_i32(desc, shift, SIMD_DATA_SHIFT); + tcg_gen_ori_i32(desc, desc, simd_desc(oprsz, maxsz, 0)); + tcg_gen_addi_ptr(a0, cpu_env, dofs); + tcg_gen_addi_ptr(a1, cpu_env, aofs); + + g->fno[vece](a0, a1, desc); + + tcg_temp_free_ptr(a0); + tcg_temp_free_ptr(a1); + tcg_temp_free_i32(desc); + return; + } + + clear_tail: + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2sh g = { + .fni4 = tcg_gen_shl_i32, + .fni8 = tcg_gen_shl_i64, + .fniv_s = tcg_gen_shls_vec, + .fniv_v = tcg_gen_shlv_vec, + .fno = { + gen_helper_gvec_shl8i, + gen_helper_gvec_shl16i, + gen_helper_gvec_shl32i, + gen_helper_gvec_shl64i, + }, + .s_list = { INDEX_op_shls_vec, 0 }, + .v_list = { INDEX_op_shlv_vec, 0 }, + }; + + tcg_debug_assert(vece <= MO_64); + do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); +} + +void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2sh g = { + .fni4 = tcg_gen_shr_i32, + .fni8 = tcg_gen_shr_i64, + .fniv_s = tcg_gen_shrs_vec, + .fniv_v = tcg_gen_shrv_vec, + .fno = { + gen_helper_gvec_shr8i, + gen_helper_gvec_shr16i, + gen_helper_gvec_shr32i, + gen_helper_gvec_shr64i, + }, + .s_list = { INDEX_op_shrs_vec, 0 }, + .v_list = { INDEX_op_shrv_vec, 0 }, + }; + + tcg_debug_assert(vece <= MO_64); + do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); +} + +void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2sh g = { + .fni4 = tcg_gen_sar_i32, + .fni8 = tcg_gen_sar_i64, + .fniv_s = tcg_gen_sars_vec, + .fniv_v = tcg_gen_sarv_vec, + .fno = { + gen_helper_gvec_sar8i, + gen_helper_gvec_sar16i, + gen_helper_gvec_sar32i, + gen_helper_gvec_sar64i, + }, + .s_list = { INDEX_op_sars_vec, 0 }, + .v_list = { INDEX_op_sarv_vec, 0 }, + }; + + tcg_debug_assert(vece <= MO_64); + do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); +} + +void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2sh g = { + .fni4 = tcg_gen_rotl_i32, + .fni8 = tcg_gen_rotl_i64, + .fniv_s = tcg_gen_rotls_vec, + .fniv_v = tcg_gen_rotlv_vec, + .fno = { + gen_helper_gvec_rotl8i, + gen_helper_gvec_rotl16i, + gen_helper_gvec_rotl32i, + gen_helper_gvec_rotl64i, + }, + .s_list = { INDEX_op_rotls_vec, 0 }, + .v_list = { INDEX_op_rotlv_vec, 0 }, + }; + + tcg_debug_assert(vece <= MO_64); + do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); +} + +/* + * Expand D = A << (B % element bits) + * + * Unlike scalar shifts, where it is easy for the target front end + * to include the modulo as part of the expansion. If the target + * naturally includes the modulo as part of the operation, great! + * If the target has some other behaviour from out-of-range shifts, + * then it could not use this function anyway, and would need to + * do it's own expansion with custom functions. + */ +static void tcg_gen_shlv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_shlv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_shl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_shl_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_shl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_shl_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_shlv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_shlv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_shlv_mod_vec, + .fno = gen_helper_gvec_shl8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_shlv_mod_vec, + .fno = gen_helper_gvec_shl16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_shl_mod_i32, + .fniv = tcg_gen_shlv_mod_vec, + .fno = gen_helper_gvec_shl32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_shl_mod_i64, + .fniv = tcg_gen_shlv_mod_vec, + .fno = gen_helper_gvec_shl64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +/* + * Similarly for logical right shifts. + */ + +static void tcg_gen_shrv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_shrv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_shr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_shr_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_shr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_shr_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_shrv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_shrv_mod_vec, + .fno = gen_helper_gvec_shr8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_shrv_mod_vec, + .fno = gen_helper_gvec_shr16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_shr_mod_i32, + .fniv = tcg_gen_shrv_mod_vec, + .fno = gen_helper_gvec_shr32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_shr_mod_i64, + .fniv = tcg_gen_shrv_mod_vec, + .fno = gen_helper_gvec_shr64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +/* + * Similarly for arithmetic right shifts. + */ + +static void tcg_gen_sarv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_sarv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_sar_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_sar_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_sar_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_sar_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_sarv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_sarv_mod_vec, + .fno = gen_helper_gvec_sar8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_sarv_mod_vec, + .fno = gen_helper_gvec_sar16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_sar_mod_i32, + .fniv = tcg_gen_sarv_mod_vec, + .fno = gen_helper_gvec_sar32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_sar_mod_i64, + .fniv = tcg_gen_sarv_mod_vec, + .fno = gen_helper_gvec_sar64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +/* + * Similarly for rotates. + */ + +static void tcg_gen_rotlv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_rotlv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_rotl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_rotl_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_rotl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_rotl_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotlv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotl_mod_i32, + .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotl_mod_i64, + .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +static void tcg_gen_rotrv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_rotrv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_rotr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_rotr_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_rotr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_rotr_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotrv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotr_mod_i32, + .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotr_mod_i64, + .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ +static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, TCGCond cond) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); + tcg_gen_ld_i32(t1, cpu_env, bofs + i); + tcg_gen_setcond_i32(cond, t0, t0, t1); + tcg_gen_neg_i32(t0, t0); + tcg_gen_st_i32(t0, cpu_env, dofs + i); + } + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, + uint32_t oprsz, TCGCond cond) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); + tcg_gen_ld_i64(t1, cpu_env, bofs + i); + tcg_gen_setcond_i64(cond, t0, t0, t1); + tcg_gen_neg_i64(t0, t0); + tcg_gen_st_i64(t0, cpu_env, dofs + i); + } + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static void expand_cmp_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t tysz, + TCGType type, TCGCond cond) +{ + TCGv_vec t0 = tcg_temp_new_vec(type); + TCGv_vec t1 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); + tcg_gen_ld_vec(t1, cpu_env, bofs + i); + tcg_gen_cmp_vec(cond, vece, t0, t0, t1); + tcg_gen_st_vec(t0, cpu_env, dofs + i); + } + tcg_temp_free_vec(t1); + tcg_temp_free_vec(t0); +} + +void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs, + uint32_t aofs, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode cmp_list[] = { INDEX_op_cmp_vec, 0 }; + static gen_helper_gvec_3 * const eq_fn[4] = { + gen_helper_gvec_eq8, gen_helper_gvec_eq16, + gen_helper_gvec_eq32, gen_helper_gvec_eq64 + }; + static gen_helper_gvec_3 * const ne_fn[4] = { + gen_helper_gvec_ne8, gen_helper_gvec_ne16, + gen_helper_gvec_ne32, gen_helper_gvec_ne64 + }; + static gen_helper_gvec_3 * const lt_fn[4] = { + gen_helper_gvec_lt8, gen_helper_gvec_lt16, + gen_helper_gvec_lt32, gen_helper_gvec_lt64 + }; + static gen_helper_gvec_3 * const le_fn[4] = { + gen_helper_gvec_le8, gen_helper_gvec_le16, + gen_helper_gvec_le32, gen_helper_gvec_le64 + }; + static gen_helper_gvec_3 * const ltu_fn[4] = { + gen_helper_gvec_ltu8, gen_helper_gvec_ltu16, + gen_helper_gvec_ltu32, gen_helper_gvec_ltu64 + }; + static gen_helper_gvec_3 * const leu_fn[4] = { + gen_helper_gvec_leu8, gen_helper_gvec_leu16, + gen_helper_gvec_leu32, gen_helper_gvec_leu64 + }; + static gen_helper_gvec_3 * const * const fns[16] = { + [TCG_COND_EQ] = eq_fn, + [TCG_COND_NE] = ne_fn, + [TCG_COND_LT] = lt_fn, + [TCG_COND_LE] = le_fn, + [TCG_COND_LTU] = ltu_fn, + [TCG_COND_LEU] = leu_fn, + }; + + const TCGOpcode *hold_list; + TCGType type; + uint32_t some; + + check_size_align(oprsz, maxsz, dofs | aofs | bofs); + check_overlap_3(dofs, aofs, bofs, maxsz); + + if (cond == TCG_COND_NEVER || cond == TCG_COND_ALWAYS) { + do_dup(MO_8, dofs, oprsz, maxsz, + NULL, NULL, -(cond == TCG_COND_ALWAYS)); + return; + } + + /* + * Implement inline with a vector type, if possible. + * Prefer integer when 64-bit host and 64-bit comparison. + */ + hold_list = tcg_swap_vecop_list(cmp_list); + type = choose_vector_type(cmp_list, vece, oprsz, + TCG_TARGET_REG_BITS == 64 && vece == MO_64); + switch (type) { + case TCG_TYPE_V256: + /* Recall that ARM SVE allows vector sizes that are not a + * power of 2, but always a multiple of 16. The intent is + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); + expand_cmp_vec(vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, cond); + if (some == oprsz) { + break; + } + dofs += some; + aofs += some; + bofs += some; + oprsz -= some; + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: + expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, cond); + break; + case TCG_TYPE_V64: + expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, cond); + break; + + case 0: + if (vece == MO_64 && check_size_impl(oprsz, 8)) { + expand_cmp_i64(dofs, aofs, bofs, oprsz, cond); + } else if (vece == MO_32 && check_size_impl(oprsz, 4)) { + expand_cmp_i32(dofs, aofs, bofs, oprsz, cond); + } else { + gen_helper_gvec_3 * const *fn = fns[cond]; + + if (fn == NULL) { + uint32_t tmp; + tmp = aofs, aofs = bofs, bofs = tmp; + cond = tcg_swap_cond(cond); + fn = fns[cond]; + assert(fn != NULL); + } + tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, 0, fn[vece]); + oprsz = maxsz; + } + break; + + default: + g_assert_not_reached(); + } + tcg_swap_vecop_list(hold_list); + + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } +} + +static void tcg_gen_bitsel_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_and_i64(t, b, a); + tcg_gen_andc_i64(d, c, a); + tcg_gen_or_i64(d, d, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_bitsel(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t cofs, + uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen4 g = { + .fni8 = tcg_gen_bitsel_i64, + .fniv = tcg_gen_bitsel_vec, + .fno = gen_helper_gvec_bitsel, + }; + + tcg_gen_gvec_4(dofs, aofs, bofs, cofs, oprsz, maxsz, &g); +} From patchwork Thu Sep 3 07:43:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752583 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BC456739 for ; Thu, 3 Sep 2020 07:46:27 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 76A9B206C0 for ; Thu, 3 Sep 2020 07:46:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="l8wxX/89" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 76A9B206C0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:52792 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjww-0005Gh-IR for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:46:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43352) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuM-0008Kk-E9 for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:46 -0400 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]:54713) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuI-0003rW-Ch for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:46 -0400 Received: by mail-pj1-x1044.google.com with SMTP id mm21so1098948pjb.4 for ; Thu, 03 Sep 2020 00:43:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=huTQukiVEQnbnV6oUpHw80TH1WL6GqzC6d5q3yiaZGo=; b=l8wxX/89oWmJ+w+iU3vMiZt+6q+eOpGBjvAPuNr4NRtO3yyQKof9+KPFKP3hG7Z5IY 71aQn7fXvTxZQtisUlj5Rs3ogce/Ha5mtVg+cpUENx83Rv3V5/g1hsQp3d8XwKMbwyM2 32wYu+DQVvgmAPwFuqZqkpFytUjMwbOwp5F0J/xrUllzdgsFRf3HzAKYszUKqExl7Ofx UwSilhsyrzWf8Y2aa921lBFBOOMa44xZA2pieGlBAv0dXZulDbJ5QB3IqfXL0cutx3oO qFHBzyNJCARG+pNgGdNpXbU1szGYkwgrSgRlKod8wNwuugPn4Gi/IOMjAyuz0Tl4Ls0S hrgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=huTQukiVEQnbnV6oUpHw80TH1WL6GqzC6d5q3yiaZGo=; b=kyGHCz8Cy4AL7i333ck3TUFGN5OkCtLZ2npG+F94ZIE7uW3G4AZTP70jXCxzuvv5xr h6/tC5Mz7e25XSYjQIg5GQtwxFmXhiol4ffMxTyOZbqINsTkaepCy5X3lRW3FTmt2Fjl GSs0CT7aVq9ujFyGMBI5w8+bCeULAlM76beB3CraAAz+MoiHJYVVIIP63CUQMsY1kbgi HBEKKXp/oVMgDKBjL2V1ZKUlwg+ZTe+fXaIqzNaj6KkNtEP41VrTKNfjyvMGfXpKFbzN vJXUt+8OGdQyegvxsYB3QYAfk/mMU9ZtxhUsBlqv7PVHRb+17SxTzMzSZSJnBSjOJgSD IgAQ== X-Gm-Message-State: AOAM531mDQ8usqNHXPeBwz4yvk1lT1/YYfvCgZ+PlcBFqFpppG0UZXtb 7fQ/tkzgHpU4UyGPfiwYFG07dV/M755xhgtE X-Google-Smtp-Source: ABdhPJxi5I3vbmjE7EHdfmTr3VoSQFncd3LDkgsP1epfOeOLwOo0iRUdoWa0Kg1ndZY2rO3CXDq3GA== X-Received: by 2002:a17:90a:a088:: with SMTP id r8mr1959182pjp.73.1599119019797; Thu, 03 Sep 2020 00:43:39 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:38 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 04/12] tests: handling signal on win32 properly Date: Thu, 3 Sep 2020 15:43:05 +0800 Message-Id: <20200903074313.1498-5-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1044; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1044.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" SIGABRT should use signal(SIGABRT, sigabrt_handler) to handle on win32 The error: E:/CI-Cor-Ready/xemu/qemu.org/tests/test-replication.c:559:33: error: invalid use of undefined type 'struct sigaction' 559 | sigact = (struct sigaction) { | ^ Signed-off-by: Yonggang Luo --- tests/test-replication.c | 1214 +++++++++++++++++++------------------- 1 file changed, 609 insertions(+), 605 deletions(-) diff --git a/tests/test-replication.c b/tests/test-replication.c index e0b03dafc2..9ab3666a90 100644 --- a/tests/test-replication.c +++ b/tests/test-replication.c @@ -1,605 +1,609 @@ -/* - * Block replication tests - * - * Copyright (c) 2016 FUJITSU LIMITED - * Author: Changlong Xie - * - * 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 "qapi/error.h" -#include "qapi/qmp/qdict.h" -#include "qemu/option.h" -#include "qemu/main-loop.h" -#include "replication.h" -#include "block/block_int.h" -#include "block/qdict.h" -#include "sysemu/block-backend.h" - -#define IMG_SIZE (64 * 1024 * 1024) - -/* primary */ -#define P_ID "primary-id" -static char p_local_disk[] = "/tmp/p_local_disk.XXXXXX"; - -/* secondary */ -#define S_ID "secondary-id" -#define S_LOCAL_DISK_ID "secondary-local-disk-id" -static char s_local_disk[] = "/tmp/s_local_disk.XXXXXX"; -static char s_active_disk[] = "/tmp/s_active_disk.XXXXXX"; -static char s_hidden_disk[] = "/tmp/s_hidden_disk.XXXXXX"; - -/* FIXME: steal from blockdev.c */ -QemuOptsList qemu_drive_opts = { - .name = "drive", - .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head), - .desc = { - { /* end of list */ } - }, -}; - -#define NOT_DONE 0x7fffffff - -static void blk_rw_done(void *opaque, int ret) -{ - *(int *)opaque = ret; -} - -static void test_blk_read(BlockBackend *blk, long pattern, - int64_t pattern_offset, int64_t pattern_count, - int64_t offset, int64_t count, - bool expect_failed) -{ - void *pattern_buf = NULL; - QEMUIOVector qiov; - void *cmp_buf = NULL; - int async_ret = NOT_DONE; - - if (pattern) { - cmp_buf = g_malloc(pattern_count); - memset(cmp_buf, pattern, pattern_count); - } - - pattern_buf = g_malloc(count); - if (pattern) { - memset(pattern_buf, pattern, count); - } else { - memset(pattern_buf, 0x00, count); - } - - qemu_iovec_init(&qiov, 1); - qemu_iovec_add(&qiov, pattern_buf, count); - - blk_aio_preadv(blk, offset, &qiov, 0, blk_rw_done, &async_ret); - while (async_ret == NOT_DONE) { - main_loop_wait(false); - } - - if (expect_failed) { - g_assert(async_ret != 0); - } else { - g_assert(async_ret == 0); - if (pattern) { - g_assert(memcmp(pattern_buf + pattern_offset, - cmp_buf, pattern_count) <= 0); - } - } - - g_free(pattern_buf); - g_free(cmp_buf); - qemu_iovec_destroy(&qiov); -} - -static void test_blk_write(BlockBackend *blk, long pattern, int64_t offset, - int64_t count, bool expect_failed) -{ - void *pattern_buf = NULL; - QEMUIOVector qiov; - int async_ret = NOT_DONE; - - pattern_buf = g_malloc(count); - if (pattern) { - memset(pattern_buf, pattern, count); - } else { - memset(pattern_buf, 0x00, count); - } - - qemu_iovec_init(&qiov, 1); - qemu_iovec_add(&qiov, pattern_buf, count); - - blk_aio_pwritev(blk, offset, &qiov, 0, blk_rw_done, &async_ret); - while (async_ret == NOT_DONE) { - main_loop_wait(false); - } - - if (expect_failed) { - g_assert(async_ret != 0); - } else { - g_assert(async_ret == 0); - } - - g_free(pattern_buf); - qemu_iovec_destroy(&qiov); -} - -/* - * Create a uniquely-named empty temporary file. - */ -static void make_temp(char *template) -{ - int fd; - - fd = mkstemp(template); - g_assert(fd >= 0); - close(fd); -} - -static void prepare_imgs(void) -{ - make_temp(p_local_disk); - make_temp(s_local_disk); - make_temp(s_active_disk); - make_temp(s_hidden_disk); - - /* Primary */ - bdrv_img_create(p_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &error_abort); - - /* Secondary */ - bdrv_img_create(s_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &error_abort); - bdrv_img_create(s_active_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &error_abort); - bdrv_img_create(s_hidden_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &error_abort); -} - -static void cleanup_imgs(void) -{ - /* Primary */ - unlink(p_local_disk); - - /* Secondary */ - unlink(s_local_disk); - unlink(s_active_disk); - unlink(s_hidden_disk); -} - -static BlockBackend *start_primary(void) -{ - BlockBackend *blk; - QemuOpts *opts; - QDict *qdict; - char *cmdline; - - cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx," - "file.driver=qcow2,file.file.filename=%s," - "file.file.locking=off" - , p_local_disk); - opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); - g_free(cmdline); - - qdict = qemu_opts_to_qdict(opts, NULL); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); - g_assert(blk); - - monitor_add_blk(blk, P_ID, &error_abort); - - qemu_opts_del(opts); - - return blk; -} - -static void teardown_primary(void) -{ - BlockBackend *blk; - AioContext *ctx; - - /* remove P_ID */ - blk = blk_by_name(P_ID); - assert(blk); - - ctx = blk_get_aio_context(blk); - aio_context_acquire(ctx); - monitor_remove_blk(blk); - blk_unref(blk); - aio_context_release(ctx); -} - -static void test_primary_read(void) -{ - BlockBackend *blk; - - blk = start_primary(); - - /* read from 0 to IMG_SIZE */ - test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); - - teardown_primary(); -} - -static void test_primary_write(void) -{ - BlockBackend *blk; - - blk = start_primary(); - - /* write from 0 to IMG_SIZE */ - test_blk_write(blk, 0, 0, IMG_SIZE, true); - - teardown_primary(); -} - -static void test_primary_start(void) -{ - BlockBackend *blk = NULL; - - blk = start_primary(); - - replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - - /* read from 0 to IMG_SIZE */ - test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); - - /* write 0x22 from 0 to IMG_SIZE */ - test_blk_write(blk, 0x22, 0, IMG_SIZE, false); - - teardown_primary(); -} - -static void test_primary_stop(void) -{ - bool failover = true; - - start_primary(); - - replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - - replication_stop_all(failover, &error_abort); - - teardown_primary(); -} - -static void test_primary_do_checkpoint(void) -{ - start_primary(); - - replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - - replication_do_checkpoint_all(&error_abort); - - teardown_primary(); -} - -static void test_primary_get_error_all(void) -{ - start_primary(); - - replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - - replication_get_error_all(&error_abort); - - teardown_primary(); -} - -static BlockBackend *start_secondary(void) -{ - QemuOpts *opts; - QDict *qdict; - BlockBackend *blk; - char *cmdline; - - /* add s_local_disk and forge S_LOCAL_DISK_ID */ - cmdline = g_strdup_printf("file.filename=%s,driver=qcow2," - "file.locking=off", - s_local_disk); - opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); - g_free(cmdline); - - qdict = qemu_opts_to_qdict(opts, NULL); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); - assert(blk); - monitor_add_blk(blk, S_LOCAL_DISK_ID, &error_abort); - - /* format s_local_disk with pattern "0x11" */ - test_blk_write(blk, 0x11, 0, IMG_SIZE, false); - - qemu_opts_del(opts); - - /* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */ - cmdline = g_strdup_printf("driver=replication,mode=secondary,top-id=%s," - "file.driver=qcow2,file.file.filename=%s," - "file.file.locking=off," - "file.backing.driver=qcow2," - "file.backing.file.filename=%s," - "file.backing.file.locking=off," - "file.backing.backing=%s" - , S_ID, s_active_disk, s_hidden_disk - , S_LOCAL_DISK_ID); - opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); - g_free(cmdline); - - qdict = qemu_opts_to_qdict(opts, NULL); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); - qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); - assert(blk); - monitor_add_blk(blk, S_ID, &error_abort); - - qemu_opts_del(opts); - - return blk; -} - -static void teardown_secondary(void) -{ - /* only need to destroy two BBs */ - BlockBackend *blk; - AioContext *ctx; - - /* remove S_LOCAL_DISK_ID */ - blk = blk_by_name(S_LOCAL_DISK_ID); - assert(blk); - - ctx = blk_get_aio_context(blk); - aio_context_acquire(ctx); - monitor_remove_blk(blk); - blk_unref(blk); - aio_context_release(ctx); - - /* remove S_ID */ - blk = blk_by_name(S_ID); - assert(blk); - - ctx = blk_get_aio_context(blk); - aio_context_acquire(ctx); - monitor_remove_blk(blk); - blk_unref(blk); - aio_context_release(ctx); -} - -static void test_secondary_read(void) -{ - BlockBackend *blk; - - blk = start_secondary(); - - /* read from 0 to IMG_SIZE */ - test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); - - teardown_secondary(); -} - -static void test_secondary_write(void) -{ - BlockBackend *blk; - - blk = start_secondary(); - - /* write from 0 to IMG_SIZE */ - test_blk_write(blk, 0, 0, IMG_SIZE, true); - - teardown_secondary(); -} - -static void test_secondary_start(void) -{ - BlockBackend *top_blk, *local_blk; - bool failover = true; - - top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - - /* read from s_local_disk (0, IMG_SIZE) */ - test_blk_read(top_blk, 0x11, 0, IMG_SIZE, 0, IMG_SIZE, false); - - /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - local_blk = blk_by_name(S_LOCAL_DISK_ID); - test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); - - /* replication will backup s_local_disk to s_hidden_disk */ - test_blk_read(top_blk, 0x11, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ - test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); - - /* read from s_active_disk (0, IMG_SIZE/2) */ - test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, - 0, IMG_SIZE / 2, false); - - /* unblock top_bs */ - replication_stop_all(failover, &error_abort); - - teardown_secondary(); -} - - -static void test_secondary_stop(void) -{ - BlockBackend *top_blk, *local_blk; - bool failover = true; - - top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - - /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - local_blk = blk_by_name(S_LOCAL_DISK_ID); - test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); - - /* replication will backup s_local_disk to s_hidden_disk */ - test_blk_read(top_blk, 0x11, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ - test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); - - /* do active commit */ - replication_stop_all(failover, &error_abort); - - /* read from s_local_disk (0, IMG_SIZE / 2) */ - test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, - 0, IMG_SIZE / 2, false); - - - /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - test_blk_read(top_blk, 0x22, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - teardown_secondary(); -} - -static void test_secondary_continuous_replication(void) -{ - BlockBackend *top_blk, *local_blk; - - top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - - /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - local_blk = blk_by_name(S_LOCAL_DISK_ID); - test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); - - /* replication will backup s_local_disk to s_hidden_disk */ - test_blk_read(top_blk, 0x11, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ - test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); - - /* do failover (active commit) */ - replication_stop_all(true, &error_abort); - - /* it should ignore all requests from now on */ - - /* start after failover */ - replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - - /* checkpoint */ - replication_do_checkpoint_all(&error_abort); - - /* stop */ - replication_stop_all(true, &error_abort); - - /* read from s_local_disk (0, IMG_SIZE / 2) */ - test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, - 0, IMG_SIZE / 2, false); - - - /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - test_blk_read(top_blk, 0x22, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - teardown_secondary(); -} - -static void test_secondary_do_checkpoint(void) -{ - BlockBackend *top_blk, *local_blk; - bool failover = true; - - top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - - /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ - local_blk = blk_by_name(S_LOCAL_DISK_ID); - test_blk_write(local_blk, 0x22, IMG_SIZE / 2, - IMG_SIZE / 2, false); - - /* replication will backup s_local_disk to s_hidden_disk */ - test_blk_read(top_blk, 0x11, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - replication_do_checkpoint_all(&error_abort); - - /* after checkpoint, read pattern 0x22 from s_local_disk */ - test_blk_read(top_blk, 0x22, IMG_SIZE / 2, - IMG_SIZE / 2, 0, IMG_SIZE, false); - - /* unblock top_bs */ - replication_stop_all(failover, &error_abort); - - teardown_secondary(); -} - -static void test_secondary_get_error_all(void) -{ - bool failover = true; - - start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - - replication_get_error_all(&error_abort); - - /* unblock top_bs */ - replication_stop_all(failover, &error_abort); - - teardown_secondary(); -} - -static void sigabrt_handler(int signo) -{ - cleanup_imgs(); -} - -static void setup_sigabrt_handler(void) -{ - struct sigaction sigact; - - sigact = (struct sigaction) { - .sa_handler = sigabrt_handler, - .sa_flags = SA_RESETHAND, - }; - sigemptyset(&sigact.sa_mask); - sigaction(SIGABRT, &sigact, NULL); -} - -int main(int argc, char **argv) -{ - int ret; - qemu_init_main_loop(&error_fatal); - bdrv_init(); - - g_test_init(&argc, &argv, NULL); - setup_sigabrt_handler(); - - prepare_imgs(); - - /* Primary */ - g_test_add_func("/replication/primary/read", test_primary_read); - g_test_add_func("/replication/primary/write", test_primary_write); - g_test_add_func("/replication/primary/start", test_primary_start); - g_test_add_func("/replication/primary/stop", test_primary_stop); - g_test_add_func("/replication/primary/do_checkpoint", - test_primary_do_checkpoint); - g_test_add_func("/replication/primary/get_error_all", - test_primary_get_error_all); - - /* Secondary */ - g_test_add_func("/replication/secondary/read", test_secondary_read); - g_test_add_func("/replication/secondary/write", test_secondary_write); - g_test_add_func("/replication/secondary/start", test_secondary_start); - g_test_add_func("/replication/secondary/stop", test_secondary_stop); - g_test_add_func("/replication/secondary/continuous_replication", - test_secondary_continuous_replication); - g_test_add_func("/replication/secondary/do_checkpoint", - test_secondary_do_checkpoint); - g_test_add_func("/replication/secondary/get_error_all", - test_secondary_get_error_all); - - ret = g_test_run(); - - cleanup_imgs(); - - return ret; -} +/* + * Block replication tests + * + * Copyright (c) 2016 FUJITSU LIMITED + * Author: Changlong Xie + * + * 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 "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "qemu/option.h" +#include "qemu/main-loop.h" +#include "replication.h" +#include "block/block_int.h" +#include "block/qdict.h" +#include "sysemu/block-backend.h" + +#define IMG_SIZE (64 * 1024 * 1024) + +/* primary */ +#define P_ID "primary-id" +static char p_local_disk[] = "/tmp/p_local_disk.XXXXXX"; + +/* secondary */ +#define S_ID "secondary-id" +#define S_LOCAL_DISK_ID "secondary-local-disk-id" +static char s_local_disk[] = "/tmp/s_local_disk.XXXXXX"; +static char s_active_disk[] = "/tmp/s_active_disk.XXXXXX"; +static char s_hidden_disk[] = "/tmp/s_hidden_disk.XXXXXX"; + +/* FIXME: steal from blockdev.c */ +QemuOptsList qemu_drive_opts = { + .name = "drive", + .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head), + .desc = { + { /* end of list */ } + }, +}; + +#define NOT_DONE 0x7fffffff + +static void blk_rw_done(void *opaque, int ret) +{ + *(int *)opaque = ret; +} + +static void test_blk_read(BlockBackend *blk, long pattern, + int64_t pattern_offset, int64_t pattern_count, + int64_t offset, int64_t count, + bool expect_failed) +{ + void *pattern_buf = NULL; + QEMUIOVector qiov; + void *cmp_buf = NULL; + int async_ret = NOT_DONE; + + if (pattern) { + cmp_buf = g_malloc(pattern_count); + memset(cmp_buf, pattern, pattern_count); + } + + pattern_buf = g_malloc(count); + if (pattern) { + memset(pattern_buf, pattern, count); + } else { + memset(pattern_buf, 0x00, count); + } + + qemu_iovec_init(&qiov, 1); + qemu_iovec_add(&qiov, pattern_buf, count); + + blk_aio_preadv(blk, offset, &qiov, 0, blk_rw_done, &async_ret); + while (async_ret == NOT_DONE) { + main_loop_wait(false); + } + + if (expect_failed) { + g_assert(async_ret != 0); + } else { + g_assert(async_ret == 0); + if (pattern) { + g_assert(memcmp(pattern_buf + pattern_offset, + cmp_buf, pattern_count) <= 0); + } + } + + g_free(pattern_buf); + g_free(cmp_buf); + qemu_iovec_destroy(&qiov); +} + +static void test_blk_write(BlockBackend *blk, long pattern, int64_t offset, + int64_t count, bool expect_failed) +{ + void *pattern_buf = NULL; + QEMUIOVector qiov; + int async_ret = NOT_DONE; + + pattern_buf = g_malloc(count); + if (pattern) { + memset(pattern_buf, pattern, count); + } else { + memset(pattern_buf, 0x00, count); + } + + qemu_iovec_init(&qiov, 1); + qemu_iovec_add(&qiov, pattern_buf, count); + + blk_aio_pwritev(blk, offset, &qiov, 0, blk_rw_done, &async_ret); + while (async_ret == NOT_DONE) { + main_loop_wait(false); + } + + if (expect_failed) { + g_assert(async_ret != 0); + } else { + g_assert(async_ret == 0); + } + + g_free(pattern_buf); + qemu_iovec_destroy(&qiov); +} + +/* + * Create a uniquely-named empty temporary file. + */ +static void make_temp(char *template) +{ + int fd; + + fd = mkstemp(template); + g_assert(fd >= 0); + close(fd); +} + +static void prepare_imgs(void) +{ + make_temp(p_local_disk); + make_temp(s_local_disk); + make_temp(s_active_disk); + make_temp(s_hidden_disk); + + /* Primary */ + bdrv_img_create(p_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, + BDRV_O_RDWR, true, &error_abort); + + /* Secondary */ + bdrv_img_create(s_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, + BDRV_O_RDWR, true, &error_abort); + bdrv_img_create(s_active_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, + BDRV_O_RDWR, true, &error_abort); + bdrv_img_create(s_hidden_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, + BDRV_O_RDWR, true, &error_abort); +} + +static void cleanup_imgs(void) +{ + /* Primary */ + unlink(p_local_disk); + + /* Secondary */ + unlink(s_local_disk); + unlink(s_active_disk); + unlink(s_hidden_disk); +} + +static BlockBackend *start_primary(void) +{ + BlockBackend *blk; + QemuOpts *opts; + QDict *qdict; + char *cmdline; + + cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx," + "file.driver=qcow2,file.file.filename=%s," + "file.file.locking=off" + , p_local_disk); + opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); + g_free(cmdline); + + qdict = qemu_opts_to_qdict(opts, NULL); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); + + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); + g_assert(blk); + + monitor_add_blk(blk, P_ID, &error_abort); + + qemu_opts_del(opts); + + return blk; +} + +static void teardown_primary(void) +{ + BlockBackend *blk; + AioContext *ctx; + + /* remove P_ID */ + blk = blk_by_name(P_ID); + assert(blk); + + ctx = blk_get_aio_context(blk); + aio_context_acquire(ctx); + monitor_remove_blk(blk); + blk_unref(blk); + aio_context_release(ctx); +} + +static void test_primary_read(void) +{ + BlockBackend *blk; + + blk = start_primary(); + + /* read from 0 to IMG_SIZE */ + test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); + + teardown_primary(); +} + +static void test_primary_write(void) +{ + BlockBackend *blk; + + blk = start_primary(); + + /* write from 0 to IMG_SIZE */ + test_blk_write(blk, 0, 0, IMG_SIZE, true); + + teardown_primary(); +} + +static void test_primary_start(void) +{ + BlockBackend *blk = NULL; + + blk = start_primary(); + + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); + + /* read from 0 to IMG_SIZE */ + test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); + + /* write 0x22 from 0 to IMG_SIZE */ + test_blk_write(blk, 0x22, 0, IMG_SIZE, false); + + teardown_primary(); +} + +static void test_primary_stop(void) +{ + bool failover = true; + + start_primary(); + + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); + + replication_stop_all(failover, &error_abort); + + teardown_primary(); +} + +static void test_primary_do_checkpoint(void) +{ + start_primary(); + + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); + + replication_do_checkpoint_all(&error_abort); + + teardown_primary(); +} + +static void test_primary_get_error_all(void) +{ + start_primary(); + + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); + + replication_get_error_all(&error_abort); + + teardown_primary(); +} + +static BlockBackend *start_secondary(void) +{ + QemuOpts *opts; + QDict *qdict; + BlockBackend *blk; + char *cmdline; + + /* add s_local_disk and forge S_LOCAL_DISK_ID */ + cmdline = g_strdup_printf("file.filename=%s,driver=qcow2," + "file.locking=off", + s_local_disk); + opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); + g_free(cmdline); + + qdict = qemu_opts_to_qdict(opts, NULL); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); + + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); + assert(blk); + monitor_add_blk(blk, S_LOCAL_DISK_ID, &error_abort); + + /* format s_local_disk with pattern "0x11" */ + test_blk_write(blk, 0x11, 0, IMG_SIZE, false); + + qemu_opts_del(opts); + + /* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */ + cmdline = g_strdup_printf("driver=replication,mode=secondary,top-id=%s," + "file.driver=qcow2,file.file.filename=%s," + "file.file.locking=off," + "file.backing.driver=qcow2," + "file.backing.file.filename=%s," + "file.backing.file.locking=off," + "file.backing.backing=%s" + , S_ID, s_active_disk, s_hidden_disk + , S_LOCAL_DISK_ID); + opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); + g_free(cmdline); + + qdict = qemu_opts_to_qdict(opts, NULL); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); + qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); + + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); + assert(blk); + monitor_add_blk(blk, S_ID, &error_abort); + + qemu_opts_del(opts); + + return blk; +} + +static void teardown_secondary(void) +{ + /* only need to destroy two BBs */ + BlockBackend *blk; + AioContext *ctx; + + /* remove S_LOCAL_DISK_ID */ + blk = blk_by_name(S_LOCAL_DISK_ID); + assert(blk); + + ctx = blk_get_aio_context(blk); + aio_context_acquire(ctx); + monitor_remove_blk(blk); + blk_unref(blk); + aio_context_release(ctx); + + /* remove S_ID */ + blk = blk_by_name(S_ID); + assert(blk); + + ctx = blk_get_aio_context(blk); + aio_context_acquire(ctx); + monitor_remove_blk(blk); + blk_unref(blk); + aio_context_release(ctx); +} + +static void test_secondary_read(void) +{ + BlockBackend *blk; + + blk = start_secondary(); + + /* read from 0 to IMG_SIZE */ + test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); + + teardown_secondary(); +} + +static void test_secondary_write(void) +{ + BlockBackend *blk; + + blk = start_secondary(); + + /* write from 0 to IMG_SIZE */ + test_blk_write(blk, 0, 0, IMG_SIZE, true); + + teardown_secondary(); +} + +static void test_secondary_start(void) +{ + BlockBackend *top_blk, *local_blk; + bool failover = true; + + top_blk = start_secondary(); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); + + /* read from s_local_disk (0, IMG_SIZE) */ + test_blk_read(top_blk, 0x11, 0, IMG_SIZE, 0, IMG_SIZE, false); + + /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + local_blk = blk_by_name(S_LOCAL_DISK_ID); + test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); + + /* replication will backup s_local_disk to s_hidden_disk */ + test_blk_read(top_blk, 0x11, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ + test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); + + /* read from s_active_disk (0, IMG_SIZE/2) */ + test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, + 0, IMG_SIZE / 2, false); + + /* unblock top_bs */ + replication_stop_all(failover, &error_abort); + + teardown_secondary(); +} + + +static void test_secondary_stop(void) +{ + BlockBackend *top_blk, *local_blk; + bool failover = true; + + top_blk = start_secondary(); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); + + /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + local_blk = blk_by_name(S_LOCAL_DISK_ID); + test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); + + /* replication will backup s_local_disk to s_hidden_disk */ + test_blk_read(top_blk, 0x11, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ + test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); + + /* do active commit */ + replication_stop_all(failover, &error_abort); + + /* read from s_local_disk (0, IMG_SIZE / 2) */ + test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, + 0, IMG_SIZE / 2, false); + + + /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + test_blk_read(top_blk, 0x22, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + teardown_secondary(); +} + +static void test_secondary_continuous_replication(void) +{ + BlockBackend *top_blk, *local_blk; + + top_blk = start_secondary(); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); + + /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + local_blk = blk_by_name(S_LOCAL_DISK_ID); + test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false); + + /* replication will backup s_local_disk to s_hidden_disk */ + test_blk_read(top_blk, 0x11, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */ + test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); + + /* do failover (active commit) */ + replication_stop_all(true, &error_abort); + + /* it should ignore all requests from now on */ + + /* start after failover */ + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); + + /* checkpoint */ + replication_do_checkpoint_all(&error_abort); + + /* stop */ + replication_stop_all(true, &error_abort); + + /* read from s_local_disk (0, IMG_SIZE / 2) */ + test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, + 0, IMG_SIZE / 2, false); + + + /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + test_blk_read(top_blk, 0x22, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + teardown_secondary(); +} + +static void test_secondary_do_checkpoint(void) +{ + BlockBackend *top_blk, *local_blk; + bool failover = true; + + top_blk = start_secondary(); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); + + /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ + local_blk = blk_by_name(S_LOCAL_DISK_ID); + test_blk_write(local_blk, 0x22, IMG_SIZE / 2, + IMG_SIZE / 2, false); + + /* replication will backup s_local_disk to s_hidden_disk */ + test_blk_read(top_blk, 0x11, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + replication_do_checkpoint_all(&error_abort); + + /* after checkpoint, read pattern 0x22 from s_local_disk */ + test_blk_read(top_blk, 0x22, IMG_SIZE / 2, + IMG_SIZE / 2, 0, IMG_SIZE, false); + + /* unblock top_bs */ + replication_stop_all(failover, &error_abort); + + teardown_secondary(); +} + +static void test_secondary_get_error_all(void) +{ + bool failover = true; + + start_secondary(); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); + + replication_get_error_all(&error_abort); + + /* unblock top_bs */ + replication_stop_all(failover, &error_abort); + + teardown_secondary(); +} + +static void sigabrt_handler(int signo) +{ + cleanup_imgs(); +} + +static void setup_sigabrt_handler(void) +{ +#ifdef _WIN32 + signal(SIGABRT, sigabrt_handler); +#else + struct sigaction sigact; + + sigact = (struct sigaction) { + .sa_handler = sigabrt_handler, + .sa_flags = SA_RESETHAND, + }; + sigemptyset(&sigact.sa_mask); + sigaction(SIGABRT, &sigact, NULL); +#endif +} + +int main(int argc, char **argv) +{ + int ret; + qemu_init_main_loop(&error_fatal); + bdrv_init(); + + g_test_init(&argc, &argv, NULL); + setup_sigabrt_handler(); + + prepare_imgs(); + + /* Primary */ + g_test_add_func("/replication/primary/read", test_primary_read); + g_test_add_func("/replication/primary/write", test_primary_write); + g_test_add_func("/replication/primary/start", test_primary_start); + g_test_add_func("/replication/primary/stop", test_primary_stop); + g_test_add_func("/replication/primary/do_checkpoint", + test_primary_do_checkpoint); + g_test_add_func("/replication/primary/get_error_all", + test_primary_get_error_all); + + /* Secondary */ + g_test_add_func("/replication/secondary/read", test_secondary_read); + g_test_add_func("/replication/secondary/write", test_secondary_write); + g_test_add_func("/replication/secondary/start", test_secondary_start); + g_test_add_func("/replication/secondary/stop", test_secondary_stop); + g_test_add_func("/replication/secondary/continuous_replication", + test_secondary_continuous_replication); + g_test_add_func("/replication/secondary/do_checkpoint", + test_secondary_do_checkpoint); + g_test_add_func("/replication/secondary/get_error_all", + test_secondary_get_error_all); + + ret = g_test_run(); + + cleanup_imgs(); + + return ret; +} From patchwork Thu Sep 3 07:43:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752577 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CF7A9739 for ; Thu, 3 Sep 2020 07:44:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A00E22071B for ; Thu, 3 Sep 2020 07:44:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Wtw9iMxi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A00E22071B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:44318 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjv7-0001iq-Nd for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:44:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43362) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuN-0008NA-He for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:47 -0400 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]:39091) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuK-0003s7-QL for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:47 -0400 Received: by mail-pj1-x1043.google.com with SMTP id s2so1058091pjr.4 for ; Thu, 03 Sep 2020 00:43:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=voK9C8LiSWL+Sm9aw369V+YjsDRfz05KST8rSNgg5Yw=; b=Wtw9iMxic1Ytac8zBMJ7f/CHaZshDu3ZqMq47D6EUzzhUYVfqHl7rGJ/X4ElpjHRWq ixHVi/MSzOhxC9uOLEEHBHDzskxkktNiwE8mdF0C4sGsyF/67hzRVC5r5FV3pOJHWccV C4DarvGRDWF2vpp74iqPpDx8Utw9Sqe2lA5bfCAW4mfhVA5HJwiTWE9wHGw2lc5HVOUV CMYz6RWPpTR5b1uJAn+X0PuK4NwwSJ5zXXJaTERlX2yrpz+SzS3O6UG8uzTnieGQd1SN J/N3DvoeltfQn9ugT9I/7vpfK4fql23xBiOSe5nbFhbR/usxsaVcsZbMKiCkThxKKtPc Q1ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=voK9C8LiSWL+Sm9aw369V+YjsDRfz05KST8rSNgg5Yw=; b=S7uUdibuMR2tweyXGg54V1nFWAf8FImkvJwrE1BVhtPfTZXKeiFNeu5ScAMtBAWhHX FiNYaY/xF14kM636ukUgPjVEHavt0Nc6E7bSWIEPhgyv4MRNwuTnrS9ACxCKzyP5RpxQ vZPlSFeVYA/rG+yHTOR7W7sb/GkO+ZwJWUy6+EzkIwrBut+ZMQYiyvmyWwjXgmsMyt4w qqVDxgfEYDB5t4R+FkoAFTURUjrCYTqQHtUkHwurv1dSm8LlZ7BgOp1gOi5V99iL8npG Q4Y/MDI7aSbF/DTBv0vbzCQfHXYcc3Kl6q55Z+ukpn1sDzTZ0ljYj1BZoB5Wc59k8ZHx BCuQ== X-Gm-Message-State: AOAM5335FPg6De3B2F9O2lnLEg1PK+Ia0I8Ol3STjXuzOnJtdyzY2MDM PG9cuOHYSDToESOxNrUaksfuV/H2A7ost4ql X-Google-Smtp-Source: ABdhPJz1l9nhz2Wbj2PvRbYYT9YZDSyA6eizKIlyrEz9+0WqEFy4/VAazPMFK7GX4zTgVJCBxhQFaw== X-Received: by 2002:a17:90a:fa8b:: with SMTP id cu11mr743957pjb.10.1599119022978; Thu, 03 Sep 2020 00:43:42 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:42 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 05/12] configure: Fix include and linkage issue on msys2 Date: Thu, 3 Sep 2020 15:43:06 +0800 Message-Id: <20200903074313.1498-6-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1043; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1043.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" On msys2, the -I/e/path/to/qemu -L/e/path/to/qemu are not recognized by the compiler Cause $PWD are result posix style path such as /e/path/to/qemu that can not be recognized by mingw gcc, and `pwd -W` are result Windows style path such as E:/path/to/qemu that can be recognized by the mingw gcc. So we replace all $PWD with $build_path that can building qemu under msys2/mingw environment. Signed-off-by: Yonggang Luo --- configure | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 30f8c4db29..5f2bcc4b57 100755 --- a/configure +++ b/configure @@ -13,8 +13,13 @@ export CCACHE_RECACHE=yes # make source path absolute source_path=$(cd "$(dirname -- "$0")"; pwd) +build_path=$PWD +if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then +source_path=$(cd "$(dirname -- "$0")"; pwd -W) +build_path=`pwd -W` +fi -if test "$PWD" = "$source_path" +if test "$build_path" = "$source_path" then echo "Using './build' as the directory for build output" @@ -346,7 +351,12 @@ ld_has() { $ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1 } -if printf %s\\n "$source_path" "$PWD" | grep -q "[[:space:]:]"; +check_valid_build_path="[[:space:]:]" +if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then +check_valid_build_path="[[:space:]]" +fi + +if printf %s\\n "$source_path" "$build_path" | grep -q "$check_valid_build_path"; then error_exit "main directory cannot contain spaces nor colons" fi @@ -943,7 +953,7 @@ Linux) linux="yes" linux_user="yes" kvm="yes" - QEMU_INCLUDES="-isystem ${source_path}/linux-headers -I$PWD/linux-headers $QEMU_INCLUDES" + QEMU_INCLUDES="-isystem ${source_path}/linux-headers -I${build_path}/linux-headers $QEMU_INCLUDES" libudev="yes" ;; esac @@ -4259,7 +4269,7 @@ EOF fdt=git mkdir -p dtc fdt_cflags="-I${source_path}/dtc/libfdt" - fdt_ldflags="-L$PWD/dtc/libfdt" + fdt_ldflags="-L${build_path}/dtc/libfdt" fdt_libs="$fdt_libs" elif test "$fdt" = "yes" ; then # Not a git build & no libfdt found, prompt for system install @@ -5244,7 +5254,7 @@ case "$capstone" in else LIBCAPSTONE=libcapstone.a fi - capstone_libs="-L$PWD/capstone -lcapstone" + capstone_libs="-L${build_path}/capstone -lcapstone" capstone_cflags="-I${source_path}/capstone/include" ;; @@ -6244,8 +6254,8 @@ case "$slirp" in git_submodules="${git_submodules} slirp" fi mkdir -p slirp - slirp_cflags="-I${source_path}/slirp/src -I$PWD/slirp/src" - slirp_libs="-L$PWD/slirp -lslirp" + slirp_cflags="-I${source_path}/slirp/src -I${build_path}/slirp/src" + slirp_libs="-L${build_path}/slirp -lslirp" if test "$mingw32" = "yes" ; then slirp_libs="$slirp_libs -lws2_32 -liphlpapi" fi @@ -8190,7 +8200,7 @@ fi mv $cross config-meson.cross rm -rf meson-private meson-info meson-logs -NINJA=${ninja:-$PWD/ninjatool} $meson setup \ +NINJA=${ninja:-${build_path}/ninjatool} $meson setup \ --prefix "${pre_prefix}$prefix" \ --libdir "${pre_prefix}$libdir" \ --libexecdir "${pre_prefix}$libexecdir" \ @@ -8212,7 +8222,7 @@ NINJA=${ninja:-$PWD/ninjatool} $meson setup \ -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f\ $cross_arg \ - "$PWD" "$source_path" + "$build_path" "$source_path" if test "$?" -ne 0 ; then error_exit "meson setup failed" From patchwork Thu Sep 3 07:43:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752579 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3C2ED739 for ; Thu, 3 Sep 2020 07:45:48 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D2D2E206A5 for ; Thu, 3 Sep 2020 07:45:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MgGhlS/p" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D2D2E206A5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:50522 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjwI-0004M9-Ti for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:45:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43388) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuS-00006I-Kp for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:52 -0400 Received: from mail-pg1-x532.google.com ([2607:f8b0:4864:20::532]:32781) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuO-0003sL-CU for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:52 -0400 Received: by mail-pg1-x532.google.com with SMTP id e33so1464308pgm.0 for ; Thu, 03 Sep 2020 00:43:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=H8XrF8Pb9GWB51Qq/Erw8qteOrJrg0KP5nGwFRkDrXA=; b=MgGhlS/pEz0BkLa5HNQZumnxoFHs2L91ynvwZ/aWelU62FuTrzy9DpAGI+FuttUe2B 8G0PFkzsqF/tUNefYKi5zHm0S5nQopxwtEoLoQLXfFZSGa0dgHCnOKxXtcgWf1dAOH7e SPc9kEml2JZMy84d/g3IRiEiLtBqrKgV9vZibihswQleFOEnP50c3KsGtDpAYgpDvQVa e0e50yPxCEAysbb3L8lliIhXEIBsi5RqnKAFPDjGKIy8oZUgcK5rt8+7FEXZWl6oJbbh 3d10rlO5UCOcdAxDvvwIZr6RqRCLrx6iTt5yPfy0nE01Sr6NLNP1T3vuLZFgb2A9VKKW bRTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=H8XrF8Pb9GWB51Qq/Erw8qteOrJrg0KP5nGwFRkDrXA=; b=VsiFdsVh+0SRX4Jaa7nvdQyD2Ei2Hs3haesOcR9NIYRl3s+dlNe4o83rCMtlEx4gLi h6OR2jmYge6LUkGD1XcUAWGrvemWE4hL4ao0ZUphHNp+CAW0IDB7h1qqDAccGivW2m5s iMlIKB/ctcM/YJLG80mcpWCzKlJkU6+wkJPAju7QXv56sASyWD5L4hDW8ihNOMViw4Mf kgzIjSjeY3yWnTdSyR2xgMxTUgIwCH0JZcU7430N5aSMNBsEiL1qMAiEySs/1txxWafM HggTPJrd9B1JBLnbxZVE0MY5p7VfESUCYz35HZr/HrBkFNPde6OrTEF3+JGeUFOczaQH BU0g== X-Gm-Message-State: AOAM533csRUHbkfFomjBTGjs8CBNtTunfGhjO8N1yzbm5z1LVHAlXuAg nLhQpNviNJfxIQW/qCengz7SszOxEJnOmQEo X-Google-Smtp-Source: ABdhPJxsbsX/06Oq+q7KLJH29b+x81/h7UNM6zh0A5N/X4tpFbMm18fLDZojvmJBw8J56nxl1TL1cg== X-Received: by 2002:a62:d44e:0:b029:13c:1611:652f with SMTP id u14-20020a62d44e0000b029013c1611652fmr911552pfl.15.1599119025539; Thu, 03 Sep 2020 00:43:45 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:44 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 06/12] block: Fixes nfs on msys2/mingw Date: Thu, 3 Sep 2020 15:43:07 +0800 Message-Id: <20200903074313.1498-7-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::532; envelope-from=luoyonggang@gmail.com; helo=mail-pg1-x532.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yonggang Luo --- block/nfs.c | 1812 ++++++++++++++++++++++++++------------------------- 1 file changed, 910 insertions(+), 902 deletions(-) diff --git a/block/nfs.c b/block/nfs.c index 61a249a9fc..34b2cd5708 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -1,902 +1,910 @@ -/* - * QEMU Block driver for native access to files on NFS shares - * - * Copyright (c) 2014-2017 Peter Lieven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" - -#include -#include "qemu/config-file.h" -#include "qemu/error-report.h" -#include "qapi/error.h" -#include "block/block_int.h" -#include "block/qdict.h" -#include "trace.h" -#include "qemu/iov.h" -#include "qemu/main-loop.h" -#include "qemu/module.h" -#include "qemu/option.h" -#include "qemu/uri.h" -#include "qemu/cutils.h" -#include "sysemu/sysemu.h" -#include "sysemu/replay.h" -#include "qapi/qapi-visit-block-core.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qobject-input-visitor.h" -#include "qapi/qobject-output-visitor.h" -#include - - -#define QEMU_NFS_MAX_READAHEAD_SIZE 1048576 -#define QEMU_NFS_MAX_PAGECACHE_SIZE (8388608 / NFS_BLKSIZE) -#define QEMU_NFS_MAX_DEBUG_LEVEL 2 - -typedef struct NFSClient { - struct nfs_context *context; - struct nfsfh *fh; - int events; - bool has_zero_init; - AioContext *aio_context; - QemuMutex mutex; - blkcnt_t st_blocks; - bool cache_used; - NFSServer *server; - char *path; - int64_t uid, gid, tcp_syncnt, readahead, pagecache, debug; -} NFSClient; - -typedef struct NFSRPC { - BlockDriverState *bs; - int ret; - int complete; - QEMUIOVector *iov; - struct stat *st; - Coroutine *co; - NFSClient *client; -} NFSRPC; - -static int nfs_parse_uri(const char *filename, QDict *options, Error **errp) -{ - URI *uri = NULL; - QueryParams *qp = NULL; - int ret = -EINVAL, i; - - uri = uri_parse(filename); - if (!uri) { - error_setg(errp, "Invalid URI specified"); - goto out; - } - if (g_strcmp0(uri->scheme, "nfs") != 0) { - error_setg(errp, "URI scheme must be 'nfs'"); - goto out; - } - - if (!uri->server) { - error_setg(errp, "missing hostname in URI"); - goto out; - } - - if (!uri->path) { - error_setg(errp, "missing file path in URI"); - goto out; - } - - qp = query_params_parse(uri->query); - if (!qp) { - error_setg(errp, "could not parse query parameters"); - goto out; - } - - qdict_put_str(options, "server.host", uri->server); - qdict_put_str(options, "server.type", "inet"); - qdict_put_str(options, "path", uri->path); - - for (i = 0; i < qp->n; i++) { - unsigned long long val; - if (!qp->p[i].value) { - error_setg(errp, "Value for NFS parameter expected: %s", - qp->p[i].name); - goto out; - } - if (parse_uint_full(qp->p[i].value, &val, 0)) { - error_setg(errp, "Illegal value for NFS parameter: %s", - qp->p[i].name); - goto out; - } - if (!strcmp(qp->p[i].name, "uid")) { - qdict_put_str(options, "user", qp->p[i].value); - } else if (!strcmp(qp->p[i].name, "gid")) { - qdict_put_str(options, "group", qp->p[i].value); - } else if (!strcmp(qp->p[i].name, "tcp-syncnt")) { - qdict_put_str(options, "tcp-syn-count", qp->p[i].value); - } else if (!strcmp(qp->p[i].name, "readahead")) { - qdict_put_str(options, "readahead-size", qp->p[i].value); - } else if (!strcmp(qp->p[i].name, "pagecache")) { - qdict_put_str(options, "page-cache-size", qp->p[i].value); - } else if (!strcmp(qp->p[i].name, "debug")) { - qdict_put_str(options, "debug", qp->p[i].value); - } else { - error_setg(errp, "Unknown NFS parameter name: %s", - qp->p[i].name); - goto out; - } - } - ret = 0; -out: - if (qp) { - query_params_free(qp); - } - if (uri) { - uri_free(uri); - } - return ret; -} - -static bool nfs_has_filename_options_conflict(QDict *options, Error **errp) -{ - const QDictEntry *qe; - - for (qe = qdict_first(options); qe; qe = qdict_next(options, qe)) { - if (!strcmp(qe->key, "host") || - !strcmp(qe->key, "path") || - !strcmp(qe->key, "user") || - !strcmp(qe->key, "group") || - !strcmp(qe->key, "tcp-syn-count") || - !strcmp(qe->key, "readahead-size") || - !strcmp(qe->key, "page-cache-size") || - !strcmp(qe->key, "debug") || - strstart(qe->key, "server.", NULL)) - { - error_setg(errp, "Option %s cannot be used with a filename", - qe->key); - return true; - } - } - - return false; -} - -static void nfs_parse_filename(const char *filename, QDict *options, - Error **errp) -{ - if (nfs_has_filename_options_conflict(options, errp)) { - return; - } - - nfs_parse_uri(filename, options, errp); -} - -static void nfs_process_read(void *arg); -static void nfs_process_write(void *arg); - -/* Called with QemuMutex held. */ -static void nfs_set_events(NFSClient *client) -{ - int ev = nfs_which_events(client->context); - if (ev != client->events) { - aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - false, - (ev & POLLIN) ? nfs_process_read : NULL, - (ev & POLLOUT) ? nfs_process_write : NULL, - NULL, client); - - } - client->events = ev; -} - -static void nfs_process_read(void *arg) -{ - NFSClient *client = arg; - - qemu_mutex_lock(&client->mutex); - nfs_service(client->context, POLLIN); - nfs_set_events(client); - qemu_mutex_unlock(&client->mutex); -} - -static void nfs_process_write(void *arg) -{ - NFSClient *client = arg; - - qemu_mutex_lock(&client->mutex); - nfs_service(client->context, POLLOUT); - nfs_set_events(client); - qemu_mutex_unlock(&client->mutex); -} - -static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task) -{ - *task = (NFSRPC) { - .co = qemu_coroutine_self(), - .bs = bs, - .client = bs->opaque, - }; -} - -static void nfs_co_generic_bh_cb(void *opaque) -{ - NFSRPC *task = opaque; - - task->complete = 1; - aio_co_wake(task->co); -} - -/* Called (via nfs_service) with QemuMutex held. */ -static void -nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, - void *private_data) -{ - NFSRPC *task = private_data; - task->ret = ret; - assert(!task->st); - if (task->ret > 0 && task->iov) { - if (task->ret <= task->iov->size) { - qemu_iovec_from_buf(task->iov, 0, data, task->ret); - } else { - task->ret = -EIO; - } - } - if (task->ret < 0) { - error_report("NFS Error: %s", nfs_get_error(nfs)); - } - replay_bh_schedule_oneshot_event(task->client->aio_context, - nfs_co_generic_bh_cb, task); -} - -static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *iov, - int flags) -{ - NFSClient *client = bs->opaque; - NFSRPC task; - - nfs_co_init_task(bs, &task); - task.iov = iov; - - WITH_QEMU_LOCK_GUARD(&client->mutex) { - if (nfs_pread_async(client->context, client->fh, - offset, bytes, nfs_co_generic_cb, &task) != 0) { - return -ENOMEM; - } - - nfs_set_events(client); - } - while (!task.complete) { - qemu_coroutine_yield(); - } - - if (task.ret < 0) { - return task.ret; - } - - /* zero pad short reads */ - if (task.ret < iov->size) { - qemu_iovec_memset(iov, task.ret, 0, iov->size - task.ret); - } - - return 0; -} - -static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *iov, - int flags) -{ - NFSClient *client = bs->opaque; - NFSRPC task; - char *buf = NULL; - bool my_buffer = false; - - nfs_co_init_task(bs, &task); - - if (iov->niov != 1) { - buf = g_try_malloc(bytes); - if (bytes && buf == NULL) { - return -ENOMEM; - } - qemu_iovec_to_buf(iov, 0, buf, bytes); - my_buffer = true; - } else { - buf = iov->iov[0].iov_base; - } - - WITH_QEMU_LOCK_GUARD(&client->mutex) { - if (nfs_pwrite_async(client->context, client->fh, - offset, bytes, buf, - nfs_co_generic_cb, &task) != 0) { - if (my_buffer) { - g_free(buf); - } - return -ENOMEM; - } - - nfs_set_events(client); - } - while (!task.complete) { - qemu_coroutine_yield(); - } - - if (my_buffer) { - g_free(buf); - } - - if (task.ret != bytes) { - return task.ret < 0 ? task.ret : -EIO; - } - - return 0; -} - -static int coroutine_fn nfs_co_flush(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - NFSRPC task; - - nfs_co_init_task(bs, &task); - - WITH_QEMU_LOCK_GUARD(&client->mutex) { - if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, - &task) != 0) { - return -ENOMEM; - } - - nfs_set_events(client); - } - while (!task.complete) { - qemu_coroutine_yield(); - } - - return task.ret; -} - -static void nfs_detach_aio_context(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - - aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - false, NULL, NULL, NULL, NULL); - client->events = 0; -} - -static void nfs_attach_aio_context(BlockDriverState *bs, - AioContext *new_context) -{ - NFSClient *client = bs->opaque; - - client->aio_context = new_context; - nfs_set_events(client); -} - -static void nfs_client_close(NFSClient *client) -{ - if (client->context) { - qemu_mutex_lock(&client->mutex); - aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - false, NULL, NULL, NULL, NULL); - qemu_mutex_unlock(&client->mutex); - if (client->fh) { - nfs_close(client->context, client->fh); - client->fh = NULL; - } -#ifdef LIBNFS_FEATURE_UMOUNT - nfs_umount(client->context); -#endif - nfs_destroy_context(client->context); - client->context = NULL; - } - g_free(client->path); - qemu_mutex_destroy(&client->mutex); - qapi_free_NFSServer(client->server); - client->server = NULL; -} - -static void nfs_file_close(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - nfs_client_close(client); -} - -static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts, - int flags, int open_flags, Error **errp) -{ - int64_t ret = -EINVAL; - struct stat st; - char *file = NULL, *strp = NULL; - - qemu_mutex_init(&client->mutex); - - client->path = g_strdup(opts->path); - - strp = strrchr(client->path, '/'); - if (strp == NULL) { - error_setg(errp, "Invalid URL specified"); - goto fail; - } - file = g_strdup(strp); - *strp = 0; - - /* Steal the NFSServer object from opts; set the original pointer to NULL - * to avoid use after free and double free. */ - client->server = opts->server; - opts->server = NULL; - - client->context = nfs_init_context(); - if (client->context == NULL) { - error_setg(errp, "Failed to init NFS context"); - goto fail; - } - - if (opts->has_user) { - client->uid = opts->user; - nfs_set_uid(client->context, client->uid); - } - - if (opts->has_group) { - client->gid = opts->group; - nfs_set_gid(client->context, client->gid); - } - - if (opts->has_tcp_syn_count) { - client->tcp_syncnt = opts->tcp_syn_count; - nfs_set_tcp_syncnt(client->context, client->tcp_syncnt); - } - -#ifdef LIBNFS_FEATURE_READAHEAD - if (opts->has_readahead_size) { - if (open_flags & BDRV_O_NOCACHE) { - error_setg(errp, "Cannot enable NFS readahead " - "if cache.direct = on"); - goto fail; - } - client->readahead = opts->readahead_size; - if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) { - warn_report("Truncating NFS readahead size to %d", - QEMU_NFS_MAX_READAHEAD_SIZE); - client->readahead = QEMU_NFS_MAX_READAHEAD_SIZE; - } - nfs_set_readahead(client->context, client->readahead); -#ifdef LIBNFS_FEATURE_PAGECACHE - nfs_set_pagecache_ttl(client->context, 0); -#endif - client->cache_used = true; - } -#endif - -#ifdef LIBNFS_FEATURE_PAGECACHE - if (opts->has_page_cache_size) { - if (open_flags & BDRV_O_NOCACHE) { - error_setg(errp, "Cannot enable NFS pagecache " - "if cache.direct = on"); - goto fail; - } - client->pagecache = opts->page_cache_size; - if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) { - warn_report("Truncating NFS pagecache size to %d pages", - QEMU_NFS_MAX_PAGECACHE_SIZE); - client->pagecache = QEMU_NFS_MAX_PAGECACHE_SIZE; - } - nfs_set_pagecache(client->context, client->pagecache); - nfs_set_pagecache_ttl(client->context, 0); - client->cache_used = true; - } -#endif - -#ifdef LIBNFS_FEATURE_DEBUG - if (opts->has_debug) { - client->debug = opts->debug; - /* limit the maximum debug level to avoid potential flooding - * of our log files. */ - if (client->debug > QEMU_NFS_MAX_DEBUG_LEVEL) { - warn_report("Limiting NFS debug level to %d", - QEMU_NFS_MAX_DEBUG_LEVEL); - client->debug = QEMU_NFS_MAX_DEBUG_LEVEL; - } - nfs_set_debug(client->context, client->debug); - } -#endif - - ret = nfs_mount(client->context, client->server->host, client->path); - if (ret < 0) { - error_setg(errp, "Failed to mount nfs share: %s", - nfs_get_error(client->context)); - goto fail; - } - - if (flags & O_CREAT) { - ret = nfs_creat(client->context, file, 0600, &client->fh); - if (ret < 0) { - error_setg(errp, "Failed to create file: %s", - nfs_get_error(client->context)); - goto fail; - } - } else { - ret = nfs_open(client->context, file, flags, &client->fh); - if (ret < 0) { - error_setg(errp, "Failed to open file : %s", - nfs_get_error(client->context)); - goto fail; - } - } - - ret = nfs_fstat(client->context, client->fh, &st); - if (ret < 0) { - error_setg(errp, "Failed to fstat file: %s", - nfs_get_error(client->context)); - goto fail; - } - - ret = DIV_ROUND_UP(st.st_size, BDRV_SECTOR_SIZE); - client->st_blocks = st.st_blocks; - client->has_zero_init = S_ISREG(st.st_mode); - *strp = '/'; - goto out; - -fail: - nfs_client_close(client); -out: - g_free(file); - return ret; -} - -static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options, - Error **errp) -{ - BlockdevOptionsNfs *opts = NULL; - Visitor *v; - const QDictEntry *e; - - v = qobject_input_visitor_new_flat_confused(options, errp); - if (!v) { - return NULL; - } - - visit_type_BlockdevOptionsNfs(v, NULL, &opts, errp); - visit_free(v); - if (!opts) { - return NULL; - } - - /* Remove the processed options from the QDict (the visitor processes - * _all_ options in the QDict) */ - while ((e = qdict_first(options))) { - qdict_del(options, e->key); - } - - return opts; -} - -static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options, - int flags, int open_flags, Error **errp) -{ - BlockdevOptionsNfs *opts; - int ret; - - opts = nfs_options_qdict_to_qapi(options, errp); - if (opts == NULL) { - ret = -EINVAL; - goto fail; - } - - ret = nfs_client_open(client, opts, flags, open_flags, errp); -fail: - qapi_free_BlockdevOptionsNfs(opts); - return ret; -} - -static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, - Error **errp) { - NFSClient *client = bs->opaque; - int64_t ret; - - client->aio_context = bdrv_get_aio_context(bs); - - ret = nfs_client_open_qdict(client, options, - (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY, - bs->open_flags, errp); - if (ret < 0) { - return ret; - } - - bs->total_sectors = ret; - if (client->has_zero_init) { - bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; - } - return 0; -} - -static QemuOptsList nfs_create_opts = { - .name = "nfs-create-opts", - .head = QTAILQ_HEAD_INITIALIZER(nfs_create_opts.head), - .desc = { - { - .name = BLOCK_OPT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Virtual disk size" - }, - { /* end of list */ } - } -}; - -static int nfs_file_co_create(BlockdevCreateOptions *options, Error **errp) -{ - BlockdevCreateOptionsNfs *opts = &options->u.nfs; - NFSClient *client = g_new0(NFSClient, 1); - int ret; - - assert(options->driver == BLOCKDEV_DRIVER_NFS); - - client->aio_context = qemu_get_aio_context(); - - ret = nfs_client_open(client, opts->location, O_CREAT, 0, errp); - if (ret < 0) { - goto out; - } - ret = nfs_ftruncate(client->context, client->fh, opts->size); - nfs_client_close(client); - -out: - g_free(client); - return ret; -} - -static int coroutine_fn nfs_file_co_create_opts(BlockDriver *drv, - const char *url, - QemuOpts *opts, - Error **errp) -{ - BlockdevCreateOptions *create_options; - BlockdevCreateOptionsNfs *nfs_opts; - QDict *options; - int ret; - - create_options = g_new0(BlockdevCreateOptions, 1); - create_options->driver = BLOCKDEV_DRIVER_NFS; - nfs_opts = &create_options->u.nfs; - - /* Read out options */ - nfs_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), - BDRV_SECTOR_SIZE); - - options = qdict_new(); - ret = nfs_parse_uri(url, options, errp); - if (ret < 0) { - goto out; - } - - nfs_opts->location = nfs_options_qdict_to_qapi(options, errp); - if (nfs_opts->location == NULL) { - ret = -EINVAL; - goto out; - } - - ret = nfs_file_co_create(create_options, errp); - if (ret < 0) { - goto out; - } - - ret = 0; -out: - qobject_unref(options); - qapi_free_BlockdevCreateOptions(create_options); - return ret; -} - -static int nfs_has_zero_init(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - return client->has_zero_init; -} - -/* Called (via nfs_service) with QemuMutex held. */ -static void -nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data, - void *private_data) -{ - NFSRPC *task = private_data; - task->ret = ret; - if (task->ret == 0) { - memcpy(task->st, data, sizeof(struct stat)); - } - if (task->ret < 0) { - error_report("NFS Error: %s", nfs_get_error(nfs)); - } - - /* Set task->complete before reading bs->wakeup. */ - atomic_mb_set(&task->complete, 1); - bdrv_wakeup(task->bs); -} - -static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - NFSRPC task = {0}; - struct stat st; - - if (bdrv_is_read_only(bs) && - !(bs->open_flags & BDRV_O_NOCACHE)) { - return client->st_blocks * 512; - } - - task.bs = bs; - task.st = &st; - if (nfs_fstat_async(client->context, client->fh, nfs_get_allocated_file_size_cb, - &task) != 0) { - return -ENOMEM; - } - - nfs_set_events(client); - BDRV_POLL_WHILE(bs, !task.complete); - - return (task.ret < 0 ? task.ret : st.st_blocks * 512); -} - -static int coroutine_fn -nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, - PreallocMode prealloc, BdrvRequestFlags flags, - Error **errp) -{ - NFSClient *client = bs->opaque; - int ret; - - if (prealloc != PREALLOC_MODE_OFF) { - error_setg(errp, "Unsupported preallocation mode '%s'", - PreallocMode_str(prealloc)); - return -ENOTSUP; - } - - ret = nfs_ftruncate(client->context, client->fh, offset); - if (ret < 0) { - error_setg_errno(errp, -ret, "Failed to truncate file"); - return ret; - } - - return 0; -} - -/* Note that this will not re-establish a connection with the NFS server - * - it is effectively a NOP. */ -static int nfs_reopen_prepare(BDRVReopenState *state, - BlockReopenQueue *queue, Error **errp) -{ - NFSClient *client = state->bs->opaque; - struct stat st; - int ret = 0; - - if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) { - error_setg(errp, "Cannot open a read-only mount as read-write"); - return -EACCES; - } - - if ((state->flags & BDRV_O_NOCACHE) && client->cache_used) { - error_setg(errp, "Cannot disable cache if libnfs readahead or" - " pagecache is enabled"); - return -EINVAL; - } - - /* Update cache for read-only reopens */ - if (!(state->flags & BDRV_O_RDWR)) { - ret = nfs_fstat(client->context, client->fh, &st); - if (ret < 0) { - error_setg(errp, "Failed to fstat file: %s", - nfs_get_error(client->context)); - return ret; - } - client->st_blocks = st.st_blocks; - } - - return 0; -} - -static void nfs_refresh_filename(BlockDriverState *bs) -{ - NFSClient *client = bs->opaque; - - if (client->uid && !client->gid) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nfs://%s%s?uid=%" PRId64, client->server->host, client->path, - client->uid); - } else if (!client->uid && client->gid) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nfs://%s%s?gid=%" PRId64, client->server->host, client->path, - client->gid); - } else if (client->uid && client->gid) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nfs://%s%s?uid=%" PRId64 "&gid=%" PRId64, - client->server->host, client->path, client->uid, client->gid); - } else { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nfs://%s%s", client->server->host, client->path); - } -} - -static char *nfs_dirname(BlockDriverState *bs, Error **errp) -{ - NFSClient *client = bs->opaque; - - if (client->uid || client->gid) { - bdrv_refresh_filename(bs); - error_setg(errp, "Cannot generate a base directory for NFS node '%s'", - bs->filename); - return NULL; - } - - return g_strdup_printf("nfs://%s%s/", client->server->host, client->path); -} - -#ifdef LIBNFS_FEATURE_PAGECACHE -static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs, - Error **errp) -{ - NFSClient *client = bs->opaque; - nfs_pagecache_invalidate(client->context, client->fh); -} -#endif - -static const char *nfs_strong_runtime_opts[] = { - "path", - "user", - "group", - "server.", - - NULL -}; - -static BlockDriver bdrv_nfs = { - .format_name = "nfs", - .protocol_name = "nfs", - - .instance_size = sizeof(NFSClient), - .bdrv_parse_filename = nfs_parse_filename, - .create_opts = &nfs_create_opts, - - .bdrv_has_zero_init = nfs_has_zero_init, - .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, - .bdrv_co_truncate = nfs_file_co_truncate, - - .bdrv_file_open = nfs_file_open, - .bdrv_close = nfs_file_close, - .bdrv_co_create = nfs_file_co_create, - .bdrv_co_create_opts = nfs_file_co_create_opts, - .bdrv_reopen_prepare = nfs_reopen_prepare, - - .bdrv_co_preadv = nfs_co_preadv, - .bdrv_co_pwritev = nfs_co_pwritev, - .bdrv_co_flush_to_disk = nfs_co_flush, - - .bdrv_detach_aio_context = nfs_detach_aio_context, - .bdrv_attach_aio_context = nfs_attach_aio_context, - .bdrv_refresh_filename = nfs_refresh_filename, - .bdrv_dirname = nfs_dirname, - - .strong_runtime_opts = nfs_strong_runtime_opts, - -#ifdef LIBNFS_FEATURE_PAGECACHE - .bdrv_co_invalidate_cache = nfs_co_invalidate_cache, -#endif -}; - -static void nfs_block_init(void) -{ - bdrv_register(&bdrv_nfs); -} - -block_init(nfs_block_init); +/* + * QEMU Block driver for native access to files on NFS shares + * + * Copyright (c) 2014-2017 Peter Lieven + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#if !defined(_WIN32) +#include +#endif +#include "qemu/config-file.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "block/block_int.h" +#include "block/qdict.h" +#include "trace.h" +#include "qemu/iov.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qemu/uri.h" +#include "qemu/cutils.h" +#include "sysemu/sysemu.h" +#include "sysemu/replay.h" +#include "qapi/qapi-visit-block-core.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" +#include + + +#define QEMU_NFS_MAX_READAHEAD_SIZE 1048576 +#define QEMU_NFS_MAX_PAGECACHE_SIZE (8388608 / NFS_BLKSIZE) +#define QEMU_NFS_MAX_DEBUG_LEVEL 2 + +#if defined (_WIN32) +#define nfs_stat __stat64 +#else +#define nfs_stat stat +#endif + +typedef struct NFSClient { + struct nfs_context *context; + struct nfsfh *fh; + int events; + bool has_zero_init; + AioContext *aio_context; + QemuMutex mutex; + int64_t st_size; + bool cache_used; + NFSServer *server; + char *path; + int64_t uid, gid, tcp_syncnt, readahead, pagecache, debug; +} NFSClient; + +typedef struct NFSRPC { + BlockDriverState *bs; + int ret; + int complete; + QEMUIOVector *iov; + struct nfs_stat *st; + Coroutine *co; + NFSClient *client; +} NFSRPC; + +static int nfs_parse_uri(const char *filename, QDict *options, Error **errp) +{ + URI *uri = NULL; + QueryParams *qp = NULL; + int ret = -EINVAL, i; + + uri = uri_parse(filename); + if (!uri) { + error_setg(errp, "Invalid URI specified"); + goto out; + } + if (g_strcmp0(uri->scheme, "nfs") != 0) { + error_setg(errp, "URI scheme must be 'nfs'"); + goto out; + } + + if (!uri->server) { + error_setg(errp, "missing hostname in URI"); + goto out; + } + + if (!uri->path) { + error_setg(errp, "missing file path in URI"); + goto out; + } + + qp = query_params_parse(uri->query); + if (!qp) { + error_setg(errp, "could not parse query parameters"); + goto out; + } + + qdict_put_str(options, "server.host", uri->server); + qdict_put_str(options, "server.type", "inet"); + qdict_put_str(options, "path", uri->path); + + for (i = 0; i < qp->n; i++) { + unsigned long long val; + if (!qp->p[i].value) { + error_setg(errp, "Value for NFS parameter expected: %s", + qp->p[i].name); + goto out; + } + if (parse_uint_full(qp->p[i].value, &val, 0)) { + error_setg(errp, "Illegal value for NFS parameter: %s", + qp->p[i].name); + goto out; + } + if (!strcmp(qp->p[i].name, "uid")) { + qdict_put_str(options, "user", qp->p[i].value); + } else if (!strcmp(qp->p[i].name, "gid")) { + qdict_put_str(options, "group", qp->p[i].value); + } else if (!strcmp(qp->p[i].name, "tcp-syncnt")) { + qdict_put_str(options, "tcp-syn-count", qp->p[i].value); + } else if (!strcmp(qp->p[i].name, "readahead")) { + qdict_put_str(options, "readahead-size", qp->p[i].value); + } else if (!strcmp(qp->p[i].name, "pagecache")) { + qdict_put_str(options, "page-cache-size", qp->p[i].value); + } else if (!strcmp(qp->p[i].name, "debug")) { + qdict_put_str(options, "debug", qp->p[i].value); + } else { + error_setg(errp, "Unknown NFS parameter name: %s", + qp->p[i].name); + goto out; + } + } + ret = 0; +out: + if (qp) { + query_params_free(qp); + } + if (uri) { + uri_free(uri); + } + return ret; +} + +static bool nfs_has_filename_options_conflict(QDict *options, Error **errp) +{ + const QDictEntry *qe; + + for (qe = qdict_first(options); qe; qe = qdict_next(options, qe)) { + if (!strcmp(qe->key, "host") || + !strcmp(qe->key, "path") || + !strcmp(qe->key, "user") || + !strcmp(qe->key, "group") || + !strcmp(qe->key, "tcp-syn-count") || + !strcmp(qe->key, "readahead-size") || + !strcmp(qe->key, "page-cache-size") || + !strcmp(qe->key, "debug") || + strstart(qe->key, "server.", NULL)) + { + error_setg(errp, "Option %s cannot be used with a filename", + qe->key); + return true; + } + } + + return false; +} + +static void nfs_parse_filename(const char *filename, QDict *options, + Error **errp) +{ + if (nfs_has_filename_options_conflict(options, errp)) { + return; + } + + nfs_parse_uri(filename, options, errp); +} + +static void nfs_process_read(void *arg); +static void nfs_process_write(void *arg); + +/* Called with QemuMutex held. */ +static void nfs_set_events(NFSClient *client) +{ + int ev = nfs_which_events(client->context); + if (ev != client->events) { + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + false, + (ev & POLLIN) ? nfs_process_read : NULL, + (ev & POLLOUT) ? nfs_process_write : NULL, + NULL, client); + + } + client->events = ev; +} + +static void nfs_process_read(void *arg) +{ + NFSClient *client = arg; + + qemu_mutex_lock(&client->mutex); + nfs_service(client->context, POLLIN); + nfs_set_events(client); + qemu_mutex_unlock(&client->mutex); +} + +static void nfs_process_write(void *arg) +{ + NFSClient *client = arg; + + qemu_mutex_lock(&client->mutex); + nfs_service(client->context, POLLOUT); + nfs_set_events(client); + qemu_mutex_unlock(&client->mutex); +} + +static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task) +{ + *task = (NFSRPC) { + .co = qemu_coroutine_self(), + .bs = bs, + .client = bs->opaque, + }; +} + +static void nfs_co_generic_bh_cb(void *opaque) +{ + NFSRPC *task = opaque; + + task->complete = 1; + aio_co_wake(task->co); +} + +/* Called (via nfs_service) with QemuMutex held. */ +static void +nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, + void *private_data) +{ + NFSRPC *task = private_data; + task->ret = ret; + assert(!task->st); + if (task->ret > 0 && task->iov) { + if (task->ret <= task->iov->size) { + qemu_iovec_from_buf(task->iov, 0, data, task->ret); + } else { + task->ret = -EIO; + } + } + if (task->ret < 0) { + error_report("NFS Error: %s", nfs_get_error(nfs)); + } + replay_bh_schedule_oneshot_event(task->client->aio_context, + nfs_co_generic_bh_cb, task); +} + +static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *iov, + int flags) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + + nfs_co_init_task(bs, &task); + task.iov = iov; + + WITH_QEMU_LOCK_GUARD(&client->mutex) { + if (nfs_pread_async(client->context, client->fh, + offset, bytes, nfs_co_generic_cb, &task) != 0) { + return -ENOMEM; + } + + nfs_set_events(client); + } + while (!task.complete) { + qemu_coroutine_yield(); + } + + if (task.ret < 0) { + return task.ret; + } + + /* zero pad short reads */ + if (task.ret < iov->size) { + qemu_iovec_memset(iov, task.ret, 0, iov->size - task.ret); + } + + return 0; +} + +static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *iov, + int flags) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + char *buf = NULL; + bool my_buffer = false; + + nfs_co_init_task(bs, &task); + + if (iov->niov != 1) { + buf = g_try_malloc(bytes); + if (bytes && buf == NULL) { + return -ENOMEM; + } + qemu_iovec_to_buf(iov, 0, buf, bytes); + my_buffer = true; + } else { + buf = iov->iov[0].iov_base; + } + + WITH_QEMU_LOCK_GUARD(&client->mutex) { + if (nfs_pwrite_async(client->context, client->fh, + offset, bytes, buf, + nfs_co_generic_cb, &task) != 0) { + if (my_buffer) { + g_free(buf); + } + return -ENOMEM; + } + + nfs_set_events(client); + } + while (!task.complete) { + qemu_coroutine_yield(); + } + + if (my_buffer) { + g_free(buf); + } + + if (task.ret != bytes) { + return task.ret < 0 ? task.ret : -EIO; + } + + return 0; +} + +static int coroutine_fn nfs_co_flush(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + + nfs_co_init_task(bs, &task); + + WITH_QEMU_LOCK_GUARD(&client->mutex) { + if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, + &task) != 0) { + return -ENOMEM; + } + + nfs_set_events(client); + } + while (!task.complete) { + qemu_coroutine_yield(); + } + + return task.ret; +} + +static void nfs_detach_aio_context(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + false, NULL, NULL, NULL, NULL); + client->events = 0; +} + +static void nfs_attach_aio_context(BlockDriverState *bs, + AioContext *new_context) +{ + NFSClient *client = bs->opaque; + + client->aio_context = new_context; + nfs_set_events(client); +} + +static void nfs_client_close(NFSClient *client) +{ + if (client->context) { + qemu_mutex_lock(&client->mutex); + aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), + false, NULL, NULL, NULL, NULL); + qemu_mutex_unlock(&client->mutex); + if (client->fh) { + nfs_close(client->context, client->fh); + client->fh = NULL; + } +#ifdef LIBNFS_FEATURE_UMOUNT + nfs_umount(client->context); +#endif + nfs_destroy_context(client->context); + client->context = NULL; + } + g_free(client->path); + qemu_mutex_destroy(&client->mutex); + qapi_free_NFSServer(client->server); + client->server = NULL; +} + +static void nfs_file_close(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + nfs_client_close(client); +} + +static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts, + int flags, int open_flags, Error **errp) +{ + int64_t ret = -EINVAL; + struct nfs_stat st; + char *file = NULL, *strp = NULL; + + qemu_mutex_init(&client->mutex); + + client->path = g_strdup(opts->path); + + strp = strrchr(client->path, '/'); + if (strp == NULL) { + error_setg(errp, "Invalid URL specified"); + goto fail; + } + file = g_strdup(strp); + *strp = 0; + + /* Steal the NFSServer object from opts; set the original pointer to NULL + * to avoid use after free and double free. */ + client->server = opts->server; + opts->server = NULL; + + client->context = nfs_init_context(); + if (client->context == NULL) { + error_setg(errp, "Failed to init NFS context"); + goto fail; + } + + if (opts->has_user) { + client->uid = opts->user; + nfs_set_uid(client->context, client->uid); + } + + if (opts->has_group) { + client->gid = opts->group; + nfs_set_gid(client->context, client->gid); + } + + if (opts->has_tcp_syn_count) { + client->tcp_syncnt = opts->tcp_syn_count; + nfs_set_tcp_syncnt(client->context, client->tcp_syncnt); + } + +#ifdef LIBNFS_FEATURE_READAHEAD + if (opts->has_readahead_size) { + if (open_flags & BDRV_O_NOCACHE) { + error_setg(errp, "Cannot enable NFS readahead " + "if cache.direct = on"); + goto fail; + } + client->readahead = opts->readahead_size; + if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) { + warn_report("Truncating NFS readahead size to %d", + QEMU_NFS_MAX_READAHEAD_SIZE); + client->readahead = QEMU_NFS_MAX_READAHEAD_SIZE; + } + nfs_set_readahead(client->context, client->readahead); +#ifdef LIBNFS_FEATURE_PAGECACHE + nfs_set_pagecache_ttl(client->context, 0); +#endif + client->cache_used = true; + } +#endif + +#ifdef LIBNFS_FEATURE_PAGECACHE + if (opts->has_page_cache_size) { + if (open_flags & BDRV_O_NOCACHE) { + error_setg(errp, "Cannot enable NFS pagecache " + "if cache.direct = on"); + goto fail; + } + client->pagecache = opts->page_cache_size; + if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) { + warn_report("Truncating NFS pagecache size to %d pages", + QEMU_NFS_MAX_PAGECACHE_SIZE); + client->pagecache = QEMU_NFS_MAX_PAGECACHE_SIZE; + } + nfs_set_pagecache(client->context, client->pagecache); + nfs_set_pagecache_ttl(client->context, 0); + client->cache_used = true; + } +#endif + +#ifdef LIBNFS_FEATURE_DEBUG + if (opts->has_debug) { + client->debug = opts->debug; + /* limit the maximum debug level to avoid potential flooding + * of our log files. */ + if (client->debug > QEMU_NFS_MAX_DEBUG_LEVEL) { + warn_report("Limiting NFS debug level to %d", + QEMU_NFS_MAX_DEBUG_LEVEL); + client->debug = QEMU_NFS_MAX_DEBUG_LEVEL; + } + nfs_set_debug(client->context, client->debug); + } +#endif + + ret = nfs_mount(client->context, client->server->host, client->path); + if (ret < 0) { + error_setg(errp, "Failed to mount nfs share: %s", + nfs_get_error(client->context)); + goto fail; + } + + if (flags & O_CREAT) { + ret = nfs_creat(client->context, file, 0600, &client->fh); + if (ret < 0) { + error_setg(errp, "Failed to create file: %s", + nfs_get_error(client->context)); + goto fail; + } + } else { + ret = nfs_open(client->context, file, flags, &client->fh); + if (ret < 0) { + error_setg(errp, "Failed to open file : %s", + nfs_get_error(client->context)); + goto fail; + } + } + + ret = nfs_fstat(client->context, client->fh, &st); + if (ret < 0) { + error_setg(errp, "Failed to fstat file: %s", + nfs_get_error(client->context)); + goto fail; + } + + ret = DIV_ROUND_UP(st.st_size, BDRV_SECTOR_SIZE); + client->st_size = st.st_size; + client->has_zero_init = S_ISREG(st.st_mode); + *strp = '/'; + goto out; + +fail: + nfs_client_close(client); +out: + g_free(file); + return ret; +} + +static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options, + Error **errp) +{ + BlockdevOptionsNfs *opts = NULL; + Visitor *v; + const QDictEntry *e; + + v = qobject_input_visitor_new_flat_confused(options, errp); + if (!v) { + return NULL; + } + + visit_type_BlockdevOptionsNfs(v, NULL, &opts, errp); + visit_free(v); + if (!opts) { + return NULL; + } + + /* Remove the processed options from the QDict (the visitor processes + * _all_ options in the QDict) */ + while ((e = qdict_first(options))) { + qdict_del(options, e->key); + } + + return opts; +} + +static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options, + int flags, int open_flags, Error **errp) +{ + BlockdevOptionsNfs *opts; + int ret; + + opts = nfs_options_qdict_to_qapi(options, errp); + if (opts == NULL) { + ret = -EINVAL; + goto fail; + } + + ret = nfs_client_open(client, opts, flags, open_flags, errp); +fail: + qapi_free_BlockdevOptionsNfs(opts); + return ret; +} + +static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) { + NFSClient *client = bs->opaque; + int64_t ret; + + client->aio_context = bdrv_get_aio_context(bs); + + ret = nfs_client_open_qdict(client, options, + (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY, + bs->open_flags, errp); + if (ret < 0) { + return ret; + } + + bs->total_sectors = ret; + if (client->has_zero_init) { + bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; + } + return 0; +} + +static QemuOptsList nfs_create_opts = { + .name = "nfs-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(nfs_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } +}; + +static int nfs_file_co_create(BlockdevCreateOptions *options, Error **errp) +{ + BlockdevCreateOptionsNfs *opts = &options->u.nfs; + NFSClient *client = g_new0(NFSClient, 1); + int ret; + + assert(options->driver == BLOCKDEV_DRIVER_NFS); + + client->aio_context = qemu_get_aio_context(); + + ret = nfs_client_open(client, opts->location, O_CREAT, 0, errp); + if (ret < 0) { + goto out; + } + ret = nfs_ftruncate(client->context, client->fh, opts->size); + nfs_client_close(client); + +out: + g_free(client); + return ret; +} + +static int coroutine_fn nfs_file_co_create_opts(BlockDriver *drv, + const char *url, + QemuOpts *opts, + Error **errp) +{ + BlockdevCreateOptions *create_options; + BlockdevCreateOptionsNfs *nfs_opts; + QDict *options; + int ret; + + create_options = g_new0(BlockdevCreateOptions, 1); + create_options->driver = BLOCKDEV_DRIVER_NFS; + nfs_opts = &create_options->u.nfs; + + /* Read out options */ + nfs_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); + + options = qdict_new(); + ret = nfs_parse_uri(url, options, errp); + if (ret < 0) { + goto out; + } + + nfs_opts->location = nfs_options_qdict_to_qapi(options, errp); + if (nfs_opts->location == NULL) { + ret = -EINVAL; + goto out; + } + + ret = nfs_file_co_create(create_options, errp); + if (ret < 0) { + goto out; + } + + ret = 0; +out: + qobject_unref(options); + qapi_free_BlockdevCreateOptions(create_options); + return ret; +} + +static int nfs_has_zero_init(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + return client->has_zero_init; +} + +/* Called (via nfs_service) with QemuMutex held. */ +static void +nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data, + void *private_data) +{ + NFSRPC *task = private_data; + task->ret = ret; + if (task->ret == 0) { + memcpy(task->st, data, sizeof(struct stat)); + } + if (task->ret < 0) { + error_report("NFS Error: %s", nfs_get_error(nfs)); + } + + /* Set task->complete before reading bs->wakeup. */ + atomic_mb_set(&task->complete, 1); + bdrv_wakeup(task->bs); +} + +static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + NFSRPC task = {0}; + struct nfs_stat st; + + if (bdrv_is_read_only(bs) && + !(bs->open_flags & BDRV_O_NOCACHE)) { + return client->st_size; + } + + task.bs = bs; + task.st = &st; + if (nfs_fstat_async(client->context, client->fh, nfs_get_allocated_file_size_cb, + &task) != 0) { + return -ENOMEM; + } + + nfs_set_events(client); + BDRV_POLL_WHILE(bs, !task.complete); + + return (task.ret < 0 ? task.ret : st.st_size); +} + +static int coroutine_fn +nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, + Error **errp) +{ + NFSClient *client = bs->opaque; + int ret; + + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_str(prealloc)); + return -ENOTSUP; + } + + ret = nfs_ftruncate(client->context, client->fh, offset); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to truncate file"); + return ret; + } + + return 0; +} + +/* Note that this will not re-establish a connection with the NFS server + * - it is effectively a NOP. */ +static int nfs_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + NFSClient *client = state->bs->opaque; + struct nfs_stat st; + int ret = 0; + + if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) { + error_setg(errp, "Cannot open a read-only mount as read-write"); + return -EACCES; + } + + if ((state->flags & BDRV_O_NOCACHE) && client->cache_used) { + error_setg(errp, "Cannot disable cache if libnfs readahead or" + " pagecache is enabled"); + return -EINVAL; + } + + /* Update cache for read-only reopens */ + if (!(state->flags & BDRV_O_RDWR)) { + ret = nfs_fstat(client->context, client->fh, &st); + if (ret < 0) { + error_setg(errp, "Failed to fstat file: %s", + nfs_get_error(client->context)); + return ret; + } + client->st_size = st.st_size; + } + + return 0; +} + +static void nfs_refresh_filename(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + + if (client->uid && !client->gid) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nfs://%s%s?uid=%" PRId64, client->server->host, client->path, + client->uid); + } else if (!client->uid && client->gid) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nfs://%s%s?gid=%" PRId64, client->server->host, client->path, + client->gid); + } else if (client->uid && client->gid) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nfs://%s%s?uid=%" PRId64 "&gid=%" PRId64, + client->server->host, client->path, client->uid, client->gid); + } else { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nfs://%s%s", client->server->host, client->path); + } +} + +static char *nfs_dirname(BlockDriverState *bs, Error **errp) +{ + NFSClient *client = bs->opaque; + + if (client->uid || client->gid) { + bdrv_refresh_filename(bs); + error_setg(errp, "Cannot generate a base directory for NFS node '%s'", + bs->filename); + return NULL; + } + + return g_strdup_printf("nfs://%s%s/", client->server->host, client->path); +} + +#ifdef LIBNFS_FEATURE_PAGECACHE +static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs, + Error **errp) +{ + NFSClient *client = bs->opaque; + nfs_pagecache_invalidate(client->context, client->fh); +} +#endif + +static const char *nfs_strong_runtime_opts[] = { + "path", + "user", + "group", + "server.", + + NULL +}; + +static BlockDriver bdrv_nfs = { + .format_name = "nfs", + .protocol_name = "nfs", + + .instance_size = sizeof(NFSClient), + .bdrv_parse_filename = nfs_parse_filename, + .create_opts = &nfs_create_opts, + + .bdrv_has_zero_init = nfs_has_zero_init, + .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, + .bdrv_co_truncate = nfs_file_co_truncate, + + .bdrv_file_open = nfs_file_open, + .bdrv_close = nfs_file_close, + .bdrv_co_create = nfs_file_co_create, + .bdrv_co_create_opts = nfs_file_co_create_opts, + .bdrv_reopen_prepare = nfs_reopen_prepare, + + .bdrv_co_preadv = nfs_co_preadv, + .bdrv_co_pwritev = nfs_co_pwritev, + .bdrv_co_flush_to_disk = nfs_co_flush, + + .bdrv_detach_aio_context = nfs_detach_aio_context, + .bdrv_attach_aio_context = nfs_attach_aio_context, + .bdrv_refresh_filename = nfs_refresh_filename, + .bdrv_dirname = nfs_dirname, + + .strong_runtime_opts = nfs_strong_runtime_opts, + +#ifdef LIBNFS_FEATURE_PAGECACHE + .bdrv_co_invalidate_cache = nfs_co_invalidate_cache, +#endif +}; + +static void nfs_block_init(void) +{ + bdrv_register(&bdrv_nfs); +} + +block_init(nfs_block_init); From patchwork Thu Sep 3 07:43:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752581 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 36B1E739 for ; Thu, 3 Sep 2020 07:46:07 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CC8F1206C0 for ; Thu, 3 Sep 2020 07:46:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HN+AGNaV" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CC8F1206C0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:51900 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjwb-0004uG-U0 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:46:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43408) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuW-0000G2-7E for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:56 -0400 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]:42938) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuR-0003t0-QA for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:55 -0400 Received: by mail-pg1-x533.google.com with SMTP id m5so1439681pgj.9 for ; Thu, 03 Sep 2020 00:43:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HH+mCBnKGF/uCXFL1Exd9geD9MTauuClce/JbIg2O48=; b=HN+AGNaVLH+KmW55Pi2OutSNYueb0Yee9qINdRhgRdQYwsOkBavSe6nrP2F0nG+lYj sLDSSjK7ehb/n1Z0V1NbfjKN2KFe2h8o9lFyyxKtS4iAERKiF5Q4Liix1USUyV9MxOum CJOQzv7UW5qS5+e8HbnFhLKHPzNd2hgKgqXN/BvpvLzDC8VPr6JuWzpv0zQnLJVb25du 1/ABvsgh+af2JgLCXHFuMRKSYWc2/Xw1M9IYgT/9XjDBM5fA+576TQJSR3Yi3XvPRg/o 6c1AnuM0XBJbQk6QUulcjXV5EHmwXGIiqTmLtdiU9mPawRbWdKaWXXOaQCso1RpERCj8 v19w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HH+mCBnKGF/uCXFL1Exd9geD9MTauuClce/JbIg2O48=; b=dh37IL558Op/SVky65LFVzkKGeBkznn8d1431VeWAcF2mHg/3ZRDuqGLUHnG+kUg4H FEtkGge1B+h+EJ7/7Fd4M+qs5hNHe1/lOBXsiLszTf2KqU3KvmGLlH3tdC2GkcnySEQJ 5AW2JF0Lek/6x+o5t+tgo60ZmCxkocqeY9FARPlHLgcQTq4IMh+P+9bvINBeQSshozGm A3NxsgE7YOBXjMWj5diM9cq+DhC5z+jxFEfUmiLkGF7RKLRb86F/dOA0iexoTsXM6QwV U1IQHiJ3SM7sfve3dP/X/x9gaVd2/PLPUnPFDLcXnwKpRkVBzffE/IlaOkWxj4/6Ajdf Lb+A== X-Gm-Message-State: AOAM533ZDfB550vCIiFBVmOgu9e3PJoI09hu24CGI93Lvaac0RGbukfR PSaXYrt3yDa3Q2jlQYdrzOi74pdHfIJuPmnD X-Google-Smtp-Source: ABdhPJwumR/4Mo2Lk1rF5FKHijerEoQtcsej4d07i099o87801otZ9JarnsugZAJ2UuJFTlgm2DSlw== X-Received: by 2002:aa7:80d3:: with SMTP id a19mr2661743pfn.102.1599119028595; Thu, 03 Sep 2020 00:43:48 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:47 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 07/12] osdep: These function are only available on Non-Win32 system. Date: Thu, 3 Sep 2020 15:43:08 +0800 Message-Id: <20200903074313.1498-8-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::533; envelope-from=luoyonggang@gmail.com; helo=mail-pg1-x533.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive); int qemu_unlock_fd(int fd, int64_t start, int64_t len); int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); bool qemu_has_ofd_lock(void); Signed-off-by: Yonggang Luo --- include/qemu/osdep.h | 1372 +++++++++++++++++++++--------------------- 1 file changed, 686 insertions(+), 686 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 412962d91a..e80fddd1e8 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -1,686 +1,686 @@ -/* - * OS includes and handling of OS dependencies - * - * This header exists to pull in some common system headers that - * most code in QEMU will want, and to fix up some possible issues with - * it (missing defines, Windows weirdness, and so on). - * - * To avoid getting into possible circular include dependencies, this - * file should not include any other QEMU headers, with the exceptions - * of config-host.h, config-target.h, qemu/compiler.h, - * sysemu/os-posix.h, sysemu/os-win32.h, glib-compat.h and - * qemu/typedefs.h, all of which are doing a similar job to this file - * and are under similar constraints. - * - * This header also contains prototypes for functions defined in - * os-*.c and util/oslib-*.c; those would probably be better split - * out into separate header files. - * - * In an ideal world this header would contain only: - * (1) things which everybody needs - * (2) things without which code would work on most platforms but - * fail to compile or misbehave on a minority of host OSes - * - * 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_OSDEP_H -#define QEMU_OSDEP_H - -#include "config-host.h" -#ifdef NEED_CPU_H -#include CONFIG_TARGET -#else -#include "exec/poison.h" -#endif - -#include "qemu/compiler.h" - -/* Older versions of C++ don't get definitions of various macros from - * stdlib.h unless we define these macros before first inclusion of - * that system header. - */ -#ifndef __STDC_CONSTANT_MACROS -#define __STDC_CONSTANT_MACROS -#endif -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif - -/* The following block of code temporarily renames the daemon() function so the - * compiler does not see the warning associated with it in stdlib.h on OSX - */ -#ifdef __APPLE__ -#define daemon qemu_fake_daemon_function -#include -#undef daemon -extern int daemon(int, int); -#endif - -#ifdef _WIN32 -/* as defined in sdkddkver.h */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 /* Vista */ -#endif -/* reduces the number of implicitly included headers */ -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#endif - -/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */ -#ifdef __MINGW32__ -#define __USE_MINGW_ANSI_STDIO 1 -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -/* Put unistd.h before time.h as that triggers localtime_r/gmtime_r - * function availability on recentish Mingw-w64 platforms. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* setjmp must be declared before sysemu/os-win32.h - * because it is redefined there. */ -#include -#include - -#ifdef HAVE_SYS_SIGNAL_H -#include -#endif - -#ifndef _WIN32 -#include -#else -#define WIFEXITED(x) 1 -#define WEXITSTATUS(x) (x) -#endif - -#ifdef _WIN32 -#include "sysemu/os-win32.h" -#endif - -#ifdef CONFIG_POSIX -#include "sysemu/os-posix.h" -#endif - -#include "glib-compat.h" -#include "qemu/typedefs.h" - -/* - * For mingw, as of v6.0.0, the function implementing the assert macro is - * not marked as noreturn, so the compiler cannot delete code following an - * assert(false) as unused. We rely on this within the code base to delete - * code that is unreachable when features are disabled. - * All supported versions of Glib's g_assert() satisfy this requirement. - */ -#ifdef __MINGW32__ -#undef assert -#define assert(x) g_assert(x) -#endif - -/* - * According to waitpid man page: - * WCOREDUMP - * This macro is not specified in POSIX.1-2001 and is not - * available on some UNIX implementations (e.g., AIX, SunOS). - * Therefore, enclose its use inside #ifdef WCOREDUMP ... #endif. - */ -#ifndef WCOREDUMP -#define WCOREDUMP(status) 0 -#endif -/* - * We have a lot of unaudited code that may fail in strange ways, or - * even be a security risk during migration, if you disable assertions - * at compile-time. You may comment out these safety checks if you - * absolutely want to disable assertion overhead, but it is not - * supported upstream so the risk is all yours. Meanwhile, please - * submit patches to remove any side-effects inside an assertion, or - * fixing error handling that should use Error instead of assert. - */ -#ifdef NDEBUG -#error building with NDEBUG is not supported -#endif -#ifdef G_DISABLE_ASSERT -#error building with G_DISABLE_ASSERT is not supported -#endif - -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif -#ifndef O_BINARY -#define O_BINARY 0 -#endif -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -#ifndef MAP_FIXED_NOREPLACE -#define MAP_FIXED_NOREPLACE 0 -#endif -#ifndef ENOMEDIUM -#define ENOMEDIUM ENODEV -#endif -#if !defined(ENOTSUP) -#define ENOTSUP 4096 -#endif -#if !defined(ECANCELED) -#define ECANCELED 4097 -#endif -#if !defined(EMEDIUMTYPE) -#define EMEDIUMTYPE 4098 -#endif -#if !defined(ESHUTDOWN) -#define ESHUTDOWN 4099 -#endif - -/* time_t may be either 32 or 64 bits depending on the host OS, and - * can be either signed or unsigned, so we can't just hardcode a - * specific maximum value. This is not a C preprocessor constant, - * so you can't use TIME_MAX in an #ifdef, but for our purposes - * this isn't a problem. - */ - -/* The macros TYPE_SIGNED, TYPE_WIDTH, and TYPE_MAXIMUM are from - * Gnulib, and are under the LGPL v2.1 or (at your option) any - * later version. - */ - -/* True if the real type T is signed. */ -#define TYPE_SIGNED(t) (!((t)0 < (t)-1)) - -/* The width in bits of the integer type or expression T. - * Padding bits are not supported. - */ -#define TYPE_WIDTH(t) (sizeof(t) * CHAR_BIT) - -/* The maximum and minimum values for the integer type T. */ -#define TYPE_MAXIMUM(t) \ - ((t) (!TYPE_SIGNED(t) \ - ? (t)-1 \ - : ((((t)1 << (TYPE_WIDTH(t) - 2)) - 1) * 2 + 1))) - -#ifndef TIME_MAX -#define TIME_MAX TYPE_MAXIMUM(time_t) -#endif - -/* HOST_LONG_BITS is the size of a native pointer in bits. */ -#if UINTPTR_MAX == UINT32_MAX -# define HOST_LONG_BITS 32 -#elif UINTPTR_MAX == UINT64_MAX -# define HOST_LONG_BITS 64 -#else -# error Unknown pointer size -#endif - -/* Mac OSX has a bug that incorrectly defines SIZE_MAX with - * the wrong type. Our replacement isn't usable in preprocessor - * expressions, but it is sufficient for our needs. */ -#if defined(HAVE_BROKEN_SIZE_MAX) && HAVE_BROKEN_SIZE_MAX -#undef SIZE_MAX -#define SIZE_MAX ((size_t)-1) -#endif - -/* - * Two variations of MIN/MAX macros. The first is for runtime use, and - * evaluates arguments only once (so it is safe even with side - * effects), but will not work in constant contexts (such as array - * size declarations) because of the '{}'. The second is for constant - * expression use, where evaluating arguments twice is safe because - * the result is going to be constant anyway, but will not work in a - * runtime context because of a void expression where a value is - * expected. Thus, both gcc and clang will fail to compile if you use - * the wrong macro (even if the error may seem a bit cryptic). - * - * Note that neither form is usable as an #if condition; if you truly - * need to write conditional code that depends on a minimum or maximum - * determined by the pre-processor instead of the compiler, you'll - * have to open-code it. Sadly, Coverity is severely confused by the - * constant variants, so we have to dumb things down there. - */ -#undef MIN -#define MIN(a, b) \ - ({ \ - typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ - _a < _b ? _a : _b; \ - }) -#undef MAX -#define MAX(a, b) \ - ({ \ - typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ - _a > _b ? _a : _b; \ - }) - -#ifdef __COVERITY__ -# define MIN_CONST(a, b) ((a) < (b) ? (a) : (b)) -# define MAX_CONST(a, b) ((a) > (b) ? (a) : (b)) -#else -# define MIN_CONST(a, b) \ - __builtin_choose_expr( \ - __builtin_constant_p(a) && __builtin_constant_p(b), \ - (a) < (b) ? (a) : (b), \ - ((void)0)) -# define MAX_CONST(a, b) \ - __builtin_choose_expr( \ - __builtin_constant_p(a) && __builtin_constant_p(b), \ - (a) > (b) ? (a) : (b), \ - ((void)0)) -#endif - -/* - * Minimum function that returns zero only if both values are zero. - * Intended for use with unsigned values only. - */ -#ifndef MIN_NON_ZERO -#define MIN_NON_ZERO(a, b) \ - ({ \ - typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ - _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \ - }) -#endif - -/* Round number down to multiple */ -#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m)) - -/* Round number up to multiple. Safe when m is not a power of 2 (see - * ROUND_UP for a faster version when a power of 2 is guaranteed) */ -#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m)) - -/* Check if n is a multiple of m */ -#define QEMU_IS_ALIGNED(n, m) (((n) % (m)) == 0) - -/* n-byte align pointer down */ -#define QEMU_ALIGN_PTR_DOWN(p, n) \ - ((typeof(p))QEMU_ALIGN_DOWN((uintptr_t)(p), (n))) - -/* n-byte align pointer up */ -#define QEMU_ALIGN_PTR_UP(p, n) \ - ((typeof(p))QEMU_ALIGN_UP((uintptr_t)(p), (n))) - -/* Check if pointer p is n-bytes aligned */ -#define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n)) - -/* Round number up to multiple. Requires that d be a power of 2 (see - * QEMU_ALIGN_UP for a safer but slower version on arbitrary - * numbers); works even if d is a smaller type than n. */ -#ifndef ROUND_UP -#define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) -#endif - -#ifndef DIV_ROUND_UP -#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) -#endif - -/* - * &(x)[0] is always a pointer - if it's same type as x then the argument is a - * pointer, not an array. - */ -#define QEMU_IS_ARRAY(x) (!__builtin_types_compatible_p(typeof(x), \ - typeof(&(x)[0]))) -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \ - QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(x))) -#endif - -int qemu_daemon(int nochdir, int noclose); -void *qemu_try_memalign(size_t alignment, size_t size); -void *qemu_memalign(size_t alignment, size_t size); -void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared); -void qemu_vfree(void *ptr); -void qemu_anon_ram_free(void *ptr, size_t size); - -#define QEMU_MADV_INVALID -1 - -#if defined(CONFIG_MADVISE) - -#define QEMU_MADV_WILLNEED MADV_WILLNEED -#define QEMU_MADV_DONTNEED MADV_DONTNEED -#ifdef MADV_DONTFORK -#define QEMU_MADV_DONTFORK MADV_DONTFORK -#else -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#endif -#ifdef MADV_MERGEABLE -#define QEMU_MADV_MERGEABLE MADV_MERGEABLE -#else -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#endif -#ifdef MADV_UNMERGEABLE -#define QEMU_MADV_UNMERGEABLE MADV_UNMERGEABLE -#else -#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID -#endif -#ifdef MADV_DODUMP -#define QEMU_MADV_DODUMP MADV_DODUMP -#else -#define QEMU_MADV_DODUMP QEMU_MADV_INVALID -#endif -#ifdef MADV_DONTDUMP -#define QEMU_MADV_DONTDUMP MADV_DONTDUMP -#else -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#endif -#ifdef MADV_HUGEPAGE -#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE -#else -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID -#endif -#ifdef MADV_NOHUGEPAGE -#define QEMU_MADV_NOHUGEPAGE MADV_NOHUGEPAGE -#else -#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID -#endif -#ifdef MADV_REMOVE -#define QEMU_MADV_REMOVE MADV_REMOVE -#else -#define QEMU_MADV_REMOVE QEMU_MADV_INVALID -#endif - -#elif defined(CONFIG_POSIX_MADVISE) - -#define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED -#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_DODUMP QEMU_MADV_INVALID -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID -#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID -#define QEMU_MADV_REMOVE QEMU_MADV_INVALID - -#else /* no-op */ - -#define QEMU_MADV_WILLNEED QEMU_MADV_INVALID -#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_DODUMP QEMU_MADV_INVALID -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID -#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID -#define QEMU_MADV_REMOVE QEMU_MADV_INVALID - -#endif - -#ifdef _WIN32 -#define HAVE_CHARDEV_SERIAL 1 -#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ - || defined(__GLIBC__) || defined(__APPLE__) -#define HAVE_CHARDEV_SERIAL 1 -#endif - -#if defined(__linux__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__DragonFly__) -#define HAVE_CHARDEV_PARPORT 1 -#endif - -#if defined(__HAIKU__) -#define SIGIO SIGPOLL -#endif - -#if defined(CONFIG_LINUX) -#ifndef BUS_MCEERR_AR -#define BUS_MCEERR_AR 4 -#endif -#ifndef BUS_MCEERR_AO -#define BUS_MCEERR_AO 5 -#endif -#endif - -#if defined(__linux__) && \ - (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) \ - || defined(__powerpc64__)) - /* Use 2 MiB alignment so transparent hugepages can be used by KVM. - Valgrind does not support alignments larger than 1 MiB, - therefore we need special code which handles running on Valgrind. */ -# define QEMU_VMALLOC_ALIGN (512 * 4096) -#elif defined(__linux__) && defined(__s390x__) - /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ -# define QEMU_VMALLOC_ALIGN (256 * 4096) -#elif defined(__linux__) && defined(__sparc__) -#include -# define QEMU_VMALLOC_ALIGN MAX(qemu_real_host_page_size, SHMLBA) -#else -# define QEMU_VMALLOC_ALIGN qemu_real_host_page_size -#endif - -#ifdef CONFIG_POSIX -struct qemu_signalfd_siginfo { - uint32_t ssi_signo; /* Signal number */ - int32_t ssi_errno; /* Error number (unused) */ - int32_t ssi_code; /* Signal code */ - uint32_t ssi_pid; /* PID of sender */ - uint32_t ssi_uid; /* Real UID of sender */ - int32_t ssi_fd; /* File descriptor (SIGIO) */ - uint32_t ssi_tid; /* Kernel timer ID (POSIX timers) */ - uint32_t ssi_band; /* Band event (SIGIO) */ - uint32_t ssi_overrun; /* POSIX timer overrun count */ - uint32_t ssi_trapno; /* Trap number that caused signal */ - int32_t ssi_status; /* Exit status or signal (SIGCHLD) */ - int32_t ssi_int; /* Integer sent by sigqueue(2) */ - uint64_t ssi_ptr; /* Pointer sent by sigqueue(2) */ - uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */ - uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */ - uint64_t ssi_addr; /* Address that generated signal - (for hardware-generated signals) */ - uint8_t pad[48]; /* Pad size to 128 bytes (allow for - additional fields in the future) */ -}; - -int qemu_signalfd(const sigset_t *mask); -void sigaction_invoke(struct sigaction *action, - struct qemu_signalfd_siginfo *info); -#endif - -int qemu_madvise(void *addr, size_t len, int advice); -int qemu_mprotect_rwx(void *addr, size_t size); -int qemu_mprotect_none(void *addr, size_t size); - -int qemu_open(const char *name, int flags, ...); -int qemu_close(int fd); -int qemu_unlink(const char *name); -#ifndef _WIN32 -int qemu_dup(int fd); -#endif -int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive); -int qemu_unlock_fd(int fd, int64_t start, int64_t len); -int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); -bool qemu_has_ofd_lock(void); - -#if defined(__HAIKU__) && defined(__i386__) -#define FMT_pid "%ld" -#elif defined(WIN64) -#define FMT_pid "%" PRId64 -#else -#define FMT_pid "%d" -#endif - -bool qemu_write_pidfile(const char *pidfile, Error **errp); - -int qemu_get_thread_id(void); - -#ifndef CONFIG_IOVEC -struct iovec { - void *iov_base; - size_t iov_len; -}; -/* - * Use the same value as Linux for now. - */ -#define IOV_MAX 1024 - -ssize_t readv(int fd, const struct iovec *iov, int iov_cnt); -ssize_t writev(int fd, const struct iovec *iov, int iov_cnt); -#else -#include -#endif - -#ifdef _WIN32 -static inline void qemu_timersub(const struct timeval *val1, - const struct timeval *val2, - struct timeval *res) -{ - res->tv_sec = val1->tv_sec - val2->tv_sec; - if (val1->tv_usec < val2->tv_usec) { - res->tv_sec--; - res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000; - } else { - res->tv_usec = val1->tv_usec - val2->tv_usec; - } -} -#else -#define qemu_timersub timersub -#endif - -void qemu_set_cloexec(int fd); - -/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default - * instead of QEMU_VERSION, so setting hw_version on MachineClass - * is no longer mandatory. - * - * Do NOT change this string, or it will break compatibility on all - * machine classes that don't set hw_version. - */ -#define QEMU_HW_VERSION "2.5+" - -/* QEMU "hardware version" setting. Used to replace code that exposed - * QEMU_VERSION to guests in the past and need to keep compatibility. - * Do not use qemu_hw_version() in new code. - */ -void qemu_set_hw_version(const char *); -const char *qemu_hw_version(void); - -void fips_set_state(bool requested); -bool fips_get_state(void); - -/* Return a dynamically allocated pathname denoting a file or directory that is - * appropriate for storing local state. - * - * @relative_pathname need not start with a directory separator; one will be - * added automatically. - * - * The caller is responsible for releasing the value returned with g_free() - * after use. - */ -char *qemu_get_local_state_pathname(const char *relative_pathname); - -/* Find program directory, and save it for later usage with - * qemu_get_exec_dir(). - * Try OS specific API first, if not working, parse from argv0. */ -void qemu_init_exec_dir(const char *argv0); - -/* Get the saved exec dir. - * - * The caller is responsible for releasing the value returned with g_free() - * after use. - */ -char *qemu_get_exec_dir(void); - -/** - * qemu_getauxval: - * @type: the auxiliary vector key to lookup - * - * Search the auxiliary vector for @type, returning the value - * or 0 if @type is not present. - */ -unsigned long qemu_getauxval(unsigned long type); - -void qemu_set_tty_echo(int fd, bool echo); - -void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus, - Error **errp); - -/** - * qemu_get_pid_name: - * @pid: pid of a process - * - * For given @pid fetch its name. Caller is responsible for - * freeing the string when no longer needed. - * Returns allocated string on success, NULL on failure. - */ -char *qemu_get_pid_name(pid_t pid); - -/** - * qemu_fork: - * - * A version of fork that avoids signal handler race - * conditions that can lead to child process getting - * signals that are otherwise only expected by the - * parent. It also resets all signal handlers to the - * default settings. - * - * Returns 0 to child process, pid number to parent - * or -1 on failure. - */ -pid_t qemu_fork(Error **errp); - -/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even - * when intptr_t is 32-bit and we are aligning a long long. - */ -extern uintptr_t qemu_real_host_page_size; -extern intptr_t qemu_real_host_page_mask; - -extern int qemu_icache_linesize; -extern int qemu_icache_linesize_log; -extern int qemu_dcache_linesize; -extern int qemu_dcache_linesize_log; - -/* - * After using getopt or getopt_long, if you need to parse another set - * of options, then you must reset optind. Unfortunately the way to - * do this varies between implementations of getopt. - */ -static inline void qemu_reset_optind(void) -{ -#ifdef HAVE_OPTRESET - optind = 1; - optreset = 1; -#else - optind = 0; -#endif -} - -/** - * qemu_get_host_name: - * @errp: Error object - * - * Operating system agnostic way of querying host name. - * - * Returns allocated hostname (caller should free), NULL on failure. - */ -char *qemu_get_host_name(Error **errp); - -/** - * qemu_get_host_physmem: - * - * Operating system agnostic way of querying host memory. - * - * Returns amount of physical memory on the system. This is purely - * advisery and may return 0 if we can't work it out. At the other - * end we saturate to SIZE_MAX if you are lucky enough to have that - * much memory. - */ -size_t qemu_get_host_physmem(void); - -#endif +/* + * OS includes and handling of OS dependencies + * + * This header exists to pull in some common system headers that + * most code in QEMU will want, and to fix up some possible issues with + * it (missing defines, Windows weirdness, and so on). + * + * To avoid getting into possible circular include dependencies, this + * file should not include any other QEMU headers, with the exceptions + * of config-host.h, config-target.h, qemu/compiler.h, + * sysemu/os-posix.h, sysemu/os-win32.h, glib-compat.h and + * qemu/typedefs.h, all of which are doing a similar job to this file + * and are under similar constraints. + * + * This header also contains prototypes for functions defined in + * os-*.c and util/oslib-*.c; those would probably be better split + * out into separate header files. + * + * In an ideal world this header would contain only: + * (1) things which everybody needs + * (2) things without which code would work on most platforms but + * fail to compile or misbehave on a minority of host OSes + * + * 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_OSDEP_H +#define QEMU_OSDEP_H + +#include "config-host.h" +#ifdef NEED_CPU_H +#include CONFIG_TARGET +#else +#include "exec/poison.h" +#endif + +#include "qemu/compiler.h" + +/* Older versions of C++ don't get definitions of various macros from + * stdlib.h unless we define these macros before first inclusion of + * that system header. + */ +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +/* The following block of code temporarily renames the daemon() function so the + * compiler does not see the warning associated with it in stdlib.h on OSX + */ +#ifdef __APPLE__ +#define daemon qemu_fake_daemon_function +#include +#undef daemon +extern int daemon(int, int); +#endif + +#ifdef _WIN32 +/* as defined in sdkddkver.h */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 /* Vista */ +#endif +/* reduces the number of implicitly included headers */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#endif + +/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */ +#ifdef __MINGW32__ +#define __USE_MINGW_ANSI_STDIO 1 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +/* Put unistd.h before time.h as that triggers localtime_r/gmtime_r + * function availability on recentish Mingw-w64 platforms. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* setjmp must be declared before sysemu/os-win32.h + * because it is redefined there. */ +#include +#include + +#ifdef HAVE_SYS_SIGNAL_H +#include +#endif + +#ifndef _WIN32 +#include +#else +#define WIFEXITED(x) 1 +#define WEXITSTATUS(x) (x) +#endif + +#ifdef _WIN32 +#include "sysemu/os-win32.h" +#endif + +#ifdef CONFIG_POSIX +#include "sysemu/os-posix.h" +#endif + +#include "glib-compat.h" +#include "qemu/typedefs.h" + +/* + * For mingw, as of v6.0.0, the function implementing the assert macro is + * not marked as noreturn, so the compiler cannot delete code following an + * assert(false) as unused. We rely on this within the code base to delete + * code that is unreachable when features are disabled. + * All supported versions of Glib's g_assert() satisfy this requirement. + */ +#ifdef __MINGW32__ +#undef assert +#define assert(x) g_assert(x) +#endif + +/* + * According to waitpid man page: + * WCOREDUMP + * This macro is not specified in POSIX.1-2001 and is not + * available on some UNIX implementations (e.g., AIX, SunOS). + * Therefore, enclose its use inside #ifdef WCOREDUMP ... #endif. + */ +#ifndef WCOREDUMP +#define WCOREDUMP(status) 0 +#endif +/* + * We have a lot of unaudited code that may fail in strange ways, or + * even be a security risk during migration, if you disable assertions + * at compile-time. You may comment out these safety checks if you + * absolutely want to disable assertion overhead, but it is not + * supported upstream so the risk is all yours. Meanwhile, please + * submit patches to remove any side-effects inside an assertion, or + * fixing error handling that should use Error instead of assert. + */ +#ifdef NDEBUG +#error building with NDEBUG is not supported +#endif +#ifdef G_DISABLE_ASSERT +#error building with G_DISABLE_ASSERT is not supported +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0 +#endif +#ifndef ENOMEDIUM +#define ENOMEDIUM ENODEV +#endif +#if !defined(ENOTSUP) +#define ENOTSUP 4096 +#endif +#if !defined(ECANCELED) +#define ECANCELED 4097 +#endif +#if !defined(EMEDIUMTYPE) +#define EMEDIUMTYPE 4098 +#endif +#if !defined(ESHUTDOWN) +#define ESHUTDOWN 4099 +#endif + +/* time_t may be either 32 or 64 bits depending on the host OS, and + * can be either signed or unsigned, so we can't just hardcode a + * specific maximum value. This is not a C preprocessor constant, + * so you can't use TIME_MAX in an #ifdef, but for our purposes + * this isn't a problem. + */ + +/* The macros TYPE_SIGNED, TYPE_WIDTH, and TYPE_MAXIMUM are from + * Gnulib, and are under the LGPL v2.1 or (at your option) any + * later version. + */ + +/* True if the real type T is signed. */ +#define TYPE_SIGNED(t) (!((t)0 < (t)-1)) + +/* The width in bits of the integer type or expression T. + * Padding bits are not supported. + */ +#define TYPE_WIDTH(t) (sizeof(t) * CHAR_BIT) + +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MAXIMUM(t) \ + ((t) (!TYPE_SIGNED(t) \ + ? (t)-1 \ + : ((((t)1 << (TYPE_WIDTH(t) - 2)) - 1) * 2 + 1))) + +#ifndef TIME_MAX +#define TIME_MAX TYPE_MAXIMUM(time_t) +#endif + +/* HOST_LONG_BITS is the size of a native pointer in bits. */ +#if UINTPTR_MAX == UINT32_MAX +# define HOST_LONG_BITS 32 +#elif UINTPTR_MAX == UINT64_MAX +# define HOST_LONG_BITS 64 +#else +# error Unknown pointer size +#endif + +/* Mac OSX has a bug that incorrectly defines SIZE_MAX with + * the wrong type. Our replacement isn't usable in preprocessor + * expressions, but it is sufficient for our needs. */ +#if defined(HAVE_BROKEN_SIZE_MAX) && HAVE_BROKEN_SIZE_MAX +#undef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif + +/* + * Two variations of MIN/MAX macros. The first is for runtime use, and + * evaluates arguments only once (so it is safe even with side + * effects), but will not work in constant contexts (such as array + * size declarations) because of the '{}'. The second is for constant + * expression use, where evaluating arguments twice is safe because + * the result is going to be constant anyway, but will not work in a + * runtime context because of a void expression where a value is + * expected. Thus, both gcc and clang will fail to compile if you use + * the wrong macro (even if the error may seem a bit cryptic). + * + * Note that neither form is usable as an #if condition; if you truly + * need to write conditional code that depends on a minimum or maximum + * determined by the pre-processor instead of the compiler, you'll + * have to open-code it. Sadly, Coverity is severely confused by the + * constant variants, so we have to dumb things down there. + */ +#undef MIN +#define MIN(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a < _b ? _a : _b; \ + }) +#undef MAX +#define MAX(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#ifdef __COVERITY__ +# define MIN_CONST(a, b) ((a) < (b) ? (a) : (b)) +# define MAX_CONST(a, b) ((a) > (b) ? (a) : (b)) +#else +# define MIN_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) < (b) ? (a) : (b), \ + ((void)0)) +# define MAX_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) > (b) ? (a) : (b), \ + ((void)0)) +#endif + +/* + * Minimum function that returns zero only if both values are zero. + * Intended for use with unsigned values only. + */ +#ifndef MIN_NON_ZERO +#define MIN_NON_ZERO(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \ + }) +#endif + +/* Round number down to multiple */ +#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m)) + +/* Round number up to multiple. Safe when m is not a power of 2 (see + * ROUND_UP for a faster version when a power of 2 is guaranteed) */ +#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m)) + +/* Check if n is a multiple of m */ +#define QEMU_IS_ALIGNED(n, m) (((n) % (m)) == 0) + +/* n-byte align pointer down */ +#define QEMU_ALIGN_PTR_DOWN(p, n) \ + ((typeof(p))QEMU_ALIGN_DOWN((uintptr_t)(p), (n))) + +/* n-byte align pointer up */ +#define QEMU_ALIGN_PTR_UP(p, n) \ + ((typeof(p))QEMU_ALIGN_UP((uintptr_t)(p), (n))) + +/* Check if pointer p is n-bytes aligned */ +#define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n)) + +/* Round number up to multiple. Requires that d be a power of 2 (see + * QEMU_ALIGN_UP for a safer but slower version on arbitrary + * numbers); works even if d is a smaller type than n. */ +#ifndef ROUND_UP +#define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) +#endif + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +/* + * &(x)[0] is always a pointer - if it's same type as x then the argument is a + * pointer, not an array. + */ +#define QEMU_IS_ARRAY(x) (!__builtin_types_compatible_p(typeof(x), \ + typeof(&(x)[0]))) +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \ + QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(x))) +#endif + +int qemu_daemon(int nochdir, int noclose); +void *qemu_try_memalign(size_t alignment, size_t size); +void *qemu_memalign(size_t alignment, size_t size); +void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared); +void qemu_vfree(void *ptr); +void qemu_anon_ram_free(void *ptr, size_t size); + +#define QEMU_MADV_INVALID -1 + +#if defined(CONFIG_MADVISE) + +#define QEMU_MADV_WILLNEED MADV_WILLNEED +#define QEMU_MADV_DONTNEED MADV_DONTNEED +#ifdef MADV_DONTFORK +#define QEMU_MADV_DONTFORK MADV_DONTFORK +#else +#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID +#endif +#ifdef MADV_MERGEABLE +#define QEMU_MADV_MERGEABLE MADV_MERGEABLE +#else +#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#endif +#ifdef MADV_UNMERGEABLE +#define QEMU_MADV_UNMERGEABLE MADV_UNMERGEABLE +#else +#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID +#endif +#ifdef MADV_DODUMP +#define QEMU_MADV_DODUMP MADV_DODUMP +#else +#define QEMU_MADV_DODUMP QEMU_MADV_INVALID +#endif +#ifdef MADV_DONTDUMP +#define QEMU_MADV_DONTDUMP MADV_DONTDUMP +#else +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#endif +#ifdef MADV_HUGEPAGE +#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE +#else +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID +#endif +#ifdef MADV_NOHUGEPAGE +#define QEMU_MADV_NOHUGEPAGE MADV_NOHUGEPAGE +#else +#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID +#endif +#ifdef MADV_REMOVE +#define QEMU_MADV_REMOVE MADV_REMOVE +#else +#define QEMU_MADV_REMOVE QEMU_MADV_INVALID +#endif + +#elif defined(CONFIG_POSIX_MADVISE) + +#define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED +#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED +#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID +#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DODUMP QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID +#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID +#define QEMU_MADV_REMOVE QEMU_MADV_INVALID + +#else /* no-op */ + +#define QEMU_MADV_WILLNEED QEMU_MADV_INVALID +#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID +#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID +#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DODUMP QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID +#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID +#define QEMU_MADV_REMOVE QEMU_MADV_INVALID + +#endif + +#ifdef _WIN32 +#define HAVE_CHARDEV_SERIAL 1 +#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ + || defined(__GLIBC__) || defined(__APPLE__) +#define HAVE_CHARDEV_SERIAL 1 +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#define HAVE_CHARDEV_PARPORT 1 +#endif + +#if defined(__HAIKU__) +#define SIGIO SIGPOLL +#endif + +#if defined(CONFIG_LINUX) +#ifndef BUS_MCEERR_AR +#define BUS_MCEERR_AR 4 +#endif +#ifndef BUS_MCEERR_AO +#define BUS_MCEERR_AO 5 +#endif +#endif + +#if defined(__linux__) && \ + (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) \ + || defined(__powerpc64__)) + /* Use 2 MiB alignment so transparent hugepages can be used by KVM. + Valgrind does not support alignments larger than 1 MiB, + therefore we need special code which handles running on Valgrind. */ +# define QEMU_VMALLOC_ALIGN (512 * 4096) +#elif defined(__linux__) && defined(__s390x__) + /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ +# define QEMU_VMALLOC_ALIGN (256 * 4096) +#elif defined(__linux__) && defined(__sparc__) +#include +# define QEMU_VMALLOC_ALIGN MAX(qemu_real_host_page_size, SHMLBA) +#else +# define QEMU_VMALLOC_ALIGN qemu_real_host_page_size +#endif + +#ifdef CONFIG_POSIX +struct qemu_signalfd_siginfo { + uint32_t ssi_signo; /* Signal number */ + int32_t ssi_errno; /* Error number (unused) */ + int32_t ssi_code; /* Signal code */ + uint32_t ssi_pid; /* PID of sender */ + uint32_t ssi_uid; /* Real UID of sender */ + int32_t ssi_fd; /* File descriptor (SIGIO) */ + uint32_t ssi_tid; /* Kernel timer ID (POSIX timers) */ + uint32_t ssi_band; /* Band event (SIGIO) */ + uint32_t ssi_overrun; /* POSIX timer overrun count */ + uint32_t ssi_trapno; /* Trap number that caused signal */ + int32_t ssi_status; /* Exit status or signal (SIGCHLD) */ + int32_t ssi_int; /* Integer sent by sigqueue(2) */ + uint64_t ssi_ptr; /* Pointer sent by sigqueue(2) */ + uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */ + uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */ + uint64_t ssi_addr; /* Address that generated signal + (for hardware-generated signals) */ + uint8_t pad[48]; /* Pad size to 128 bytes (allow for + additional fields in the future) */ +}; + +int qemu_signalfd(const sigset_t *mask); +void sigaction_invoke(struct sigaction *action, + struct qemu_signalfd_siginfo *info); +#endif + +int qemu_madvise(void *addr, size_t len, int advice); +int qemu_mprotect_rwx(void *addr, size_t size); +int qemu_mprotect_none(void *addr, size_t size); + +int qemu_open(const char *name, int flags, ...); +int qemu_close(int fd); +int qemu_unlink(const char *name); +#ifndef _WIN32 +int qemu_dup(int fd); +int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive); +int qemu_unlock_fd(int fd, int64_t start, int64_t len); +int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); +bool qemu_has_ofd_lock(void); +#endif + +#if defined(__HAIKU__) && defined(__i386__) +#define FMT_pid "%ld" +#elif defined(WIN64) +#define FMT_pid "%" PRId64 +#else +#define FMT_pid "%d" +#endif + +bool qemu_write_pidfile(const char *pidfile, Error **errp); + +int qemu_get_thread_id(void); + +#ifndef CONFIG_IOVEC +struct iovec { + void *iov_base; + size_t iov_len; +}; +/* + * Use the same value as Linux for now. + */ +#define IOV_MAX 1024 + +ssize_t readv(int fd, const struct iovec *iov, int iov_cnt); +ssize_t writev(int fd, const struct iovec *iov, int iov_cnt); +#else +#include +#endif + +#ifdef _WIN32 +static inline void qemu_timersub(const struct timeval *val1, + const struct timeval *val2, + struct timeval *res) +{ + res->tv_sec = val1->tv_sec - val2->tv_sec; + if (val1->tv_usec < val2->tv_usec) { + res->tv_sec--; + res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000; + } else { + res->tv_usec = val1->tv_usec - val2->tv_usec; + } +} +#else +#define qemu_timersub timersub +#endif + +void qemu_set_cloexec(int fd); + +/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default + * instead of QEMU_VERSION, so setting hw_version on MachineClass + * is no longer mandatory. + * + * Do NOT change this string, or it will break compatibility on all + * machine classes that don't set hw_version. + */ +#define QEMU_HW_VERSION "2.5+" + +/* QEMU "hardware version" setting. Used to replace code that exposed + * QEMU_VERSION to guests in the past and need to keep compatibility. + * Do not use qemu_hw_version() in new code. + */ +void qemu_set_hw_version(const char *); +const char *qemu_hw_version(void); + +void fips_set_state(bool requested); +bool fips_get_state(void); + +/* Return a dynamically allocated pathname denoting a file or directory that is + * appropriate for storing local state. + * + * @relative_pathname need not start with a directory separator; one will be + * added automatically. + * + * The caller is responsible for releasing the value returned with g_free() + * after use. + */ +char *qemu_get_local_state_pathname(const char *relative_pathname); + +/* Find program directory, and save it for later usage with + * qemu_get_exec_dir(). + * Try OS specific API first, if not working, parse from argv0. */ +void qemu_init_exec_dir(const char *argv0); + +/* Get the saved exec dir. + * + * The caller is responsible for releasing the value returned with g_free() + * after use. + */ +char *qemu_get_exec_dir(void); + +/** + * qemu_getauxval: + * @type: the auxiliary vector key to lookup + * + * Search the auxiliary vector for @type, returning the value + * or 0 if @type is not present. + */ +unsigned long qemu_getauxval(unsigned long type); + +void qemu_set_tty_echo(int fd, bool echo); + +void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus, + Error **errp); + +/** + * qemu_get_pid_name: + * @pid: pid of a process + * + * For given @pid fetch its name. Caller is responsible for + * freeing the string when no longer needed. + * Returns allocated string on success, NULL on failure. + */ +char *qemu_get_pid_name(pid_t pid); + +/** + * qemu_fork: + * + * A version of fork that avoids signal handler race + * conditions that can lead to child process getting + * signals that are otherwise only expected by the + * parent. It also resets all signal handlers to the + * default settings. + * + * Returns 0 to child process, pid number to parent + * or -1 on failure. + */ +pid_t qemu_fork(Error **errp); + +/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even + * when intptr_t is 32-bit and we are aligning a long long. + */ +extern uintptr_t qemu_real_host_page_size; +extern intptr_t qemu_real_host_page_mask; + +extern int qemu_icache_linesize; +extern int qemu_icache_linesize_log; +extern int qemu_dcache_linesize; +extern int qemu_dcache_linesize_log; + +/* + * After using getopt or getopt_long, if you need to parse another set + * of options, then you must reset optind. Unfortunately the way to + * do this varies between implementations of getopt. + */ +static inline void qemu_reset_optind(void) +{ +#ifdef HAVE_OPTRESET + optind = 1; + optreset = 1; +#else + optind = 0; +#endif +} + +/** + * qemu_get_host_name: + * @errp: Error object + * + * Operating system agnostic way of querying host name. + * + * Returns allocated hostname (caller should free), NULL on failure. + */ +char *qemu_get_host_name(Error **errp); + +/** + * qemu_get_host_physmem: + * + * Operating system agnostic way of querying host memory. + * + * Returns amount of physical memory on the system. This is purely + * advisery and may return 0 if we can't work it out. At the other + * end we saturate to SIZE_MAX if you are lucky enough to have that + * much memory. + */ +size_t qemu_get_host_physmem(void); + +#endif From patchwork Thu Sep 3 07:43:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752593 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 68F1A14E3 for ; Thu, 3 Sep 2020 07:50:37 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7BFB7206C0 for ; Thu, 3 Sep 2020 07:50:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WRN1mR9U" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7BFB7206C0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:37572 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDk0x-0002CW-Ik for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:50:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43456) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjue-0000dB-Rp for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:04 -0400 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]:36402) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuY-0003uG-1h for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:04 -0400 Received: by mail-pj1-x1043.google.com with SMTP id q1so1065184pjd.1 for ; Thu, 03 Sep 2020 00:43:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/GaUltnz0Pg3c4Cd+mTYTkHsnyZ4IcQD2a8N3N67cLI=; b=WRN1mR9UF1ZOZZtgmHtz4tVK6IUF61JxzDNJTBM8syZ4YHS6A1+UQdyhiqaf1qnEMI t+YPK1mXGMW5wo5ovsbaWF5rmtjUzXGkHrpCOkT1ATYyFqlg81gny0jSsR+aeJUfMML1 mizKY8He5AzA40vB/x8s77dLLWRQLeya01dWdtgaeEDhIxkcwuFR6hu0L2+X929Ru2OK Bsphayi3F1o46NQ/Ghy7USA0oN8VPY6anIfR+Op2LnCsIvwsev7WPq1k5FeBVlnKxce+ ge/TXqE1219Hp/ML6KYQTp6QSOA2DO2P40gVDZLeAtASVTxapcMJJnD5grxfGTzMUYY+ D+BQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/GaUltnz0Pg3c4Cd+mTYTkHsnyZ4IcQD2a8N3N67cLI=; b=OG3hWCjFj3MKvmypYnyC9YtgNL7wyUqFnq81pufdQY5DOlT5cQlMx7JHZhyop9BlFS 72lkGmKo/pbqJCFMy4w2P0iFSxcPiz/Msd2bXhiSDBmiVaxQb2GRw3UG7hpMmbTvV+dV CwVntRk09XPcMOzWdriELBPyaVKlnf6L9BuqgcBQtVLIs3ro3/LKs7DeTxfavx5osYg/ g6FSIsIWrFuvo6525ye80h+gqOk/4S5eJn3ZDoFSrmsIGID1uRORdcAfHOkd80GX5QyR AKyMFs3Th11n6FTrq4ZOxC6weFxdKmFXg88qTPy+zEHl2TMNYPJjjq5ud1GkNgs2BW6C So0g== X-Gm-Message-State: AOAM531YU7IYnJwpYTtR5qDXTffOI/tngx9IeTRWuIKmitqFoIp72GwF 5qnJnNMGyyVhHyErAigSzJ99/SGcx+kTXIyg X-Google-Smtp-Source: ABdhPJyjVWKavDCA3el1bB6qn8u27nFycdfHunj+A2OV58RMRUrnhSXudkbYqC07ailnIrcJf5VqJQ== X-Received: by 2002:a17:90a:4046:: with SMTP id k6mr2069873pjg.11.1599119033186; Thu, 03 Sep 2020 00:43:53 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:51 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 08/12] ci: fixes msys2 build by upgrading capstone to 4.0.2 Date: Thu, 3 Sep 2020 15:43:09 +0800 Message-Id: <20200903074313.1498-9-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1043; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1043.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yonggang Luo --- capstone | 2 +- configure | 16574 ++++++++++++++++++++++++++-------------------------- 2 files changed, 8288 insertions(+), 8288 deletions(-) diff --git a/capstone b/capstone index 22ead3e0bf..1d23053284 160000 --- a/capstone +++ b/capstone @@ -1 +1 @@ -Subproject commit 22ead3e0bfdb87516656453336160e0a37b066bf +Subproject commit 1d230532840a37ac032c6ab80128238fc930c6c1 diff --git a/configure b/configure index 5f2bcc4b57..e42d210e5f 100755 --- a/configure +++ b/configure @@ -1,8287 +1,8287 @@ -#!/bin/sh -# -# qemu configure script (c) 2003 Fabrice Bellard -# - -# Unset some variables known to interfere with behavior of common tools, -# just as autoconf does. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -# Don't allow CCACHE, if present, to use cached results of compile tests! -export CCACHE_RECACHE=yes - -# make source path absolute -source_path=$(cd "$(dirname -- "$0")"; pwd) -build_path=$PWD -if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then -source_path=$(cd "$(dirname -- "$0")"; pwd -W) -build_path=`pwd -W` -fi - -if test "$build_path" = "$source_path" -then - echo "Using './build' as the directory for build output" - - MARKER=build/auto-created-by-configure - - if test -e build - then - if test -f $MARKER - then - rm -rf build - else - echo "ERROR: ./build dir already exists and was not previously created by configure" - exit 1 - fi - fi - - mkdir build - touch $MARKER - - cat > GNUmakefile <<'EOF' -# This file is auto-generated by configure to support in-source tree -# 'make' command invocation - -ifeq ($(MAKECMDGOALS),) -recurse: all -endif - -.NOTPARALLEL: % -%: force - @echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...' - @$(MAKE) -C build -f Makefile $(MAKECMDGOALS) - @if test "$(MAKECMDGOALS)" = "distclean" && \ - test -e build/auto-created-by-configure ; \ - then \ - rm -rf build GNUmakefile ; \ - fi -force: ; -.PHONY: force -GNUmakefile: ; - -EOF - cd build - exec $source_path/configure "$@" -fi - -# Temporary directory used for files created while -# configure runs. Since it is in the build directory -# we can safely blow away any previous version of it -# (and we need not jump through hoops to try to delete -# it when configure exits.) -TMPDIR1="config-temp" -rm -rf "${TMPDIR1}" -mkdir -p "${TMPDIR1}" -if [ $? -ne 0 ]; then - echo "ERROR: failed to create temporary directory" - exit 1 -fi - -TMPB="qemu-conf" -TMPC="${TMPDIR1}/${TMPB}.c" -TMPO="${TMPDIR1}/${TMPB}.o" -TMPCXX="${TMPDIR1}/${TMPB}.cxx" -TMPE="${TMPDIR1}/${TMPB}.exe" -TMPTXT="${TMPDIR1}/${TMPB}.txt" - -rm -f config.log - -# Print a helpful header at the top of config.log -echo "# QEMU configure log $(date)" >> config.log -printf "# Configured with:" >> config.log -printf " '%s'" "$0" "$@" >> config.log -echo >> config.log -echo "#" >> config.log - -print_error() { - (echo - echo "ERROR: $1" - while test -n "$2"; do - echo " $2" - shift - done - echo) >&2 -} - -error_exit() { - print_error "$@" - exit 1 -} - -do_compiler() { - # Run the compiler, capturing its output to the log. First argument - # is compiler binary to execute. - local compiler="$1" - shift - if test -n "$BASH_VERSION"; then eval ' - echo >>config.log " -funcs: ${FUNCNAME[*]} -lines: ${BASH_LINENO[*]}" - '; fi - echo $compiler "$@" >> config.log - $compiler "$@" >> config.log 2>&1 || return $? - # Test passed. If this is an --enable-werror build, rerun - # the test with -Werror and bail out if it fails. This - # makes warning-generating-errors in configure test code - # obvious to developers. - if test "$werror" != "yes"; then - return 0 - fi - # Don't bother rerunning the compile if we were already using -Werror - case "$*" in - *-Werror*) - return 0 - ;; - esac - echo $compiler -Werror "$@" >> config.log - $compiler -Werror "$@" >> config.log 2>&1 && return $? - error_exit "configure test passed without -Werror but failed with -Werror." \ - "This is probably a bug in the configure script. The failing command" \ - "will be at the bottom of config.log." \ - "You can run configure with --disable-werror to bypass this check." -} - -do_cc() { - do_compiler "$cc" "$@" -} - -do_cxx() { - do_compiler "$cxx" "$@" -} - -# Append $2 to the variable named $1, with space separation -add_to() { - eval $1=\${$1:+\"\$$1 \"}\$2 -} - -update_cxxflags() { - # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those - # options which some versions of GCC's C++ compiler complain about - # because they only make sense for C programs. - QEMU_CXXFLAGS="$QEMU_CXXFLAGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS" - CXXFLAGS=$(echo "$CFLAGS" | sed s/-std=gnu99/-std=gnu++11/) - for arg in $QEMU_CFLAGS; do - case $arg in - -Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\ - -Wold-style-declaration|-Wold-style-definition|-Wredundant-decls) - ;; - *) - QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg - ;; - esac - done -} - -compile_object() { - local_cflags="$1" - do_cc $CFLAGS $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC -} - -compile_prog() { - local_cflags="$1" - local_ldflags="$2" - do_cc $CFLAGS $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $QEMU_LDFLAGS $local_ldflags -} - -# symbolically link $1 to $2. Portable version of "ln -sf". -symlink() { - rm -rf "$2" - mkdir -p "$(dirname "$2")" - ln -s "$1" "$2" -} - -# check whether a command is available to this shell (may be either an -# executable or a builtin) -has() { - type "$1" >/dev/null 2>&1 -} - -# search for an executable in PATH -path_of() { - local_command="$1" - local_ifs="$IFS" - local_dir="" - - # pathname has a dir component? - if [ "${local_command#*/}" != "$local_command" ]; then - if [ -x "$local_command" ] && [ ! -d "$local_command" ]; then - echo "$local_command" - return 0 - fi - fi - if [ -z "$local_command" ]; then - return 1 - fi - - IFS=: - for local_dir in $PATH; do - if [ -x "$local_dir/$local_command" ] && [ ! -d "$local_dir/$local_command" ]; then - echo "$local_dir/$local_command" - IFS="${local_ifs:-$(printf ' \t\n')}" - return 0 - fi - done - # not found - IFS="${local_ifs:-$(printf ' \t\n')}" - return 1 -} - -version_ge () { - local_ver1=`echo $1 | tr . ' '` - local_ver2=`echo $2 | tr . ' '` - while true; do - set x $local_ver1 - local_first=${2-0} - # 'shift 2' if $2 is set, or 'shift' if $2 is not set - shift ${2:+2} - local_ver1=$* - set x $local_ver2 - # the second argument finished, the first must be greater or equal - test $# = 1 && return 0 - test $local_first -lt $2 && return 1 - test $local_first -gt $2 && return 0 - shift ${2:+2} - local_ver2=$* - done -} - -have_backend () { - echo "$trace_backends" | grep "$1" >/dev/null -} - -glob() { - eval test -z '"${1#'"$2"'}"' -} - -supported_hax_target() { - test "$hax" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_kvm_target() { - test "$kvm" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}:$cpu" in - arm:arm | aarch64:aarch64 | \ - i386:i386 | i386:x86_64 | i386:x32 | \ - x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ - mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \ - ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ - s390x:s390x) - return 0 - ;; - esac - return 1 -} - -supported_xen_target() { - test "$xen" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - # Only i386 and x86_64 provide the xenpv machine. - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_hvf_target() { - test "$hvf" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - x86_64) - return 0 - ;; - esac - return 1 -} - -supported_whpx_target() { - test "$whpx" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_target() { - case "$1" in - *-softmmu) - ;; - *-linux-user) - if test "$linux" != "yes"; then - print_error "Target '$target' is only available on a Linux host" - return 1 - fi - ;; - *-bsd-user) - if test "$bsd" != "yes"; then - print_error "Target '$target' is only available on a BSD host" - return 1 - fi - ;; - *) - print_error "Invalid target name '$target'" - return 1 - ;; - esac - test "$tcg" = "yes" && return 0 - supported_kvm_target "$1" && return 0 - supported_xen_target "$1" && return 0 - supported_hax_target "$1" && return 0 - supported_hvf_target "$1" && return 0 - supported_whpx_target "$1" && return 0 - print_error "TCG disabled, but hardware accelerator not available for '$target'" - return 1 -} - - -ld_has() { - $ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1 -} - -check_valid_build_path="[[:space:]:]" -if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then -check_valid_build_path="[[:space:]]" -fi - -if printf %s\\n "$source_path" "$build_path" | grep -q "$check_valid_build_path"; -then - error_exit "main directory cannot contain spaces nor colons" -fi - -# default parameters -cpu="" -iasl="iasl" -interp_prefix="/usr/gnemul/qemu-%M" -static="no" -cross_prefix="" -audio_drv_list="" -block_drv_rw_whitelist="" -block_drv_ro_whitelist="" -host_cc="cc" -libs_tools="" -audio_win_int="" -libs_qga="" -debug_info="yes" -stack_protector="" -safe_stack="" -use_containers="yes" -gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb") - -if test -e "$source_path/.git" -then - git_update=yes - git_submodules="ui/keycodemapdb" - git_submodules="$git_submodules tests/fp/berkeley-testfloat-3" - git_submodules="$git_submodules tests/fp/berkeley-softfloat-3" -else - git_update=no - git_submodules="" - - if ! test -f "$source_path/ui/keycodemapdb/README" - then - echo - echo "ERROR: missing file $source_path/ui/keycodemapdb/README" - echo - echo "This is not a GIT checkout but module content appears to" - echo "be missing. Do not use 'git archive' or GitHub download links" - echo "to acquire QEMU source archives. Non-GIT builds are only" - echo "supported with source archives linked from:" - echo - echo " https://www.qemu.org/download/#source" - echo - echo "Developers working with GIT can use scripts/archive-source.sh" - echo "if they need to create valid source archives." - echo - exit 1 - fi -fi -git="git" - -# Don't accept a target_list environment variable. -unset target_list -unset target_list_exclude - -# Default value for a variable defining feature "foo". -# * foo="no" feature will only be used if --enable-foo arg is given -# * foo="" feature will be searched for, and if found, will be used -# unless --disable-foo is given -# * foo="yes" this value will only be set by --enable-foo flag. -# feature will searched for, -# if not found, configure exits with error -# -# Always add --enable-foo and --disable-foo command line args. -# Distributions want to ensure that several features are compiled in, and it -# is impossible without a --enable-foo that exits if a feature is not found. - -brlapi="" -curl="" -curses="" -docs="" -fdt="" -netmap="no" -sdl="auto" -sdl_image="auto" -virtfs="" -mpath="" -vnc="enabled" -sparse="no" -vde="" -vnc_sasl="auto" -vnc_jpeg="auto" -vnc_png="auto" -xkbcommon="auto" -xen="" -xen_ctrl_version="" -xen_pci_passthrough="" -linux_aio="" -linux_io_uring="" -cap_ng="" -attr="" -libattr="" -xfs="" -tcg="yes" -membarrier="" -vhost_net="" -vhost_crypto="" -vhost_scsi="" -vhost_vsock="" -vhost_user="" -vhost_user_fs="" -kvm="no" -hax="no" -hvf="no" -whpx="no" -rdma="" -pvrdma="" -gprof="no" -debug_tcg="no" -debug="no" -sanitizers="no" -tsan="no" -fortify_source="" -strip_opt="yes" -tcg_interpreter="no" -bigendian="no" -mingw32="no" -gcov="no" -EXESUF="" -HOST_DSOSUF=".so" -LDFLAGS_SHARED="-shared" -modules="no" -module_upgrades="no" -prefix="/usr/local" -qemu_suffix="qemu" -slirp="" -oss_lib="" -bsd="no" -linux="no" -solaris="no" -profiler="no" -cocoa="no" -softmmu="yes" -linux_user="no" -bsd_user="no" -blobs="yes" -edk2_blobs="no" -pkgversion="" -pie="" -qom_cast_debug="yes" -trace_backends="log" -trace_file="trace" -spice="" -rbd="" -smartcard="" -u2f="auto" -libusb="" -usb_redir="" -opengl="" -opengl_dmabuf="no" -cpuid_h="no" -avx2_opt="" -capstone="" -lzo="" -snappy="" -bzip2="" -lzfse="" -zstd="" -guest_agent="" -guest_agent_with_vss="no" -guest_agent_ntddscsi="no" -guest_agent_msi="" -vss_win32_sdk="" -win_sdk="no" -want_tools="" -libiscsi="" -libnfs="" -coroutine="" -coroutine_pool="" -debug_stack_usage="no" -crypto_afalg="no" -seccomp="" -glusterfs="" -glusterfs_xlator_opt="no" -glusterfs_discard="no" -glusterfs_fallocate="no" -glusterfs_zerofill="no" -glusterfs_ftruncate_has_stat="no" -glusterfs_iocb_has_stat="no" -gtk="" -gtk_gl="no" -tls_priority="NORMAL" -gnutls="" -nettle="" -nettle_xts="no" -gcrypt="" -gcrypt_hmac="no" -gcrypt_xts="no" -qemu_private_xts="yes" -auth_pam="" -vte="" -virglrenderer="" -tpm="" -libssh="" -live_block_migration="yes" -numa="" -tcmalloc="no" -jemalloc="no" -replication="yes" -bochs="yes" -cloop="yes" -dmg="yes" -qcow1="yes" -vdi="yes" -vvfat="yes" -qed="yes" -parallels="yes" -sheepdog="yes" -libxml2="" -debug_mutex="no" -libpmem="" -default_devices="yes" -plugins="no" -fuzzing="no" -rng_none="no" -secret_keyring="" -libdaxctl="" -meson="" -ninja="" -skip_meson=no -gettext="" - -bogus_os="no" -malloc_trim="" - -# parse CC options first -for opt do - optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') - case "$opt" in - --cross-prefix=*) cross_prefix="$optarg" - ;; - --cc=*) CC="$optarg" - ;; - --cxx=*) CXX="$optarg" - ;; - --cpu=*) cpu="$optarg" - ;; - --extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg" - QEMU_LDFLAGS="$QEMU_LDFLAGS $optarg" - ;; - --extra-cxxflags=*) QEMU_CXXFLAGS="$QEMU_CXXFLAGS $optarg" - ;; - --extra-ldflags=*) QEMU_LDFLAGS="$QEMU_LDFLAGS $optarg" - EXTRA_LDFLAGS="$optarg" - ;; - --enable-debug-info) debug_info="yes" - ;; - --disable-debug-info) debug_info="no" - ;; - --cross-cc-*[!a-zA-Z0-9_-]*=*) error_exit "Passed bad --cross-cc-FOO option" - ;; - --cross-cc-cflags-*) cc_arch=${opt#--cross-cc-flags-}; cc_arch=${cc_arch%%=*} - eval "cross_cc_cflags_${cc_arch}=\$optarg" - cross_cc_vars="$cross_cc_vars cross_cc_cflags_${cc_arch}" - ;; - --cross-cc-*) cc_arch=${opt#--cross-cc-}; cc_arch=${cc_arch%%=*} - cc_archs="$cc_archs $cc_arch" - eval "cross_cc_${cc_arch}=\$optarg" - cross_cc_vars="$cross_cc_vars cross_cc_${cc_arch}" - ;; - esac -done -# OS specific -# Using uname is really, really broken. Once we have the right set of checks -# we can eliminate its usage altogether. - -# Preferred compiler: -# ${CC} (if set) -# ${cross_prefix}gcc (if cross-prefix specified) -# system compiler -if test -z "${CC}${cross_prefix}"; then - cc="$host_cc" -else - cc="${CC-${cross_prefix}gcc}" -fi - -if test -z "${CXX}${cross_prefix}"; then - cxx="c++" -else - cxx="${CXX-${cross_prefix}g++}" -fi - -ar="${AR-${cross_prefix}ar}" -as="${AS-${cross_prefix}as}" -ccas="${CCAS-$cc}" -cpp="${CPP-$cc -E}" -objcopy="${OBJCOPY-${cross_prefix}objcopy}" -ld="${LD-${cross_prefix}ld}" -ranlib="${RANLIB-${cross_prefix}ranlib}" -nm="${NM-${cross_prefix}nm}" -strip="${STRIP-${cross_prefix}strip}" -windres="${WINDRES-${cross_prefix}windres}" -pkg_config_exe="${PKG_CONFIG-${cross_prefix}pkg-config}" -query_pkg_config() { - "${pkg_config_exe}" ${QEMU_PKG_CONFIG_FLAGS} "$@" -} -pkg_config=query_pkg_config -sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}" - -# If the user hasn't specified ARFLAGS, default to 'rv', just as make does. -ARFLAGS="${ARFLAGS-rv}" - -# default flags for all hosts -# We use -fwrapv to tell the compiler that we require a C dialect where -# left shift of signed integers is well defined and has the expected -# 2s-complement style results. (Both clang and gcc agree that it -# provides these semantics.) -QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv $QEMU_CFLAGS" -QEMU_CFLAGS="-Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" -QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" -QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" -QEMU_INCLUDES="-iquote . -iquote ${source_path} -iquote ${source_path}/accel/tcg -iquote ${source_path}/include" -QEMU_INCLUDES="$QEMU_INCLUDES -iquote ${source_path}/disas/libvixl" -CFLAGS="-std=gnu99 -Wall" - - -# running configure in the source tree? -# we know that's the case if configure is there. -if test -f "./configure"; then - pwd_is_source_path="y" -else - pwd_is_source_path="n" -fi - -check_define() { -cat > $TMPC < $TMPC < -int main(void) { return 0; } -EOF - compile_object -} - -write_c_skeleton() { - cat > $TMPC < $TMPC < -#include -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } -EOF -} - -if check_define __linux__ ; then - targetos="Linux" -elif check_define _WIN32 ; then - targetos='MINGW32' -elif check_define __OpenBSD__ ; then - targetos='OpenBSD' -elif check_define __sun__ ; then - targetos='SunOS' -elif check_define __HAIKU__ ; then - targetos='Haiku' -elif check_define __FreeBSD__ ; then - targetos='FreeBSD' -elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then - targetos='GNU/kFreeBSD' -elif check_define __DragonFly__ ; then - targetos='DragonFly' -elif check_define __NetBSD__; then - targetos='NetBSD' -elif check_define __APPLE__; then - targetos='Darwin' -else - # This is a fatal error, but don't report it yet, because we - # might be going to just print the --help text, or it might - # be the result of a missing compiler. - targetos='bogus' - bogus_os='yes' -fi - -# Some host OSes need non-standard checks for which CPU to use. -# Note that these checks are broken for cross-compilation: if you're -# cross-compiling to one of these OSes then you'll need to specify -# the correct CPU with the --cpu option. -case $targetos in -Darwin) - # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can - # run 64-bit userspace code. - # If the user didn't specify a CPU explicitly and the kernel says this is - # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code. - if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then - cpu="x86_64" - fi - ;; -SunOS) - # $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo - if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then - cpu="x86_64" - fi -esac - -if test ! -z "$cpu" ; then - # command line argument - : -elif check_define __i386__ ; then - cpu="i386" -elif check_define __x86_64__ ; then - if check_define __ILP32__ ; then - cpu="x32" - else - cpu="x86_64" - fi -elif check_define __sparc__ ; then - if check_define __arch64__ ; then - cpu="sparc64" - else - cpu="sparc" - fi -elif check_define _ARCH_PPC ; then - if check_define _ARCH_PPC64 ; then - if check_define _LITTLE_ENDIAN ; then - cpu="ppc64le" - else - cpu="ppc64" - fi - else - cpu="ppc" - fi -elif check_define __mips__ ; then - cpu="mips" -elif check_define __s390__ ; then - if check_define __s390x__ ; then - cpu="s390x" - else - cpu="s390" - fi -elif check_define __riscv ; then - if check_define _LP64 ; then - cpu="riscv64" - else - cpu="riscv32" - fi -elif check_define __arm__ ; then - cpu="arm" -elif check_define __aarch64__ ; then - cpu="aarch64" -else - cpu=$(uname -m) -fi - -ARCH= -# Normalise host CPU name and set ARCH. -# Note that this case should only have supported host CPUs, not guests. -case "$cpu" in - ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64) - ;; - ppc64le) - ARCH="ppc64" - ;; - i386|i486|i586|i686|i86pc|BePC) - cpu="i386" - ;; - x86_64|amd64) - cpu="x86_64" - ;; - armv*b|armv*l|arm) - cpu="arm" - ;; - aarch64) - cpu="aarch64" - ;; - mips*) - cpu="mips" - ;; - sparc|sun4[cdmuv]) - cpu="sparc" - ;; - *) - # This will result in either an error or falling back to TCI later - ARCH=unknown - ;; -esac -if test -z "$ARCH"; then - ARCH="$cpu" -fi - -# OS specific - -# host *BSD for user mode -HOST_VARIANT_DIR="" - -case $targetos in -MINGW32*) - mingw32="yes" - hax="yes" - vhost_user="no" - audio_possible_drivers="dsound sdl" - if check_include dsound.h; then - audio_drv_list="dsound" - else - audio_drv_list="" - fi - supported_os="yes" - pie="no" -;; -GNU/kFreeBSD) - bsd="yes" - audio_drv_list="oss try-sdl" - audio_possible_drivers="oss sdl pa" -;; -FreeBSD) - bsd="yes" - make="${MAKE-gmake}" - audio_drv_list="oss try-sdl" - audio_possible_drivers="oss sdl pa" - # needed for kinfo_getvmmap(3) in libutil.h - LIBS="-lutil $LIBS" - netmap="" # enable netmap autodetect - HOST_VARIANT_DIR="freebsd" -;; -DragonFly) - bsd="yes" - make="${MAKE-gmake}" - audio_drv_list="oss try-sdl" - audio_possible_drivers="oss sdl pa" - HOST_VARIANT_DIR="dragonfly" -;; -NetBSD) - bsd="yes" - hax="yes" - make="${MAKE-gmake}" - audio_drv_list="oss try-sdl" - audio_possible_drivers="oss sdl" - oss_lib="-lossaudio" - HOST_VARIANT_DIR="netbsd" -;; -OpenBSD) - bsd="yes" - make="${MAKE-gmake}" - audio_drv_list="try-sdl" - audio_possible_drivers="sdl" - HOST_VARIANT_DIR="openbsd" -;; -Darwin) - bsd="yes" - darwin="yes" - hax="yes" - hvf="yes" - LDFLAGS_SHARED="-bundle -undefined dynamic_lookup" - if [ "$cpu" = "x86_64" ] ; then - QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" - QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS" - fi - cocoa="yes" - audio_drv_list="coreaudio try-sdl" - audio_possible_drivers="coreaudio sdl" - QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS" - # Disable attempts to use ObjectiveC features in os/object.h since they - # won't work when we're compiling with gcc as a C compiler. - QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS" - HOST_VARIANT_DIR="darwin" -;; -SunOS) - solaris="yes" - make="${MAKE-gmake}" - install="${INSTALL-ginstall}" - smbd="${SMBD-/usr/sfw/sbin/smbd}" - if test -f /usr/include/sys/soundcard.h ; then - audio_drv_list="oss try-sdl" - fi - audio_possible_drivers="oss sdl" -# needed for CMSG_ macros in sys/socket.h - QEMU_CFLAGS="-D_XOPEN_SOURCE=600 $QEMU_CFLAGS" -# needed for TIOCWIN* defines in termios.h - QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS" - solarisnetlibs="-lsocket -lnsl -lresolv" - LIBS="$solarisnetlibs $LIBS" -;; -Haiku) - haiku="yes" - QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -DBSD_SOURCE $QEMU_CFLAGS" - LIBS="-lposix_error_mapper -lnetwork -lbsd $LIBS" -;; -Linux) - audio_drv_list="try-pa oss" - audio_possible_drivers="oss alsa sdl pa" - linux="yes" - linux_user="yes" - kvm="yes" - QEMU_INCLUDES="-isystem ${source_path}/linux-headers -I${build_path}/linux-headers $QEMU_INCLUDES" - libudev="yes" -;; -esac - -if [ "$bsd" = "yes" ] ; then - if [ "$darwin" != "yes" ] ; then - bsd_user="yes" - fi -fi - -: ${make=${MAKE-make}} -: ${install=${INSTALL-install}} -# We prefer python 3.x. A bare 'python' is traditionally -# python 2.x, but some distros have it as python 3.x, so -# we check that too -python= -explicit_python=no -for binary in "${PYTHON-python3}" python -do - if has "$binary" - then - python=$(command -v "$binary") - break - fi -done - -sphinx_build= -for binary in sphinx-build-3 sphinx-build -do - if has "$binary" - then - sphinx_build=$(command -v "$binary") - break - fi -done - -# Check for ancillary tools used in testing -genisoimage= -for binary in genisoimage mkisofs -do - if has $binary - then - genisoimage=$(command -v "$binary") - break - fi -done - -: ${smbd=${SMBD-/usr/sbin/smbd}} - -# Default objcc to clang if available, otherwise use CC -if has clang; then - objcc=clang -else - objcc="$cc" -fi - -if test "$mingw32" = "yes" ; then - EXESUF=".exe" - HOST_DSOSUF=".dll" - # MinGW needs -mthreads for TLS and macro _MT. - CFLAGS="-mthreads $CFLAGS" - LIBS="-lwinmm -lws2_32 $LIBS" - write_c_skeleton; - if compile_prog "" "-liberty" ; then - LIBS="-liberty $LIBS" - fi - prefix="c:/Program Files/QEMU" - qemu_suffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -lwininet -liphlpapi -lnetapi32 $libs_qga" -fi - -werror="" - -for opt do - optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') - case "$opt" in - --help|-h) show_help=yes - ;; - --version|-V) exec cat $source_path/VERSION - ;; - --prefix=*) prefix="$optarg" - ;; - --interp-prefix=*) interp_prefix="$optarg" - ;; - --cross-prefix=*) - ;; - --cc=*) - ;; - --host-cc=*) host_cc="$optarg" - ;; - --cxx=*) - ;; - --iasl=*) iasl="$optarg" - ;; - --objcc=*) objcc="$optarg" - ;; - --make=*) make="$optarg" - ;; - --install=*) install="$optarg" - ;; - --python=*) python="$optarg" ; explicit_python=yes - ;; - --sphinx-build=*) sphinx_build="$optarg" - ;; - --skip-meson) skip_meson=yes - ;; - --meson=*) meson="$optarg" - ;; - --ninja=*) ninja="$optarg" - ;; - --smbd=*) smbd="$optarg" - ;; - --extra-cflags=*) - ;; - --extra-cxxflags=*) - ;; - --extra-ldflags=*) - ;; - --enable-debug-info) - ;; - --disable-debug-info) - ;; - --cross-cc-*) - ;; - --enable-modules) - modules="yes" - ;; - --disable-modules) - modules="no" - ;; - --disable-module-upgrades) module_upgrades="no" - ;; - --enable-module-upgrades) module_upgrades="yes" - ;; - --cpu=*) - ;; - --target-list=*) target_list="$optarg" - if test "$target_list_exclude"; then - error_exit "Can't mix --target-list with --target-list-exclude" - fi - ;; - --target-list-exclude=*) target_list_exclude="$optarg" - if test "$target_list"; then - error_exit "Can't mix --target-list-exclude with --target-list" - fi - ;; - --enable-trace-backends=*) trace_backends="$optarg" - ;; - # XXX: backwards compatibility - --enable-trace-backend=*) trace_backends="$optarg" - ;; - --with-trace-file=*) trace_file="$optarg" - ;; - --with-default-devices) default_devices="yes" - ;; - --without-default-devices) default_devices="no" - ;; - --enable-gprof) gprof="yes" - ;; - --enable-gcov) gcov="yes" - ;; - --static) - static="yes" - QEMU_PKG_CONFIG_FLAGS="--static $QEMU_PKG_CONFIG_FLAGS" - ;; - --mandir=*) mandir="$optarg" - ;; - --bindir=*) bindir="$optarg" - ;; - --libdir=*) libdir="$optarg" - ;; - --libexecdir=*) libexecdir="$optarg" - ;; - --includedir=*) includedir="$optarg" - ;; - --datadir=*) datadir="$optarg" - ;; - --with-suffix=*) qemu_suffix="$optarg" - ;; - --docdir=*) qemu_docdir="$optarg" - ;; - --sysconfdir=*) sysconfdir="$optarg" - ;; - --localstatedir=*) local_statedir="$optarg" - ;; - --firmwarepath=*) firmwarepath="$optarg" - ;; - --host=*|--build=*|\ - --disable-dependency-tracking|\ - --sbindir=*|--sharedstatedir=*|\ - --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\ - --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*) - # These switches are silently ignored, for compatibility with - # autoconf-generated configure scripts. This allows QEMU's - # configure to be used by RPM and similar macros that set - # lots of directory switches by default. - ;; - --disable-sdl) sdl="disabled" - ;; - --enable-sdl) sdl="enabled" - ;; - --disable-sdl-image) sdl_image="disabled" - ;; - --enable-sdl-image) sdl_image="enabled" - ;; - --disable-qom-cast-debug) qom_cast_debug="no" - ;; - --enable-qom-cast-debug) qom_cast_debug="yes" - ;; - --disable-virtfs) virtfs="no" - ;; - --enable-virtfs) virtfs="yes" - ;; - --disable-mpath) mpath="no" - ;; - --enable-mpath) mpath="yes" - ;; - --disable-vnc) vnc="disabled" - ;; - --enable-vnc) vnc="enabled" - ;; - --disable-gettext) gettext="false" - ;; - --enable-gettext) gettext="true" - ;; - --oss-lib=*) oss_lib="$optarg" - ;; - --audio-drv-list=*) audio_drv_list="$optarg" - ;; - --block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=$(echo "$optarg" | sed -e 's/,/ /g') - ;; - --block-drv-ro-whitelist=*) block_drv_ro_whitelist=$(echo "$optarg" | sed -e 's/,/ /g') - ;; - --enable-debug-tcg) debug_tcg="yes" - ;; - --disable-debug-tcg) debug_tcg="no" - ;; - --enable-debug) - # Enable debugging options that aren't excessively noisy - debug_tcg="yes" - debug_mutex="yes" - debug="yes" - strip_opt="no" - fortify_source="no" - ;; - --enable-sanitizers) sanitizers="yes" - ;; - --disable-sanitizers) sanitizers="no" - ;; - --enable-tsan) tsan="yes" - ;; - --disable-tsan) tsan="no" - ;; - --enable-sparse) sparse="yes" - ;; - --disable-sparse) sparse="no" - ;; - --disable-strip) strip_opt="no" - ;; - --disable-vnc-sasl) vnc_sasl="disabled" - ;; - --enable-vnc-sasl) vnc_sasl="enabled" - ;; - --disable-vnc-jpeg) vnc_jpeg="disabled" - ;; - --enable-vnc-jpeg) vnc_jpeg="enabled" - ;; - --disable-vnc-png) vnc_png="disabled" - ;; - --enable-vnc-png) vnc_png="enabled" - ;; - --disable-slirp) slirp="no" - ;; - --enable-slirp=git) slirp="git" - ;; - --enable-slirp=system) slirp="system" - ;; - --disable-vde) vde="no" - ;; - --enable-vde) vde="yes" - ;; - --disable-netmap) netmap="no" - ;; - --enable-netmap) netmap="yes" - ;; - --disable-xen) xen="no" - ;; - --enable-xen) xen="yes" - ;; - --disable-xen-pci-passthrough) xen_pci_passthrough="no" - ;; - --enable-xen-pci-passthrough) xen_pci_passthrough="yes" - ;; - --disable-brlapi) brlapi="no" - ;; - --enable-brlapi) brlapi="yes" - ;; - --disable-kvm) kvm="no" - ;; - --enable-kvm) kvm="yes" - ;; - --disable-hax) hax="no" - ;; - --enable-hax) hax="yes" - ;; - --disable-hvf) hvf="no" - ;; - --enable-hvf) hvf="yes" - ;; - --disable-whpx) whpx="no" - ;; - --enable-whpx) whpx="yes" - ;; - --disable-tcg-interpreter) tcg_interpreter="no" - ;; - --enable-tcg-interpreter) tcg_interpreter="yes" - ;; - --disable-cap-ng) cap_ng="no" - ;; - --enable-cap-ng) cap_ng="yes" - ;; - --disable-tcg) tcg="no" - ;; - --enable-tcg) tcg="yes" - ;; - --disable-malloc-trim) malloc_trim="no" - ;; - --enable-malloc-trim) malloc_trim="yes" - ;; - --disable-spice) spice="no" - ;; - --enable-spice) spice="yes" - ;; - --disable-libiscsi) libiscsi="no" - ;; - --enable-libiscsi) libiscsi="yes" - ;; - --disable-libnfs) libnfs="no" - ;; - --enable-libnfs) libnfs="yes" - ;; - --enable-profiler) profiler="yes" - ;; - --disable-cocoa) cocoa="no" - ;; - --enable-cocoa) - cocoa="yes" ; - audio_drv_list="coreaudio $(echo $audio_drv_list | sed s,coreaudio,,g)" - ;; - --disable-system) softmmu="no" - ;; - --enable-system) softmmu="yes" - ;; - --disable-user) - linux_user="no" ; - bsd_user="no" ; - ;; - --enable-user) ;; - --disable-linux-user) linux_user="no" - ;; - --enable-linux-user) linux_user="yes" - ;; - --disable-bsd-user) bsd_user="no" - ;; - --enable-bsd-user) bsd_user="yes" - ;; - --enable-pie) pie="yes" - ;; - --disable-pie) pie="no" - ;; - --enable-werror) werror="yes" - ;; - --disable-werror) werror="no" - ;; - --enable-stack-protector) stack_protector="yes" - ;; - --disable-stack-protector) stack_protector="no" - ;; - --enable-safe-stack) safe_stack="yes" - ;; - --disable-safe-stack) safe_stack="no" - ;; - --disable-curses) curses="no" - ;; - --enable-curses) curses="yes" - ;; - --disable-iconv) iconv="no" - ;; - --enable-iconv) iconv="yes" - ;; - --disable-curl) curl="no" - ;; - --enable-curl) curl="yes" - ;; - --disable-fdt) fdt="no" - ;; - --enable-fdt) fdt="yes" - ;; - --disable-linux-aio) linux_aio="no" - ;; - --enable-linux-aio) linux_aio="yes" - ;; - --disable-linux-io-uring) linux_io_uring="no" - ;; - --enable-linux-io-uring) linux_io_uring="yes" - ;; - --disable-attr) attr="no" - ;; - --enable-attr) attr="yes" - ;; - --disable-membarrier) membarrier="no" - ;; - --enable-membarrier) membarrier="yes" - ;; - --disable-blobs) blobs="no" - ;; - --with-pkgversion=*) pkgversion="$optarg" - ;; - --with-coroutine=*) coroutine="$optarg" - ;; - --disable-coroutine-pool) coroutine_pool="no" - ;; - --enable-coroutine-pool) coroutine_pool="yes" - ;; - --enable-debug-stack-usage) debug_stack_usage="yes" - ;; - --enable-crypto-afalg) crypto_afalg="yes" - ;; - --disable-crypto-afalg) crypto_afalg="no" - ;; - --disable-docs) docs="no" - ;; - --enable-docs) docs="yes" - ;; - --disable-vhost-net) vhost_net="no" - ;; - --enable-vhost-net) vhost_net="yes" - ;; - --disable-vhost-crypto) vhost_crypto="no" - ;; - --enable-vhost-crypto) vhost_crypto="yes" - ;; - --disable-vhost-scsi) vhost_scsi="no" - ;; - --enable-vhost-scsi) vhost_scsi="yes" - ;; - --disable-vhost-vsock) vhost_vsock="no" - ;; - --enable-vhost-vsock) vhost_vsock="yes" - ;; - --disable-vhost-user-fs) vhost_user_fs="no" - ;; - --enable-vhost-user-fs) vhost_user_fs="yes" - ;; - --disable-opengl) opengl="no" - ;; - --enable-opengl) opengl="yes" - ;; - --disable-rbd) rbd="no" - ;; - --enable-rbd) rbd="yes" - ;; - --disable-xfsctl) xfs="no" - ;; - --enable-xfsctl) xfs="yes" - ;; - --disable-smartcard) smartcard="no" - ;; - --enable-smartcard) smartcard="yes" - ;; - --disable-u2f) u2f="disabled" - ;; - --enable-u2f) u2f="enabled" - ;; - --disable-libusb) libusb="no" - ;; - --enable-libusb) libusb="yes" - ;; - --disable-usb-redir) usb_redir="no" - ;; - --enable-usb-redir) usb_redir="yes" - ;; - --disable-zlib-test) - ;; - --disable-lzo) lzo="no" - ;; - --enable-lzo) lzo="yes" - ;; - --disable-snappy) snappy="no" - ;; - --enable-snappy) snappy="yes" - ;; - --disable-bzip2) bzip2="no" - ;; - --enable-bzip2) bzip2="yes" - ;; - --enable-lzfse) lzfse="yes" - ;; - --disable-lzfse) lzfse="no" - ;; - --disable-zstd) zstd="no" - ;; - --enable-zstd) zstd="yes" - ;; - --enable-guest-agent) guest_agent="yes" - ;; - --disable-guest-agent) guest_agent="no" - ;; - --enable-guest-agent-msi) guest_agent_msi="yes" - ;; - --disable-guest-agent-msi) guest_agent_msi="no" - ;; - --with-vss-sdk) vss_win32_sdk="" - ;; - --with-vss-sdk=*) vss_win32_sdk="$optarg" - ;; - --without-vss-sdk) vss_win32_sdk="no" - ;; - --with-win-sdk) win_sdk="" - ;; - --with-win-sdk=*) win_sdk="$optarg" - ;; - --without-win-sdk) win_sdk="no" - ;; - --enable-tools) want_tools="yes" - ;; - --disable-tools) want_tools="no" - ;; - --enable-seccomp) seccomp="yes" - ;; - --disable-seccomp) seccomp="no" - ;; - --disable-glusterfs) glusterfs="no" - ;; - --disable-avx2) avx2_opt="no" - ;; - --enable-avx2) avx2_opt="yes" - ;; - --disable-avx512f) avx512f_opt="no" - ;; - --enable-avx512f) avx512f_opt="yes" - ;; - - --enable-glusterfs) glusterfs="yes" - ;; - --disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane) - echo "$0: $opt is obsolete, virtio-blk data-plane is always on" >&2 - ;; - --enable-vhdx|--disable-vhdx) - echo "$0: $opt is obsolete, VHDX driver is always built" >&2 - ;; - --enable-uuid|--disable-uuid) - echo "$0: $opt is obsolete, UUID support is always built" >&2 - ;; - --disable-gtk) gtk="no" - ;; - --enable-gtk) gtk="yes" - ;; - --tls-priority=*) tls_priority="$optarg" - ;; - --disable-gnutls) gnutls="no" - ;; - --enable-gnutls) gnutls="yes" - ;; - --disable-nettle) nettle="no" - ;; - --enable-nettle) nettle="yes" - ;; - --disable-gcrypt) gcrypt="no" - ;; - --enable-gcrypt) gcrypt="yes" - ;; - --disable-auth-pam) auth_pam="no" - ;; - --enable-auth-pam) auth_pam="yes" - ;; - --enable-rdma) rdma="yes" - ;; - --disable-rdma) rdma="no" - ;; - --enable-pvrdma) pvrdma="yes" - ;; - --disable-pvrdma) pvrdma="no" - ;; - --disable-vte) vte="no" - ;; - --enable-vte) vte="yes" - ;; - --disable-virglrenderer) virglrenderer="no" - ;; - --enable-virglrenderer) virglrenderer="yes" - ;; - --disable-tpm) tpm="no" - ;; - --enable-tpm) tpm="yes" - ;; - --disable-libssh) libssh="no" - ;; - --enable-libssh) libssh="yes" - ;; - --disable-live-block-migration) live_block_migration="no" - ;; - --enable-live-block-migration) live_block_migration="yes" - ;; - --disable-numa) numa="no" - ;; - --enable-numa) numa="yes" - ;; - --disable-libxml2) libxml2="no" - ;; - --enable-libxml2) libxml2="yes" - ;; - --disable-tcmalloc) tcmalloc="no" - ;; - --enable-tcmalloc) tcmalloc="yes" - ;; - --disable-jemalloc) jemalloc="no" - ;; - --enable-jemalloc) jemalloc="yes" - ;; - --disable-replication) replication="no" - ;; - --enable-replication) replication="yes" - ;; - --disable-bochs) bochs="no" - ;; - --enable-bochs) bochs="yes" - ;; - --disable-cloop) cloop="no" - ;; - --enable-cloop) cloop="yes" - ;; - --disable-dmg) dmg="no" - ;; - --enable-dmg) dmg="yes" - ;; - --disable-qcow1) qcow1="no" - ;; - --enable-qcow1) qcow1="yes" - ;; - --disable-vdi) vdi="no" - ;; - --enable-vdi) vdi="yes" - ;; - --disable-vvfat) vvfat="no" - ;; - --enable-vvfat) vvfat="yes" - ;; - --disable-qed) qed="no" - ;; - --enable-qed) qed="yes" - ;; - --disable-parallels) parallels="no" - ;; - --enable-parallels) parallels="yes" - ;; - --disable-sheepdog) sheepdog="no" - ;; - --enable-sheepdog) sheepdog="yes" - ;; - --disable-vhost-user) vhost_user="no" - ;; - --enable-vhost-user) vhost_user="yes" - ;; - --disable-vhost-vdpa) vhost_vdpa="no" - ;; - --enable-vhost-vdpa) vhost_vdpa="yes" - ;; - --disable-vhost-kernel) vhost_kernel="no" - ;; - --enable-vhost-kernel) vhost_kernel="yes" - ;; - --disable-capstone) capstone="no" - ;; - --enable-capstone) capstone="yes" - ;; - --enable-capstone=git) capstone="git" - ;; - --enable-capstone=system) capstone="system" - ;; - --with-git=*) git="$optarg" - ;; - --enable-git-update) git_update=yes - ;; - --disable-git-update) git_update=no - ;; - --enable-debug-mutex) debug_mutex=yes - ;; - --disable-debug-mutex) debug_mutex=no - ;; - --enable-libpmem) libpmem=yes - ;; - --disable-libpmem) libpmem=no - ;; - --enable-xkbcommon) xkbcommon="enabled" - ;; - --disable-xkbcommon) xkbcommon="disabled" - ;; - --enable-plugins) plugins="yes" - ;; - --disable-plugins) plugins="no" - ;; - --enable-containers) use_containers="yes" - ;; - --disable-containers) use_containers="no" - ;; - --enable-fuzzing) fuzzing=yes - ;; - --disable-fuzzing) fuzzing=no - ;; - --gdb=*) gdb_bin="$optarg" - ;; - --enable-rng-none) rng_none=yes - ;; - --disable-rng-none) rng_none=no - ;; - --enable-keyring) secret_keyring="yes" - ;; - --disable-keyring) secret_keyring="no" - ;; - --enable-libdaxctl) libdaxctl=yes - ;; - --disable-libdaxctl) libdaxctl=no - ;; - *) - echo "ERROR: unknown option $opt" - echo "Try '$0 --help' for more information" - exit 1 - ;; - esac -done - -firmwarepath="${firmwarepath:-$prefix/share/qemu-firmware}" -libdir="${libdir:-$prefix/lib}" -libexecdir="${libexecdir:-$prefix/libexec}" -includedir="${includedir:-$prefix/include}" - -if test "$mingw32" = "yes" ; then - mandir="$prefix" - datadir="$prefix" - docdir="$prefix" - bindir="$prefix" - sysconfdir="$prefix" - local_statedir= -else - mandir="${mandir:-$prefix/share/man}" - datadir="${datadir:-$prefix/share}" - docdir="${docdir:-$prefix/share/doc}" - bindir="${bindir:-$prefix/bin}" - sysconfdir="${sysconfdir:-$prefix/etc}" - local_statedir="${local_statedir:-$prefix/var}" -fi - -case "$cpu" in - ppc) - CPU_CFLAGS="-m32" - QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS" - ;; - ppc64) - CPU_CFLAGS="-m64" - QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" - ;; - sparc) - CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" - QEMU_LDFLAGS="-m32 -mv8plus $QEMU_LDFLAGS" - ;; - sparc64) - CPU_CFLAGS="-m64 -mcpu=ultrasparc" - QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" - ;; - s390) - CPU_CFLAGS="-m31" - QEMU_LDFLAGS="-m31 $QEMU_LDFLAGS" - ;; - s390x) - CPU_CFLAGS="-m64" - QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" - ;; - i386) - CPU_CFLAGS="-m32" - QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS" - ;; - x86_64) - # ??? Only extremely old AMD cpus do not have cmpxchg16b. - # If we truly care, we should simply detect this case at - # runtime and generate the fallback to serial emulation. - CPU_CFLAGS="-m64 -mcx16" - QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" - ;; - x32) - CPU_CFLAGS="-mx32" - QEMU_LDFLAGS="-mx32 $QEMU_LDFLAGS" - ;; - # No special flags required for other host CPUs -esac - -eval "cross_cc_${cpu}=\$host_cc" -cross_cc_vars="$cross_cc_vars cross_cc_${cpu}" -QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS" - -# For user-mode emulation the host arch has to be one we explicitly -# support, even if we're using TCI. -if [ "$ARCH" = "unknown" ]; then - bsd_user="no" - linux_user="no" -fi - -if [ "$bsd_user" = "no" -a "$linux_user" = "no" -a "$softmmu" = "no" ] ; then - tcg="no" -fi - -default_target_list="" - -mak_wilds="" - -if [ "$softmmu" = "yes" ]; then - mak_wilds="${mak_wilds} $source_path/default-configs/*-softmmu.mak" -fi -if [ "$linux_user" = "yes" ]; then - mak_wilds="${mak_wilds} $source_path/default-configs/*-linux-user.mak" -fi -if [ "$bsd_user" = "yes" ]; then - mak_wilds="${mak_wilds} $source_path/default-configs/*-bsd-user.mak" -fi - -if test -z "$target_list_exclude"; then - for config in $mak_wilds; do - default_target_list="${default_target_list} $(basename "$config" .mak)" - done -else - exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g') - for config in $mak_wilds; do - target="$(basename "$config" .mak)" - exclude="no" - for excl in $exclude_list; do - if test "$excl" = "$target"; then - exclude="yes" - break; - fi - done - if test "$exclude" = "no"; then - default_target_list="${default_target_list} $target" - fi - done -fi - -# Enumerate public trace backends for --help output -trace_backend_list=$(echo $(grep -le '^PUBLIC = True$' "$source_path"/scripts/tracetool/backend/*.py | sed -e 's/^.*\/\(.*\)\.py$/\1/')) - -if test x"$show_help" = x"yes" ; then -cat << EOF - -Usage: configure [options] -Options: [defaults in brackets after descriptions] - -Standard options: - --help print this message - --prefix=PREFIX install in PREFIX [$prefix] - --interp-prefix=PREFIX where to find shared libraries, etc. - use %M for cpu name [$interp_prefix] - --target-list=LIST set target list (default: build everything) -$(echo Available targets: $default_target_list | \ - fold -s -w 53 | sed -e 's/^/ /') - --target-list-exclude=LIST exclude a set of targets from the default target-list - -Advanced options (experts only): - --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix] - --cc=CC use C compiler CC [$cc] - --iasl=IASL use ACPI compiler IASL [$iasl] - --host-cc=CC use C compiler CC [$host_cc] for code run at - build time - --cxx=CXX use C++ compiler CXX [$cxx] - --objcc=OBJCC use Objective-C compiler OBJCC [$objcc] - --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS - --extra-cxxflags=CXXFLAGS append extra C++ compiler flags QEMU_CXXFLAGS - --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS - --cross-cc-ARCH=CC use compiler when building ARCH guest test cases - --cross-cc-flags-ARCH= use compiler flags when building ARCH guest tests - --make=MAKE use specified make [$make] - --install=INSTALL use specified install [$install] - --python=PYTHON use specified python [$python] - --sphinx-build=SPHINX use specified sphinx-build [$sphinx_build] - --meson=MESON use specified meson [$meson] - --ninja=NINJA use specified ninja [$ninja] - --smbd=SMBD use specified smbd [$smbd] - --with-git=GIT use specified git [$git] - --static enable static build [$static] - --mandir=PATH install man pages in PATH - --datadir=PATH install firmware in PATH/$qemu_suffix - --docdir=PATH install documentation in PATH/$qemu_suffix - --bindir=PATH install binaries in PATH - --libdir=PATH install libraries in PATH - --libexecdir=PATH install helper binaries in PATH - --sysconfdir=PATH install config in PATH/$qemu_suffix - --localstatedir=PATH install local state in PATH (set at runtime on win32) - --firmwarepath=PATH search PATH for firmware files - --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. - --with-suffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir/docdir [$qemu_suffix] - --with-pkgversion=VERS use specified string as sub-version of the package - --enable-debug enable common debug build options - --enable-sanitizers enable default sanitizers - --enable-tsan enable thread sanitizer - --disable-strip disable stripping binaries - --disable-werror disable compilation abort on warning - --disable-stack-protector disable compiler-provided stack protection - --audio-drv-list=LIST set audio drivers list: - Available drivers: $audio_possible_drivers - --block-drv-whitelist=L Same as --block-drv-rw-whitelist=L - --block-drv-rw-whitelist=L - set block driver read-write whitelist - (affects only QEMU, not qemu-img) - --block-drv-ro-whitelist=L - set block driver read-only whitelist - (affects only QEMU, not qemu-img) - --enable-trace-backends=B Set trace backend - Available backends: $trace_backend_list - --with-trace-file=NAME Full PATH,NAME of file to store traces - Default:trace- - --disable-slirp disable SLIRP userspace network connectivity - --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI) - --enable-malloc-trim enable libc malloc_trim() for memory optimization - --oss-lib path to OSS library - --cpu=CPU Build for host CPU [$cpu] - --with-coroutine=BACKEND coroutine backend. Supported options: - ucontext, sigaltstack, windows - --enable-gcov enable test coverage analysis with gcov - --disable-blobs disable installing provided firmware blobs - --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent - --with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb) - --tls-priority default TLS protocol/cipher priority string - --enable-gprof QEMU profiling with gprof - --enable-profiler profiler support - --enable-debug-stack-usage - track the maximum stack usage of stacks created by qemu_alloc_stack - --enable-plugins - enable plugins via shared library loading - --disable-containers don't use containers for cross-building - --gdb=GDB-path gdb to use for gdbstub tests [$gdb_bin] - -Optional features, enabled with --enable-FEATURE and -disabled with --disable-FEATURE, default is enabled if available: - - system all system emulation targets - user supported user emulation targets - linux-user all linux usermode emulation targets - bsd-user all BSD usermode emulation targets - docs build documentation - guest-agent build the QEMU Guest Agent - guest-agent-msi build guest agent Windows MSI installation package - pie Position Independent Executables - modules modules support (non-Windows) - module-upgrades try to load modules from alternate paths for upgrades - debug-tcg TCG debugging (default is disabled) - debug-info debugging information - sparse sparse checker - safe-stack SafeStack Stack Smash Protection. Depends on - clang/llvm >= 3.7 and requires coroutine backend ucontext. - - gnutls GNUTLS cryptography support - nettle nettle cryptography support - gcrypt libgcrypt cryptography support - auth-pam PAM access control - sdl SDL UI - sdl-image SDL Image support for icons - gtk gtk UI - vte vte support for the gtk UI - curses curses UI - iconv font glyph conversion support - vnc VNC UI support - vnc-sasl SASL encryption for VNC server - vnc-jpeg JPEG lossy compression for VNC server - vnc-png PNG compression for VNC server - cocoa Cocoa UI (Mac OS X only) - virtfs VirtFS - mpath Multipath persistent reservation passthrough - xen xen backend driver support - xen-pci-passthrough PCI passthrough support for Xen - brlapi BrlAPI (Braile) - curl curl connectivity - membarrier membarrier system call (for Linux 4.14+ or Windows) - fdt fdt device tree - kvm KVM acceleration support - hax HAX acceleration support - hvf Hypervisor.framework acceleration support - whpx Windows Hypervisor Platform acceleration support - rdma Enable RDMA-based migration - pvrdma Enable PVRDMA support - vde support for vde network - netmap support for netmap network - linux-aio Linux AIO support - linux-io-uring Linux io_uring support - cap-ng libcap-ng support - attr attr and xattr support - vhost-net vhost-net kernel acceleration support - vhost-vsock virtio sockets device support - vhost-scsi vhost-scsi kernel target support - vhost-crypto vhost-user-crypto backend support - vhost-kernel vhost kernel backend support - vhost-user vhost-user backend support - vhost-vdpa vhost-vdpa kernel backend support - spice spice - rbd rados block device (rbd) - libiscsi iscsi support - libnfs nfs support - smartcard smartcard support (libcacard) - u2f U2F support (u2f-emu) - libusb libusb (for usb passthrough) - live-block-migration Block migration in the main migration stream - usb-redir usb network redirection support - lzo support of lzo compression library - snappy support of snappy compression library - bzip2 support of bzip2 compression library - (for reading bzip2-compressed dmg images) - lzfse support of lzfse compression library - (for reading lzfse-compressed dmg images) - zstd support for zstd compression library - (for migration compression and qcow2 cluster compression) - seccomp seccomp support - coroutine-pool coroutine freelist (better performance) - glusterfs GlusterFS backend - tpm TPM support - libssh ssh block device support - numa libnuma support - libxml2 for Parallels image format - tcmalloc tcmalloc support - jemalloc jemalloc support - avx2 AVX2 optimization support - avx512f AVX512F optimization support - replication replication support - opengl opengl support - virglrenderer virgl rendering support - xfsctl xfsctl support - qom-cast-debug cast debugging support - tools build qemu-io, qemu-nbd and qemu-img tools - bochs bochs image format support - cloop cloop image format support - dmg dmg image format support - qcow1 qcow v1 image format support - vdi vdi image format support - vvfat vvfat image format support - qed qed image format support - parallels parallels image format support - sheepdog sheepdog block driver support - crypto-afalg Linux AF_ALG crypto backend driver - capstone capstone disassembler support - debug-mutex mutex debugging support - libpmem libpmem support - xkbcommon xkbcommon support - rng-none dummy RNG, avoid using /dev/(u)random and getrandom() - libdaxctl libdaxctl support - -NOTE: The object files are built at the place where configure is launched -EOF -exit 0 -fi - -# Remove old dependency files to make sure that they get properly regenerated -rm -f */config-devices.mak.d - -if test -z "$python" -then - error_exit "Python not found. Use --python=/path/to/python" -fi - -# Note that if the Python conditional here evaluates True we will exit -# with status 1 which is a shell 'false' value. -if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then - error_exit "Cannot use '$python', Python >= 3.5 is required." \ - "Use --python=/path/to/python to specify a supported Python." -fi - -# Preserve python version since some functionality is dependent on it -python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))' 2>/dev/null) - -# Suppress writing compiled files -python="$python -B" - -if test -z "$meson"; then - if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.1; then - meson=meson - elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then - meson=git - elif test -e "${source_path}/meson/meson.py" ; then - meson=internal - else - if test "$explicit_python" = yes; then - error_exit "--python requires using QEMU's embedded Meson distribution, but it was not found." - else - error_exit "Meson not found. Use --meson=/path/to/meson" - fi - fi -else - # Meson uses its own Python interpreter to invoke other Python scripts, - # but the user wants to use the one they specified with --python. - # - # We do not want to override the distro Python interpreter (and sometimes - # cannot: for example in Homebrew /usr/bin/meson is a bash script), so - # just require --meson=git|internal together with --python. - if test "$explicit_python" = yes; then - case "$meson" in - git | internal) ;; - *) error_exit "--python requires using QEMU's embedded Meson distribution." ;; - esac - fi -fi - -if test "$meson" = git; then - git_submodules="${git_submodules} meson" -fi - -case "$meson" in - git | internal) - if ! $python -c 'import pkg_resources' > /dev/null 2>&1; then - error_exit "Python setuptools not found" - fi - meson="$python ${source_path}/meson/meson.py" - ;; - *) meson=$(command -v meson) ;; -esac - -# Probe for ninja (used for compdb) - -if test -z "$ninja"; then - for c in ninja ninja-build samu; do - if has $c; then - ninja=$(command -v "$c") - break - fi - done -fi - -# Check that the C compiler works. Doing this here before testing -# the host CPU ensures that we had a valid CC to autodetect the -# $cpu var (and we should bail right here if that's not the case). -# It also allows the help message to be printed without a CC. -write_c_skeleton; -if compile_object ; then - : C compiler works ok -else - error_exit "\"$cc\" either does not exist or does not work" -fi -if ! compile_prog ; then - error_exit "\"$cc\" cannot build an executable (is your linker broken?)" -fi - -# Now we have handled --enable-tcg-interpreter and know we're not just -# printing the help message, bail out if the host CPU isn't supported. -if test "$ARCH" = "unknown"; then - if test "$tcg_interpreter" = "yes" ; then - echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)" - else - error_exit "Unsupported CPU = $cpu, try --enable-tcg-interpreter" - fi -fi - -# Consult white-list to determine whether to enable werror -# by default. Only enable by default for git builds -if test -z "$werror" ; then - if test -e "$source_path/.git" && \ - { test "$linux" = "yes" || test "$mingw32" = "yes"; }; then - werror="yes" - else - werror="no" - fi -fi - -if test "$bogus_os" = "yes"; then - # Now that we know that we're not printing the help and that - # the compiler works (so the results of the check_defines we used - # to identify the OS are reliable), if we didn't recognize the - # host OS we should stop now. - error_exit "Unrecognized host OS (uname -s reports '$(uname -s)')" -fi - -# Check whether the compiler matches our minimum requirements: -cat > $TMPC << EOF -#if defined(__clang_major__) && defined(__clang_minor__) -# ifdef __apple_build_version__ -# if __clang_major__ < 5 || (__clang_major__ == 5 && __clang_minor__ < 1) -# error You need at least XCode Clang v5.1 to compile QEMU -# endif -# else -# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4) -# error You need at least Clang v3.4 to compile QEMU -# endif -# endif -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) -# error You need at least GCC v4.8 to compile QEMU -# endif -#else -# error You either need GCC or Clang to compiler QEMU -#endif -int main (void) { return 0; } -EOF -if ! compile_prog "" "" ; then - error_exit "You need at least GCC v4.8 or Clang v3.4 (or XCode Clang v5.1)" -fi - -# Accumulate -Wfoo and -Wno-bar separately. -# We will list all of the enable flags first, and the disable flags second. -# Note that we do not add -Werror, because that would enable it for all -# configure tests. If a configure test failed due to -Werror this would -# just silently disable some features, so it's too error prone. - -warn_flags= -add_to warn_flags -Wold-style-declaration -add_to warn_flags -Wold-style-definition -add_to warn_flags -Wtype-limits -add_to warn_flags -Wformat-security -add_to warn_flags -Wformat-y2k -add_to warn_flags -Winit-self -add_to warn_flags -Wignored-qualifiers -add_to warn_flags -Wempty-body -add_to warn_flags -Wnested-externs -add_to warn_flags -Wendif-labels -add_to warn_flags -Wexpansion-to-defined - -nowarn_flags= -add_to nowarn_flags -Wno-initializer-overrides -add_to nowarn_flags -Wno-missing-include-dirs -add_to nowarn_flags -Wno-shift-negative-value -add_to nowarn_flags -Wno-string-plus-int -add_to nowarn_flags -Wno-typedef-redefinition -add_to nowarn_flags -Wno-tautological-type-limit-compare -add_to nowarn_flags -Wno-psabi - -gcc_flags="$warn_flags $nowarn_flags" - -cc_has_warning_flag() { - write_c_skeleton; - - # Use the positive sense of the flag when testing for -Wno-wombat - # support (gcc will happily accept the -Wno- form of unknown - # warning options). - optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')" - compile_prog "-Werror $optflag" "" -} - -for flag in $gcc_flags; do - if cc_has_warning_flag $flag ; then - QEMU_CFLAGS="$QEMU_CFLAGS $flag" - fi -done - -if test "$stack_protector" != "no"; then - cat > $TMPC << EOF -int main(int argc, char *argv[]) -{ - char arr[64], *p = arr, *c = argv[0]; - while (*c) { - *p++ = *c++; - } - return 0; -} -EOF - gcc_flags="-fstack-protector-strong -fstack-protector-all" - sp_on=0 - for flag in $gcc_flags; do - # We need to check both a compile and a link, since some compiler - # setups fail only on a .c->.o compile and some only at link time - if compile_object "-Werror $flag" && - compile_prog "-Werror $flag" ""; then - QEMU_CFLAGS="$QEMU_CFLAGS $flag" - QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" - sp_on=1 - break - fi - done - if test "$stack_protector" = yes; then - if test $sp_on = 0; then - error_exit "Stack protector not supported" - fi - fi -fi - -# Disable -Wmissing-braces on older compilers that warn even for -# the "universal" C zero initializer {0}. -cat > $TMPC << EOF -struct { - int a[2]; -} x = {0}; -EOF -if compile_object "-Werror" "" ; then - : -else - QEMU_CFLAGS="$QEMU_CFLAGS -Wno-missing-braces" -fi - -# Our module code doesn't support Windows -if test "$modules" = "yes" && test "$mingw32" = "yes" ; then - error_exit "Modules are not available for Windows" -fi - -# module_upgrades is only reasonable if modules are enabled -if test "$modules" = "no" && test "$module_upgrades" = "yes" ; then - error_exit "Can't enable module-upgrades as Modules are not enabled" -fi - -# Static linking is not possible with modules or PIE -if test "$static" = "yes" ; then - if test "$modules" = "yes" ; then - error_exit "static and modules are mutually incompatible" - fi -fi - -# Unconditional check for compiler __thread support - cat > $TMPC << EOF -static __thread int tls_var; -int main(void) { return tls_var; } -EOF - -if ! compile_prog "-Werror" "" ; then - error_exit "Your compiler does not support the __thread specifier for " \ - "Thread-Local Storage (TLS). Please upgrade to a version that does." -fi - -cat > $TMPC << EOF - -#ifdef __linux__ -# define THREAD __thread -#else -# define THREAD -#endif -static THREAD int tls_var; -int main(void) { return tls_var; } -EOF - -# Check we support --no-pie first; we will need this for building ROMs. -if compile_prog "-Werror -fno-pie" "-no-pie"; then - CFLAGS_NOPIE="-fno-pie" - LDFLAGS_NOPIE="-no-pie" -fi - -if test "$static" = "yes"; then - if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then - CFLAGS="-fPIE -DPIE $CFLAGS" - QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS" - pie="yes" - elif test "$pie" = "yes"; then - error_exit "-static-pie not available due to missing toolchain support" - else - QEMU_LDFLAGS="-static $QEMU_LDFLAGS" - pie="no" - fi -elif test "$pie" = "no"; then - CFLAGS="$CFLAGS_NOPIE $CFLAGS" - LDFLAGS="$LDFLAGS_NOPIE $LDFLAGS" -elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then - CFLAGS="-fPIE -DPIE $CFLAGS" - LDFLAGS="-pie $LDFLAGS" - pie="yes" -elif test "$pie" = "yes"; then - error_exit "PIE not available due to missing toolchain support" -else - echo "Disabling PIE due to missing toolchain support" - pie="no" -fi - -# Detect support for PT_GNU_RELRO + DT_BIND_NOW. -# The combination is known as "full relro", because .got.plt is read-only too. -if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then - QEMU_LDFLAGS="-Wl,-z,relro -Wl,-z,now $QEMU_LDFLAGS" -fi - -########################################## -# __sync_fetch_and_and requires at least -march=i486. Many toolchains -# use i686 as default anyway, but for those that don't, an explicit -# specification is necessary - -if test "$cpu" = "i386"; then - cat > $TMPC << EOF -static int sfaa(int *ptr) -{ - return __sync_fetch_and_and(ptr, 0); -} - -int main(void) -{ - int val = 42; - val = __sync_val_compare_and_swap(&val, 0, 1); - sfaa(&val); - return val; -} -EOF - if ! compile_prog "" "" ; then - QEMU_CFLAGS="-march=i486 $QEMU_CFLAGS" - fi -fi - -######################################### -# Solaris specific configure tool chain decisions - -if test "$solaris" = "yes" ; then - if has $install; then - : - else - error_exit "Solaris install program not found. Use --install=/usr/ucb/install or" \ - "install fileutils from www.blastwave.org using pkg-get -i fileutils" \ - "to get ginstall which is used by default (which lives in /opt/csw/bin)" - fi - if test "$(path_of $install)" = "/usr/sbin/install" ; then - error_exit "Solaris /usr/sbin/install is not an appropriate install program." \ - "try ginstall from the GNU fileutils available from www.blastwave.org" \ - "using pkg-get -i fileutils, or use --install=/usr/ucb/install" - fi - if has ar; then - : - else - if test -f /usr/ccs/bin/ar ; then - error_exit "No path includes ar" \ - "Add /usr/ccs/bin to your path and rerun configure" - fi - error_exit "No path includes ar" - fi -fi - -if test -z "${target_list+xxx}" ; then - for target in $default_target_list; do - supported_target $target 2>/dev/null && \ - target_list="$target_list $target" - done - target_list="${target_list# }" -else - target_list=$(echo "$target_list" | sed -e 's/,/ /g') - for target in $target_list; do - # Check that we recognised the target name; this allows a more - # friendly error message than if we let it fall through. - case " $default_target_list " in - *" $target "*) - ;; - *) - error_exit "Unknown target name '$target'" - ;; - esac - supported_target $target || exit 1 - done -fi - -# see if system emulation was really requested -case " $target_list " in - *"-softmmu "*) softmmu=yes - ;; - *) softmmu=no - ;; -esac - -for target in $target_list; do - case "$target" in - arm-softmmu | aarch64-softmmu | i386-softmmu | x86_64-softmmu) - edk2_blobs="yes" - ;; - esac -done -# The EDK2 binaries are compressed with bzip2 -if test "$edk2_blobs" = "yes" && ! has bzip2; then - error_exit "The bzip2 program is required for building QEMU" -fi - -feature_not_found() { - feature=$1 - remedy=$2 - - error_exit "User requested feature $feature" \ - "configure was not able to find it." \ - "$remedy" -} - -# --- -# big/little endian test -cat > $TMPC << EOF -short big_endian[] = { 0x4269, 0x4765, 0x4e64, 0x4961, 0x4e00, 0, }; -short little_endian[] = { 0x694c, 0x7454, 0x654c, 0x6e45, 0x6944, 0x6e41, 0, }; -extern int foo(short *, short *); -int main(int argc, char *argv[]) { - return foo(big_endian, little_endian); -} -EOF - -if compile_object ; then - if strings -a $TMPO | grep -q BiGeNdIaN ; then - bigendian="yes" - elif strings -a $TMPO | grep -q LiTtLeEnDiAn ; then - bigendian="no" - else - echo big/little test failed - fi -else - echo big/little test failed -fi - -########################################## -# system tools -if test -z "$want_tools"; then - if test "$softmmu" = "no"; then - want_tools=no - else - want_tools=yes - fi -fi - -########################################## -# cocoa implies not SDL or GTK -# (the cocoa UI code currently assumes it is always the active UI -# and doesn't interact well with other UI frontend code) -if test "$cocoa" = "yes"; then - if test "$sdl" = "yes"; then - error_exit "Cocoa and SDL UIs cannot both be enabled at once" - fi - if test "$gtk" = "yes"; then - error_exit "Cocoa and GTK UIs cannot both be enabled at once" - fi - gtk=no - sdl=disabled -fi - -# Some versions of Mac OS X incorrectly define SIZE_MAX -cat > $TMPC << EOF -#include -#include -int main(int argc, char *argv[]) { - return printf("%zu", SIZE_MAX); -} -EOF -have_broken_size_max=no -if ! compile_object -Werror ; then - have_broken_size_max=yes -fi - -########################################## -# L2TPV3 probe - -cat > $TMPC < -#include -int main(void) { return sizeof(struct mmsghdr); } -EOF -if compile_prog "" "" ; then - l2tpv3=yes -else - l2tpv3=no -fi - -if check_include "pty.h" ; then - pty_h=yes -else - pty_h=no -fi - -cat > $TMPC < -int main(int argc, char *argv[]) { - return mlockall(MCL_FUTURE); -} -EOF -if compile_prog "" "" ; then - have_mlockall=yes -else - have_mlockall=no -fi - -######################################### -# vhost interdependencies and host support - -# vhost backends -test "$vhost_user" = "" && vhost_user=yes -if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then - error_exit "vhost-user isn't available on win32" -fi -test "$vhost_vdpa" = "" && vhost_vdpa=$linux -if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then - error_exit "vhost-vdpa is only available on Linux" -fi -test "$vhost_kernel" = "" && vhost_kernel=$linux -if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then - error_exit "vhost-kernel is only available on Linux" -fi - -# vhost-kernel devices -test "$vhost_scsi" = "" && vhost_scsi=$vhost_kernel -if test "$vhost_scsi" = "yes" && test "$vhost_kernel" != "yes"; then - error_exit "--enable-vhost-scsi requires --enable-vhost-kernel" -fi -test "$vhost_vsock" = "" && vhost_vsock=$vhost_kernel -if test "$vhost_vsock" = "yes" && test "$vhost_kernel" != "yes"; then - error_exit "--enable-vhost-vsock requires --enable-vhost-kernel" -fi - -# vhost-user backends -test "$vhost_net_user" = "" && vhost_net_user=$vhost_user -if test "$vhost_net_user" = "yes" && test "$vhost_user" = "no"; then - error_exit "--enable-vhost-net-user requires --enable-vhost-user" -fi -test "$vhost_crypto" = "" && vhost_crypto=$vhost_user -if test "$vhost_crypto" = "yes" && test "$vhost_user" = "no"; then - error_exit "--enable-vhost-crypto requires --enable-vhost-user" -fi -test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user -if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then - error_exit "--enable-vhost-user-fs requires --enable-vhost-user" -fi -#vhost-vdpa backends -test "$vhost_net_vdpa" = "" && vhost_net_vdpa=$vhost_vdpa -if test "$vhost_net_vdpa" = "yes" && test "$vhost_vdpa" = "no"; then - error_exit "--enable-vhost-net-vdpa requires --enable-vhost-vdpa" -fi - -# OR the vhost-kernel and vhost-user values for simplicity -if test "$vhost_net" = ""; then - test "$vhost_net_user" = "yes" && vhost_net=yes - test "$vhost_kernel" = "yes" && vhost_net=yes -fi - -########################################## -# MinGW / Mingw-w64 localtime_r/gmtime_r check - -if test "$mingw32" = "yes"; then - # Some versions of MinGW / Mingw-w64 lack localtime_r - # and gmtime_r entirely. - # - # Some versions of Mingw-w64 define a macro for - # localtime_r/gmtime_r. - # - # Some versions of Mingw-w64 will define functions - # for localtime_r/gmtime_r, but only if you have - # _POSIX_THREAD_SAFE_FUNCTIONS defined. For fun - # though, unistd.h and pthread.h both define - # that for you. - # - # So this #undef localtime_r and #include - # are not in fact redundant. -cat > $TMPC << EOF -#include -#include -#undef localtime_r -int main(void) { localtime_r(NULL, NULL); return 0; } -EOF - if compile_prog "" "" ; then - localtime_r="yes" - else - localtime_r="no" - fi -fi - -########################################## -# pkg-config probe - -if ! has "$pkg_config_exe"; then - error_exit "pkg-config binary '$pkg_config_exe' not found" -fi - -########################################## -# NPTL probe - -if test "$linux_user" = "yes"; then - cat > $TMPC < -#include -int main(void) { -#if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT) -#error bork -#endif - return 0; -} -EOF - if ! compile_object ; then - feature_not_found "nptl" "Install glibc and linux kernel headers." - fi -fi - -########################################## -# lzo check - -if test "$lzo" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { lzo_version(); return 0; } -EOF - if compile_prog "" "-llzo2" ; then - lzo_libs="-llzo2" - lzo="yes" - else - if test "$lzo" = "yes"; then - feature_not_found "liblzo2" "Install liblzo2 devel" - fi - lzo="no" - fi -fi - -########################################## -# snappy check - -if test "$snappy" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { snappy_max_compressed_length(4096); return 0; } -EOF - if compile_prog "" "-lsnappy" ; then - snappy_libs='-lsnappy' - snappy="yes" - else - if test "$snappy" = "yes"; then - feature_not_found "libsnappy" "Install libsnappy devel" - fi - snappy="no" - fi -fi - -########################################## -# bzip2 check - -if test "$bzip2" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { BZ2_bzlibVersion(); return 0; } -EOF - if compile_prog "" "-lbz2" ; then - bzip2="yes" - else - if test "$bzip2" = "yes"; then - feature_not_found "libbzip2" "Install libbzip2 devel" - fi - bzip2="no" - fi -fi - -########################################## -# lzfse check - -if test "$lzfse" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { lzfse_decode_scratch_size(); return 0; } -EOF - if compile_prog "" "-llzfse" ; then - lzfse="yes" - else - if test "$lzfse" = "yes"; then - feature_not_found "lzfse" "Install lzfse devel" - fi - lzfse="no" - fi -fi - -########################################## -# zstd check - -if test "$zstd" != "no" ; then - libzstd_minver="1.4.0" - if $pkg_config --atleast-version=$libzstd_minver libzstd ; then - zstd_cflags="$($pkg_config --cflags libzstd)" - zstd_libs="$($pkg_config --libs libzstd)" - zstd="yes" - else - if test "$zstd" = "yes" ; then - feature_not_found "libzstd" "Install libzstd devel" - fi - zstd="no" - fi -fi - -########################################## -# libseccomp check - -if test "$seccomp" != "no" ; then - libseccomp_minver="2.3.0" - if $pkg_config --atleast-version=$libseccomp_minver libseccomp ; then - seccomp_cflags="$($pkg_config --cflags libseccomp)" - seccomp_libs="$($pkg_config --libs libseccomp)" - seccomp="yes" - else - if test "$seccomp" = "yes" ; then - feature_not_found "libseccomp" \ - "Install libseccomp devel >= $libseccomp_minver" - fi - seccomp="no" - fi -fi -########################################## -# xen probe - -if test "$xen" != "no" ; then - # Check whether Xen library path is specified via --extra-ldflags to avoid - # overriding this setting with pkg-config output. If not, try pkg-config - # to obtain all needed flags. - - if ! echo $EXTRA_LDFLAGS | grep tools/libxc > /dev/null && \ - $pkg_config --exists xencontrol ; then - xen_ctrl_version="$(printf '%d%02d%02d' \ - $($pkg_config --modversion xencontrol | sed 's/\./ /g') )" - xen=yes - xen_pc="xencontrol xenstore xenguest xenforeignmemory xengnttab" - xen_pc="$xen_pc xenevtchn xendevicemodel" - if $pkg_config --exists xentoolcore; then - xen_pc="$xen_pc xentoolcore" - fi - QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags $xen_pc)" - xen_cflags="$($pkg_config --cflags $xen_pc)" - xen_libs="$($pkg_config --libs $xen_pc)" - else - - xen_libs="-lxenstore -lxenctrl -lxenguest" - xen_stable_libs="-lxenforeignmemory -lxengnttab -lxenevtchn" - - # First we test whether Xen headers and libraries are available. - # If no, we are done and there is no Xen support. - # If yes, more tests are run to detect the Xen version. - - # Xen (any) - cat > $TMPC < -int main(void) { - return 0; -} -EOF - if ! compile_prog "" "$xen_libs" ; then - # Xen not found - if test "$xen" = "yes" ; then - feature_not_found "xen" "Install xen devel" - fi - xen=no - - # Xen unstable - elif - cat > $TMPC < -#include -int main(void) { - xendevicemodel_handle *xd; - xenforeignmemory_handle *xfmem; - - xd = xendevicemodel_open(0, 0); - xendevicemodel_pin_memory_cacheattr(xd, 0, 0, 0, 0); - - xfmem = xenforeignmemory_open(0, 0); - xenforeignmemory_map_resource(xfmem, 0, 0, 0, 0, 0, NULL, 0, 0); - - return 0; -} -EOF - compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs -lxentoolcore" - then - xen_stable_libs="-lxendevicemodel $xen_stable_libs -lxentoolcore" - xen_ctrl_version=41100 - xen=yes - elif - cat > $TMPC < -#include -int main(void) { - xenforeignmemory_handle *xfmem; - - xfmem = xenforeignmemory_open(0, 0); - xenforeignmemory_map2(xfmem, 0, 0, 0, 0, 0, 0, 0); - xentoolcore_restrict_all(0); - - return 0; -} -EOF - compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs -lxentoolcore" - then - xen_stable_libs="-lxendevicemodel $xen_stable_libs -lxentoolcore" - xen_ctrl_version=41000 - xen=yes - elif - cat > $TMPC < -int main(void) { - xendevicemodel_handle *xd; - - xd = xendevicemodel_open(0, 0); - xendevicemodel_close(xd); - - return 0; -} -EOF - compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs" - then - xen_stable_libs="-lxendevicemodel $xen_stable_libs" - xen_ctrl_version=40900 - xen=yes - elif - cat > $TMPC < -#include -#include -#include -#include -#include -#include -#if !defined(HVM_MAX_VCPUS) -# error HVM_MAX_VCPUS not defined -#endif -int main(void) { - xc_interface *xc = NULL; - xenforeignmemory_handle *xfmem; - xenevtchn_handle *xe; - xengnttab_handle *xg; - xengnttab_grant_copy_segment_t* seg = NULL; - - xs_daemon_open(); - - xc = xc_interface_open(0, 0, 0); - xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); - xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); - xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); - xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); - - xfmem = xenforeignmemory_open(0, 0); - xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); - - xe = xenevtchn_open(0, 0); - xenevtchn_fd(xe); - - xg = xengnttab_open(0, 0); - xengnttab_grant_copy(xg, 0, seg); - - return 0; -} -EOF - compile_prog "" "$xen_libs $xen_stable_libs" - then - xen_ctrl_version=40800 - xen=yes - elif - cat > $TMPC < -#include -#include -#include -#include -#include -#include -#if !defined(HVM_MAX_VCPUS) -# error HVM_MAX_VCPUS not defined -#endif -int main(void) { - xc_interface *xc = NULL; - xenforeignmemory_handle *xfmem; - xenevtchn_handle *xe; - xengnttab_handle *xg; - - xs_daemon_open(); - - xc = xc_interface_open(0, 0, 0); - xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); - xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); - xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); - xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); - - xfmem = xenforeignmemory_open(0, 0); - xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); - - xe = xenevtchn_open(0, 0); - xenevtchn_fd(xe); - - xg = xengnttab_open(0, 0); - xengnttab_map_grant_ref(xg, 0, 0, 0); - - return 0; -} -EOF - compile_prog "" "$xen_libs $xen_stable_libs" - then - xen_ctrl_version=40701 - xen=yes - - # Xen 4.6 - elif - cat > $TMPC < -#include -#include -#include -#if !defined(HVM_MAX_VCPUS) -# error HVM_MAX_VCPUS not defined -#endif -int main(void) { - xc_interface *xc; - xs_daemon_open(); - xc = xc_interface_open(0, 0, 0); - xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); - xc_gnttab_open(NULL, 0); - xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); - xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); - xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); - xc_reserved_device_memory_map(xc, 0, 0, 0, 0, NULL, 0); - return 0; -} -EOF - compile_prog "" "$xen_libs" - then - xen_ctrl_version=40600 - xen=yes - - # Xen 4.5 - elif - cat > $TMPC < -#include -#include -#include -#if !defined(HVM_MAX_VCPUS) -# error HVM_MAX_VCPUS not defined -#endif -int main(void) { - xc_interface *xc; - xs_daemon_open(); - xc = xc_interface_open(0, 0, 0); - xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); - xc_gnttab_open(NULL, 0); - xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); - xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); - xc_hvm_create_ioreq_server(xc, 0, 0, NULL); - return 0; -} -EOF - compile_prog "" "$xen_libs" - then - xen_ctrl_version=40500 - xen=yes - - elif - cat > $TMPC < -#include -#include -#include -#if !defined(HVM_MAX_VCPUS) -# error HVM_MAX_VCPUS not defined -#endif -int main(void) { - xc_interface *xc; - xs_daemon_open(); - xc = xc_interface_open(0, 0, 0); - xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); - xc_gnttab_open(NULL, 0); - xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); - xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); - return 0; -} -EOF - compile_prog "" "$xen_libs" - then - xen_ctrl_version=40200 - xen=yes - - else - if test "$xen" = "yes" ; then - feature_not_found "xen (unsupported version)" \ - "Install a supported xen (xen 4.2 or newer)" - fi - xen=no - fi - - if test "$xen" = yes; then - if test $xen_ctrl_version -ge 40701 ; then - xen_libs="$xen_libs $xen_stable_libs " - fi - fi - fi -fi - -if test "$xen_pci_passthrough" != "no"; then - if test "$xen" = "yes" && test "$linux" = "yes"; then - xen_pci_passthrough=yes - else - if test "$xen_pci_passthrough" = "yes"; then - error_exit "User requested feature Xen PCI Passthrough" \ - " but this feature requires /sys from Linux" - fi - xen_pci_passthrough=no - fi -fi - -########################################## -# Windows Hypervisor Platform accelerator (WHPX) check -if test "$whpx" != "no" ; then - if check_include "WinHvPlatform.h" && check_include "WinHvEmulation.h"; then - whpx="yes" - else - if test "$whpx" = "yes"; then - feature_not_found "WinHvPlatform" "WinHvEmulation is not installed" - fi - whpx="no" - fi -fi - -########################################## -# gettext probe -if test "$gettext" != "false" ; then - if has xgettext; then - gettext=true - else - if test "$gettext" = "true" ; then - feature_not_found "gettext" "Install xgettext binary" - fi - gettext=false - fi -fi - -########################################## -# Sparse probe -if test "$sparse" != "no" ; then - if has sparse; then - sparse=yes - else - if test "$sparse" = "yes" ; then - feature_not_found "sparse" "Install sparse binary" - fi - sparse=no - fi -fi - -########################################## -# X11 probe -if $pkg_config --exists "x11"; then - have_x11=yes - x11_cflags=$($pkg_config --cflags x11) - x11_libs=$($pkg_config --libs x11) -fi - -########################################## -# GTK probe - -if test "$gtk" != "no"; then - gtkpackage="gtk+-3.0" - gtkx11package="gtk+-x11-3.0" - gtkversion="3.22.0" - if $pkg_config --exists "$gtkpackage >= $gtkversion"; then - gtk_cflags=$($pkg_config --cflags $gtkpackage) - gtk_libs=$($pkg_config --libs $gtkpackage) - gtk_version=$($pkg_config --modversion $gtkpackage) - if $pkg_config --exists "$gtkx11package >= $gtkversion"; then - need_x11=yes - gtk_cflags="$gtk_cflags $x11_cflags" - gtk_libs="$gtk_libs $x11_libs" - fi - gtk="yes" - elif test "$gtk" = "yes"; then - feature_not_found "gtk" "Install gtk3-devel" - else - gtk="no" - fi -fi - - -########################################## -# GNUTLS probe - -if test "$gnutls" != "no"; then - pass="no" - if $pkg_config --exists "gnutls >= 3.1.18"; then - gnutls_cflags=$($pkg_config --cflags gnutls) - gnutls_libs=$($pkg_config --libs gnutls) - # Packaging for the static libraries is not always correct. - # At least ubuntu 18.04 ships only shared libraries. - write_c_skeleton - if compile_prog "" "$gnutls_libs" ; then - LIBS="$gnutls_libs $LIBS" - QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags" - pass="yes" - fi - fi - if test "$pass" = "no" && test "$gnutls" = "yes"; then - feature_not_found "gnutls" "Install gnutls devel >= 3.1.18" - else - gnutls="$pass" - fi -fi - - -# If user didn't give a --disable/enable-gcrypt flag, -# then mark as disabled if user requested nettle -# explicitly -if test -z "$gcrypt" -then - if test "$nettle" = "yes" - then - gcrypt="no" - fi -fi - -# If user didn't give a --disable/enable-nettle flag, -# then mark as disabled if user requested gcrypt -# explicitly -if test -z "$nettle" -then - if test "$gcrypt" = "yes" - then - nettle="no" - fi -fi - -has_libgcrypt() { - if ! has "libgcrypt-config" - then - return 1 - fi - - if test -n "$cross_prefix" - then - host=$(libgcrypt-config --host) - if test "$host-" != $cross_prefix - then - return 1 - fi - fi - - maj=`libgcrypt-config --version | awk -F . '{print $1}'` - min=`libgcrypt-config --version | awk -F . '{print $2}'` - - if test $maj != 1 || test $min -lt 5 - then - return 1 - fi - - return 0 -} - - -if test "$nettle" != "no"; then - pass="no" - if $pkg_config --exists "nettle >= 2.7.1"; then - nettle_cflags=$($pkg_config --cflags nettle) - nettle_libs=$($pkg_config --libs nettle) - nettle_version=$($pkg_config --modversion nettle) - # Link test to make sure the given libraries work (e.g for static). - write_c_skeleton - if compile_prog "" "$nettle_libs" ; then - LIBS="$nettle_libs $LIBS" - QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags" - if test -z "$gcrypt"; then - gcrypt="no" - fi - pass="yes" - fi - fi - if test "$pass" = "yes" - then - cat > $TMPC << EOF -#include -int main(void) { - return 0; -} -EOF - if compile_prog "$nettle_cflags" "$nettle_libs" ; then - nettle_xts=yes - qemu_private_xts=no - fi - fi - if test "$pass" = "no" && test "$nettle" = "yes"; then - feature_not_found "nettle" "Install nettle devel >= 2.7.1" - else - nettle="$pass" - fi -fi - -if test "$gcrypt" != "no"; then - pass="no" - if has_libgcrypt; then - gcrypt_cflags=$(libgcrypt-config --cflags) - gcrypt_libs=$(libgcrypt-config --libs) - # Debian has removed -lgpg-error from libgcrypt-config - # as it "spreads unnecessary dependencies" which in - # turn breaks static builds... - if test "$static" = "yes" - then - gcrypt_libs="$gcrypt_libs -lgpg-error" - fi - - # Link test to make sure the given libraries work (e.g for static). - write_c_skeleton - if compile_prog "" "$gcrypt_libs" ; then - LIBS="$gcrypt_libs $LIBS" - QEMU_CFLAGS="$QEMU_CFLAGS $gcrypt_cflags" - pass="yes" - fi - fi - if test "$pass" = "yes"; then - gcrypt="yes" - cat > $TMPC << EOF -#include -int main(void) { - gcry_mac_hd_t handle; - gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5, - GCRY_MAC_FLAG_SECURE, NULL); - return 0; -} -EOF - if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then - gcrypt_hmac=yes - fi - cat > $TMPC << EOF -#include -int main(void) { - gcry_cipher_hd_t handle; - gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_XTS, 0); - return 0; -} -EOF - if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then - gcrypt_xts=yes - qemu_private_xts=no - fi - elif test "$gcrypt" = "yes"; then - feature_not_found "gcrypt" "Install gcrypt devel >= 1.5.0" - else - gcrypt="no" - fi -fi - - -if test "$gcrypt" = "yes" && test "$nettle" = "yes" -then - error_exit "Only one of gcrypt & nettle can be enabled" -fi - -########################################## -# libtasn1 - only for the TLS creds/session test suite - -tasn1=yes -tasn1_cflags="" -tasn1_libs="" -if $pkg_config --exists "libtasn1"; then - tasn1_cflags=$($pkg_config --cflags libtasn1) - tasn1_libs=$($pkg_config --libs libtasn1) -else - tasn1=no -fi - - -########################################## -# PAM probe - -if test "$auth_pam" != "no"; then - cat > $TMPC < -#include -int main(void) { - const char *service_name = "qemu"; - const char *user = "frank"; - const struct pam_conv pam_conv = { 0 }; - pam_handle_t *pamh = NULL; - pam_start(service_name, user, &pam_conv, &pamh); - return 0; -} -EOF - if compile_prog "" "-lpam" ; then - auth_pam=yes - else - if test "$auth_pam" = "yes"; then - feature_not_found "PAM" "Install PAM development package" - else - auth_pam=no - fi - fi -fi - -########################################## -# getifaddrs (for tests/test-io-channel-socket ) - -have_ifaddrs_h=yes -if ! check_include "ifaddrs.h" ; then - have_ifaddrs_h=no -fi - -######################################### -# libdrm check -have_drm_h=no -if check_include "libdrm/drm.h" ; then - have_drm_h=yes -fi - -######################################### -# sys/signal.h check -have_sys_signal_h=no -if check_include "sys/signal.h" ; then - have_sys_signal_h=yes -fi - -########################################## -# VTE probe - -if test "$vte" != "no"; then - vteminversion="0.32.0" - if $pkg_config --exists "vte-2.91"; then - vtepackage="vte-2.91" - else - vtepackage="vte-2.90" - fi - if $pkg_config --exists "$vtepackage >= $vteminversion"; then - vte_cflags=$($pkg_config --cflags $vtepackage) - vte_libs=$($pkg_config --libs $vtepackage) - vteversion=$($pkg_config --modversion $vtepackage) - vte="yes" - elif test "$vte" = "yes"; then - feature_not_found "vte" "Install libvte-2.90/2.91 devel" - else - vte="no" - fi -fi - -########################################## -# RDMA needs OpenFabrics libraries -if test "$rdma" != "no" ; then - cat > $TMPC < -int main(void) { return 0; } -EOF - rdma_libs="-lrdmacm -libverbs -libumad" - if compile_prog "" "$rdma_libs" ; then - rdma="yes" - else - if test "$rdma" = "yes" ; then - error_exit \ - " OpenFabrics librdmacm/libibverbs/libibumad not present." \ - " Your options:" \ - " (1) Fast: Install infiniband packages (devel) from your distro." \ - " (2) Cleanest: Install libraries from www.openfabrics.org" \ - " (3) Also: Install softiwarp if you don't have RDMA hardware" - fi - rdma="no" - fi -fi - -########################################## -# PVRDMA detection - -cat > $TMPC < - -int -main(void) -{ - char buf = 0; - void *addr = &buf; - addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED); - - return 0; -} -EOF - -if test "$rdma" = "yes" ; then - case "$pvrdma" in - "") - if compile_prog "" ""; then - pvrdma="yes" - else - pvrdma="no" - fi - ;; - "yes") - if ! compile_prog "" ""; then - error_exit "PVRDMA is not supported since mremap is not implemented" - fi - pvrdma="yes" - ;; - "no") - pvrdma="no" - ;; - esac -else - if test "$pvrdma" = "yes" ; then - error_exit "PVRDMA requires rdma suppport" - fi - pvrdma="no" -fi - -# Let's see if enhanced reg_mr is supported -if test "$pvrdma" = "yes" ; then - -cat > $TMPC < - -int -main(void) -{ - struct ibv_mr *mr; - struct ibv_pd *pd = NULL; - size_t length = 10; - uint64_t iova = 0; - int access = 0; - void *addr = NULL; - - mr = ibv_reg_mr_iova(pd, addr, length, iova, access); - - ibv_dereg_mr(mr); - - return 0; -} -EOF - if ! compile_prog "" "-libverbs"; then - QEMU_CFLAGS="$QEMU_CFLAGS -DLEGACY_RDMA_REG_MR" - fi -fi - -########################################## -# xfsctl() probe, used for file-posix.c -if test "$xfs" != "no" ; then - cat > $TMPC << EOF -#include /* NULL */ -#include -int main(void) -{ - xfsctl(NULL, 0, 0, NULL); - return 0; -} -EOF - if compile_prog "" "" ; then - xfs="yes" - else - if test "$xfs" = "yes" ; then - feature_not_found "xfs" "Instal xfsprogs/xfslibs devel" - fi - xfs=no - fi -fi - -########################################## -# vde libraries probe -if test "$vde" != "no" ; then - vde_libs="-lvdeplug" - cat > $TMPC << EOF -#include -int main(void) -{ - struct vde_open_args a = {0, 0, 0}; - char s[] = ""; - vde_open(s, s, &a); - return 0; -} -EOF - if compile_prog "" "$vde_libs" ; then - vde=yes - else - if test "$vde" = "yes" ; then - feature_not_found "vde" "Install vde (Virtual Distributed Ethernet) devel" - fi - vde=no - fi -fi - -########################################## -# netmap support probe -# Apart from looking for netmap headers, we make sure that the host API version -# supports the netmap backend (>=11). The upper bound (15) is meant to simulate -# a minor/major version number. Minor new features will be marked with values up -# to 15, and if something happens that requires a change to the backend we will -# move above 15, submit the backend fixes and modify this two bounds. -if test "$netmap" != "no" ; then - cat > $TMPC << EOF -#include -#include -#include -#include -#if (NETMAP_API < 11) || (NETMAP_API > 15) -#error -#endif -int main(void) { return 0; } -EOF - if compile_prog "" "" ; then - netmap=yes - else - if test "$netmap" = "yes" ; then - feature_not_found "netmap" - fi - netmap=no - fi -fi - -########################################## -# libcap-ng library probe -if test "$cap_ng" != "no" ; then - cap_libs="-lcap-ng" - cat > $TMPC << EOF -#include -int main(void) -{ - capng_capability_to_name(CAPNG_EFFECTIVE); - return 0; -} -EOF - if compile_prog "" "$cap_libs" ; then - cap_ng=yes - else - if test "$cap_ng" = "yes" ; then - feature_not_found "cap_ng" "Install libcap-ng devel" - fi - cap_ng=no - fi -fi - -########################################## -# Sound support libraries probe - -audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/,/ /g') -for drv in $audio_drv_list; do - case $drv in - alsa | try-alsa) - if $pkg_config alsa --exists; then - alsa_libs=$($pkg_config alsa --libs) - alsa_cflags=$($pkg_config alsa --cflags) - alsa=yes - if test "$drv" = "try-alsa"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-alsa/alsa/') - fi - else - if test "$drv" = "try-alsa"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-alsa//') - else - error_exit "$drv check failed" \ - "Make sure to have the $drv libs and headers installed." - fi - fi - ;; - - pa | try-pa) - if $pkg_config libpulse --exists; then - libpulse=yes - pulse_libs=$($pkg_config libpulse --libs) - pulse_cflags=$($pkg_config libpulse --cflags) - if test "$drv" = "try-pa"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/') - fi - else - if test "$drv" = "try-pa"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa//') - else - error_exit "$drv check failed" \ - "Make sure to have the $drv libs and headers installed." - fi - fi - ;; - - sdl) - if test "$sdl" = "no"; then - error_exit "sdl not found or disabled, can not use sdl audio driver" - fi - ;; - - try-sdl) - if test "$sdl" = "no"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sdl//') - else - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sdl/sdl/') - fi - ;; - - coreaudio) - coreaudio_libs="-framework CoreAudio" - ;; - - dsound) - dsound_libs="-lole32 -ldxguid" - audio_win_int="yes" - ;; - - oss) - oss_libs="$oss_lib" - ;; - - jack | try-jack) - if $pkg_config jack --exists; then - libjack=yes - jack_libs=$($pkg_config jack --libs) - if test "$drv" = "try-jack"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack/jack/') - fi - else - if test "$drv" = "try-jack"; then - audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack//') - else - error_exit "$drv check failed" \ - "Make sure to have the $drv libs and headers installed." - fi - fi - ;; - - *) - echo "$audio_possible_drivers" | grep -q "\<$drv\>" || { - error_exit "Unknown driver '$drv' selected" \ - "Possible drivers are: $audio_possible_drivers" - } - ;; - esac -done - -########################################## -# BrlAPI probe - -if test "$brlapi" != "no" ; then - brlapi_libs="-lbrlapi" - cat > $TMPC << EOF -#include -#include -int main( void ) { return brlapi__openConnection (NULL, NULL, NULL); } -EOF - if compile_prog "" "$brlapi_libs" ; then - brlapi=yes - else - if test "$brlapi" = "yes" ; then - feature_not_found "brlapi" "Install brlapi devel" - fi - brlapi=no - fi -fi - -########################################## -# iconv probe -if test "$iconv" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { - iconv_t conv = iconv_open("WCHAR_T", "UCS-2"); - return conv != (iconv_t) -1; -} -EOF - iconv_prefix_list="/usr/local:/usr" - iconv_lib_list=":-liconv" - IFS=: - for iconv_prefix in $iconv_prefix_list; do - IFS=: - iconv_cflags="-I$iconv_prefix/include" - iconv_ldflags="-L$iconv_prefix/lib" - for iconv_link in $iconv_lib_list; do - unset IFS - iconv_lib="$iconv_ldflags $iconv_link" - echo "looking at iconv in '$iconv_cflags' '$iconv_lib'" >> config.log - if compile_prog "$iconv_cflags" "$iconv_lib" ; then - iconv_found=yes - break - fi - done - if test "$iconv_found" = yes ; then - break - fi - done - if test "$iconv_found" = "yes" ; then - iconv=yes - else - if test "$iconv" = "yes" ; then - feature_not_found "iconv" "Install iconv devel" - fi - iconv=no - fi -fi - -########################################## -# curses probe -if test "$iconv" = "no" ; then - # curses will need iconv - curses=no -fi -if test "$curses" != "no" ; then - if test "$mingw32" = "yes" ; then - curses_inc_list="$($pkg_config --cflags ncurses 2>/dev/null):" - curses_lib_list="$($pkg_config --libs ncurses 2>/dev/null):-lpdcurses" - else - curses_inc_list="$($pkg_config --cflags ncursesw 2>/dev/null):-I/usr/include/ncursesw:" - curses_lib_list="$($pkg_config --libs ncursesw 2>/dev/null):-lncursesw:-lcursesw" - fi - curses_found=no - cat > $TMPC << EOF -#include -#include -#include -#include -int main(void) { - const char *codeset; - wchar_t wch = L'w'; - setlocale(LC_ALL, ""); - resize_term(0, 0); - addwstr(L"wide chars\n"); - addnwstr(&wch, 1); - add_wch(WACS_DEGREE); - codeset = nl_langinfo(CODESET); - return codeset != 0; -} -EOF - IFS=: - for curses_inc in $curses_inc_list; do - # Make sure we get the wide character prototypes - curses_inc="-DNCURSES_WIDECHAR $curses_inc" - IFS=: - for curses_lib in $curses_lib_list; do - unset IFS - if compile_prog "$curses_inc" "$curses_lib" ; then - curses_found=yes - break - fi - done - if test "$curses_found" = yes ; then - break - fi - done - unset IFS - if test "$curses_found" = "yes" ; then - curses=yes - else - if test "$curses" = "yes" ; then - feature_not_found "curses" "Install ncurses devel" - fi - curses=no - fi -fi - -########################################## -# curl probe -if test "$curl" != "no" ; then - if $pkg_config libcurl --exists; then - curlconfig="$pkg_config libcurl" - else - curlconfig=curl-config - fi - cat > $TMPC << EOF -#include -int main(void) { curl_easy_init(); curl_multi_setopt(0, 0, 0); return 0; } -EOF - curl_cflags=$($curlconfig --cflags 2>/dev/null) - curl_libs=$($curlconfig --libs 2>/dev/null) - if compile_prog "$curl_cflags" "$curl_libs" ; then - curl=yes - else - if test "$curl" = "yes" ; then - feature_not_found "curl" "Install libcurl devel" - fi - curl=no - fi -fi # test "$curl" - -########################################## -# glib support probe - -glib_req_ver=2.48 -glib_modules=gthread-2.0 -if test "$modules" = yes; then - glib_modules="$glib_modules gmodule-export-2.0" -fi -if test "$plugins" = yes; then - glib_modules="$glib_modules gmodule-2.0" -fi - -# This workaround is required due to a bug in pkg-config file for glib as it -# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static - -if test "$static" = yes && test "$mingw32" = yes; then - QEMU_CFLAGS="-DGLIB_STATIC_COMPILATION $QEMU_CFLAGS" -fi - -for i in $glib_modules; do - if $pkg_config --atleast-version=$glib_req_ver $i; then - glib_cflags=$($pkg_config --cflags $i) - glib_libs=$($pkg_config --libs $i) - QEMU_CFLAGS="$glib_cflags $QEMU_CFLAGS" - LIBS="$glib_libs $LIBS" - else - error_exit "glib-$glib_req_ver $i is required to compile QEMU" - fi -done - -if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then - gio=yes - gio_cflags=$($pkg_config --cflags gio-2.0) - gio_libs=$($pkg_config --libs gio-2.0) - gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0) - if [ ! -x "$gdbus_codegen" ]; then - gdbus_codegen= - fi -else - gio=no -fi - -if $pkg_config --atleast-version=$glib_req_ver gio-unix-2.0; then - gio_cflags="$gio_cflags $($pkg_config --cflags gio-unix-2.0)" - gio_libs="$gio_libs $($pkg_config --libs gio-unix-2.0)" -fi - -# Sanity check that the current size_t matches the -# size that glib thinks it should be. This catches -# problems on multi-arch where people try to build -# 32-bit QEMU while pointing at 64-bit glib headers -cat > $TMPC < -#include - -#define QEMU_BUILD_BUG_ON(x) \ - typedef char qemu_build_bug_on[(x)?-1:1] __attribute__((unused)); - -int main(void) { - QEMU_BUILD_BUG_ON(sizeof(size_t) != GLIB_SIZEOF_SIZE_T); - return 0; -} -EOF - -if ! compile_prog "$CFLAGS" "$LIBS" ; then - error_exit "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\ - "You probably need to set PKG_CONFIG_LIBDIR"\ - "to point to the right pkg-config files for your"\ - "build target" -fi - -# Silence clang 3.5.0 warnings about glib attribute __alloc_size__ usage -cat > $TMPC << EOF -#include -int main(void) { return 0; } -EOF -if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then - if cc_has_warning_flag "-Wno-unknown-attributes"; then - glib_cflags="-Wno-unknown-attributes $glib_cflags" - QEMU_CFLAGS="-Wno-unknown-attributes $CFLAGS" - fi -fi - -# Silence clang warnings triggered by glib < 2.57.2 -cat > $TMPC << EOF -#include -typedef struct Foo { - int i; -} Foo; -static void foo_free(Foo *f) -{ - g_free(f); -} -G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free); -int main(void) { return 0; } -EOF -if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then - if cc_has_warning_flag "-Wno-unused-function"; then - glib_cflags="$glib_cflags -Wno-unused-function" - CFLAGS="$CFLAGS -Wno-unused-function" - fi -fi - -########################################## -# SHA command probe for modules -if test "$modules" = yes; then - shacmd_probe="sha1sum sha1 shasum" - for c in $shacmd_probe; do - if has $c; then - shacmd="$c" - break - fi - done - if test "$shacmd" = ""; then - error_exit "one of the checksum commands is required to enable modules: $shacmd_probe" - fi -fi - -########################################## -# libmpathpersist probe - -if test "$mpath" != "no" ; then - # probe for the new API - cat > $TMPC < -#include -unsigned mpath_mx_alloc_len = 1024; -int logsink; -static struct config *multipath_conf; -extern struct udev *udev; -extern struct config *get_multipath_config(void); -extern void put_multipath_config(struct config *conf); -struct udev *udev; -struct config *get_multipath_config(void) { return multipath_conf; } -void put_multipath_config(struct config *conf) { } - -int main(void) { - udev = udev_new(); - multipath_conf = mpath_lib_init(); - return 0; -} -EOF - if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then - mpathpersist=yes - mpathpersist_new_api=yes - else - # probe for the old API - cat > $TMPC < -#include -unsigned mpath_mx_alloc_len = 1024; -int logsink; -int main(void) { - struct udev *udev = udev_new(); - mpath_lib_init(udev); - return 0; -} -EOF - if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then - mpathpersist=yes - mpathpersist_new_api=no - else - mpathpersist=no - fi - fi -else - mpathpersist=no -fi - -########################################## -# pthread probe -PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2" - -pthread=no -cat > $TMPC << EOF -#include -static void *f(void *p) { return NULL; } -int main(void) { - pthread_t thread; - pthread_create(&thread, 0, f, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - pthread=yes -else - for pthread_lib in $PTHREADLIBS_LIST; do - if compile_prog "" "$pthread_lib" ; then - pthread=yes - found=no - for lib_entry in $LIBS; do - if test "$lib_entry" = "$pthread_lib"; then - found=yes - break - fi - done - if test "$found" = "no"; then - LIBS="$pthread_lib $LIBS" - fi - PTHREAD_LIB="$pthread_lib" - break - fi - done -fi - -if test "$mingw32" != yes && test "$pthread" = no; then - error_exit "pthread check failed" \ - "Make sure to have the pthread libs and headers installed." -fi - -# check for pthread_setname_np with thread id -pthread_setname_np_w_tid=no -cat > $TMPC << EOF -#include - -static void *f(void *p) { return NULL; } -int main(void) -{ - pthread_t thread; - pthread_create(&thread, 0, f, 0); - pthread_setname_np(thread, "QEMU"); - return 0; -} -EOF -if compile_prog "" "$pthread_lib" ; then - pthread_setname_np_w_tid=yes -fi - -# check for pthread_setname_np without thread id -pthread_setname_np_wo_tid=no -cat > $TMPC << EOF -#include - -static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; } -int main(void) -{ - pthread_t thread; - pthread_create(&thread, 0, f, 0); - return 0; -} -EOF -if compile_prog "" "$pthread_lib" ; then - pthread_setname_np_wo_tid=yes -fi - -########################################## -# rbd probe -if test "$rbd" != "no" ; then - cat > $TMPC < -#include -int main(void) { - rados_t cluster; - rados_create(&cluster, NULL); - return 0; -} -EOF - rbd_libs="-lrbd -lrados" - if compile_prog "" "$rbd_libs" ; then - rbd=yes - else - if test "$rbd" = "yes" ; then - feature_not_found "rados block device" "Install librbd/ceph devel" - fi - rbd=no - fi -fi - -########################################## -# libssh probe -if test "$libssh" != "no" ; then - if $pkg_config --exists libssh; then - libssh_cflags=$($pkg_config libssh --cflags) - libssh_libs=$($pkg_config libssh --libs) - libssh=yes - else - if test "$libssh" = "yes" ; then - error_exit "libssh required for --enable-libssh" - fi - libssh=no - fi -fi - -########################################## -# Check for libssh 0.8 -# This is done like this instead of using the LIBSSH_VERSION_* and -# SSH_VERSION_* macros because some distributions in the past shipped -# snapshots of the future 0.8 from Git, and those snapshots did not -# have updated version numbers (still referring to 0.7.0). - -if test "$libssh" = "yes"; then - cat > $TMPC < -int main(void) { return ssh_get_server_publickey(NULL, NULL); } -EOF - if compile_prog "$libssh_cflags" "$libssh_libs"; then - libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags" - fi -fi - -########################################## -# linux-aio probe - -if test "$linux_aio" != "no" ; then - cat > $TMPC < -#include -#include -int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); return 0; } -EOF - if compile_prog "" "-laio" ; then - linux_aio=yes - else - if test "$linux_aio" = "yes" ; then - feature_not_found "linux AIO" "Install libaio devel" - fi - linux_aio=no - fi -fi -########################################## -# linux-io-uring probe - -if test "$linux_io_uring" != "no" ; then - if $pkg_config liburing; then - linux_io_uring_cflags=$($pkg_config --cflags liburing) - linux_io_uring_libs=$($pkg_config --libs liburing) - linux_io_uring=yes - - # io_uring is used in libqemuutil.a where per-file -libs variables are not - # seen by programs linking the archive. It's not ideal, but just add the - # library dependency globally. - LIBS="$linux_io_uring_libs $LIBS" - else - if test "$linux_io_uring" = "yes" ; then - feature_not_found "linux io_uring" "Install liburing devel" - fi - linux_io_uring=no - fi -fi - -########################################## -# TPM emulation is only on POSIX - -if test "$tpm" = ""; then - if test "$mingw32" = "yes"; then - tpm=no - else - tpm=yes - fi -elif test "$tpm" = "yes"; then - if test "$mingw32" = "yes" ; then - error_exit "TPM emulation only available on POSIX systems" - fi -fi - -########################################## -# attr probe - -libattr_libs= -if test "$attr" != "no" ; then - cat > $TMPC < -#include -#ifdef CONFIG_LIBATTR -#include -#else -#include -#endif -int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; } -EOF - if compile_prog "" "" ; then - attr=yes - # Older distros have , and need -lattr: - elif compile_prog "-DCONFIG_LIBATTR" "-lattr" ; then - attr=yes - libattr_libs="-lattr" - LIBS="$libattr_libs $LIBS" - libattr=yes - else - if test "$attr" = "yes" ; then - feature_not_found "ATTR" "Install libc6 or libattr devel" - fi - attr=no - fi -fi - -########################################## -# iovec probe -cat > $TMPC < -#include -#include -int main(void) { return sizeof(struct iovec); } -EOF -iovec=no -if compile_prog "" "" ; then - iovec=yes -fi - -########################################## -# preadv probe -cat > $TMPC < -#include -#include -int main(void) { return preadv(0, 0, 0, 0); } -EOF -preadv=no -if compile_prog "" "" ; then - preadv=yes -fi - -########################################## -# fdt probe -# fdt support is mandatory for at least some target architectures, -# so insist on it if we're building those system emulators. -fdt_required=no -for target in $target_list; do - case $target in - aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu|rx-softmmu) - fdt_required=yes - ;; - esac -done - -if test "$fdt_required" = "yes"; then - if test "$fdt" = "no"; then - error_exit "fdt disabled but some requested targets require it." \ - "You can turn off fdt only if you also disable all the system emulation" \ - "targets which need it (by specifying a cut down --target-list)." - fi - fdt=yes -elif test "$fdt" != "yes" ; then - fdt=no -fi - -# fdt is only required when building softmmu targets -if test -z "$fdt" -a "$softmmu" != "yes" ; then - fdt="no" -fi - -if test "$fdt" != "no" ; then - fdt_libs="-lfdt" - # explicitly check for libfdt_env.h as it is missing in some stable installs - # and test for required functions to make sure we are on a version >= 1.4.2 - cat > $TMPC << EOF -#include -#include -int main(void) { fdt_check_full(NULL, 0); return 0; } -EOF - if compile_prog "" "$fdt_libs" ; then - # system DTC is good - use it - fdt=system - else - # have GIT checkout, so activate dtc submodule - if test -e "${source_path}/.git" ; then - git_submodules="${git_submodules} dtc" - fi - if test -d "${source_path}/dtc/libfdt" || test -e "${source_path}/.git" ; then - fdt=git - mkdir -p dtc - fdt_cflags="-I${source_path}/dtc/libfdt" - fdt_ldflags="-L${build_path}/dtc/libfdt" - fdt_libs="$fdt_libs" - elif test "$fdt" = "yes" ; then - # Not a git build & no libfdt found, prompt for system install - error_exit "DTC (libfdt) version >= 1.4.2 not present." \ - "Please install the DTC (libfdt) devel package" - else - # don't have and don't want - fdt_libs= - fdt=no - fi - fi -fi - -########################################## -# opengl probe (for sdl2, gtk, milkymist-tmu2) - -gbm="no" -if $pkg_config gbm; then - gbm_cflags="$($pkg_config --cflags gbm)" - gbm_libs="$($pkg_config --libs gbm)" - gbm="yes" -fi - -if test "$opengl" != "no" ; then - opengl_pkgs="epoxy gbm" - if $pkg_config $opengl_pkgs; then - opengl_cflags="$($pkg_config --cflags $opengl_pkgs)" - opengl_libs="$($pkg_config --libs $opengl_pkgs)" - opengl=yes - if test "$gtk" = "yes" && $pkg_config --exists "$gtkpackage >= 3.16"; then - gtk_gl="yes" - fi - QEMU_CFLAGS="$QEMU_CFLAGS $opengl_cflags" - else - if test "$opengl" = "yes" ; then - feature_not_found "opengl" "Please install opengl (mesa) devel pkgs: $opengl_pkgs" - fi - opengl_cflags="" - opengl_libs="" - opengl=no - fi -fi - -if test "$opengl" = "yes"; then - cat > $TMPC << EOF -#include -#ifndef EGL_MESA_image_dma_buf_export -# error mesa/epoxy lacks support for dmabufs (mesa 10.6+) -#endif -int main(void) { return 0; } -EOF - if compile_prog "" "" ; then - opengl_dmabuf=yes - fi -fi - -if test "$opengl" = "yes" && test "$have_x11" = "yes"; then - for target in $target_list; do - case $target in - lm32-softmmu) # milkymist-tmu2 requires X11 and OpenGL - need_x11=yes - ;; - esac - done -fi - -########################################## -# libxml2 probe -if test "$libxml2" != "no" ; then - if $pkg_config --exists libxml-2.0; then - libxml2="yes" - libxml2_cflags=$($pkg_config --cflags libxml-2.0) - libxml2_libs=$($pkg_config --libs libxml-2.0) - else - if test "$libxml2" = "yes"; then - feature_not_found "libxml2" "Install libxml2 devel" - fi - libxml2="no" - fi -fi - -########################################## -# glusterfs probe -if test "$glusterfs" != "no" ; then - if $pkg_config --atleast-version=3 glusterfs-api; then - glusterfs="yes" - glusterfs_cflags=$($pkg_config --cflags glusterfs-api) - glusterfs_libs=$($pkg_config --libs glusterfs-api) - if $pkg_config --atleast-version=4 glusterfs-api; then - glusterfs_xlator_opt="yes" - fi - if $pkg_config --atleast-version=5 glusterfs-api; then - glusterfs_discard="yes" - fi - if $pkg_config --atleast-version=6 glusterfs-api; then - glusterfs_fallocate="yes" - glusterfs_zerofill="yes" - fi - cat > $TMPC << EOF -#include - -int -main(void) -{ - /* new glfs_ftruncate() passes two additional args */ - return glfs_ftruncate(NULL, 0, NULL, NULL); -} -EOF - if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then - glusterfs_ftruncate_has_stat="yes" - fi - cat > $TMPC << EOF -#include - -/* new glfs_io_cbk() passes two additional glfs_stat structs */ -static void -glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data) -{} - -int -main(void) -{ - glfs_io_cbk iocb = &glusterfs_iocb; - iocb(NULL, 0 , NULL, NULL, NULL); - return 0; -} -EOF - if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then - glusterfs_iocb_has_stat="yes" - fi - else - if test "$glusterfs" = "yes" ; then - feature_not_found "GlusterFS backend support" \ - "Install glusterfs-api devel >= 3" - fi - glusterfs="no" - fi -fi - -# Check for inotify functions when we are building linux-user -# emulator. This is done because older glibc versions don't -# have syscall stubs for these implemented. In that case we -# don't provide them even if kernel supports them. -# -inotify=no -cat > $TMPC << EOF -#include - -int -main(void) -{ - /* try to start inotify */ - return inotify_init(); -} -EOF -if compile_prog "" "" ; then - inotify=yes -fi - -inotify1=no -cat > $TMPC << EOF -#include - -int -main(void) -{ - /* try to start inotify */ - return inotify_init1(0); -} -EOF -if compile_prog "" "" ; then - inotify1=yes -fi - -# check if pipe2 is there -pipe2=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - int pipefd[2]; - return pipe2(pipefd, O_CLOEXEC); -} -EOF -if compile_prog "" "" ; then - pipe2=yes -fi - -# check if accept4 is there -accept4=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - accept4(0, NULL, NULL, SOCK_CLOEXEC); - return 0; -} -EOF -if compile_prog "" "" ; then - accept4=yes -fi - -# check if tee/splice is there. vmsplice was added same time. -splice=no -cat > $TMPC << EOF -#include -#include -#include - -int main(void) -{ - int len, fd = 0; - len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK); - splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE); - return 0; -} -EOF -if compile_prog "" "" ; then - splice=yes -fi - -########################################## -# libnuma probe - -if test "$numa" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { return numa_available(); } -EOF - - if compile_prog "" "-lnuma" ; then - numa=yes - numa_libs="-lnuma" - else - if test "$numa" = "yes" ; then - feature_not_found "numa" "install numactl devel" - fi - numa=no - fi -fi - -if test "$tcmalloc" = "yes" && test "$jemalloc" = "yes" ; then - echo "ERROR: tcmalloc && jemalloc can't be used at the same time" - exit 1 -fi - -# Even if malloc_trim() is available, these non-libc memory allocators -# do not support it. -if test "$tcmalloc" = "yes" || test "$jemalloc" = "yes" ; then - if test "$malloc_trim" = "yes" ; then - echo "Disabling malloc_trim with non-libc memory allocator" - fi - malloc_trim="no" -fi - -####################################### -# malloc_trim - -if test "$malloc_trim" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { malloc_trim(0); return 0; } -EOF - if compile_prog "" "" ; then - malloc_trim="yes" - else - malloc_trim="no" - fi -fi - -########################################## -# tcmalloc probe - -if test "$tcmalloc" = "yes" ; then - cat > $TMPC << EOF -#include -int main(void) { - void *tmp = malloc(1); - if (tmp != NULL) { - return 0; - } - return 1; -} -EOF - - if compile_prog "" "-ltcmalloc" ; then - LIBS="-ltcmalloc $LIBS" - else - feature_not_found "tcmalloc" "install gperftools devel" - fi -fi - -########################################## -# jemalloc probe - -if test "$jemalloc" = "yes" ; then - cat > $TMPC << EOF -#include -int main(void) { - void *tmp = malloc(1); - if (tmp != NULL) { - return 0; - } - return 1; -} -EOF - - if compile_prog "" "-ljemalloc" ; then - LIBS="-ljemalloc $LIBS" - else - feature_not_found "jemalloc" "install jemalloc devel" - fi -fi - -########################################## -# signalfd probe -signalfd="no" -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); } -EOF - -if compile_prog "" "" ; then - signalfd=yes -fi - -# check if optreset global is declared by -optreset="no" -cat > $TMPC << EOF -#include -int main(void) { return optreset; } -EOF - -if compile_prog "" "" ; then - optreset=yes -fi - -# check if eventfd is supported -eventfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); -} -EOF -if compile_prog "" "" ; then - eventfd=yes -fi - -# check if memfd is supported -memfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return memfd_create("foo", MFD_ALLOW_SEALING); -} -EOF -if compile_prog "" "" ; then - memfd=yes -fi - -# check for usbfs -have_usbfs=no -if test "$linux_user" = "yes"; then - cat > $TMPC << EOF -#include - -#ifndef USBDEVFS_GET_CAPABILITIES -#error "USBDEVFS_GET_CAPABILITIES undefined" -#endif - -#ifndef USBDEVFS_DISCONNECT_CLAIM -#error "USBDEVFS_DISCONNECT_CLAIM undefined" -#endif - -int main(void) -{ - return 0; -} -EOF - if compile_prog "" ""; then - have_usbfs=yes - fi -fi - -# check for fallocate -fallocate=no -cat > $TMPC << EOF -#include - -int main(void) -{ - fallocate(0, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate=yes -fi - -# check for fallocate hole punching -fallocate_punch_hole=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - fallocate(0, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate_punch_hole=yes -fi - -# check that fallocate supports range zeroing inside the file -fallocate_zero_range=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - fallocate(0, FALLOC_FL_ZERO_RANGE, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate_zero_range=yes -fi - -# check for posix_fallocate -posix_fallocate=no -cat > $TMPC << EOF -#include - -int main(void) -{ - posix_fallocate(0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - posix_fallocate=yes -fi - -# check for sync_file_range -sync_file_range=no -cat > $TMPC << EOF -#include - -int main(void) -{ - sync_file_range(0, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - sync_file_range=yes -fi - -# check for linux/fiemap.h and FS_IOC_FIEMAP -fiemap=no -cat > $TMPC << EOF -#include -#include -#include - -int main(void) -{ - ioctl(0, FS_IOC_FIEMAP, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fiemap=yes -fi - -# check for dup3 -dup3=no -cat > $TMPC << EOF -#include - -int main(void) -{ - dup3(0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - dup3=yes -fi - -# check for ppoll support -ppoll=no -cat > $TMPC << EOF -#include - -int main(void) -{ - struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 }; - ppoll(&pfd, 1, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - ppoll=yes -fi - -# check for prctl(PR_SET_TIMERSLACK , ... ) support -prctl_pr_set_timerslack=no -cat > $TMPC << EOF -#include - -int main(void) -{ - prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - prctl_pr_set_timerslack=yes -fi - -# check for epoll support -epoll=no -cat > $TMPC << EOF -#include - -int main(void) -{ - epoll_create(0); - return 0; -} -EOF -if compile_prog "" "" ; then - epoll=yes -fi - -# epoll_create1 is a later addition -# so we must check separately for its presence -epoll_create1=no -cat > $TMPC << EOF -#include - -int main(void) -{ - /* Note that we use epoll_create1 as a value, not as - * a function being called. This is necessary so that on - * old SPARC glibc versions where the function was present in - * the library but not declared in the header file we will - * fail the configure check. (Otherwise we will get a compiler - * warning but not an error, and will proceed to fail the - * qemu compile where we compile with -Werror.) - */ - return (int)(uintptr_t)&epoll_create1; -} -EOF -if compile_prog "" "" ; then - epoll_create1=yes -fi - -# check for sendfile support -sendfile=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return sendfile(0, 0, 0, 0); -} -EOF -if compile_prog "" "" ; then - sendfile=yes -fi - -# check for timerfd support (glibc 2.8 and newer) -timerfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return(timerfd_create(CLOCK_REALTIME, 0)); -} -EOF -if compile_prog "" "" ; then - timerfd=yes -fi - -# check for setns and unshare support -setns=no -cat > $TMPC << EOF -#include - -int main(void) -{ - int ret; - ret = setns(0, 0); - ret = unshare(0); - return ret; -} -EOF -if compile_prog "" "" ; then - setns=yes -fi - -# clock_adjtime probe -clock_adjtime=no -cat > $TMPC < - -int main(void) -{ - return clock_adjtime(0, 0); -} -EOF -clock_adjtime=no -if compile_prog "" "" ; then - clock_adjtime=yes -fi - -# syncfs probe -syncfs=no -cat > $TMPC < - -int main(void) -{ - return syncfs(0); -} -EOF -syncfs=no -if compile_prog "" "" ; then - syncfs=yes -fi - -# check for kcov support (kernel must be 4.4+, compiled with certain options) -kcov=no -if check_include sys/kcov.h ; then - kcov=yes -fi - -# If we're making warnings fatal, apply this to Sphinx runs as well -sphinx_werror="" -if test "$werror" = "yes"; then - sphinx_werror="-W" -fi - -# Check we have a new enough version of sphinx-build -has_sphinx_build() { - # This is a bit awkward but works: create a trivial document and - # try to run it with our configuration file (which enforces a - # version requirement). This will fail if either - # sphinx-build doesn't exist at all or if it is too old. - mkdir -p "$TMPDIR1/sphinx" - touch "$TMPDIR1/sphinx/index.rst" - "$sphinx_build" $sphinx_werror -c "$source_path/docs" \ - -b html "$TMPDIR1/sphinx" \ - "$TMPDIR1/sphinx/out" >> config.log 2>&1 -} - -# Check if tools are available to build documentation. -if test "$docs" != "no" ; then - if has_sphinx_build; then - sphinx_ok=yes - else - sphinx_ok=no - fi - if has makeinfo && has pod2man && test "$sphinx_ok" = "yes"; then - docs=yes - else - if test "$docs" = "yes" ; then - if has $sphinx_build && test "$sphinx_ok" != "yes"; then - echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2 - fi - feature_not_found "docs" "Install texinfo, Perl/perl-podlators and a Python 3 version of python-sphinx" - fi - docs=no - fi -fi - -# Search for bswap_32 function -byteswap_h=no -cat > $TMPC << EOF -#include -int main(void) { return bswap_32(0); } -EOF -if compile_prog "" "" ; then - byteswap_h=yes -fi - -# Search for bswap32 function -bswap_h=no -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return bswap32(0); } -EOF -if compile_prog "" "" ; then - bswap_h=yes -fi - -########################################## -# Do we have libiscsi >= 1.9.0 -if test "$libiscsi" != "no" ; then - if $pkg_config --atleast-version=1.9.0 libiscsi; then - libiscsi="yes" - libiscsi_cflags=$($pkg_config --cflags libiscsi) - libiscsi_libs=$($pkg_config --libs libiscsi) - else - if test "$libiscsi" = "yes" ; then - feature_not_found "libiscsi" "Install libiscsi >= 1.9.0" - fi - libiscsi="no" - fi -fi - -########################################## -# Do we need libm -cat > $TMPC << EOF -#include -int main(int argc, char **argv) { return isnan(sin((double)argc)); } -EOF -if compile_prog "" "" ; then - : -elif compile_prog "" "-lm" ; then - LIBS="-lm $LIBS" -else - error_exit "libm check failed" -fi - -########################################## -# Do we need librt -# uClibc provides 2 versions of clock_gettime(), one with realtime -# support and one without. This means that the clock_gettime() don't -# need -lrt. We still need it for timer_create() so we check for this -# function in addition. -cat > $TMPC < -#include -int main(void) { - timer_create(CLOCK_REALTIME, NULL, NULL); - return clock_gettime(CLOCK_REALTIME, NULL); -} -EOF - -if compile_prog "" "" ; then - : -# we need pthread for static linking. use previous pthread test result -elif compile_prog "" "$pthread_lib -lrt" ; then - LIBS="$LIBS -lrt" -fi - -# Check whether we need to link libutil for openpty() -cat > $TMPC << EOF -extern int openpty(int *am, int *as, char *name, void *termp, void *winp); -int main(void) { return openpty(0, 0, 0, 0, 0); } -EOF - -have_openpty="no" -if compile_prog "" "" ; then - have_openpty="yes" -else - if compile_prog "" "-lutil" ; then - libs_tools="-lutil $libs_tools" - have_openpty="yes" - fi -fi - -########################################## -# spice probe -if test "$spice" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { spice_server_new(); return 0; } -EOF - spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null) - spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null) - if $pkg_config --atleast-version=0.12.5 spice-server && \ - $pkg_config --atleast-version=0.12.3 spice-protocol && \ - compile_prog "$spice_cflags" "$spice_libs" ; then - spice="yes" - QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" - else - if test "$spice" = "yes" ; then - feature_not_found "spice" \ - "Install spice-server(>=0.12.5) and spice-protocol(>=0.12.3) devel" - fi - spice="no" - fi -fi - -# check for smartcard support -if test "$smartcard" != "no"; then - if $pkg_config --atleast-version=2.5.1 libcacard; then - libcacard_cflags=$($pkg_config --cflags libcacard) - libcacard_libs=$($pkg_config --libs libcacard) - smartcard="yes" - else - if test "$smartcard" = "yes"; then - feature_not_found "smartcard" "Install libcacard devel" - fi - smartcard="no" - fi -fi - -# check for libusb -if test "$libusb" != "no" ; then - if $pkg_config --atleast-version=1.0.13 libusb-1.0; then - libusb="yes" - libusb_cflags=$($pkg_config --cflags libusb-1.0) - libusb_libs=$($pkg_config --libs libusb-1.0) - else - if test "$libusb" = "yes"; then - feature_not_found "libusb" "Install libusb devel >= 1.0.13" - fi - libusb="no" - fi -fi - -# check for usbredirparser for usb network redirection support -if test "$usb_redir" != "no" ; then - if $pkg_config --atleast-version=0.6 libusbredirparser-0.5; then - usb_redir="yes" - usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5) - usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5) - else - if test "$usb_redir" = "yes"; then - feature_not_found "usb-redir" "Install usbredir devel" - fi - usb_redir="no" - fi -fi - -########################################## -# check if we have VSS SDK headers for win - -if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \ - test "$vss_win32_sdk" != "no" ; then - case "$vss_win32_sdk" in - "") vss_win32_include="-isystem $source_path" ;; - *\ *) # The SDK is installed in "Program Files" by default, but we cannot - # handle path with spaces. So we symlink the headers into ".sdk/vss". - vss_win32_include="-isystem $source_path/.sdk/vss" - symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" - ;; - *) vss_win32_include="-isystem $vss_win32_sdk" - esac - cat > $TMPC << EOF -#define __MIDL_user_allocate_free_DEFINED__ -#include -int main(void) { return VSS_CTX_BACKUP; } -EOF - if compile_prog "$vss_win32_include" "" ; then - guest_agent_with_vss="yes" - QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" - libs_qga="-lole32 -loleaut32 -lshlwapi -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" - qga_vss_provider="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb" - else - if test "$vss_win32_sdk" != "" ; then - echo "ERROR: Please download and install Microsoft VSS SDK:" - echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490" - echo "ERROR: On POSIX-systems, you can extract the SDK headers by:" - echo "ERROR: scripts/extract-vsssdk-headers setup.exe" - echo "ERROR: The headers are extracted in the directory \`inc'." - feature_not_found "VSS support" - fi - guest_agent_with_vss="no" - fi -fi - -########################################## -# lookup Windows platform SDK (if not specified) -# The SDK is needed only to build .tlb (type library) file of guest agent -# VSS provider from the source. It is usually unnecessary because the -# pre-compiled .tlb file is included. - -if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \ - test "$guest_agent_with_vss" = "yes" ; then - if test -z "$win_sdk"; then - programfiles="$PROGRAMFILES" - test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432" - if test -n "$programfiles"; then - win_sdk=$(ls -d "$programfiles/Microsoft SDKs/Windows/v"* | tail -1) 2>/dev/null - else - feature_not_found "Windows SDK" - fi - elif test "$win_sdk" = "no"; then - win_sdk="" - fi -fi - -########################################## -# check if mingw environment provides a recent ntddscsi.h -if test "$mingw32" = "yes" && test "$guest_agent" != "no"; then - cat > $TMPC << EOF -#include -#include -int main(void) { -#if !defined(IOCTL_SCSI_GET_ADDRESS) -#error Missing required ioctl definitions -#endif - SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 }; - return addr.Lun; -} -EOF - if compile_prog "" "" ; then - guest_agent_ntddscsi=yes - libs_qga="-lsetupapi -lcfgmgr32 $libs_qga" - fi -fi - -########################################## -# virgl renderer probe - -if test "$virglrenderer" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { virgl_renderer_poll(); return 0; } -EOF - virgl_cflags=$($pkg_config --cflags virglrenderer 2>/dev/null) - virgl_libs=$($pkg_config --libs virglrenderer 2>/dev/null) - virgl_version=$($pkg_config --modversion virglrenderer 2>/dev/null) - if $pkg_config virglrenderer >/dev/null 2>&1 && \ - compile_prog "$virgl_cflags" "$virgl_libs" ; then - virglrenderer="yes" - else - if test "$virglrenderer" = "yes" ; then - feature_not_found "virglrenderer" - fi - virglrenderer="no" - fi -fi - -########################################## -# capstone - -case "$capstone" in - "" | yes) - if $pkg_config capstone; then - capstone=system - elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then - capstone=git - elif test -e "${source_path}/capstone/Makefile" ; then - capstone=internal - elif test -z "$capstone" ; then - capstone=no - else - feature_not_found "capstone" "Install capstone devel or git submodule" - fi - ;; - - system) - if ! $pkg_config capstone; then - feature_not_found "capstone" "Install capstone devel" - fi - ;; -esac - -case "$capstone" in - git | internal) - if test "$capstone" = git; then - git_submodules="${git_submodules} capstone" - fi - mkdir -p capstone - QEMU_CFLAGS="$QEMU_CFLAGS -I${source_path}/capstone/include" - if test "$mingw32" = "yes"; then - LIBCAPSTONE=capstone.lib - else - LIBCAPSTONE=libcapstone.a - fi - capstone_libs="-L${build_path}/capstone -lcapstone" - capstone_cflags="-I${source_path}/capstone/include" - ;; - - system) - capstone_libs="$($pkg_config --libs capstone)" - capstone_cflags="$($pkg_config --cflags capstone)" - QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags capstone)" - ;; - - no) - ;; - *) - error_exit "Unknown state for capstone: $capstone" - ;; -esac - -########################################## -# check if we have fdatasync - -fdatasync=no -cat > $TMPC << EOF -#include -int main(void) { -#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 -return fdatasync(0); -#else -#error Not supported -#endif -} -EOF -if compile_prog "" "" ; then - fdatasync=yes -fi - -########################################## -# check if we have madvise - -madvise=no -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return madvise(NULL, 0, MADV_DONTNEED); } -EOF -if compile_prog "" "" ; then - madvise=yes -fi - -########################################## -# check if we have posix_madvise - -posix_madvise=no -cat > $TMPC << EOF -#include -#include -int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); } -EOF -if compile_prog "" "" ; then - posix_madvise=yes -fi - -########################################## -# check if we have posix_memalign() - -posix_memalign=no -cat > $TMPC << EOF -#include -int main(void) { - void *p; - return posix_memalign(&p, 8, 8); -} -EOF -if compile_prog "" "" ; then - posix_memalign=yes -fi - -########################################## -# check if we have posix_syslog - -posix_syslog=no -cat > $TMPC << EOF -#include -int main(void) { openlog("qemu", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "configure"); return 0; } -EOF -if compile_prog "" "" ; then - posix_syslog=yes -fi - -########################################## -# check if we have sem_timedwait - -sem_timedwait=no -cat > $TMPC << EOF -#include -int main(void) { sem_t s; struct timespec t = {0}; return sem_timedwait(&s, &t); } -EOF -if compile_prog "" "" ; then - sem_timedwait=yes -fi - -########################################## -# check if we have strchrnul - -strchrnul=no -cat > $TMPC << EOF -#include -int main(void); -// Use a haystack that the compiler shouldn't be able to constant fold -char *haystack = (char*)&main; -int main(void) { return strchrnul(haystack, 'x') != &haystack[6]; } -EOF -if compile_prog "" "" ; then - strchrnul=yes -fi - -######################################### -# check if we have st_atim - -st_atim=no -cat > $TMPC << EOF -#include -#include -int main(void) { return offsetof(struct stat, st_atim); } -EOF -if compile_prog "" "" ; then - st_atim=yes -fi - -########################################## -# check if trace backend exists - -$python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends > /dev/null 2> /dev/null -if test "$?" -ne 0 ; then - error_exit "invalid trace backends" \ - "Please choose supported trace backends." -fi - -########################################## -# For 'ust' backend, test if ust headers are present -if have_backend "ust"; then - cat > $TMPC << EOF -#include -int main(void) { return 0; } -EOF - if compile_prog "" "-Wl,--no-as-needed -ldl" ; then - if $pkg_config lttng-ust --exists; then - lttng_ust_libs=$($pkg_config --libs lttng-ust) - else - lttng_ust_libs="-llttng-ust -ldl" - fi - if $pkg_config liburcu-bp --exists; then - urcu_bp_libs=$($pkg_config --libs liburcu-bp) - else - urcu_bp_libs="-lurcu-bp" - fi - - LIBS="$lttng_ust_libs $urcu_bp_libs $LIBS" - else - error_exit "Trace backend 'ust' missing lttng-ust header files" - fi -fi - -########################################## -# For 'dtrace' backend, test if 'dtrace' command is present -if have_backend "dtrace"; then - if ! has 'dtrace' ; then - error_exit "dtrace command is not found in PATH $PATH" - fi - trace_backend_stap="no" - if has 'stap' ; then - trace_backend_stap="yes" - fi -fi - -########################################## -# check and set a backend for coroutine - -# We prefer ucontext, but it's not always possible. The fallback -# is sigcontext. On Windows the only valid backend is the Windows -# specific one. - -ucontext_works=no -if test "$darwin" != "yes"; then - cat > $TMPC << EOF -#include -#ifdef __stub_makecontext -#error Ignoring glibc stub makecontext which will always fail -#endif -int main(void) { makecontext(0, 0, 0); return 0; } -EOF - if compile_prog "" "" ; then - ucontext_works=yes - fi -fi - -if test "$coroutine" = ""; then - if test "$mingw32" = "yes"; then - coroutine=win32 - elif test "$ucontext_works" = "yes"; then - coroutine=ucontext - else - coroutine=sigaltstack - fi -else - case $coroutine in - windows) - if test "$mingw32" != "yes"; then - error_exit "'windows' coroutine backend only valid for Windows" - fi - # Unfortunately the user visible backend name doesn't match the - # coroutine-*.c filename for this case, so we have to adjust it here. - coroutine=win32 - ;; - ucontext) - if test "$ucontext_works" != "yes"; then - feature_not_found "ucontext" - fi - ;; - sigaltstack) - if test "$mingw32" = "yes"; then - error_exit "only the 'windows' coroutine backend is valid for Windows" - fi - ;; - *) - error_exit "unknown coroutine backend $coroutine" - ;; - esac -fi - -if test "$coroutine_pool" = ""; then - coroutine_pool=yes -fi - -if test "$debug_stack_usage" = "yes"; then - if test "$coroutine_pool" = "yes"; then - echo "WARN: disabling coroutine pool for stack usage debugging" - coroutine_pool=no - fi -fi - -################################################## -# SafeStack - - -if test "$safe_stack" = "yes"; then -cat > $TMPC << EOF -int main(int argc, char *argv[]) -{ -#if ! __has_feature(safe_stack) -#error SafeStack Disabled -#endif - return 0; -} -EOF - flag="-fsanitize=safe-stack" - # Check that safe-stack is supported and enabled. - if compile_prog "-Werror $flag" "$flag"; then - # Flag needed both at compilation and at linking - QEMU_CFLAGS="$QEMU_CFLAGS $flag" - QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" - else - error_exit "SafeStack not supported by your compiler" - fi - if test "$coroutine" != "ucontext"; then - error_exit "SafeStack is only supported by the coroutine backend ucontext" - fi -else -cat > $TMPC << EOF -int main(int argc, char *argv[]) -{ -#if defined(__has_feature) -#if __has_feature(safe_stack) -#error SafeStack Enabled -#endif -#endif - return 0; -} -EOF -if test "$safe_stack" = "no"; then - # Make sure that safe-stack is disabled - if ! compile_prog "-Werror" ""; then - # SafeStack was already enabled, try to explicitly remove the feature - flag="-fno-sanitize=safe-stack" - if ! compile_prog "-Werror $flag" "$flag"; then - error_exit "Configure cannot disable SafeStack" - fi - QEMU_CFLAGS="$QEMU_CFLAGS $flag" - QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" - fi -else # "$safe_stack" = "" - # Set safe_stack to yes or no based on pre-existing flags - if compile_prog "-Werror" ""; then - safe_stack="no" - else - safe_stack="yes" - if test "$coroutine" != "ucontext"; then - error_exit "SafeStack is only supported by the coroutine backend ucontext" - fi - fi -fi -fi - -########################################## -# check if we have open_by_handle_at - -open_by_handle_at=no -cat > $TMPC << EOF -#include -#if !defined(AT_EMPTY_PATH) -# error missing definition -#else -int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); } -#endif -EOF -if compile_prog "" "" ; then - open_by_handle_at=yes -fi - -######################################## -# check if we have linux/magic.h - -linux_magic_h=no -cat > $TMPC << EOF -#include -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - linux_magic_h=yes -fi - -######################################## -# check if we have valgrind/valgrind.h - -valgrind_h=no -cat > $TMPC << EOF -#include -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - valgrind_h=yes -fi - -######################################## -# check if environ is declared - -has_environ=no -cat > $TMPC << EOF -#include -int main(void) { - environ = 0; - return 0; -} -EOF -if compile_prog "" "" ; then - has_environ=yes -fi - -######################################## -# check if cpuid.h is usable. - -cat > $TMPC << EOF -#include -int main(void) { - unsigned a, b, c, d; - int max = __get_cpuid_max(0, 0); - - if (max >= 1) { - __cpuid(1, a, b, c, d); - } - - if (max >= 7) { - __cpuid_count(7, 0, a, b, c, d); - } - - return 0; -} -EOF -if compile_prog "" "" ; then - cpuid_h=yes -fi - -########################################## -# avx2 optimization requirement check -# -# There is no point enabling this if cpuid.h is not usable, -# since we won't be able to select the new routines. - -if test "$cpuid_h" = "yes" && test "$avx2_opt" != "no"; then - cat > $TMPC << EOF -#pragma GCC push_options -#pragma GCC target("avx2") -#include -#include -static int bar(void *a) { - __m256i x = *(__m256i *)a; - return _mm256_testz_si256(x, x); -} -int main(int argc, char *argv[]) { return bar(argv[0]); } -EOF - if compile_object "" ; then - avx2_opt="yes" - else - avx2_opt="no" - fi -fi - -########################################## -# avx512f optimization requirement check -# -# There is no point enabling this if cpuid.h is not usable, -# since we won't be able to select the new routines. -# by default, it is turned off. -# if user explicitly want to enable it, check environment - -if test "$cpuid_h" = "yes" && test "$avx512f_opt" = "yes"; then - cat > $TMPC << EOF -#pragma GCC push_options -#pragma GCC target("avx512f") -#include -#include -static int bar(void *a) { - __m512i x = *(__m512i *)a; - return _mm512_test_epi64_mask(x, x); -} -int main(int argc, char *argv[]) -{ - return bar(argv[0]); -} -EOF - if ! compile_object "" ; then - avx512f_opt="no" - fi -else - avx512f_opt="no" -fi - -######################################## -# check if __[u]int128_t is usable. - -int128=no -cat > $TMPC << EOF -__int128_t a; -__uint128_t b; -int main (void) { - a = a + b; - b = a * b; - a = a * a; - return 0; -} -EOF -if compile_prog "" "" ; then - int128=yes -fi - -######################################### -# See if 128-bit atomic operations are supported. - -atomic128=no -if test "$int128" = "yes"; then - cat > $TMPC << EOF -int main(void) -{ - unsigned __int128 x = 0, y = 0; - y = __atomic_load_16(&x, 0); - __atomic_store_16(&x, y, 0); - __atomic_compare_exchange_16(&x, &y, x, 0, 0, 0); - return 0; -} -EOF - if compile_prog "" "" ; then - atomic128=yes - fi -fi - -cmpxchg128=no -if test "$int128" = yes && test "$atomic128" = no; then - cat > $TMPC << EOF -int main(void) -{ - unsigned __int128 x = 0, y = 0; - __sync_val_compare_and_swap_16(&x, y, x); - return 0; -} -EOF - if compile_prog "" "" ; then - cmpxchg128=yes - fi -fi - -######################################### -# See if 64-bit atomic operations are supported. -# Note that without __atomic builtins, we can only -# assume atomic loads/stores max at pointer size. - -cat > $TMPC << EOF -#include -int main(void) -{ - uint64_t x = 0, y = 0; -#ifdef __ATOMIC_RELAXED - y = __atomic_load_8(&x, 0); - __atomic_store_8(&x, y, 0); - __atomic_compare_exchange_8(&x, &y, x, 0, 0, 0); - __atomic_exchange_8(&x, y, 0); - __atomic_fetch_add_8(&x, y, 0); -#else - typedef char is_host64[sizeof(void *) >= sizeof(uint64_t) ? 1 : -1]; - __sync_lock_test_and_set(&x, y); - __sync_val_compare_and_swap(&x, y, 0); - __sync_fetch_and_add(&x, y); -#endif - return 0; -} -EOF -if compile_prog "" "" ; then - atomic64=yes -fi - -######################################### -# See if --dynamic-list is supported by the linker -ld_dynamic_list="no" -if test "$static" = "no" ; then - cat > $TMPTXT < $TMPC < -void foo(void); - -void foo(void) -{ - printf("foo\n"); -} - -int main(void) -{ - foo(); - return 0; -} -EOF - - if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then - ld_dynamic_list="yes" - fi -fi - -######################################### -# See if -exported_symbols_list is supported by the linker - -ld_exported_symbols_list="no" -if test "$static" = "no" ; then - cat > $TMPTXT < $TMPC << EOF -int x = 1; -extern const int y __attribute__((alias("x"))); -int main(void) { return 0; } -EOF -if compile_prog "" "" ; then - attralias=yes -fi - -######################################## -# check if getauxval is available. - -getauxval=no -cat > $TMPC << EOF -#include -int main(void) { - return getauxval(AT_HWCAP) == 0; -} -EOF -if compile_prog "" "" ; then - getauxval=yes -fi - -######################################## -# check if ccache is interfering with -# semantic analysis of macros - -unset CCACHE_CPP2 -ccache_cpp2=no -cat > $TMPC << EOF -static const int Z = 1; -#define fn() ({ Z; }) -#define TAUT(X) ((X) == Z) -#define PAREN(X, Y) (X == Y) -#define ID(X) (X) -int main(int argc, char *argv[]) -{ - int x = 0, y = 0; - x = ID(x); - x = fn(); - fn(); - if (PAREN(x, y)) return 0; - if (TAUT(Z)) return 0; - return 0; -} -EOF - -if ! compile_object "-Werror"; then - ccache_cpp2=yes -fi - -################################################# -# clang does not support glibc + FORTIFY_SOURCE. - -if test "$fortify_source" != "no"; then - if echo | $cc -dM -E - | grep __clang__ > /dev/null 2>&1 ; then - fortify_source="no"; - elif test -n "$cxx" && has $cxx && - echo | $cxx -dM -E - | grep __clang__ >/dev/null 2>&1 ; then - fortify_source="no"; - else - fortify_source="yes" - fi -fi - -############################################### -# Check if copy_file_range is provided by glibc -have_copy_file_range=no -cat > $TMPC << EOF -#include -int main(void) { - copy_file_range(0, NULL, 0, NULL, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - have_copy_file_range=yes -fi - -########################################## -# check if struct fsxattr is available via linux/fs.h - -have_fsxattr=no -cat > $TMPC << EOF -#include -struct fsxattr foo; -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - have_fsxattr=yes -fi - -########################################## -# check for usable membarrier system call -if test "$membarrier" = "yes"; then - have_membarrier=no - if test "$mingw32" = "yes" ; then - have_membarrier=yes - elif test "$linux" = "yes" ; then - cat > $TMPC << EOF - #include - #include - #include - #include - int main(void) { - syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); - syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0); - exit(0); - } -EOF - if compile_prog "" "" ; then - have_membarrier=yes - fi - fi - if test "$have_membarrier" = "no"; then - feature_not_found "membarrier" "membarrier system call not available" - fi -else - # Do not enable it by default even for Mingw32, because it doesn't - # work on Wine. - membarrier=no -fi - -########################################## -# check if rtnetlink.h exists and is useful -have_rtnetlink=no -cat > $TMPC << EOF -#include -int main(void) { - return IFLA_PROTO_DOWN; -} -EOF -if compile_prog "" "" ; then - have_rtnetlink=yes -fi - -########################################## -# check for usable AF_VSOCK environment -have_af_vsock=no -cat > $TMPC << EOF -#include -#include -#include -#if !defined(AF_VSOCK) -# error missing AF_VSOCK flag -#endif -#include -int main(void) { - int sock, ret; - struct sockaddr_vm svm; - socklen_t len = sizeof(svm); - sock = socket(AF_VSOCK, SOCK_STREAM, 0); - ret = getpeername(sock, (struct sockaddr *)&svm, &len); - if ((ret == -1) && (errno == ENOTCONN)) { - return 0; - } - return -1; -} -EOF -if compile_prog "" "" ; then - have_af_vsock=yes -fi - -########################################## -# check for usable AF_ALG environment -have_afalg=no -cat > $TMPC << EOF -#include -#include -#include -#include -int main(void) { - int sock; - sock = socket(AF_ALG, SOCK_SEQPACKET, 0); - return sock; -} -EOF -if compile_prog "" "" ; then - have_afalg=yes -fi -if test "$crypto_afalg" = "yes" -then - if test "$have_afalg" != "yes" - then - error_exit "AF_ALG requested but could not be detected" - fi -fi - - -################################################# -# Check to see if we have the Hypervisor framework -if [ "$darwin" = "yes" ] ; then - cat > $TMPC << EOF -#include -int main() { return 0;} -EOF - if ! compile_object ""; then - hvf='no' - else - hvf='yes' - QEMU_LDFLAGS="-framework Hypervisor $QEMU_LDFLAGS" - fi -fi - -########################################## -# check for sysmacros.h - -have_sysmacros=no -cat > $TMPC << EOF -#include -int main(void) { - return makedev(0, 0); -} -EOF -if compile_prog "" "" ; then - have_sysmacros=yes -fi - -########################################## -# check for _Static_assert() - -have_static_assert=no -cat > $TMPC << EOF -_Static_assert(1, "success"); -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - have_static_assert=yes -fi - -########################################## -# check for utmpx.h, it is missing e.g. on OpenBSD - -have_utmpx=no -cat > $TMPC << EOF -#include -struct utmpx user_info; -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - have_utmpx=yes -fi - -########################################## -# check for getrandom() - -have_getrandom=no -cat > $TMPC << EOF -#include -int main(void) { - return getrandom(0, 0, GRND_NONBLOCK); -} -EOF -if compile_prog "" "" ; then - have_getrandom=yes -fi - -########################################## -# checks for sanitizers - -have_asan=no -have_ubsan=no -have_asan_iface_h=no -have_asan_iface_fiber=no - -if test "$sanitizers" = "yes" ; then - write_c_skeleton - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" ""; then - have_asan=yes - fi - - # we could use a simple skeleton for flags checks, but this also - # detect the static linking issue of ubsan, see also: - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285 - cat > $TMPC << EOF -#include -int main(void) { - void *tmp = malloc(10); - if (tmp != NULL) { - return *(int *)(tmp + 2); - } - return 1; -} -EOF - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then - have_ubsan=yes - fi - - if check_include "sanitizer/asan_interface.h" ; then - have_asan_iface_h=yes - fi - - cat > $TMPC << EOF -#include -int main(void) { - __sanitizer_start_switch_fiber(0, 0, 0); - return 0; -} -EOF - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" "" ; then - have_asan_iface_fiber=yes - fi -fi - -########################################## -# checks for fuzzer -if test "$fuzzing" = "yes" ; then - write_c_fuzzer_skeleton - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then - have_fuzzer=yes - else - error_exit "Your compiler doesn't support -fsanitize=fuzzer" - exit 1 - fi -fi - -# Thread sanitizer is, for now, much noisier than the other sanitizers; -# keep it separate until that is not the case. -if test "$tsan" = "yes" && test "$sanitizers" = "yes"; then - error_exit "TSAN is not supported with other sanitiziers." -fi -have_tsan=no -have_tsan_iface_fiber=no -if test "$tsan" = "yes" ; then - write_c_skeleton - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then - have_tsan=yes - fi - cat > $TMPC << EOF -#include -int main(void) { - __tsan_create_fiber(0); - return 0; -} -EOF - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then - have_tsan_iface_fiber=yes - fi -fi - -########################################## -# check for libpmem - -if test "$libpmem" != "no"; then - if $pkg_config --exists "libpmem"; then - libpmem="yes" - libpmem_libs=$($pkg_config --libs libpmem) - libpmem_cflags=$($pkg_config --cflags libpmem) - QEMU_CFLAGS="$QEMU_CFLAGS $libpmem_cflags" - else - if test "$libpmem" = "yes" ; then - feature_not_found "libpmem" "Install nvml or pmdk" - fi - libpmem="no" - fi -fi - -########################################## -# check for libdaxctl - -if test "$libdaxctl" != "no"; then - if $pkg_config --atleast-version=57 "libdaxctl"; then - libdaxctl="yes" - libdaxctl_libs=$($pkg_config --libs libdaxctl) - libdaxctl_cflags=$($pkg_config --cflags libdaxctl) - QEMU_CFLAGS="$QEMU_CFLAGS $libdaxctl_cflags" - else - if test "$libdaxctl" = "yes" ; then - feature_not_found "libdaxctl" "Install libdaxctl" - fi - libdaxctl="no" - fi -fi - -########################################## -# check for slirp - -# slirp is only required when building softmmu targets -if test -z "$slirp" -a "$softmmu" != "yes" ; then - slirp="no" -fi - -case "$slirp" in - "" | yes) - if $pkg_config slirp; then - slirp=system - elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then - slirp=git - elif test -e "${source_path}/slirp/Makefile" ; then - slirp=internal - elif test -z "$slirp" ; then - slirp=no - else - feature_not_found "slirp" "Install slirp devel or git submodule" - fi - ;; - - system) - if ! $pkg_config slirp; then - feature_not_found "slirp" "Install slirp devel" - fi - ;; -esac - -case "$slirp" in - git | internal) - if test "$slirp" = git; then - git_submodules="${git_submodules} slirp" - fi - mkdir -p slirp - slirp_cflags="-I${source_path}/slirp/src -I${build_path}/slirp/src" - slirp_libs="-L${build_path}/slirp -lslirp" - if test "$mingw32" = "yes" ; then - slirp_libs="$slirp_libs -lws2_32 -liphlpapi" - fi - ;; - - system) - slirp_version=$($pkg_config --modversion slirp 2>/dev/null) - slirp_cflags=$($pkg_config --cflags slirp 2>/dev/null) - slirp_libs=$($pkg_config --libs slirp 2>/dev/null) - ;; - - no) - ;; - *) - error_exit "Unknown state for slirp: $slirp" - ;; -esac - -########################################## -# check for usable __NR_keyctl syscall - -if test "$linux" = "yes" ; then - - have_keyring=no - cat > $TMPC << EOF -#include -#include -#include -#include -int main(void) { - return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0); -} -EOF - if compile_prog "" "" ; then - have_keyring=yes - fi -fi -if test "$secret_keyring" != "no" -then - if test "$have_keyring" = "yes" - then - secret_keyring=yes - else - if test "$secret_keyring" = "yes" - then - error_exit "syscall __NR_keyctl requested, \ -but not implemented on your system" - else - secret_keyring=no - fi - fi -fi - -########################################## -# check for usable keyutils.h - -if test "$linux" = "yes" ; then - - have_keyutils=no - cat > $TMPC << EOF -#include -#include -#include -#include -#include -int main(void) { - return request_key("user", NULL, NULL, 0); -} -EOF - if compile_prog "" "-lkeyutils"; then - have_keyutils=yes - fi -fi - - -########################################## -# End of CC checks -# After here, no more $cc or $ld runs - -write_c_skeleton - -if test "$gcov" = "yes" ; then - : -elif test "$fortify_source" = "yes" ; then - QEMU_CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" - debug=no -fi -if test "$debug_info" = "yes"; then - CFLAGS="-g $CFLAGS" - LDFLAGS="-g $LDFLAGS" -fi -if test "$debug" = "no"; then - CFLAGS="-O2 $CFLAGS" -fi - -case "$ARCH" in -alpha) - # Ensure there's only a single GP - QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" -;; -esac - -if test "$gprof" = "yes" ; then - QEMU_CFLAGS="-p $QEMU_CFLAGS" - QEMU_LDFLAGS="-p $QEMU_LDFLAGS" -fi - -if test "$have_asan" = "yes"; then - QEMU_CFLAGS="-fsanitize=address $QEMU_CFLAGS" - QEMU_LDFLAGS="-fsanitize=address $QEMU_LDFLAGS" - if test "$have_asan_iface_h" = "no" ; then - echo "ASAN build enabled, but ASAN header missing." \ - "Without code annotation, the report may be inferior." - elif test "$have_asan_iface_fiber" = "no" ; then - echo "ASAN build enabled, but ASAN header is too old." \ - "Without code annotation, the report may be inferior." - fi -fi -if test "$have_tsan" = "yes" ; then - if test "$have_tsan_iface_fiber" = "yes" ; then - QEMU_CFLAGS="-fsanitize=thread $QEMU_CFLAGS" - QEMU_LDFLAGS="-fsanitize=thread $QEMU_LDFLAGS" - else - error_exit "Cannot enable TSAN due to missing fiber annotation interface." - fi -elif test "$tsan" = "yes" ; then - error_exit "Cannot enable TSAN due to missing sanitize thread interface." -fi -if test "$have_ubsan" = "yes"; then - QEMU_CFLAGS="-fsanitize=undefined $QEMU_CFLAGS" - QEMU_LDFLAGS="-fsanitize=undefined $QEMU_LDFLAGS" -fi - -########################################## -# Do we have libnfs -if test "$libnfs" != "no" ; then - if $pkg_config --atleast-version=1.9.3 libnfs; then - libnfs="yes" - libnfs_libs=$($pkg_config --libs libnfs) - else - if test "$libnfs" = "yes" ; then - feature_not_found "libnfs" "Install libnfs devel >= 1.9.3" - fi - libnfs="no" - fi -fi - -########################################## -# Do we have libudev -if test "$libudev" != "no" ; then - if $pkg_config libudev && test "$static" != "yes"; then - libudev="yes" - libudev_libs=$($pkg_config --libs libudev) - else - libudev="no" - fi -fi - -# Now we've finished running tests it's OK to add -Werror to the compiler flags -if test "$werror" = "yes"; then - QEMU_CFLAGS="-Werror $QEMU_CFLAGS" -fi - -# Exclude --warn-common with TSan to suppress warnings from the TSan libraries. -if test "$solaris" = "no" && test "$tsan" = "no"; then - if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then - QEMU_LDFLAGS="-Wl,--warn-common $QEMU_LDFLAGS" - fi -fi - -# test if pod2man has --utf8 option -if pod2man --help | grep -q utf8; then - POD2MAN="pod2man --utf8" -else - POD2MAN="pod2man" -fi - -# Use ASLR, no-SEH and DEP if available -if test "$mingw32" = "yes" ; then - for flag in --dynamicbase --no-seh --nxcompat; do - if ld_has $flag ; then - QEMU_LDFLAGS="-Wl,$flag $QEMU_LDFLAGS" - fi - done -fi - -# Disable OpenBSD W^X if available -if test "$tcg" = "yes" && test "$targetos" = "OpenBSD"; then - cat > $TMPC <&1 | grep -q "^[[:space:]]*$emu[[:space:]]*$"; then - ld_i386_emulation="$emu" - roms="optionrom" - break - fi - done -fi - -# Only build s390-ccw bios if we're on s390x and the compiler has -march=z900 -if test "$cpu" = "s390x" ; then - write_c_skeleton - if compile_prog "-march=z900" ""; then - roms="$roms s390-ccw" - # SLOF is required for building the s390-ccw firmware on s390x, - # since it is using the libnet code from SLOF for network booting. - if test -e "${source_path}/.git" ; then - git_submodules="${git_submodules} roms/SLOF" - fi - fi -fi - -if test $git_update = 'yes' ; then - (cd "${source_path}" && GIT="$git" "./scripts/git-submodule.sh" update "$git_submodules") - - if test "$fdt" = "git" ; then - if [ "$pwd_is_source_path" != "y" ] ; then - symlink "$source_path/dtc/Makefile" "dtc/Makefile" - fi - fi -fi - -# Check that the C++ compiler exists and works with the C compiler. -# All the QEMU_CXXFLAGS are based on QEMU_CFLAGS. Keep this at the end to don't miss any other that could be added. -if has $cxx; then - cat > $TMPC < $TMPCXX <config-all-disas.mak - -echo "# Automatically generated by configure - do not modify" > $config_host_mak -echo >> $config_host_mak - -echo all: >> $config_host_mak -echo "prefix=$prefix" >> $config_host_mak -echo "bindir=$bindir" >> $config_host_mak -echo "libdir=$libdir" >> $config_host_mak -echo "libexecdir=$libexecdir" >> $config_host_mak -echo "includedir=$includedir" >> $config_host_mak -echo "sysconfdir=$sysconfdir" >> $config_host_mak -echo "qemu_confdir=$qemu_confdir" >> $config_host_mak -echo "qemu_datadir=$qemu_datadir" >> $config_host_mak -echo "qemu_firmwarepath=$firmwarepath" >> $config_host_mak -echo "qemu_moddir=$qemu_moddir" >> $config_host_mak -if test "$mingw32" = "no" ; then - echo "qemu_localstatedir=$local_statedir" >> $config_host_mak -fi -echo "qemu_helperdir=$libexecdir" >> $config_host_mak -echo "qemu_localedir=$qemu_localedir" >> $config_host_mak -echo "qemu_icondir=$qemu_icondir" >> $config_host_mak -echo "qemu_desktopdir=$qemu_desktopdir" >> $config_host_mak -echo "GIT=$git" >> $config_host_mak -echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak -echo "GIT_UPDATE=$git_update" >> $config_host_mak - -echo "ARCH=$ARCH" >> $config_host_mak - -if test "$default_devices" = "yes" ; then - echo "CONFIG_MINIKCONF_MODE=--defconfig" >> $config_host_mak -else - echo "CONFIG_MINIKCONF_MODE=--allnoconfig" >> $config_host_mak -fi -if test "$debug_tcg" = "yes" ; then - echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak -fi -if test "$strip_opt" = "yes" ; then - echo "STRIP=${strip}" >> $config_host_mak -fi -if test "$bigendian" = "yes" ; then - echo "HOST_WORDS_BIGENDIAN=y" >> $config_host_mak -fi -if test "$mingw32" = "yes" ; then - echo "CONFIG_WIN32=y" >> $config_host_mak - rc_version=$(cat $source_path/VERSION) - version_major=${rc_version%%.*} - rc_version=${rc_version#*.} - version_minor=${rc_version%%.*} - rc_version=${rc_version#*.} - version_subminor=${rc_version%%.*} - version_micro=0 - echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak - echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak - if test "$guest_agent_with_vss" = "yes" ; then - echo "CONFIG_QGA_VSS=y" >> $config_host_mak - echo "QGA_VSS_PROVIDER=$qga_vss_provider" >> $config_host_mak - echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak - fi - if test "$guest_agent_ntddscsi" = "yes" ; then - echo "CONFIG_QGA_NTDDSCSI=y" >> $config_host_mak - fi - if test "$guest_agent_msi" = "yes"; then - echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak - echo "QEMU_GA_MSI_MINGW_DLL_PATH=${QEMU_GA_MSI_MINGW_DLL_PATH}" >> $config_host_mak - echo "QEMU_GA_MSI_WITH_VSS=${QEMU_GA_MSI_WITH_VSS}" >> $config_host_mak - echo "QEMU_GA_MSI_ARCH=${QEMU_GA_MSI_ARCH}" >> $config_host_mak - echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER}" >> $config_host_mak - echo "QEMU_GA_DISTRO=${QEMU_GA_DISTRO}" >> $config_host_mak - echo "QEMU_GA_VERSION=${QEMU_GA_VERSION}" >> $config_host_mak - fi -else - echo "CONFIG_POSIX=y" >> $config_host_mak -fi - -if test "$linux" = "yes" ; then - echo "CONFIG_LINUX=y" >> $config_host_mak -fi - -if test "$darwin" = "yes" ; then - echo "CONFIG_DARWIN=y" >> $config_host_mak -fi - -if test "$solaris" = "yes" ; then - echo "CONFIG_SOLARIS=y" >> $config_host_mak -fi -if test "$haiku" = "yes" ; then - echo "CONFIG_HAIKU=y" >> $config_host_mak -fi -if test "$static" = "yes" ; then - echo "CONFIG_STATIC=y" >> $config_host_mak -fi -if test "$profiler" = "yes" ; then - echo "CONFIG_PROFILER=y" >> $config_host_mak -fi -if test "$want_tools" = "yes" ; then - echo "CONFIG_TOOLS=y" >> $config_host_mak -fi -if test "$guest_agent" = "yes" ; then - echo "CONFIG_GUEST_AGENT=y" >> $config_host_mak -fi -if test "$slirp" != "no"; then - echo "CONFIG_SLIRP=y" >> $config_host_mak - echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak - echo "SLIRP_CFLAGS=$slirp_cflags" >> $config_host_mak - echo "SLIRP_LIBS=$slirp_libs" >> $config_host_mak -fi -subdirs= -if [ "$slirp" = "git" -o "$slirp" = "internal" ]; then - subdirs="$subdirs slirp" -fi -if test "$vde" = "yes" ; then - echo "CONFIG_VDE=y" >> $config_host_mak - echo "VDE_LIBS=$vde_libs" >> $config_host_mak -fi -if test "$netmap" = "yes" ; then - echo "CONFIG_NETMAP=y" >> $config_host_mak -fi -if test "$l2tpv3" = "yes" ; then - echo "CONFIG_L2TPV3=y" >> $config_host_mak -fi -if test "$gprof" = "yes" ; then - echo "CONFIG_GPROF=y" >> $config_host_mak -fi -if test "$cap_ng" = "yes" ; then - echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak - echo "LIBCAP_NG_LIBS=$cap_libs" >> $config_host_mak -fi -echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak -for drv in $audio_drv_list; do - def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]') - echo "$def=y" >> $config_host_mak -done -if test "$alsa" = "yes" ; then - echo "CONFIG_ALSA=y" >> $config_host_mak -fi -echo "ALSA_LIBS=$alsa_libs" >> $config_host_mak -echo "ALSA_CFLAGS=$alsa_cflags" >> $config_host_mak -if test "$libpulse" = "yes" ; then - echo "CONFIG_LIBPULSE=y" >> $config_host_mak -fi -echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak -echo "PULSE_CFLAGS=$pulse_cflags" >> $config_host_mak -echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak -echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak -echo "OSS_LIBS=$oss_libs" >> $config_host_mak -if test "$libjack" = "yes" ; then - echo "CONFIG_LIBJACK=y" >> $config_host_mak -fi -echo "JACK_LIBS=$jack_libs" >> $config_host_mak -if test "$audio_win_int" = "yes" ; then - echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak -fi -echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak -echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak -if test "$xfs" = "yes" ; then - echo "CONFIG_XFS=y" >> $config_host_mak -fi -qemu_version=$(head $source_path/VERSION) -echo "PKGVERSION=$pkgversion" >>$config_host_mak -echo "SRC_PATH=$source_path" >> $config_host_mak -echo "TARGET_DIRS=$target_list" >> $config_host_mak -if [ "$docs" = "yes" ] ; then - echo "BUILD_DOCS=yes" >> $config_host_mak -fi -if test "$modules" = "yes"; then - # $shacmd can generate a hash started with digit, which the compiler doesn't - # like as an symbol. So prefix it with an underscore - echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak - echo "CONFIG_MODULES=y" >> $config_host_mak -fi -if test "$module_upgrades" = "yes"; then - echo "CONFIG_MODULE_UPGRADES=y" >> $config_host_mak -fi -if test "$have_x11" = "yes" && test "$need_x11" = "yes"; then - echo "CONFIG_X11=y" >> $config_host_mak - echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak - echo "X11_LIBS=$x11_libs" >> $config_host_mak -fi -if test "$cocoa" = "yes" ; then - echo "CONFIG_COCOA=y" >> $config_host_mak -fi -if test "$iconv" = "yes" ; then - echo "CONFIG_ICONV=y" >> $config_host_mak - echo "ICONV_CFLAGS=$iconv_cflags" >> $config_host_mak - echo "ICONV_LIBS=$iconv_lib" >> $config_host_mak -fi -if test "$curses" = "yes" ; then - echo "CONFIG_CURSES=y" >> $config_host_mak - echo "CURSES_CFLAGS=$curses_inc" >> $config_host_mak - echo "CURSES_LIBS=$curses_lib" >> $config_host_mak -fi -if test "$pipe2" = "yes" ; then - echo "CONFIG_PIPE2=y" >> $config_host_mak -fi -if test "$accept4" = "yes" ; then - echo "CONFIG_ACCEPT4=y" >> $config_host_mak -fi -if test "$splice" = "yes" ; then - echo "CONFIG_SPLICE=y" >> $config_host_mak -fi -if test "$eventfd" = "yes" ; then - echo "CONFIG_EVENTFD=y" >> $config_host_mak -fi -if test "$memfd" = "yes" ; then - echo "CONFIG_MEMFD=y" >> $config_host_mak -fi -if test "$have_usbfs" = "yes" ; then - echo "CONFIG_USBFS=y" >> $config_host_mak -fi -if test "$fallocate" = "yes" ; then - echo "CONFIG_FALLOCATE=y" >> $config_host_mak -fi -if test "$fallocate_punch_hole" = "yes" ; then - echo "CONFIG_FALLOCATE_PUNCH_HOLE=y" >> $config_host_mak -fi -if test "$fallocate_zero_range" = "yes" ; then - echo "CONFIG_FALLOCATE_ZERO_RANGE=y" >> $config_host_mak -fi -if test "$posix_fallocate" = "yes" ; then - echo "CONFIG_POSIX_FALLOCATE=y" >> $config_host_mak -fi -if test "$sync_file_range" = "yes" ; then - echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak -fi -if test "$fiemap" = "yes" ; then - echo "CONFIG_FIEMAP=y" >> $config_host_mak -fi -if test "$dup3" = "yes" ; then - echo "CONFIG_DUP3=y" >> $config_host_mak -fi -if test "$ppoll" = "yes" ; then - echo "CONFIG_PPOLL=y" >> $config_host_mak -fi -if test "$prctl_pr_set_timerslack" = "yes" ; then - echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak -fi -if test "$epoll" = "yes" ; then - echo "CONFIG_EPOLL=y" >> $config_host_mak -fi -if test "$epoll_create1" = "yes" ; then - echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak -fi -if test "$sendfile" = "yes" ; then - echo "CONFIG_SENDFILE=y" >> $config_host_mak -fi -if test "$timerfd" = "yes" ; then - echo "CONFIG_TIMERFD=y" >> $config_host_mak -fi -if test "$setns" = "yes" ; then - echo "CONFIG_SETNS=y" >> $config_host_mak -fi -if test "$clock_adjtime" = "yes" ; then - echo "CONFIG_CLOCK_ADJTIME=y" >> $config_host_mak -fi -if test "$syncfs" = "yes" ; then - echo "CONFIG_SYNCFS=y" >> $config_host_mak -fi -if test "$kcov" = "yes" ; then - echo "CONFIG_KCOV=y" >> $config_host_mak -fi -if test "$inotify" = "yes" ; then - echo "CONFIG_INOTIFY=y" >> $config_host_mak -fi -if test "$inotify1" = "yes" ; then - echo "CONFIG_INOTIFY1=y" >> $config_host_mak -fi -if test "$sem_timedwait" = "yes" ; then - echo "CONFIG_SEM_TIMEDWAIT=y" >> $config_host_mak -fi -if test "$strchrnul" = "yes" ; then - echo "HAVE_STRCHRNUL=y" >> $config_host_mak -fi -if test "$st_atim" = "yes" ; then - echo "HAVE_STRUCT_STAT_ST_ATIM=y" >> $config_host_mak -fi -if test "$byteswap_h" = "yes" ; then - echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak -fi -if test "$bswap_h" = "yes" ; then - echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak -fi -if test "$curl" = "yes" ; then - echo "CONFIG_CURL=y" >> $config_host_mak - echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak - echo "CURL_LIBS=$curl_libs" >> $config_host_mak -fi -if test "$brlapi" = "yes" ; then - echo "CONFIG_BRLAPI=y" >> $config_host_mak - echo "BRLAPI_LIBS=$brlapi_libs" >> $config_host_mak -fi -if test "$gtk" = "yes" ; then - echo "CONFIG_GTK=y" >> $config_host_mak - echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak - echo "GTK_LIBS=$gtk_libs" >> $config_host_mak - if test "$gtk_gl" = "yes" ; then - echo "CONFIG_GTK_GL=y" >> $config_host_mak - fi -fi -if test "$gio" = "yes" ; then - echo "CONFIG_GIO=y" >> $config_host_mak - echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak - echo "GIO_LIBS=$gio_libs" >> $config_host_mak - echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak -fi -echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak -if test "$gnutls" = "yes" ; then - echo "CONFIG_GNUTLS=y" >> $config_host_mak - echo "GNUTLS_CFLAGS=$gnutls_cflags" >> $config_host_mak - echo "GNUTLS_LIBS=$gnutls_libs" >> $config_host_mak -fi -if test "$gcrypt" = "yes" ; then - echo "CONFIG_GCRYPT=y" >> $config_host_mak - if test "$gcrypt_hmac" = "yes" ; then - echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak - fi -fi -if test "$nettle" = "yes" ; then - echo "CONFIG_NETTLE=y" >> $config_host_mak - echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak - echo "NETTLE_CFLAGS=$nettle_cflags" >> $config_host_mak - echo "NETTLE_LIBS=$nettle_libs" >> $config_host_mak -fi -if test "$qemu_private_xts" = "yes" ; then - echo "CONFIG_QEMU_PRIVATE_XTS=y" >> $config_host_mak -fi -if test "$tasn1" = "yes" ; then - echo "CONFIG_TASN1=y" >> $config_host_mak -fi -if test "$auth_pam" = "yes" ; then - echo "CONFIG_AUTH_PAM=y" >> $config_host_mak -fi -if test "$have_ifaddrs_h" = "yes" ; then - echo "HAVE_IFADDRS_H=y" >> $config_host_mak -fi -if test "$have_drm_h" = "yes" ; then - echo "HAVE_DRM_H=y" >> $config_host_mak -fi -if test "$have_broken_size_max" = "yes" ; then - echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak -fi -if test "$have_openpty" = "yes" ; then - echo "HAVE_OPENPTY=y" >> $config_host_mak -fi -if test "$have_sys_signal_h" = "yes" ; then - echo "HAVE_SYS_SIGNAL_H=y" >> $config_host_mak -fi - -# Work around a system header bug with some kernel/XFS header -# versions where they both try to define 'struct fsxattr': -# xfs headers will not try to redefine structs from linux headers -# if this macro is set. -if test "$have_fsxattr" = "yes" ; then - echo "HAVE_FSXATTR=y" >> $config_host_mak -fi -if test "$have_copy_file_range" = "yes" ; then - echo "HAVE_COPY_FILE_RANGE=y" >> $config_host_mak -fi -if test "$vte" = "yes" ; then - echo "CONFIG_VTE=y" >> $config_host_mak - echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak - echo "VTE_LIBS=$vte_libs" >> $config_host_mak -fi -if test "$virglrenderer" = "yes" ; then - echo "CONFIG_VIRGL=y" >> $config_host_mak - echo "VIRGL_CFLAGS=$virgl_cflags" >> $config_host_mak - echo "VIRGL_LIBS=$virgl_libs" >> $config_host_mak -fi -if test "$xen" = "yes" ; then - echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak - echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak - echo "XEN_CFLAGS=$xen_cflags" >> $config_host_mak - echo "XEN_LIBS=$xen_libs" >> $config_host_mak -fi -if test "$linux_aio" = "yes" ; then - echo "CONFIG_LINUX_AIO=y" >> $config_host_mak -fi -if test "$linux_io_uring" = "yes" ; then - echo "CONFIG_LINUX_IO_URING=y" >> $config_host_mak - echo "LINUX_IO_URING_CFLAGS=$linux_io_uring_cflags" >> $config_host_mak - echo "LINUX_IO_URING_LIBS=$linux_io_uring_libs" >> $config_host_mak -fi -if test "$attr" = "yes" ; then - echo "CONFIG_ATTR=y" >> $config_host_mak - echo "LIBATTR_LIBS=$libattr_libs" >> $config_host_mak -fi -if test "$libattr" = "yes" ; then - echo "CONFIG_LIBATTR=y" >> $config_host_mak -fi -if test "$virtfs" = "yes" ; then - echo "CONFIG_VIRTFS=y" >> $config_host_mak -fi -if test "$mpath" = "yes" ; then - echo "CONFIG_MPATH=y" >> $config_host_mak - if test "$mpathpersist_new_api" = "yes"; then - echo "CONFIG_MPATH_NEW_API=y" >> $config_host_mak - fi -fi -if test "$vhost_scsi" = "yes" ; then - echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak -fi -if test "$vhost_net" = "yes" ; then - echo "CONFIG_VHOST_NET=y" >> $config_host_mak -fi -if test "$vhost_net_user" = "yes" ; then - echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak -fi -if test "$vhost_net_vdpa" = "yes" ; then - echo "CONFIG_VHOST_NET_VDPA=y" >> $config_host_mak -fi -if test "$vhost_crypto" = "yes" ; then - echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak -fi -if test "$vhost_vsock" = "yes" ; then - echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak - if test "$vhost_user" = "yes" ; then - echo "CONFIG_VHOST_USER_VSOCK=y" >> $config_host_mak - fi -fi -if test "$vhost_kernel" = "yes" ; then - echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak -fi -if test "$vhost_user" = "yes" ; then - echo "CONFIG_VHOST_USER=y" >> $config_host_mak -fi -if test "$vhost_vdpa" = "yes" ; then - echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak -fi -if test "$vhost_user_fs" = "yes" ; then - echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak -fi -if test "$blobs" = "yes" ; then - echo "INSTALL_BLOBS=yes" >> $config_host_mak -fi -if test "$iovec" = "yes" ; then - echo "CONFIG_IOVEC=y" >> $config_host_mak -fi -if test "$preadv" = "yes" ; then - echo "CONFIG_PREADV=y" >> $config_host_mak -fi -if test "$fdt" != "no" ; then - echo "CONFIG_FDT=y" >> $config_host_mak - echo "FDT_CFLAGS=$fdt_cflags" >> $config_host_mak - echo "FDT_LIBS=$fdt_ldflags $fdt_libs" >> $config_host_mak -fi -if test "$membarrier" = "yes" ; then - echo "CONFIG_MEMBARRIER=y" >> $config_host_mak -fi -if test "$signalfd" = "yes" ; then - echo "CONFIG_SIGNALFD=y" >> $config_host_mak -fi -if test "$optreset" = "yes" ; then - echo "HAVE_OPTRESET=y" >> $config_host_mak -fi -if test "$tcg" = "yes"; then - echo "CONFIG_TCG=y" >> $config_host_mak - if test "$tcg_interpreter" = "yes" ; then - echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak - fi -fi -if test "$fdatasync" = "yes" ; then - echo "CONFIG_FDATASYNC=y" >> $config_host_mak -fi -if test "$madvise" = "yes" ; then - echo "CONFIG_MADVISE=y" >> $config_host_mak -fi -if test "$posix_madvise" = "yes" ; then - echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak -fi -if test "$posix_memalign" = "yes" ; then - echo "CONFIG_POSIX_MEMALIGN=y" >> $config_host_mak -fi -if test "$spice" = "yes" ; then - echo "CONFIG_SPICE=y" >> $config_host_mak - echo "SPICE_CFLAGS=$spice_cflags" >> $config_host_mak - echo "SPICE_LIBS=$spice_libs" >> $config_host_mak -fi - -if test "$smartcard" = "yes" ; then - echo "CONFIG_SMARTCARD=y" >> $config_host_mak - echo "SMARTCARD_CFLAGS=$libcacard_cflags" >> $config_host_mak - echo "SMARTCARD_LIBS=$libcacard_libs" >> $config_host_mak -fi - -if test "$libusb" = "yes" ; then - echo "CONFIG_USB_LIBUSB=y" >> $config_host_mak - echo "LIBUSB_CFLAGS=$libusb_cflags" >> $config_host_mak - echo "LIBUSB_LIBS=$libusb_libs" >> $config_host_mak -fi - -if test "$usb_redir" = "yes" ; then - echo "CONFIG_USB_REDIR=y" >> $config_host_mak - echo "USB_REDIR_CFLAGS=$usb_redir_cflags" >> $config_host_mak - echo "USB_REDIR_LIBS=$usb_redir_libs" >> $config_host_mak -fi - -if test "$opengl" = "yes" ; then - echo "CONFIG_OPENGL=y" >> $config_host_mak - echo "OPENGL_LIBS=$opengl_libs" >> $config_host_mak - if test "$opengl_dmabuf" = "yes" ; then - echo "CONFIG_OPENGL_DMABUF=y" >> $config_host_mak - fi -fi - -if test "$gbm" = "yes" ; then - echo "CONFIG_GBM=y" >> $config_host_mak - echo "GBM_LIBS=$gbm_libs" >> $config_host_mak - echo "GBM_CFLAGS=$gbm_cflags" >> $config_host_mak -fi - - -if test "$malloc_trim" = "yes" ; then - echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak -fi - -if test "$avx2_opt" = "yes" ; then - echo "CONFIG_AVX2_OPT=y" >> $config_host_mak -fi - -if test "$avx512f_opt" = "yes" ; then - echo "CONFIG_AVX512F_OPT=y" >> $config_host_mak -fi - -if test "$lzo" = "yes" ; then - echo "CONFIG_LZO=y" >> $config_host_mak - echo "LZO_LIBS=$lzo_libs" >> $config_host_mak -fi - -if test "$snappy" = "yes" ; then - echo "CONFIG_SNAPPY=y" >> $config_host_mak - echo "SNAPPY_LIBS=$snappy_libs" >> $config_host_mak -fi - -if test "$bzip2" = "yes" ; then - echo "CONFIG_BZIP2=y" >> $config_host_mak - echo "BZIP2_LIBS=-lbz2" >> $config_host_mak -fi - -if test "$lzfse" = "yes" ; then - echo "CONFIG_LZFSE=y" >> $config_host_mak - echo "LZFSE_LIBS=-llzfse" >> $config_host_mak -fi - -if test "$zstd" = "yes" ; then - echo "CONFIG_ZSTD=y" >> $config_host_mak - echo "ZSTD_CFLAGS=$zstd_cflags" >> $config_host_mak - echo "ZSTD_LIBS=$zstd_libs" >> $config_host_mak -fi - -if test "$libiscsi" = "yes" ; then - echo "CONFIG_LIBISCSI=y" >> $config_host_mak - echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak - echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak -fi - -if test "$libnfs" = "yes" ; then - echo "CONFIG_LIBNFS=y" >> $config_host_mak - echo "LIBNFS_LIBS=$libnfs_libs" >> $config_host_mak -fi - -if test "$seccomp" = "yes"; then - echo "CONFIG_SECCOMP=y" >> $config_host_mak - echo "SECCOMP_CFLAGS=$seccomp_cflags" >> $config_host_mak - echo "SECCOMP_LIBS=$seccomp_libs" >> $config_host_mak -fi - -# XXX: suppress that -if [ "$bsd" = "yes" ] ; then - echo "CONFIG_BSD=y" >> $config_host_mak -fi - -if test "$localtime_r" = "yes" ; then - echo "CONFIG_LOCALTIME_R=y" >> $config_host_mak -fi -if test "$qom_cast_debug" = "yes" ; then - echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak -fi -if test "$rbd" = "yes" ; then - echo "CONFIG_RBD=y" >> $config_host_mak - echo "RBD_LIBS=$rbd_libs" >> $config_host_mak -fi - -echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak -if test "$coroutine_pool" = "yes" ; then - echo "CONFIG_COROUTINE_POOL=1" >> $config_host_mak -else - echo "CONFIG_COROUTINE_POOL=0" >> $config_host_mak -fi - -if test "$debug_stack_usage" = "yes" ; then - echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak -fi - -if test "$crypto_afalg" = "yes" ; then - echo "CONFIG_AF_ALG=y" >> $config_host_mak -fi - -if test "$open_by_handle_at" = "yes" ; then - echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak -fi - -if test "$linux_magic_h" = "yes" ; then - echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak -fi - -if test "$valgrind_h" = "yes" ; then - echo "CONFIG_VALGRIND_H=y" >> $config_host_mak -fi - -if test "$have_asan_iface_fiber" = "yes" ; then - echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak -fi - -if test "$have_tsan" = "yes" && test "$have_tsan_iface_fiber" = "yes" ; then - echo "CONFIG_TSAN=y" >> $config_host_mak -fi - -if test "$has_environ" = "yes" ; then - echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak -fi - -if test "$cpuid_h" = "yes" ; then - echo "CONFIG_CPUID_H=y" >> $config_host_mak -fi - -if test "$int128" = "yes" ; then - echo "CONFIG_INT128=y" >> $config_host_mak -fi - -if test "$atomic128" = "yes" ; then - echo "CONFIG_ATOMIC128=y" >> $config_host_mak -fi - -if test "$cmpxchg128" = "yes" ; then - echo "CONFIG_CMPXCHG128=y" >> $config_host_mak -fi - -if test "$atomic64" = "yes" ; then - echo "CONFIG_ATOMIC64=y" >> $config_host_mak -fi - -if test "$attralias" = "yes" ; then - echo "CONFIG_ATTRIBUTE_ALIAS=y" >> $config_host_mak -fi - -if test "$getauxval" = "yes" ; then - echo "CONFIG_GETAUXVAL=y" >> $config_host_mak -fi - -if test "$glusterfs" = "yes" ; then - echo "CONFIG_GLUSTERFS=y" >> $config_host_mak - echo "GLUSTERFS_CFLAGS=$glusterfs_cflags" >> $config_host_mak - echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak -fi - -if test "$glusterfs_xlator_opt" = "yes" ; then - echo "CONFIG_GLUSTERFS_XLATOR_OPT=y" >> $config_host_mak -fi - -if test "$glusterfs_discard" = "yes" ; then - echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak -fi - -if test "$glusterfs_fallocate" = "yes" ; then - echo "CONFIG_GLUSTERFS_FALLOCATE=y" >> $config_host_mak -fi - -if test "$glusterfs_zerofill" = "yes" ; then - echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak -fi - -if test "$glusterfs_ftruncate_has_stat" = "yes" ; then - echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak -fi - -if test "$glusterfs_iocb_has_stat" = "yes" ; then - echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak -fi - -if test "$libssh" = "yes" ; then - echo "CONFIG_LIBSSH=y" >> $config_host_mak - echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak - echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak -fi - -if test "$live_block_migration" = "yes" ; then - echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak -fi - -if test "$tpm" = "yes"; then - echo 'CONFIG_TPM=y' >> $config_host_mak -fi - -echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak -if have_backend "nop"; then - echo "CONFIG_TRACE_NOP=y" >> $config_host_mak -fi -if have_backend "simple"; then - echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak - # Set the appropriate trace file. - trace_file="\"$trace_file-\" FMT_pid" -fi -if have_backend "log"; then - echo "CONFIG_TRACE_LOG=y" >> $config_host_mak -fi -if have_backend "ust"; then - echo "CONFIG_TRACE_UST=y" >> $config_host_mak - echo "LTTNG_UST_LIBS=$lttng_ust_libs" >> $config_host_mak - echo "URCU_BP_LIBS=$urcu_bp_libs" >> $config_host_mak -fi -if have_backend "dtrace"; then - echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak - if test "$trace_backend_stap" = "yes" ; then - echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak - fi -fi -if have_backend "ftrace"; then - if test "$linux" = "yes" ; then - echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak - else - feature_not_found "ftrace(trace backend)" "ftrace requires Linux" - fi -fi -if have_backend "syslog"; then - if test "$posix_syslog" = "yes" ; then - echo "CONFIG_TRACE_SYSLOG=y" >> $config_host_mak - else - feature_not_found "syslog(trace backend)" "syslog not available" - fi -fi -echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak - -if test "$rdma" = "yes" ; then - echo "CONFIG_RDMA=y" >> $config_host_mak - echo "RDMA_LIBS=$rdma_libs" >> $config_host_mak -fi - -if test "$pvrdma" = "yes" ; then - echo "CONFIG_PVRDMA=y" >> $config_host_mak -fi - -if test "$have_rtnetlink" = "yes" ; then - echo "CONFIG_RTNETLINK=y" >> $config_host_mak -fi - -if test "$libxml2" = "yes" ; then - echo "CONFIG_LIBXML2=y" >> $config_host_mak - echo "LIBXML2_CFLAGS=$libxml2_cflags" >> $config_host_mak - echo "LIBXML2_LIBS=$libxml2_libs" >> $config_host_mak -fi - -if test "$replication" = "yes" ; then - echo "CONFIG_REPLICATION=y" >> $config_host_mak -fi - -if test "$have_af_vsock" = "yes" ; then - echo "CONFIG_AF_VSOCK=y" >> $config_host_mak -fi - -if test "$have_sysmacros" = "yes" ; then - echo "CONFIG_SYSMACROS=y" >> $config_host_mak -fi - -if test "$have_static_assert" = "yes" ; then - echo "CONFIG_STATIC_ASSERT=y" >> $config_host_mak -fi - -if test "$have_utmpx" = "yes" ; then - echo "HAVE_UTMPX=y" >> $config_host_mak -fi -if test "$have_getrandom" = "yes" ; then - echo "CONFIG_GETRANDOM=y" >> $config_host_mak -fi -if test "$ivshmem" = "yes" ; then - echo "CONFIG_IVSHMEM=y" >> $config_host_mak -fi -if test "$capstone" != "no" ; then - echo "CONFIG_CAPSTONE=y" >> $config_host_mak - echo "CAPSTONE_CFLAGS=$capstone_cflags" >> $config_host_mak - echo "CAPSTONE_LIBS=$capstone_libs" >> $config_host_mak -fi -if test "$debug_mutex" = "yes" ; then - echo "CONFIG_DEBUG_MUTEX=y" >> $config_host_mak -fi - -# Hold two types of flag: -# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on -# a thread we have a handle to -# CONFIG_PTHREAD_SETNAME_NP_W_TID - A way of doing it on a particular -# platform -if test "$pthread_setname_np_w_tid" = "yes" ; then - echo "CONFIG_THREAD_SETNAME_BYTHREAD=y" >> $config_host_mak - echo "CONFIG_PTHREAD_SETNAME_NP_W_TID=y" >> $config_host_mak -elif test "$pthread_setname_np_wo_tid" = "yes" ; then - echo "CONFIG_THREAD_SETNAME_BYTHREAD=y" >> $config_host_mak - echo "CONFIG_PTHREAD_SETNAME_NP_WO_TID=y" >> $config_host_mak -fi - -if test "$libpmem" = "yes" ; then - echo "CONFIG_LIBPMEM=y" >> $config_host_mak - echo "LIBPMEM_LIBS=$libpmem_libs" >> $config_host_mak - echo "LIBPMEM_CFLAGS=$libpmem_cflags" >> $config_host_mak -fi - -if test "$libdaxctl" = "yes" ; then - echo "CONFIG_LIBDAXCTL=y" >> $config_host_mak - echo "LIBDAXCTL_LIBS=$libdaxctl_libs" >> $config_host_mak -fi - -if test "$bochs" = "yes" ; then - echo "CONFIG_BOCHS=y" >> $config_host_mak -fi -if test "$cloop" = "yes" ; then - echo "CONFIG_CLOOP=y" >> $config_host_mak -fi -if test "$dmg" = "yes" ; then - echo "CONFIG_DMG=y" >> $config_host_mak -fi -if test "$qcow1" = "yes" ; then - echo "CONFIG_QCOW1=y" >> $config_host_mak -fi -if test "$vdi" = "yes" ; then - echo "CONFIG_VDI=y" >> $config_host_mak -fi -if test "$vvfat" = "yes" ; then - echo "CONFIG_VVFAT=y" >> $config_host_mak -fi -if test "$qed" = "yes" ; then - echo "CONFIG_QED=y" >> $config_host_mak -fi -if test "$parallels" = "yes" ; then - echo "CONFIG_PARALLELS=y" >> $config_host_mak -fi -if test "$sheepdog" = "yes" ; then - echo "CONFIG_SHEEPDOG=y" >> $config_host_mak -fi -if test "$pty_h" = "yes" ; then - echo "HAVE_PTY_H=y" >> $config_host_mak -fi -if test "$have_mlockall" = "yes" ; then - echo "HAVE_MLOCKALL=y" >> $config_host_mak -fi -if test "$fuzzing" = "yes" ; then - QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer-no-link" -fi - -if test "$plugins" = "yes" ; then - echo "CONFIG_PLUGIN=y" >> $config_host_mak - LIBS="-ldl $LIBS" - # Copy the export object list to the build dir - if test "$ld_dynamic_list" = "yes" ; then - echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak - ld_symbols=qemu-plugins-ld.symbols - cp "$source_path/plugins/qemu-plugins.symbols" $ld_symbols - elif test "$ld_exported_symbols_list" = "yes" ; then - echo "CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST=yes" >> $config_host_mak - ld64_symbols=qemu-plugins-ld64.symbols - echo "# Automatically generated by configure - do not modify" > $ld64_symbols - grep 'qemu_' "$source_path/plugins/qemu-plugins.symbols" | sed 's/;//g' | \ - sed -E 's/^[[:space:]]*(.*)/_\1/' >> $ld64_symbols - else - error_exit \ - "If \$plugins=yes, either \$ld_dynamic_list or " \ - "\$ld_exported_symbols_list should have been set to 'yes'." - fi -fi - -if test -n "$gdb_bin" ; then - echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak -fi - -if test "$secret_keyring" = "yes" ; then - echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak - if test "$have_keyutils" = "yes" ; then - echo "CONFIG_TEST_SECRET_KEYRING=y" >> $config_host_mak - fi -fi - -if test "$tcg_interpreter" = "yes"; then - QEMU_INCLUDES="-iquote ${source_path}/tcg/tci $QEMU_INCLUDES" -elif test "$ARCH" = "sparc64" ; then - QEMU_INCLUDES="-iquote ${source_path}/tcg/sparc $QEMU_INCLUDES" -elif test "$ARCH" = "s390x" ; then - QEMU_INCLUDES="-iquote ${source_path}/tcg/s390 $QEMU_INCLUDES" -elif test "$ARCH" = "x86_64" || test "$ARCH" = "x32" ; then - QEMU_INCLUDES="-iquote ${source_path}/tcg/i386 $QEMU_INCLUDES" -elif test "$ARCH" = "ppc64" ; then - QEMU_INCLUDES="-iquote ${source_path}/tcg/ppc $QEMU_INCLUDES" -elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then - QEMU_INCLUDES="-I${source_path}/tcg/riscv $QEMU_INCLUDES" -else - QEMU_INCLUDES="-iquote ${source_path}/tcg/${ARCH} $QEMU_INCLUDES" -fi - -echo "ROMS=$roms" >> $config_host_mak -echo "MAKE=$make" >> $config_host_mak -echo "INSTALL=$install" >> $config_host_mak -echo "INSTALL_DIR=$install -d -m 0755" >> $config_host_mak -echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak -echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak -echo "INSTALL_LIB=$install -c -m 0644" >> $config_host_mak -echo "PYTHON=$python" >> $config_host_mak -echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak -echo "GENISOIMAGE=$genisoimage" >> $config_host_mak -echo "MESON=$meson" >> $config_host_mak -echo "CC=$cc" >> $config_host_mak -if $iasl -h > /dev/null 2>&1; then - echo "CONFIG_IASL=$iasl" >> $config_host_mak -fi -echo "CXX=$cxx" >> $config_host_mak -echo "OBJCC=$objcc" >> $config_host_mak -echo "AR=$ar" >> $config_host_mak -echo "ARFLAGS=$ARFLAGS" >> $config_host_mak -echo "AS=$as" >> $config_host_mak -echo "CCAS=$ccas" >> $config_host_mak -echo "CPP=$cpp" >> $config_host_mak -echo "OBJCOPY=$objcopy" >> $config_host_mak -echo "LD=$ld" >> $config_host_mak -echo "RANLIB=$ranlib" >> $config_host_mak -echo "NM=$nm" >> $config_host_mak -echo "PKG_CONFIG=$pkg_config_exe" >> $config_host_mak -echo "WINDRES=$windres" >> $config_host_mak -echo "CFLAGS=$CFLAGS" >> $config_host_mak -echo "CXXFLAGS=$CXXFLAGS" >> $config_host_mak -echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak -echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak -echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak -echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak -echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak -echo "GLIB_LIBS=$glib_libs" >> $config_host_mak -if test "$sparse" = "yes" ; then - echo "SPARSE_CFLAGS = -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak -fi -echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak -echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak -echo "LD_REL_FLAGS=$LD_REL_FLAGS" >> $config_host_mak -echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak -echo "LIBS+=$LIBS" >> $config_host_mak -echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak -echo "PTHREAD_LIB=$PTHREAD_LIB" >> $config_host_mak -echo "EXESUF=$EXESUF" >> $config_host_mak -echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak -echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak -echo "LIBS_QGA=$libs_qga" >> $config_host_mak -echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak -echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak -echo "POD2MAN=$POD2MAN" >> $config_host_mak -if test "$gcov" = "yes" ; then - echo "CONFIG_GCOV=y" >> $config_host_mak -fi - -if test "$libudev" != "no"; then - echo "CONFIG_LIBUDEV=y" >> $config_host_mak - echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak -fi -if test "$fuzzing" != "no"; then - echo "CONFIG_FUZZ=y" >> $config_host_mak -fi - -if test "$edk2_blobs" = "yes" ; then - echo "DECOMPRESS_EDK2_BLOBS=y" >> $config_host_mak -fi - -if test "$rng_none" = "yes"; then - echo "CONFIG_RNG_NONE=y" >> $config_host_mak -fi - -# use included Linux headers -if test "$linux" = "yes" ; then - mkdir -p linux-headers - case "$cpu" in - i386|x86_64|x32) - linux_arch=x86 - ;; - ppc|ppc64|ppc64le) - linux_arch=powerpc - ;; - s390x) - linux_arch=s390 - ;; - aarch64) - linux_arch=arm64 - ;; - mips64) - linux_arch=mips - ;; - *) - # For most CPUs the kernel architecture name and QEMU CPU name match. - linux_arch="$cpu" - ;; - esac - # For non-KVM architectures we will not have asm headers - if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then - symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm - fi -fi - -for target in $target_list; do -target_dir="$target" -config_target_mak=$target_dir/config-target.mak -target_name=$(echo $target | cut -d '-' -f 1) -target_aligned_only="no" -case "$target_name" in - alpha|hppa|mips64el|mips64|mipsel|mips|mipsn32|mipsn32el|sh4|sh4eb|sparc|sparc64|sparc32plus|xtensa|xtensaeb) - target_aligned_only="yes" - ;; -esac -target_bigendian="no" -case "$target_name" in - armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb) - target_bigendian="yes" - ;; -esac -target_softmmu="no" -target_user_only="no" -target_linux_user="no" -target_bsd_user="no" -case "$target" in - ${target_name}-softmmu) - target_softmmu="yes" - ;; - ${target_name}-linux-user) - target_user_only="yes" - target_linux_user="yes" - ;; - ${target_name}-bsd-user) - target_user_only="yes" - target_bsd_user="yes" - ;; - *) - error_exit "Target '$target' not recognised" - exit 1 - ;; -esac - -mkdir -p $target_dir -echo "# Automatically generated by configure - do not modify" > $config_target_mak - -bflt="no" -mttcg="no" -interp_prefix1=$(echo "$interp_prefix" | sed "s/%M/$target_name/g") -gdb_xml_files="" - -TARGET_ARCH="$target_name" -TARGET_BASE_ARCH="" -TARGET_ABI_DIR="" -TARGET_SYSTBL_ABI="" -TARGET_SYSTBL="" - -case "$target_name" in - i386) - mttcg="yes" - gdb_xml_files="i386-32bit.xml" - TARGET_SYSTBL_ABI=i386 - TARGET_SYSTBL=syscall_32.tbl - ;; - x86_64) - TARGET_BASE_ARCH=i386 - TARGET_SYSTBL_ABI=common,64 - TARGET_SYSTBL=syscall_64.tbl - mttcg="yes" - gdb_xml_files="i386-64bit.xml" - ;; - alpha) - mttcg="yes" - TARGET_SYSTBL_ABI=common - ;; - arm|armeb) - TARGET_ARCH=arm - TARGET_SYSTBL_ABI=common,oabi - bflt="yes" - mttcg="yes" - gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" - ;; - aarch64|aarch64_be) - TARGET_ARCH=aarch64 - TARGET_BASE_ARCH=arm - bflt="yes" - mttcg="yes" - gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" - ;; - avr) - gdb_xml_files="avr-cpu.xml" - target_compiler=$cross_cc_avr - ;; - cris) - ;; - hppa) - mttcg="yes" - TARGET_SYSTBL_ABI=common,32 - ;; - lm32) - ;; - m68k) - bflt="yes" - gdb_xml_files="cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml" - TARGET_SYSTBL_ABI=common - ;; - microblaze|microblazeel) - TARGET_ARCH=microblaze - TARGET_SYSTBL_ABI=common - mttcg="yes" - bflt="yes" - echo "TARGET_ABI32=y" >> $config_target_mak - ;; - mips|mipsel) - mttcg="yes" - TARGET_ARCH=mips - echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak - TARGET_SYSTBL_ABI=o32 - TARGET_SYSTBL=syscall_o32.tbl - ;; - mipsn32|mipsn32el) - mttcg="yes" - TARGET_ARCH=mips64 - TARGET_BASE_ARCH=mips - echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak - echo "TARGET_ABI32=y" >> $config_target_mak - TARGET_SYSTBL_ABI=n32 - TARGET_SYSTBL=syscall_n32.tbl - ;; - mips64|mips64el) - mttcg="no" - TARGET_ARCH=mips64 - TARGET_BASE_ARCH=mips - echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak - TARGET_SYSTBL_ABI=n64 - TARGET_SYSTBL=syscall_n64.tbl - ;; - moxie) - ;; - nios2) - ;; - or1k) - TARGET_ARCH=openrisc - TARGET_BASE_ARCH=openrisc - ;; - ppc) - gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - TARGET_SYSTBL_ABI=common,nospu,32 - ;; - ppc64) - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,64 - mttcg=yes - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - ppc64le) - TARGET_ARCH=ppc64 - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,64 - mttcg=yes - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - ppc64abi32) - TARGET_ARCH=ppc64 - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,32 - echo "TARGET_ABI32=y" >> $config_target_mak - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - riscv32) - TARGET_BASE_ARCH=riscv - TARGET_ABI_DIR=riscv - mttcg=yes - gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-csr.xml riscv-32bit-virtual.xml" - ;; - riscv64) - TARGET_BASE_ARCH=riscv - TARGET_ABI_DIR=riscv - mttcg=yes - gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml" - ;; - rx) - TARGET_ARCH=rx - bflt="yes" - target_compiler=$cross_cc_rx - gdb_xml_files="rx-core.xml" - ;; - sh4|sh4eb) - TARGET_ARCH=sh4 - TARGET_SYSTBL_ABI=common - bflt="yes" - ;; - sparc) - TARGET_SYSTBL_ABI=common,32 - ;; - sparc64) - TARGET_BASE_ARCH=sparc - TARGET_SYSTBL_ABI=common,64 - ;; - sparc32plus) - TARGET_ARCH=sparc64 - TARGET_BASE_ARCH=sparc - TARGET_ABI_DIR=sparc - TARGET_SYSTBL_ABI=common,32 - echo "TARGET_ABI32=y" >> $config_target_mak - ;; - s390x) - TARGET_SYSTBL_ABI=common,64 - mttcg=yes - gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml s390-gs.xml" - ;; - tilegx) - ;; - tricore) - ;; - unicore32) - ;; - xtensa|xtensaeb) - TARGET_ARCH=xtensa - TARGET_SYSTBL_ABI=common - bflt="yes" - mttcg="yes" - ;; - *) - error_exit "Unsupported target CPU" - ;; -esac -# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH -if [ "$TARGET_BASE_ARCH" = "" ]; then - TARGET_BASE_ARCH=$TARGET_ARCH -fi -if [ "$TARGET_SYSTBL_ABI" != "" ] && [ "$TARGET_SYSTBL" = "" ]; then - TARGET_SYSTBL=syscall.tbl -fi - -upper() { - echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' -} - -target_arch_name="$(upper $TARGET_ARCH)" -echo "TARGET_$target_arch_name=y" >> $config_target_mak -echo "TARGET_NAME=$target_name" >> $config_target_mak -echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak -if [ "$TARGET_ABI_DIR" = "" ]; then - TARGET_ABI_DIR=$TARGET_ARCH -fi -echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak -if [ "$HOST_VARIANT_DIR" != "" ]; then - echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak -fi -if [ "$TARGET_SYSTBL_ABI" != "" ]; then - echo "TARGET_SYSTBL_ABI=$TARGET_SYSTBL_ABI" >> $config_target_mak - echo "TARGET_SYSTBL=$TARGET_SYSTBL" >> $config_target_mak -fi - -if supported_xen_target $target; then - echo "CONFIG_XEN=y" >> $config_target_mak - if test "$xen_pci_passthrough" = yes; then - echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak" - fi -fi -if supported_kvm_target $target; then - echo "CONFIG_KVM=y" >> $config_target_mak -fi -if supported_hax_target $target; then - echo "CONFIG_HAX=y" >> $config_target_mak -fi -if supported_hvf_target $target; then - echo "CONFIG_HVF=y" >> $config_target_mak -fi -if supported_whpx_target $target; then - echo "CONFIG_WHPX=y" >> $config_target_mak -fi -if test "$target_aligned_only" = "yes" ; then - echo "TARGET_ALIGNED_ONLY=y" >> $config_target_mak -fi -if test "$target_bigendian" = "yes" ; then - echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak -fi -if test "$target_softmmu" = "yes" ; then - echo "CONFIG_SOFTMMU=y" >> $config_target_mak - if test "$mttcg" = "yes" ; then - echo "TARGET_SUPPORTS_MTTCG=y" >> $config_target_mak - fi -fi -if test "$target_user_only" = "yes" ; then - echo "CONFIG_USER_ONLY=y" >> $config_target_mak - echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak - symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" -else - symlink "../qemu-system-$target_name" "$target_dir/qemu-system-$target_name" -fi -if test "$target_linux_user" = "yes" ; then - echo "CONFIG_LINUX_USER=y" >> $config_target_mak -fi -list="" -if test ! -z "$gdb_xml_files" ; then - for x in $gdb_xml_files; do - list="$list gdb-xml/$x" - done - echo "TARGET_XML_FILES=$list" >> $config_target_mak -fi - -if test "$target_user_only" = "yes" && test "$bflt" = "yes"; then - echo "TARGET_HAS_BFLT=y" >> $config_target_mak -fi -if test "$target_bsd_user" = "yes" ; then - echo "CONFIG_BSD_USER=y" >> $config_target_mak -fi - - -# generate QEMU_CFLAGS/QEMU_LDFLAGS for targets - -disas_config() { - echo "CONFIG_${1}_DIS=y" >> $config_target_mak - echo "CONFIG_${1}_DIS=y" >> config-all-disas.mak -} - -for i in $ARCH $TARGET_BASE_ARCH ; do - case "$i" in - alpha) - disas_config "ALPHA" - ;; - aarch64) - if test -n "${cxx}"; then - disas_config "ARM_A64" - fi - ;; - arm) - disas_config "ARM" - if test -n "${cxx}"; then - disas_config "ARM_A64" - fi - ;; - avr) - disas_config "AVR" - ;; - cris) - disas_config "CRIS" - ;; - hppa) - disas_config "HPPA" - ;; - i386|x86_64|x32) - disas_config "I386" - ;; - lm32) - disas_config "LM32" - ;; - m68k) - disas_config "M68K" - ;; - microblaze*) - disas_config "MICROBLAZE" - ;; - mips*) - disas_config "MIPS" - if test -n "${cxx}"; then - disas_config "NANOMIPS" - fi - ;; - moxie*) - disas_config "MOXIE" - ;; - nios2) - disas_config "NIOS2" - ;; - or1k) - disas_config "OPENRISC" - ;; - ppc*) - disas_config "PPC" - ;; - riscv*) - disas_config "RISCV" - ;; - rx) - disas_config "RX" - ;; - s390*) - disas_config "S390" - ;; - sh4) - disas_config "SH4" - ;; - sparc*) - disas_config "SPARC" - ;; - xtensa*) - disas_config "XTENSA" - ;; - esac -done -if test "$tcg_interpreter" = "yes" ; then - disas_config "TCI" -fi - -done # for target in $targets - -if [ "$fdt" = "git" ]; then - subdirs="$subdirs dtc" -fi -if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then - subdirs="$subdirs capstone" -fi -echo "SUBDIRS=$subdirs" >> $config_host_mak -if test -n "$LIBCAPSTONE"; then - echo "LIBCAPSTONE=$LIBCAPSTONE" >> $config_host_mak -fi - -if test "$numa" = "yes"; then - echo "CONFIG_NUMA=y" >> $config_host_mak - echo "NUMA_LIBS=$numa_libs" >> $config_host_mak -fi - -if test "$ccache_cpp2" = "yes"; then - echo "export CCACHE_CPP2=y" >> $config_host_mak -fi - -if test "$safe_stack" = "yes"; then - echo "CONFIG_SAFESTACK=y" >> $config_host_mak -fi - -# If we're using a separate build tree, set it up now. -# DIRS are directories which we simply mkdir in the build tree; -# LINKS are things to symlink back into the source tree -# (these can be both files and directories). -# Caution: do not add files or directories here using wildcards. This -# will result in problems later if a new file matching the wildcard is -# added to the source tree -- nothing will cause configure to be rerun -# so the build tree will be missing the link back to the new file, and -# tests might fail. Prefer to keep the relevant files in their own -# directory and symlink the directory instead. -DIRS="tests tests/tcg tests/tcg/lm32 tests/qapi-schema tests/qtest/libqos" -DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph" -DIRS="$DIRS docs docs/interop fsdev scsi" -DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw" -DIRS="$DIRS roms/seabios" -LINKS="Makefile" -LINKS="$LINKS tests/tcg/lm32/Makefile" -LINKS="$LINKS tests/tcg/Makefile.target" -LINKS="$LINKS pc-bios/optionrom/Makefile" -LINKS="$LINKS pc-bios/s390-ccw/Makefile" -LINKS="$LINKS roms/seabios/Makefile" -LINKS="$LINKS pc-bios/qemu-icon.bmp" -LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit -LINKS="$LINKS tests/acceptance tests/data" -LINKS="$LINKS tests/qemu-iotests/check" -LINKS="$LINKS python" -for bios_file in \ - $source_path/pc-bios/*.bin \ - $source_path/pc-bios/*.elf \ - $source_path/pc-bios/*.lid \ - $source_path/pc-bios/*.rom \ - $source_path/pc-bios/*.dtb \ - $source_path/pc-bios/*.img \ - $source_path/pc-bios/openbios-* \ - $source_path/pc-bios/u-boot.* \ - $source_path/pc-bios/edk2-*.fd.bz2 \ - $source_path/pc-bios/palcode-* -do - LINKS="$LINKS pc-bios/$(basename $bios_file)" -done -mkdir -p $DIRS -for f in $LINKS ; do - if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then - symlink "$source_path/$f" "$f" - fi -done - -(for i in $cross_cc_vars; do - export $i -done -export target_list source_path use_containers -$source_path/tests/tcg/configure.sh) - -# temporary config to build submodules -for rom in seabios; do - config_mak=roms/$rom/config.mak - echo "# Automatically generated by configure - do not modify" > $config_mak - echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak - echo "AS=$as" >> $config_mak - echo "CCAS=$ccas" >> $config_mak - echo "CC=$cc" >> $config_mak - echo "BCC=bcc" >> $config_mak - echo "CPP=$cpp" >> $config_mak - echo "OBJCOPY=objcopy" >> $config_mak - echo "IASL=$iasl" >> $config_mak - echo "LD=$ld" >> $config_mak - echo "RANLIB=$ranlib" >> $config_mak -done - -# set up qemu-iotests in this build directory -iotests_common_env="tests/qemu-iotests/common.env" - -echo "# Automatically generated by configure - do not modify" > "$iotests_common_env" -echo >> "$iotests_common_env" -echo "export PYTHON='$python'" >> "$iotests_common_env" - -if test "$skip_meson" = no; then -cross="config-meson.cross.new" -meson_quote() { - echo "['$(echo $* | sed "s/ /','/g")']" -} - -echo "# Automatically generated by configure - do not modify" > $cross -echo "[properties]" >> $cross -test -z "$cxx" && echo "link_language = 'c'" >> $cross -echo "[binaries]" >> $cross -echo "c = $(meson_quote $cc)" >> $cross -test -n "$cxx" && echo "cpp = $(meson_quote $cxx)" >> $cross -echo "ar = $(meson_quote $ar)" >> $cross -echo "nm = $(meson_quote $nm)" >> $cross -echo "pkgconfig = $(meson_quote $pkg_config_exe)" >> $cross -echo "ranlib = $(meson_quote $ranlib)" >> $cross -echo "strip = $(meson_quote $strip)" >> $cross -echo "windres = $(meson_quote $windres)" >> $cross -if test -n "$cross_prefix"; then - cross_arg="--cross-file config-meson.cross" - # Hack: Meson expects an absolute path for the *build* machine - # for the prefix, so add a slash in front of a Windows path that - # includes a drive letter. - # - # See https://github.com/mesonbuild/meson/issues/7577. - echo "[host_machine]" >> $cross - if test "$mingw32" = "yes" ; then - echo "system = 'windows'" >> $cross - case $prefix in - ?:*) pre_prefix=/ ;; - esac - fi - case "$ARCH" in - i386|x86_64) - echo "cpu_family = 'x86'" >> $cross - ;; - ppc64le) - echo "cpu_family = 'ppc64'" >> $cross - ;; - *) - echo "cpu_family = '$ARCH'" >> $cross - ;; - esac - echo "cpu = '$cpu'" >> $cross - if test "$bigendian" = "yes" ; then - echo "endian = 'big'" >> $cross - else - echo "endian = 'little'" >> $cross - fi -else - cross_arg="--native-file config-meson.cross" -fi -mv $cross config-meson.cross - -rm -rf meson-private meson-info meson-logs -NINJA=${ninja:-${build_path}/ninjatool} $meson setup \ - --prefix "${pre_prefix}$prefix" \ - --libdir "${pre_prefix}$libdir" \ - --libexecdir "${pre_prefix}$libexecdir" \ - --bindir "${pre_prefix}$bindir" \ - --includedir "${pre_prefix}$includedir" \ - --datadir "${pre_prefix}$datadir" \ - --mandir "${pre_prefix}$mandir" \ - --sysconfdir "${pre_prefix}$sysconfdir" \ - --localstatedir "${pre_prefix}$local_statedir" \ - -Ddocdir="${pre_prefix}$docdir" \ - -Dqemu_suffix="$qemu_suffix" \ - -Doptimization=$(if test "$debug" = yes; then echo 0; else echo 2; fi) \ - -Ddebug=$(if test "$debug_info" = yes; then echo true; else echo false; fi) \ - -Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \ - -Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \ - -Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \ - -Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \ - -Dsdl=$sdl -Dsdl_image=$sdl_image \ - -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ - -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f\ - $cross_arg \ - "$build_path" "$source_path" - -if test "$?" -ne 0 ; then - error_exit "meson setup failed" -fi -touch ninjatool.stamp -fi - -# Save the configure command line for later reuse. -cat <config.status -#!/bin/sh -# Generated by configure. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. -EOD - -preserve_env() { - envname=$1 - - eval envval=\$$envname - - if test -n "$envval" - then - echo "$envname='$envval'" >> config.status - echo "export $envname" >> config.status - else - echo "unset $envname" >> config.status - fi -} - -# Preserve various env variables that influence what -# features/build target configure will detect -preserve_env AR -preserve_env AS -preserve_env CC -preserve_env CPP -preserve_env CXX -preserve_env INSTALL -preserve_env LD -preserve_env LD_LIBRARY_PATH -preserve_env LIBTOOL -preserve_env MAKE -preserve_env NM -preserve_env OBJCOPY -preserve_env PATH -preserve_env PKG_CONFIG -preserve_env PKG_CONFIG_LIBDIR -preserve_env PKG_CONFIG_PATH -preserve_env PYTHON -preserve_env SDL2_CONFIG -preserve_env SMBD -preserve_env STRIP -preserve_env WINDRES - -printf "exec" >>config.status -for i in "$0" "$@"; do - test "$i" = --skip-meson || printf " '%s'" "$i" >>config.status -done -echo ' "$@"' >>config.status -chmod +x config.status - -rm -r "$TMPDIR1" +#!/bin/sh +# +# qemu configure script (c) 2003 Fabrice Bellard +# + +# Unset some variables known to interfere with behavior of common tools, +# just as autoconf does. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +# Don't allow CCACHE, if present, to use cached results of compile tests! +export CCACHE_RECACHE=yes + +# make source path absolute +source_path=$(cd "$(dirname -- "$0")"; pwd) +build_path=$PWD +if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then +source_path=$(cd "$(dirname -- "$0")"; pwd -W) +build_path=`pwd -W` +fi + +if test "$build_path" = "$source_path" +then + echo "Using './build' as the directory for build output" + + MARKER=build/auto-created-by-configure + + if test -e build + then + if test -f $MARKER + then + rm -rf build + else + echo "ERROR: ./build dir already exists and was not previously created by configure" + exit 1 + fi + fi + + mkdir build + touch $MARKER + + cat > GNUmakefile <<'EOF' +# This file is auto-generated by configure to support in-source tree +# 'make' command invocation + +ifeq ($(MAKECMDGOALS),) +recurse: all +endif + +.NOTPARALLEL: % +%: force + @echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...' + @$(MAKE) -C build -f Makefile $(MAKECMDGOALS) + @if test "$(MAKECMDGOALS)" = "distclean" && \ + test -e build/auto-created-by-configure ; \ + then \ + rm -rf build GNUmakefile ; \ + fi +force: ; +.PHONY: force +GNUmakefile: ; + +EOF + cd build + exec $source_path/configure "$@" +fi + +# Temporary directory used for files created while +# configure runs. Since it is in the build directory +# we can safely blow away any previous version of it +# (and we need not jump through hoops to try to delete +# it when configure exits.) +TMPDIR1="config-temp" +rm -rf "${TMPDIR1}" +mkdir -p "${TMPDIR1}" +if [ $? -ne 0 ]; then + echo "ERROR: failed to create temporary directory" + exit 1 +fi + +TMPB="qemu-conf" +TMPC="${TMPDIR1}/${TMPB}.c" +TMPO="${TMPDIR1}/${TMPB}.o" +TMPCXX="${TMPDIR1}/${TMPB}.cxx" +TMPE="${TMPDIR1}/${TMPB}.exe" +TMPTXT="${TMPDIR1}/${TMPB}.txt" + +rm -f config.log + +# Print a helpful header at the top of config.log +echo "# QEMU configure log $(date)" >> config.log +printf "# Configured with:" >> config.log +printf " '%s'" "$0" "$@" >> config.log +echo >> config.log +echo "#" >> config.log + +print_error() { + (echo + echo "ERROR: $1" + while test -n "$2"; do + echo " $2" + shift + done + echo) >&2 +} + +error_exit() { + print_error "$@" + exit 1 +} + +do_compiler() { + # Run the compiler, capturing its output to the log. First argument + # is compiler binary to execute. + local compiler="$1" + shift + if test -n "$BASH_VERSION"; then eval ' + echo >>config.log " +funcs: ${FUNCNAME[*]} +lines: ${BASH_LINENO[*]}" + '; fi + echo $compiler "$@" >> config.log + $compiler "$@" >> config.log 2>&1 || return $? + # Test passed. If this is an --enable-werror build, rerun + # the test with -Werror and bail out if it fails. This + # makes warning-generating-errors in configure test code + # obvious to developers. + if test "$werror" != "yes"; then + return 0 + fi + # Don't bother rerunning the compile if we were already using -Werror + case "$*" in + *-Werror*) + return 0 + ;; + esac + echo $compiler -Werror "$@" >> config.log + $compiler -Werror "$@" >> config.log 2>&1 && return $? + error_exit "configure test passed without -Werror but failed with -Werror." \ + "This is probably a bug in the configure script. The failing command" \ + "will be at the bottom of config.log." \ + "You can run configure with --disable-werror to bypass this check." +} + +do_cc() { + do_compiler "$cc" "$@" +} + +do_cxx() { + do_compiler "$cxx" "$@" +} + +# Append $2 to the variable named $1, with space separation +add_to() { + eval $1=\${$1:+\"\$$1 \"}\$2 +} + +update_cxxflags() { + # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those + # options which some versions of GCC's C++ compiler complain about + # because they only make sense for C programs. + QEMU_CXXFLAGS="$QEMU_CXXFLAGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS" + CXXFLAGS=$(echo "$CFLAGS" | sed s/-std=gnu99/-std=gnu++11/) + for arg in $QEMU_CFLAGS; do + case $arg in + -Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\ + -Wold-style-declaration|-Wold-style-definition|-Wredundant-decls) + ;; + *) + QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg + ;; + esac + done +} + +compile_object() { + local_cflags="$1" + do_cc $CFLAGS $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC +} + +compile_prog() { + local_cflags="$1" + local_ldflags="$2" + do_cc $CFLAGS $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $QEMU_LDFLAGS $local_ldflags +} + +# symbolically link $1 to $2. Portable version of "ln -sf". +symlink() { + rm -rf "$2" + mkdir -p "$(dirname "$2")" + ln -s "$1" "$2" +} + +# check whether a command is available to this shell (may be either an +# executable or a builtin) +has() { + type "$1" >/dev/null 2>&1 +} + +# search for an executable in PATH +path_of() { + local_command="$1" + local_ifs="$IFS" + local_dir="" + + # pathname has a dir component? + if [ "${local_command#*/}" != "$local_command" ]; then + if [ -x "$local_command" ] && [ ! -d "$local_command" ]; then + echo "$local_command" + return 0 + fi + fi + if [ -z "$local_command" ]; then + return 1 + fi + + IFS=: + for local_dir in $PATH; do + if [ -x "$local_dir/$local_command" ] && [ ! -d "$local_dir/$local_command" ]; then + echo "$local_dir/$local_command" + IFS="${local_ifs:-$(printf ' \t\n')}" + return 0 + fi + done + # not found + IFS="${local_ifs:-$(printf ' \t\n')}" + return 1 +} + +version_ge () { + local_ver1=`echo $1 | tr . ' '` + local_ver2=`echo $2 | tr . ' '` + while true; do + set x $local_ver1 + local_first=${2-0} + # 'shift 2' if $2 is set, or 'shift' if $2 is not set + shift ${2:+2} + local_ver1=$* + set x $local_ver2 + # the second argument finished, the first must be greater or equal + test $# = 1 && return 0 + test $local_first -lt $2 && return 1 + test $local_first -gt $2 && return 0 + shift ${2:+2} + local_ver2=$* + done +} + +have_backend () { + echo "$trace_backends" | grep "$1" >/dev/null +} + +glob() { + eval test -z '"${1#'"$2"'}"' +} + +supported_hax_target() { + test "$hax" = "yes" || return 1 + glob "$1" "*-softmmu" || return 1 + case "${1%-softmmu}" in + i386|x86_64) + return 0 + ;; + esac + return 1 +} + +supported_kvm_target() { + test "$kvm" = "yes" || return 1 + glob "$1" "*-softmmu" || return 1 + case "${1%-softmmu}:$cpu" in + arm:arm | aarch64:aarch64 | \ + i386:i386 | i386:x86_64 | i386:x32 | \ + x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ + mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \ + ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ + s390x:s390x) + return 0 + ;; + esac + return 1 +} + +supported_xen_target() { + test "$xen" = "yes" || return 1 + glob "$1" "*-softmmu" || return 1 + # Only i386 and x86_64 provide the xenpv machine. + case "${1%-softmmu}" in + i386|x86_64) + return 0 + ;; + esac + return 1 +} + +supported_hvf_target() { + test "$hvf" = "yes" || return 1 + glob "$1" "*-softmmu" || return 1 + case "${1%-softmmu}" in + x86_64) + return 0 + ;; + esac + return 1 +} + +supported_whpx_target() { + test "$whpx" = "yes" || return 1 + glob "$1" "*-softmmu" || return 1 + case "${1%-softmmu}" in + i386|x86_64) + return 0 + ;; + esac + return 1 +} + +supported_target() { + case "$1" in + *-softmmu) + ;; + *-linux-user) + if test "$linux" != "yes"; then + print_error "Target '$target' is only available on a Linux host" + return 1 + fi + ;; + *-bsd-user) + if test "$bsd" != "yes"; then + print_error "Target '$target' is only available on a BSD host" + return 1 + fi + ;; + *) + print_error "Invalid target name '$target'" + return 1 + ;; + esac + test "$tcg" = "yes" && return 0 + supported_kvm_target "$1" && return 0 + supported_xen_target "$1" && return 0 + supported_hax_target "$1" && return 0 + supported_hvf_target "$1" && return 0 + supported_whpx_target "$1" && return 0 + print_error "TCG disabled, but hardware accelerator not available for '$target'" + return 1 +} + + +ld_has() { + $ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1 +} + +check_valid_build_path="[[:space:]:]" +if [ "$MSYSTEM" = "MINGW64" -o "$MSYSTEM" = "MINGW32" ]; then +check_valid_build_path="[[:space:]]" +fi + +if printf %s\\n "$source_path" "$build_path" | grep -q "$check_valid_build_path"; +then + error_exit "main directory cannot contain spaces nor colons" +fi + +# default parameters +cpu="" +iasl="iasl" +interp_prefix="/usr/gnemul/qemu-%M" +static="no" +cross_prefix="" +audio_drv_list="" +block_drv_rw_whitelist="" +block_drv_ro_whitelist="" +host_cc="cc" +libs_tools="" +audio_win_int="" +libs_qga="" +debug_info="yes" +stack_protector="" +safe_stack="" +use_containers="yes" +gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb") + +if test -e "$source_path/.git" +then + git_update=yes + git_submodules="ui/keycodemapdb" + git_submodules="$git_submodules tests/fp/berkeley-testfloat-3" + git_submodules="$git_submodules tests/fp/berkeley-softfloat-3" +else + git_update=no + git_submodules="" + + if ! test -f "$source_path/ui/keycodemapdb/README" + then + echo + echo "ERROR: missing file $source_path/ui/keycodemapdb/README" + echo + echo "This is not a GIT checkout but module content appears to" + echo "be missing. Do not use 'git archive' or GitHub download links" + echo "to acquire QEMU source archives. Non-GIT builds are only" + echo "supported with source archives linked from:" + echo + echo " https://www.qemu.org/download/#source" + echo + echo "Developers working with GIT can use scripts/archive-source.sh" + echo "if they need to create valid source archives." + echo + exit 1 + fi +fi +git="git" + +# Don't accept a target_list environment variable. +unset target_list +unset target_list_exclude + +# Default value for a variable defining feature "foo". +# * foo="no" feature will only be used if --enable-foo arg is given +# * foo="" feature will be searched for, and if found, will be used +# unless --disable-foo is given +# * foo="yes" this value will only be set by --enable-foo flag. +# feature will searched for, +# if not found, configure exits with error +# +# Always add --enable-foo and --disable-foo command line args. +# Distributions want to ensure that several features are compiled in, and it +# is impossible without a --enable-foo that exits if a feature is not found. + +brlapi="" +curl="" +curses="" +docs="" +fdt="" +netmap="no" +sdl="auto" +sdl_image="auto" +virtfs="" +mpath="" +vnc="enabled" +sparse="no" +vde="" +vnc_sasl="auto" +vnc_jpeg="auto" +vnc_png="auto" +xkbcommon="auto" +xen="" +xen_ctrl_version="" +xen_pci_passthrough="" +linux_aio="" +linux_io_uring="" +cap_ng="" +attr="" +libattr="" +xfs="" +tcg="yes" +membarrier="" +vhost_net="" +vhost_crypto="" +vhost_scsi="" +vhost_vsock="" +vhost_user="" +vhost_user_fs="" +kvm="no" +hax="no" +hvf="no" +whpx="no" +rdma="" +pvrdma="" +gprof="no" +debug_tcg="no" +debug="no" +sanitizers="no" +tsan="no" +fortify_source="" +strip_opt="yes" +tcg_interpreter="no" +bigendian="no" +mingw32="no" +gcov="no" +EXESUF="" +HOST_DSOSUF=".so" +LDFLAGS_SHARED="-shared" +modules="no" +module_upgrades="no" +prefix="/usr/local" +qemu_suffix="qemu" +slirp="" +oss_lib="" +bsd="no" +linux="no" +solaris="no" +profiler="no" +cocoa="no" +softmmu="yes" +linux_user="no" +bsd_user="no" +blobs="yes" +edk2_blobs="no" +pkgversion="" +pie="" +qom_cast_debug="yes" +trace_backends="log" +trace_file="trace" +spice="" +rbd="" +smartcard="" +u2f="auto" +libusb="" +usb_redir="" +opengl="" +opengl_dmabuf="no" +cpuid_h="no" +avx2_opt="" +capstone="" +lzo="" +snappy="" +bzip2="" +lzfse="" +zstd="" +guest_agent="" +guest_agent_with_vss="no" +guest_agent_ntddscsi="no" +guest_agent_msi="" +vss_win32_sdk="" +win_sdk="no" +want_tools="" +libiscsi="" +libnfs="" +coroutine="" +coroutine_pool="" +debug_stack_usage="no" +crypto_afalg="no" +seccomp="" +glusterfs="" +glusterfs_xlator_opt="no" +glusterfs_discard="no" +glusterfs_fallocate="no" +glusterfs_zerofill="no" +glusterfs_ftruncate_has_stat="no" +glusterfs_iocb_has_stat="no" +gtk="" +gtk_gl="no" +tls_priority="NORMAL" +gnutls="" +nettle="" +nettle_xts="no" +gcrypt="" +gcrypt_hmac="no" +gcrypt_xts="no" +qemu_private_xts="yes" +auth_pam="" +vte="" +virglrenderer="" +tpm="" +libssh="" +live_block_migration="yes" +numa="" +tcmalloc="no" +jemalloc="no" +replication="yes" +bochs="yes" +cloop="yes" +dmg="yes" +qcow1="yes" +vdi="yes" +vvfat="yes" +qed="yes" +parallels="yes" +sheepdog="yes" +libxml2="" +debug_mutex="no" +libpmem="" +default_devices="yes" +plugins="no" +fuzzing="no" +rng_none="no" +secret_keyring="" +libdaxctl="" +meson="" +ninja="" +skip_meson=no +gettext="" + +bogus_os="no" +malloc_trim="" + +# parse CC options first +for opt do + optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') + case "$opt" in + --cross-prefix=*) cross_prefix="$optarg" + ;; + --cc=*) CC="$optarg" + ;; + --cxx=*) CXX="$optarg" + ;; + --cpu=*) cpu="$optarg" + ;; + --extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg" + QEMU_LDFLAGS="$QEMU_LDFLAGS $optarg" + ;; + --extra-cxxflags=*) QEMU_CXXFLAGS="$QEMU_CXXFLAGS $optarg" + ;; + --extra-ldflags=*) QEMU_LDFLAGS="$QEMU_LDFLAGS $optarg" + EXTRA_LDFLAGS="$optarg" + ;; + --enable-debug-info) debug_info="yes" + ;; + --disable-debug-info) debug_info="no" + ;; + --cross-cc-*[!a-zA-Z0-9_-]*=*) error_exit "Passed bad --cross-cc-FOO option" + ;; + --cross-cc-cflags-*) cc_arch=${opt#--cross-cc-flags-}; cc_arch=${cc_arch%%=*} + eval "cross_cc_cflags_${cc_arch}=\$optarg" + cross_cc_vars="$cross_cc_vars cross_cc_cflags_${cc_arch}" + ;; + --cross-cc-*) cc_arch=${opt#--cross-cc-}; cc_arch=${cc_arch%%=*} + cc_archs="$cc_archs $cc_arch" + eval "cross_cc_${cc_arch}=\$optarg" + cross_cc_vars="$cross_cc_vars cross_cc_${cc_arch}" + ;; + esac +done +# OS specific +# Using uname is really, really broken. Once we have the right set of checks +# we can eliminate its usage altogether. + +# Preferred compiler: +# ${CC} (if set) +# ${cross_prefix}gcc (if cross-prefix specified) +# system compiler +if test -z "${CC}${cross_prefix}"; then + cc="$host_cc" +else + cc="${CC-${cross_prefix}gcc}" +fi + +if test -z "${CXX}${cross_prefix}"; then + cxx="c++" +else + cxx="${CXX-${cross_prefix}g++}" +fi + +ar="${AR-${cross_prefix}ar}" +as="${AS-${cross_prefix}as}" +ccas="${CCAS-$cc}" +cpp="${CPP-$cc -E}" +objcopy="${OBJCOPY-${cross_prefix}objcopy}" +ld="${LD-${cross_prefix}ld}" +ranlib="${RANLIB-${cross_prefix}ranlib}" +nm="${NM-${cross_prefix}nm}" +strip="${STRIP-${cross_prefix}strip}" +windres="${WINDRES-${cross_prefix}windres}" +pkg_config_exe="${PKG_CONFIG-${cross_prefix}pkg-config}" +query_pkg_config() { + "${pkg_config_exe}" ${QEMU_PKG_CONFIG_FLAGS} "$@" +} +pkg_config=query_pkg_config +sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}" + +# If the user hasn't specified ARFLAGS, default to 'rv', just as make does. +ARFLAGS="${ARFLAGS-rv}" + +# default flags for all hosts +# We use -fwrapv to tell the compiler that we require a C dialect where +# left shift of signed integers is well defined and has the expected +# 2s-complement style results. (Both clang and gcc agree that it +# provides these semantics.) +QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv $QEMU_CFLAGS" +QEMU_CFLAGS="-Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" +QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" +QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" +QEMU_INCLUDES="-iquote . -iquote ${source_path} -iquote ${source_path}/accel/tcg -iquote ${source_path}/include" +QEMU_INCLUDES="$QEMU_INCLUDES -iquote ${source_path}/disas/libvixl" +CFLAGS="-std=gnu99 -Wall" + + +# running configure in the source tree? +# we know that's the case if configure is there. +if test -f "./configure"; then + pwd_is_source_path="y" +else + pwd_is_source_path="n" +fi + +check_define() { +cat > $TMPC < $TMPC < +int main(void) { return 0; } +EOF + compile_object +} + +write_c_skeleton() { + cat > $TMPC < $TMPC < +#include +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } +EOF +} + +if check_define __linux__ ; then + targetos="Linux" +elif check_define _WIN32 ; then + targetos='MINGW32' +elif check_define __OpenBSD__ ; then + targetos='OpenBSD' +elif check_define __sun__ ; then + targetos='SunOS' +elif check_define __HAIKU__ ; then + targetos='Haiku' +elif check_define __FreeBSD__ ; then + targetos='FreeBSD' +elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then + targetos='GNU/kFreeBSD' +elif check_define __DragonFly__ ; then + targetos='DragonFly' +elif check_define __NetBSD__; then + targetos='NetBSD' +elif check_define __APPLE__; then + targetos='Darwin' +else + # This is a fatal error, but don't report it yet, because we + # might be going to just print the --help text, or it might + # be the result of a missing compiler. + targetos='bogus' + bogus_os='yes' +fi + +# Some host OSes need non-standard checks for which CPU to use. +# Note that these checks are broken for cross-compilation: if you're +# cross-compiling to one of these OSes then you'll need to specify +# the correct CPU with the --cpu option. +case $targetos in +Darwin) + # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can + # run 64-bit userspace code. + # If the user didn't specify a CPU explicitly and the kernel says this is + # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code. + if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then + cpu="x86_64" + fi + ;; +SunOS) + # $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo + if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then + cpu="x86_64" + fi +esac + +if test ! -z "$cpu" ; then + # command line argument + : +elif check_define __i386__ ; then + cpu="i386" +elif check_define __x86_64__ ; then + if check_define __ILP32__ ; then + cpu="x32" + else + cpu="x86_64" + fi +elif check_define __sparc__ ; then + if check_define __arch64__ ; then + cpu="sparc64" + else + cpu="sparc" + fi +elif check_define _ARCH_PPC ; then + if check_define _ARCH_PPC64 ; then + if check_define _LITTLE_ENDIAN ; then + cpu="ppc64le" + else + cpu="ppc64" + fi + else + cpu="ppc" + fi +elif check_define __mips__ ; then + cpu="mips" +elif check_define __s390__ ; then + if check_define __s390x__ ; then + cpu="s390x" + else + cpu="s390" + fi +elif check_define __riscv ; then + if check_define _LP64 ; then + cpu="riscv64" + else + cpu="riscv32" + fi +elif check_define __arm__ ; then + cpu="arm" +elif check_define __aarch64__ ; then + cpu="aarch64" +else + cpu=$(uname -m) +fi + +ARCH= +# Normalise host CPU name and set ARCH. +# Note that this case should only have supported host CPUs, not guests. +case "$cpu" in + ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64) + ;; + ppc64le) + ARCH="ppc64" + ;; + i386|i486|i586|i686|i86pc|BePC) + cpu="i386" + ;; + x86_64|amd64) + cpu="x86_64" + ;; + armv*b|armv*l|arm) + cpu="arm" + ;; + aarch64) + cpu="aarch64" + ;; + mips*) + cpu="mips" + ;; + sparc|sun4[cdmuv]) + cpu="sparc" + ;; + *) + # This will result in either an error or falling back to TCI later + ARCH=unknown + ;; +esac +if test -z "$ARCH"; then + ARCH="$cpu" +fi + +# OS specific + +# host *BSD for user mode +HOST_VARIANT_DIR="" + +case $targetos in +MINGW32*) + mingw32="yes" + hax="yes" + vhost_user="no" + audio_possible_drivers="dsound sdl" + if check_include dsound.h; then + audio_drv_list="dsound" + else + audio_drv_list="" + fi + supported_os="yes" + pie="no" +;; +GNU/kFreeBSD) + bsd="yes" + audio_drv_list="oss try-sdl" + audio_possible_drivers="oss sdl pa" +;; +FreeBSD) + bsd="yes" + make="${MAKE-gmake}" + audio_drv_list="oss try-sdl" + audio_possible_drivers="oss sdl pa" + # needed for kinfo_getvmmap(3) in libutil.h + LIBS="-lutil $LIBS" + netmap="" # enable netmap autodetect + HOST_VARIANT_DIR="freebsd" +;; +DragonFly) + bsd="yes" + make="${MAKE-gmake}" + audio_drv_list="oss try-sdl" + audio_possible_drivers="oss sdl pa" + HOST_VARIANT_DIR="dragonfly" +;; +NetBSD) + bsd="yes" + hax="yes" + make="${MAKE-gmake}" + audio_drv_list="oss try-sdl" + audio_possible_drivers="oss sdl" + oss_lib="-lossaudio" + HOST_VARIANT_DIR="netbsd" +;; +OpenBSD) + bsd="yes" + make="${MAKE-gmake}" + audio_drv_list="try-sdl" + audio_possible_drivers="sdl" + HOST_VARIANT_DIR="openbsd" +;; +Darwin) + bsd="yes" + darwin="yes" + hax="yes" + hvf="yes" + LDFLAGS_SHARED="-bundle -undefined dynamic_lookup" + if [ "$cpu" = "x86_64" ] ; then + QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" + QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS" + fi + cocoa="yes" + audio_drv_list="coreaudio try-sdl" + audio_possible_drivers="coreaudio sdl" + QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS" + # Disable attempts to use ObjectiveC features in os/object.h since they + # won't work when we're compiling with gcc as a C compiler. + QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS" + HOST_VARIANT_DIR="darwin" +;; +SunOS) + solaris="yes" + make="${MAKE-gmake}" + install="${INSTALL-ginstall}" + smbd="${SMBD-/usr/sfw/sbin/smbd}" + if test -f /usr/include/sys/soundcard.h ; then + audio_drv_list="oss try-sdl" + fi + audio_possible_drivers="oss sdl" +# needed for CMSG_ macros in sys/socket.h + QEMU_CFLAGS="-D_XOPEN_SOURCE=600 $QEMU_CFLAGS" +# needed for TIOCWIN* defines in termios.h + QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS" + solarisnetlibs="-lsocket -lnsl -lresolv" + LIBS="$solarisnetlibs $LIBS" +;; +Haiku) + haiku="yes" + QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -DBSD_SOURCE $QEMU_CFLAGS" + LIBS="-lposix_error_mapper -lnetwork -lbsd $LIBS" +;; +Linux) + audio_drv_list="try-pa oss" + audio_possible_drivers="oss alsa sdl pa" + linux="yes" + linux_user="yes" + kvm="yes" + QEMU_INCLUDES="-isystem ${source_path}/linux-headers -I${build_path}/linux-headers $QEMU_INCLUDES" + libudev="yes" +;; +esac + +if [ "$bsd" = "yes" ] ; then + if [ "$darwin" != "yes" ] ; then + bsd_user="yes" + fi +fi + +: ${make=${MAKE-make}} +: ${install=${INSTALL-install}} +# We prefer python 3.x. A bare 'python' is traditionally +# python 2.x, but some distros have it as python 3.x, so +# we check that too +python= +explicit_python=no +for binary in "${PYTHON-python3}" python +do + if has "$binary" + then + python=$(command -v "$binary") + break + fi +done + +sphinx_build= +for binary in sphinx-build-3 sphinx-build +do + if has "$binary" + then + sphinx_build=$(command -v "$binary") + break + fi +done + +# Check for ancillary tools used in testing +genisoimage= +for binary in genisoimage mkisofs +do + if has $binary + then + genisoimage=$(command -v "$binary") + break + fi +done + +: ${smbd=${SMBD-/usr/sbin/smbd}} + +# Default objcc to clang if available, otherwise use CC +if has clang; then + objcc=clang +else + objcc="$cc" +fi + +if test "$mingw32" = "yes" ; then + EXESUF=".exe" + HOST_DSOSUF=".dll" + # MinGW needs -mthreads for TLS and macro _MT. + CFLAGS="-mthreads $CFLAGS" + LIBS="-lwinmm -lws2_32 $LIBS" + write_c_skeleton; + if compile_prog "" "-liberty" ; then + LIBS="-liberty $LIBS" + fi + prefix="c:/Program Files/QEMU" + qemu_suffix="" + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -lwininet -liphlpapi -lnetapi32 $libs_qga" +fi + +werror="" + +for opt do + optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') + case "$opt" in + --help|-h) show_help=yes + ;; + --version|-V) exec cat $source_path/VERSION + ;; + --prefix=*) prefix="$optarg" + ;; + --interp-prefix=*) interp_prefix="$optarg" + ;; + --cross-prefix=*) + ;; + --cc=*) + ;; + --host-cc=*) host_cc="$optarg" + ;; + --cxx=*) + ;; + --iasl=*) iasl="$optarg" + ;; + --objcc=*) objcc="$optarg" + ;; + --make=*) make="$optarg" + ;; + --install=*) install="$optarg" + ;; + --python=*) python="$optarg" ; explicit_python=yes + ;; + --sphinx-build=*) sphinx_build="$optarg" + ;; + --skip-meson) skip_meson=yes + ;; + --meson=*) meson="$optarg" + ;; + --ninja=*) ninja="$optarg" + ;; + --smbd=*) smbd="$optarg" + ;; + --extra-cflags=*) + ;; + --extra-cxxflags=*) + ;; + --extra-ldflags=*) + ;; + --enable-debug-info) + ;; + --disable-debug-info) + ;; + --cross-cc-*) + ;; + --enable-modules) + modules="yes" + ;; + --disable-modules) + modules="no" + ;; + --disable-module-upgrades) module_upgrades="no" + ;; + --enable-module-upgrades) module_upgrades="yes" + ;; + --cpu=*) + ;; + --target-list=*) target_list="$optarg" + if test "$target_list_exclude"; then + error_exit "Can't mix --target-list with --target-list-exclude" + fi + ;; + --target-list-exclude=*) target_list_exclude="$optarg" + if test "$target_list"; then + error_exit "Can't mix --target-list-exclude with --target-list" + fi + ;; + --enable-trace-backends=*) trace_backends="$optarg" + ;; + # XXX: backwards compatibility + --enable-trace-backend=*) trace_backends="$optarg" + ;; + --with-trace-file=*) trace_file="$optarg" + ;; + --with-default-devices) default_devices="yes" + ;; + --without-default-devices) default_devices="no" + ;; + --enable-gprof) gprof="yes" + ;; + --enable-gcov) gcov="yes" + ;; + --static) + static="yes" + QEMU_PKG_CONFIG_FLAGS="--static $QEMU_PKG_CONFIG_FLAGS" + ;; + --mandir=*) mandir="$optarg" + ;; + --bindir=*) bindir="$optarg" + ;; + --libdir=*) libdir="$optarg" + ;; + --libexecdir=*) libexecdir="$optarg" + ;; + --includedir=*) includedir="$optarg" + ;; + --datadir=*) datadir="$optarg" + ;; + --with-suffix=*) qemu_suffix="$optarg" + ;; + --docdir=*) qemu_docdir="$optarg" + ;; + --sysconfdir=*) sysconfdir="$optarg" + ;; + --localstatedir=*) local_statedir="$optarg" + ;; + --firmwarepath=*) firmwarepath="$optarg" + ;; + --host=*|--build=*|\ + --disable-dependency-tracking|\ + --sbindir=*|--sharedstatedir=*|\ + --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\ + --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*) + # These switches are silently ignored, for compatibility with + # autoconf-generated configure scripts. This allows QEMU's + # configure to be used by RPM and similar macros that set + # lots of directory switches by default. + ;; + --disable-sdl) sdl="disabled" + ;; + --enable-sdl) sdl="enabled" + ;; + --disable-sdl-image) sdl_image="disabled" + ;; + --enable-sdl-image) sdl_image="enabled" + ;; + --disable-qom-cast-debug) qom_cast_debug="no" + ;; + --enable-qom-cast-debug) qom_cast_debug="yes" + ;; + --disable-virtfs) virtfs="no" + ;; + --enable-virtfs) virtfs="yes" + ;; + --disable-mpath) mpath="no" + ;; + --enable-mpath) mpath="yes" + ;; + --disable-vnc) vnc="disabled" + ;; + --enable-vnc) vnc="enabled" + ;; + --disable-gettext) gettext="false" + ;; + --enable-gettext) gettext="true" + ;; + --oss-lib=*) oss_lib="$optarg" + ;; + --audio-drv-list=*) audio_drv_list="$optarg" + ;; + --block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=$(echo "$optarg" | sed -e 's/,/ /g') + ;; + --block-drv-ro-whitelist=*) block_drv_ro_whitelist=$(echo "$optarg" | sed -e 's/,/ /g') + ;; + --enable-debug-tcg) debug_tcg="yes" + ;; + --disable-debug-tcg) debug_tcg="no" + ;; + --enable-debug) + # Enable debugging options that aren't excessively noisy + debug_tcg="yes" + debug_mutex="yes" + debug="yes" + strip_opt="no" + fortify_source="no" + ;; + --enable-sanitizers) sanitizers="yes" + ;; + --disable-sanitizers) sanitizers="no" + ;; + --enable-tsan) tsan="yes" + ;; + --disable-tsan) tsan="no" + ;; + --enable-sparse) sparse="yes" + ;; + --disable-sparse) sparse="no" + ;; + --disable-strip) strip_opt="no" + ;; + --disable-vnc-sasl) vnc_sasl="disabled" + ;; + --enable-vnc-sasl) vnc_sasl="enabled" + ;; + --disable-vnc-jpeg) vnc_jpeg="disabled" + ;; + --enable-vnc-jpeg) vnc_jpeg="enabled" + ;; + --disable-vnc-png) vnc_png="disabled" + ;; + --enable-vnc-png) vnc_png="enabled" + ;; + --disable-slirp) slirp="no" + ;; + --enable-slirp=git) slirp="git" + ;; + --enable-slirp=system) slirp="system" + ;; + --disable-vde) vde="no" + ;; + --enable-vde) vde="yes" + ;; + --disable-netmap) netmap="no" + ;; + --enable-netmap) netmap="yes" + ;; + --disable-xen) xen="no" + ;; + --enable-xen) xen="yes" + ;; + --disable-xen-pci-passthrough) xen_pci_passthrough="no" + ;; + --enable-xen-pci-passthrough) xen_pci_passthrough="yes" + ;; + --disable-brlapi) brlapi="no" + ;; + --enable-brlapi) brlapi="yes" + ;; + --disable-kvm) kvm="no" + ;; + --enable-kvm) kvm="yes" + ;; + --disable-hax) hax="no" + ;; + --enable-hax) hax="yes" + ;; + --disable-hvf) hvf="no" + ;; + --enable-hvf) hvf="yes" + ;; + --disable-whpx) whpx="no" + ;; + --enable-whpx) whpx="yes" + ;; + --disable-tcg-interpreter) tcg_interpreter="no" + ;; + --enable-tcg-interpreter) tcg_interpreter="yes" + ;; + --disable-cap-ng) cap_ng="no" + ;; + --enable-cap-ng) cap_ng="yes" + ;; + --disable-tcg) tcg="no" + ;; + --enable-tcg) tcg="yes" + ;; + --disable-malloc-trim) malloc_trim="no" + ;; + --enable-malloc-trim) malloc_trim="yes" + ;; + --disable-spice) spice="no" + ;; + --enable-spice) spice="yes" + ;; + --disable-libiscsi) libiscsi="no" + ;; + --enable-libiscsi) libiscsi="yes" + ;; + --disable-libnfs) libnfs="no" + ;; + --enable-libnfs) libnfs="yes" + ;; + --enable-profiler) profiler="yes" + ;; + --disable-cocoa) cocoa="no" + ;; + --enable-cocoa) + cocoa="yes" ; + audio_drv_list="coreaudio $(echo $audio_drv_list | sed s,coreaudio,,g)" + ;; + --disable-system) softmmu="no" + ;; + --enable-system) softmmu="yes" + ;; + --disable-user) + linux_user="no" ; + bsd_user="no" ; + ;; + --enable-user) ;; + --disable-linux-user) linux_user="no" + ;; + --enable-linux-user) linux_user="yes" + ;; + --disable-bsd-user) bsd_user="no" + ;; + --enable-bsd-user) bsd_user="yes" + ;; + --enable-pie) pie="yes" + ;; + --disable-pie) pie="no" + ;; + --enable-werror) werror="yes" + ;; + --disable-werror) werror="no" + ;; + --enable-stack-protector) stack_protector="yes" + ;; + --disable-stack-protector) stack_protector="no" + ;; + --enable-safe-stack) safe_stack="yes" + ;; + --disable-safe-stack) safe_stack="no" + ;; + --disable-curses) curses="no" + ;; + --enable-curses) curses="yes" + ;; + --disable-iconv) iconv="no" + ;; + --enable-iconv) iconv="yes" + ;; + --disable-curl) curl="no" + ;; + --enable-curl) curl="yes" + ;; + --disable-fdt) fdt="no" + ;; + --enable-fdt) fdt="yes" + ;; + --disable-linux-aio) linux_aio="no" + ;; + --enable-linux-aio) linux_aio="yes" + ;; + --disable-linux-io-uring) linux_io_uring="no" + ;; + --enable-linux-io-uring) linux_io_uring="yes" + ;; + --disable-attr) attr="no" + ;; + --enable-attr) attr="yes" + ;; + --disable-membarrier) membarrier="no" + ;; + --enable-membarrier) membarrier="yes" + ;; + --disable-blobs) blobs="no" + ;; + --with-pkgversion=*) pkgversion="$optarg" + ;; + --with-coroutine=*) coroutine="$optarg" + ;; + --disable-coroutine-pool) coroutine_pool="no" + ;; + --enable-coroutine-pool) coroutine_pool="yes" + ;; + --enable-debug-stack-usage) debug_stack_usage="yes" + ;; + --enable-crypto-afalg) crypto_afalg="yes" + ;; + --disable-crypto-afalg) crypto_afalg="no" + ;; + --disable-docs) docs="no" + ;; + --enable-docs) docs="yes" + ;; + --disable-vhost-net) vhost_net="no" + ;; + --enable-vhost-net) vhost_net="yes" + ;; + --disable-vhost-crypto) vhost_crypto="no" + ;; + --enable-vhost-crypto) vhost_crypto="yes" + ;; + --disable-vhost-scsi) vhost_scsi="no" + ;; + --enable-vhost-scsi) vhost_scsi="yes" + ;; + --disable-vhost-vsock) vhost_vsock="no" + ;; + --enable-vhost-vsock) vhost_vsock="yes" + ;; + --disable-vhost-user-fs) vhost_user_fs="no" + ;; + --enable-vhost-user-fs) vhost_user_fs="yes" + ;; + --disable-opengl) opengl="no" + ;; + --enable-opengl) opengl="yes" + ;; + --disable-rbd) rbd="no" + ;; + --enable-rbd) rbd="yes" + ;; + --disable-xfsctl) xfs="no" + ;; + --enable-xfsctl) xfs="yes" + ;; + --disable-smartcard) smartcard="no" + ;; + --enable-smartcard) smartcard="yes" + ;; + --disable-u2f) u2f="disabled" + ;; + --enable-u2f) u2f="enabled" + ;; + --disable-libusb) libusb="no" + ;; + --enable-libusb) libusb="yes" + ;; + --disable-usb-redir) usb_redir="no" + ;; + --enable-usb-redir) usb_redir="yes" + ;; + --disable-zlib-test) + ;; + --disable-lzo) lzo="no" + ;; + --enable-lzo) lzo="yes" + ;; + --disable-snappy) snappy="no" + ;; + --enable-snappy) snappy="yes" + ;; + --disable-bzip2) bzip2="no" + ;; + --enable-bzip2) bzip2="yes" + ;; + --enable-lzfse) lzfse="yes" + ;; + --disable-lzfse) lzfse="no" + ;; + --disable-zstd) zstd="no" + ;; + --enable-zstd) zstd="yes" + ;; + --enable-guest-agent) guest_agent="yes" + ;; + --disable-guest-agent) guest_agent="no" + ;; + --enable-guest-agent-msi) guest_agent_msi="yes" + ;; + --disable-guest-agent-msi) guest_agent_msi="no" + ;; + --with-vss-sdk) vss_win32_sdk="" + ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; + --without-vss-sdk) vss_win32_sdk="no" + ;; + --with-win-sdk) win_sdk="" + ;; + --with-win-sdk=*) win_sdk="$optarg" + ;; + --without-win-sdk) win_sdk="no" + ;; + --enable-tools) want_tools="yes" + ;; + --disable-tools) want_tools="no" + ;; + --enable-seccomp) seccomp="yes" + ;; + --disable-seccomp) seccomp="no" + ;; + --disable-glusterfs) glusterfs="no" + ;; + --disable-avx2) avx2_opt="no" + ;; + --enable-avx2) avx2_opt="yes" + ;; + --disable-avx512f) avx512f_opt="no" + ;; + --enable-avx512f) avx512f_opt="yes" + ;; + + --enable-glusterfs) glusterfs="yes" + ;; + --disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane) + echo "$0: $opt is obsolete, virtio-blk data-plane is always on" >&2 + ;; + --enable-vhdx|--disable-vhdx) + echo "$0: $opt is obsolete, VHDX driver is always built" >&2 + ;; + --enable-uuid|--disable-uuid) + echo "$0: $opt is obsolete, UUID support is always built" >&2 + ;; + --disable-gtk) gtk="no" + ;; + --enable-gtk) gtk="yes" + ;; + --tls-priority=*) tls_priority="$optarg" + ;; + --disable-gnutls) gnutls="no" + ;; + --enable-gnutls) gnutls="yes" + ;; + --disable-nettle) nettle="no" + ;; + --enable-nettle) nettle="yes" + ;; + --disable-gcrypt) gcrypt="no" + ;; + --enable-gcrypt) gcrypt="yes" + ;; + --disable-auth-pam) auth_pam="no" + ;; + --enable-auth-pam) auth_pam="yes" + ;; + --enable-rdma) rdma="yes" + ;; + --disable-rdma) rdma="no" + ;; + --enable-pvrdma) pvrdma="yes" + ;; + --disable-pvrdma) pvrdma="no" + ;; + --disable-vte) vte="no" + ;; + --enable-vte) vte="yes" + ;; + --disable-virglrenderer) virglrenderer="no" + ;; + --enable-virglrenderer) virglrenderer="yes" + ;; + --disable-tpm) tpm="no" + ;; + --enable-tpm) tpm="yes" + ;; + --disable-libssh) libssh="no" + ;; + --enable-libssh) libssh="yes" + ;; + --disable-live-block-migration) live_block_migration="no" + ;; + --enable-live-block-migration) live_block_migration="yes" + ;; + --disable-numa) numa="no" + ;; + --enable-numa) numa="yes" + ;; + --disable-libxml2) libxml2="no" + ;; + --enable-libxml2) libxml2="yes" + ;; + --disable-tcmalloc) tcmalloc="no" + ;; + --enable-tcmalloc) tcmalloc="yes" + ;; + --disable-jemalloc) jemalloc="no" + ;; + --enable-jemalloc) jemalloc="yes" + ;; + --disable-replication) replication="no" + ;; + --enable-replication) replication="yes" + ;; + --disable-bochs) bochs="no" + ;; + --enable-bochs) bochs="yes" + ;; + --disable-cloop) cloop="no" + ;; + --enable-cloop) cloop="yes" + ;; + --disable-dmg) dmg="no" + ;; + --enable-dmg) dmg="yes" + ;; + --disable-qcow1) qcow1="no" + ;; + --enable-qcow1) qcow1="yes" + ;; + --disable-vdi) vdi="no" + ;; + --enable-vdi) vdi="yes" + ;; + --disable-vvfat) vvfat="no" + ;; + --enable-vvfat) vvfat="yes" + ;; + --disable-qed) qed="no" + ;; + --enable-qed) qed="yes" + ;; + --disable-parallels) parallels="no" + ;; + --enable-parallels) parallels="yes" + ;; + --disable-sheepdog) sheepdog="no" + ;; + --enable-sheepdog) sheepdog="yes" + ;; + --disable-vhost-user) vhost_user="no" + ;; + --enable-vhost-user) vhost_user="yes" + ;; + --disable-vhost-vdpa) vhost_vdpa="no" + ;; + --enable-vhost-vdpa) vhost_vdpa="yes" + ;; + --disable-vhost-kernel) vhost_kernel="no" + ;; + --enable-vhost-kernel) vhost_kernel="yes" + ;; + --disable-capstone) capstone="no" + ;; + --enable-capstone) capstone="yes" + ;; + --enable-capstone=git) capstone="git" + ;; + --enable-capstone=system) capstone="system" + ;; + --with-git=*) git="$optarg" + ;; + --enable-git-update) git_update=yes + ;; + --disable-git-update) git_update=no + ;; + --enable-debug-mutex) debug_mutex=yes + ;; + --disable-debug-mutex) debug_mutex=no + ;; + --enable-libpmem) libpmem=yes + ;; + --disable-libpmem) libpmem=no + ;; + --enable-xkbcommon) xkbcommon="enabled" + ;; + --disable-xkbcommon) xkbcommon="disabled" + ;; + --enable-plugins) plugins="yes" + ;; + --disable-plugins) plugins="no" + ;; + --enable-containers) use_containers="yes" + ;; + --disable-containers) use_containers="no" + ;; + --enable-fuzzing) fuzzing=yes + ;; + --disable-fuzzing) fuzzing=no + ;; + --gdb=*) gdb_bin="$optarg" + ;; + --enable-rng-none) rng_none=yes + ;; + --disable-rng-none) rng_none=no + ;; + --enable-keyring) secret_keyring="yes" + ;; + --disable-keyring) secret_keyring="no" + ;; + --enable-libdaxctl) libdaxctl=yes + ;; + --disable-libdaxctl) libdaxctl=no + ;; + *) + echo "ERROR: unknown option $opt" + echo "Try '$0 --help' for more information" + exit 1 + ;; + esac +done + +firmwarepath="${firmwarepath:-$prefix/share/qemu-firmware}" +libdir="${libdir:-$prefix/lib}" +libexecdir="${libexecdir:-$prefix/libexec}" +includedir="${includedir:-$prefix/include}" + +if test "$mingw32" = "yes" ; then + mandir="$prefix" + datadir="$prefix" + docdir="$prefix" + bindir="$prefix" + sysconfdir="$prefix" + local_statedir= +else + mandir="${mandir:-$prefix/share/man}" + datadir="${datadir:-$prefix/share}" + docdir="${docdir:-$prefix/share/doc}" + bindir="${bindir:-$prefix/bin}" + sysconfdir="${sysconfdir:-$prefix/etc}" + local_statedir="${local_statedir:-$prefix/var}" +fi + +case "$cpu" in + ppc) + CPU_CFLAGS="-m32" + QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS" + ;; + ppc64) + CPU_CFLAGS="-m64" + QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" + ;; + sparc) + CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" + QEMU_LDFLAGS="-m32 -mv8plus $QEMU_LDFLAGS" + ;; + sparc64) + CPU_CFLAGS="-m64 -mcpu=ultrasparc" + QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" + ;; + s390) + CPU_CFLAGS="-m31" + QEMU_LDFLAGS="-m31 $QEMU_LDFLAGS" + ;; + s390x) + CPU_CFLAGS="-m64" + QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" + ;; + i386) + CPU_CFLAGS="-m32" + QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS" + ;; + x86_64) + # ??? Only extremely old AMD cpus do not have cmpxchg16b. + # If we truly care, we should simply detect this case at + # runtime and generate the fallback to serial emulation. + CPU_CFLAGS="-m64 -mcx16" + QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS" + ;; + x32) + CPU_CFLAGS="-mx32" + QEMU_LDFLAGS="-mx32 $QEMU_LDFLAGS" + ;; + # No special flags required for other host CPUs +esac + +eval "cross_cc_${cpu}=\$host_cc" +cross_cc_vars="$cross_cc_vars cross_cc_${cpu}" +QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS" + +# For user-mode emulation the host arch has to be one we explicitly +# support, even if we're using TCI. +if [ "$ARCH" = "unknown" ]; then + bsd_user="no" + linux_user="no" +fi + +if [ "$bsd_user" = "no" -a "$linux_user" = "no" -a "$softmmu" = "no" ] ; then + tcg="no" +fi + +default_target_list="" + +mak_wilds="" + +if [ "$softmmu" = "yes" ]; then + mak_wilds="${mak_wilds} $source_path/default-configs/*-softmmu.mak" +fi +if [ "$linux_user" = "yes" ]; then + mak_wilds="${mak_wilds} $source_path/default-configs/*-linux-user.mak" +fi +if [ "$bsd_user" = "yes" ]; then + mak_wilds="${mak_wilds} $source_path/default-configs/*-bsd-user.mak" +fi + +if test -z "$target_list_exclude"; then + for config in $mak_wilds; do + default_target_list="${default_target_list} $(basename "$config" .mak)" + done +else + exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g') + for config in $mak_wilds; do + target="$(basename "$config" .mak)" + exclude="no" + for excl in $exclude_list; do + if test "$excl" = "$target"; then + exclude="yes" + break; + fi + done + if test "$exclude" = "no"; then + default_target_list="${default_target_list} $target" + fi + done +fi + +# Enumerate public trace backends for --help output +trace_backend_list=$(echo $(grep -le '^PUBLIC = True$' "$source_path"/scripts/tracetool/backend/*.py | sed -e 's/^.*\/\(.*\)\.py$/\1/')) + +if test x"$show_help" = x"yes" ; then +cat << EOF + +Usage: configure [options] +Options: [defaults in brackets after descriptions] + +Standard options: + --help print this message + --prefix=PREFIX install in PREFIX [$prefix] + --interp-prefix=PREFIX where to find shared libraries, etc. + use %M for cpu name [$interp_prefix] + --target-list=LIST set target list (default: build everything) +$(echo Available targets: $default_target_list | \ + fold -s -w 53 | sed -e 's/^/ /') + --target-list-exclude=LIST exclude a set of targets from the default target-list + +Advanced options (experts only): + --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix] + --cc=CC use C compiler CC [$cc] + --iasl=IASL use ACPI compiler IASL [$iasl] + --host-cc=CC use C compiler CC [$host_cc] for code run at + build time + --cxx=CXX use C++ compiler CXX [$cxx] + --objcc=OBJCC use Objective-C compiler OBJCC [$objcc] + --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS + --extra-cxxflags=CXXFLAGS append extra C++ compiler flags QEMU_CXXFLAGS + --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS + --cross-cc-ARCH=CC use compiler when building ARCH guest test cases + --cross-cc-flags-ARCH= use compiler flags when building ARCH guest tests + --make=MAKE use specified make [$make] + --install=INSTALL use specified install [$install] + --python=PYTHON use specified python [$python] + --sphinx-build=SPHINX use specified sphinx-build [$sphinx_build] + --meson=MESON use specified meson [$meson] + --ninja=NINJA use specified ninja [$ninja] + --smbd=SMBD use specified smbd [$smbd] + --with-git=GIT use specified git [$git] + --static enable static build [$static] + --mandir=PATH install man pages in PATH + --datadir=PATH install firmware in PATH/$qemu_suffix + --docdir=PATH install documentation in PATH/$qemu_suffix + --bindir=PATH install binaries in PATH + --libdir=PATH install libraries in PATH + --libexecdir=PATH install helper binaries in PATH + --sysconfdir=PATH install config in PATH/$qemu_suffix + --localstatedir=PATH install local state in PATH (set at runtime on win32) + --firmwarepath=PATH search PATH for firmware files + --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. + --with-suffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir/docdir [$qemu_suffix] + --with-pkgversion=VERS use specified string as sub-version of the package + --enable-debug enable common debug build options + --enable-sanitizers enable default sanitizers + --enable-tsan enable thread sanitizer + --disable-strip disable stripping binaries + --disable-werror disable compilation abort on warning + --disable-stack-protector disable compiler-provided stack protection + --audio-drv-list=LIST set audio drivers list: + Available drivers: $audio_possible_drivers + --block-drv-whitelist=L Same as --block-drv-rw-whitelist=L + --block-drv-rw-whitelist=L + set block driver read-write whitelist + (affects only QEMU, not qemu-img) + --block-drv-ro-whitelist=L + set block driver read-only whitelist + (affects only QEMU, not qemu-img) + --enable-trace-backends=B Set trace backend + Available backends: $trace_backend_list + --with-trace-file=NAME Full PATH,NAME of file to store traces + Default:trace- + --disable-slirp disable SLIRP userspace network connectivity + --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI) + --enable-malloc-trim enable libc malloc_trim() for memory optimization + --oss-lib path to OSS library + --cpu=CPU Build for host CPU [$cpu] + --with-coroutine=BACKEND coroutine backend. Supported options: + ucontext, sigaltstack, windows + --enable-gcov enable test coverage analysis with gcov + --disable-blobs disable installing provided firmware blobs + --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent + --with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb) + --tls-priority default TLS protocol/cipher priority string + --enable-gprof QEMU profiling with gprof + --enable-profiler profiler support + --enable-debug-stack-usage + track the maximum stack usage of stacks created by qemu_alloc_stack + --enable-plugins + enable plugins via shared library loading + --disable-containers don't use containers for cross-building + --gdb=GDB-path gdb to use for gdbstub tests [$gdb_bin] + +Optional features, enabled with --enable-FEATURE and +disabled with --disable-FEATURE, default is enabled if available: + + system all system emulation targets + user supported user emulation targets + linux-user all linux usermode emulation targets + bsd-user all BSD usermode emulation targets + docs build documentation + guest-agent build the QEMU Guest Agent + guest-agent-msi build guest agent Windows MSI installation package + pie Position Independent Executables + modules modules support (non-Windows) + module-upgrades try to load modules from alternate paths for upgrades + debug-tcg TCG debugging (default is disabled) + debug-info debugging information + sparse sparse checker + safe-stack SafeStack Stack Smash Protection. Depends on + clang/llvm >= 3.7 and requires coroutine backend ucontext. + + gnutls GNUTLS cryptography support + nettle nettle cryptography support + gcrypt libgcrypt cryptography support + auth-pam PAM access control + sdl SDL UI + sdl-image SDL Image support for icons + gtk gtk UI + vte vte support for the gtk UI + curses curses UI + iconv font glyph conversion support + vnc VNC UI support + vnc-sasl SASL encryption for VNC server + vnc-jpeg JPEG lossy compression for VNC server + vnc-png PNG compression for VNC server + cocoa Cocoa UI (Mac OS X only) + virtfs VirtFS + mpath Multipath persistent reservation passthrough + xen xen backend driver support + xen-pci-passthrough PCI passthrough support for Xen + brlapi BrlAPI (Braile) + curl curl connectivity + membarrier membarrier system call (for Linux 4.14+ or Windows) + fdt fdt device tree + kvm KVM acceleration support + hax HAX acceleration support + hvf Hypervisor.framework acceleration support + whpx Windows Hypervisor Platform acceleration support + rdma Enable RDMA-based migration + pvrdma Enable PVRDMA support + vde support for vde network + netmap support for netmap network + linux-aio Linux AIO support + linux-io-uring Linux io_uring support + cap-ng libcap-ng support + attr attr and xattr support + vhost-net vhost-net kernel acceleration support + vhost-vsock virtio sockets device support + vhost-scsi vhost-scsi kernel target support + vhost-crypto vhost-user-crypto backend support + vhost-kernel vhost kernel backend support + vhost-user vhost-user backend support + vhost-vdpa vhost-vdpa kernel backend support + spice spice + rbd rados block device (rbd) + libiscsi iscsi support + libnfs nfs support + smartcard smartcard support (libcacard) + u2f U2F support (u2f-emu) + libusb libusb (for usb passthrough) + live-block-migration Block migration in the main migration stream + usb-redir usb network redirection support + lzo support of lzo compression library + snappy support of snappy compression library + bzip2 support of bzip2 compression library + (for reading bzip2-compressed dmg images) + lzfse support of lzfse compression library + (for reading lzfse-compressed dmg images) + zstd support for zstd compression library + (for migration compression and qcow2 cluster compression) + seccomp seccomp support + coroutine-pool coroutine freelist (better performance) + glusterfs GlusterFS backend + tpm TPM support + libssh ssh block device support + numa libnuma support + libxml2 for Parallels image format + tcmalloc tcmalloc support + jemalloc jemalloc support + avx2 AVX2 optimization support + avx512f AVX512F optimization support + replication replication support + opengl opengl support + virglrenderer virgl rendering support + xfsctl xfsctl support + qom-cast-debug cast debugging support + tools build qemu-io, qemu-nbd and qemu-img tools + bochs bochs image format support + cloop cloop image format support + dmg dmg image format support + qcow1 qcow v1 image format support + vdi vdi image format support + vvfat vvfat image format support + qed qed image format support + parallels parallels image format support + sheepdog sheepdog block driver support + crypto-afalg Linux AF_ALG crypto backend driver + capstone capstone disassembler support + debug-mutex mutex debugging support + libpmem libpmem support + xkbcommon xkbcommon support + rng-none dummy RNG, avoid using /dev/(u)random and getrandom() + libdaxctl libdaxctl support + +NOTE: The object files are built at the place where configure is launched +EOF +exit 0 +fi + +# Remove old dependency files to make sure that they get properly regenerated +rm -f */config-devices.mak.d + +if test -z "$python" +then + error_exit "Python not found. Use --python=/path/to/python" +fi + +# Note that if the Python conditional here evaluates True we will exit +# with status 1 which is a shell 'false' value. +if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then + error_exit "Cannot use '$python', Python >= 3.5 is required." \ + "Use --python=/path/to/python to specify a supported Python." +fi + +# Preserve python version since some functionality is dependent on it +python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))' 2>/dev/null) + +# Suppress writing compiled files +python="$python -B" + +if test -z "$meson"; then + if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.1; then + meson=meson + elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then + meson=git + elif test -e "${source_path}/meson/meson.py" ; then + meson=internal + else + if test "$explicit_python" = yes; then + error_exit "--python requires using QEMU's embedded Meson distribution, but it was not found." + else + error_exit "Meson not found. Use --meson=/path/to/meson" + fi + fi +else + # Meson uses its own Python interpreter to invoke other Python scripts, + # but the user wants to use the one they specified with --python. + # + # We do not want to override the distro Python interpreter (and sometimes + # cannot: for example in Homebrew /usr/bin/meson is a bash script), so + # just require --meson=git|internal together with --python. + if test "$explicit_python" = yes; then + case "$meson" in + git | internal) ;; + *) error_exit "--python requires using QEMU's embedded Meson distribution." ;; + esac + fi +fi + +if test "$meson" = git; then + git_submodules="${git_submodules} meson" +fi + +case "$meson" in + git | internal) + if ! $python -c 'import pkg_resources' > /dev/null 2>&1; then + error_exit "Python setuptools not found" + fi + meson="$python ${source_path}/meson/meson.py" + ;; + *) meson=$(command -v meson) ;; +esac + +# Probe for ninja (used for compdb) + +if test -z "$ninja"; then + for c in ninja ninja-build samu; do + if has $c; then + ninja=$(command -v "$c") + break + fi + done +fi + +# Check that the C compiler works. Doing this here before testing +# the host CPU ensures that we had a valid CC to autodetect the +# $cpu var (and we should bail right here if that's not the case). +# It also allows the help message to be printed without a CC. +write_c_skeleton; +if compile_object ; then + : C compiler works ok +else + error_exit "\"$cc\" either does not exist or does not work" +fi +if ! compile_prog ; then + error_exit "\"$cc\" cannot build an executable (is your linker broken?)" +fi + +# Now we have handled --enable-tcg-interpreter and know we're not just +# printing the help message, bail out if the host CPU isn't supported. +if test "$ARCH" = "unknown"; then + if test "$tcg_interpreter" = "yes" ; then + echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)" + else + error_exit "Unsupported CPU = $cpu, try --enable-tcg-interpreter" + fi +fi + +# Consult white-list to determine whether to enable werror +# by default. Only enable by default for git builds +if test -z "$werror" ; then + if test -e "$source_path/.git" && \ + { test "$linux" = "yes" || test "$mingw32" = "yes"; }; then + werror="yes" + else + werror="no" + fi +fi + +if test "$bogus_os" = "yes"; then + # Now that we know that we're not printing the help and that + # the compiler works (so the results of the check_defines we used + # to identify the OS are reliable), if we didn't recognize the + # host OS we should stop now. + error_exit "Unrecognized host OS (uname -s reports '$(uname -s)')" +fi + +# Check whether the compiler matches our minimum requirements: +cat > $TMPC << EOF +#if defined(__clang_major__) && defined(__clang_minor__) +# ifdef __apple_build_version__ +# if __clang_major__ < 5 || (__clang_major__ == 5 && __clang_minor__ < 1) +# error You need at least XCode Clang v5.1 to compile QEMU +# endif +# else +# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4) +# error You need at least Clang v3.4 to compile QEMU +# endif +# endif +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) +# error You need at least GCC v4.8 to compile QEMU +# endif +#else +# error You either need GCC or Clang to compiler QEMU +#endif +int main (void) { return 0; } +EOF +if ! compile_prog "" "" ; then + error_exit "You need at least GCC v4.8 or Clang v3.4 (or XCode Clang v5.1)" +fi + +# Accumulate -Wfoo and -Wno-bar separately. +# We will list all of the enable flags first, and the disable flags second. +# Note that we do not add -Werror, because that would enable it for all +# configure tests. If a configure test failed due to -Werror this would +# just silently disable some features, so it's too error prone. + +warn_flags= +add_to warn_flags -Wold-style-declaration +add_to warn_flags -Wold-style-definition +add_to warn_flags -Wtype-limits +add_to warn_flags -Wformat-security +add_to warn_flags -Wformat-y2k +add_to warn_flags -Winit-self +add_to warn_flags -Wignored-qualifiers +add_to warn_flags -Wempty-body +add_to warn_flags -Wnested-externs +add_to warn_flags -Wendif-labels +add_to warn_flags -Wexpansion-to-defined + +nowarn_flags= +add_to nowarn_flags -Wno-initializer-overrides +add_to nowarn_flags -Wno-missing-include-dirs +add_to nowarn_flags -Wno-shift-negative-value +add_to nowarn_flags -Wno-string-plus-int +add_to nowarn_flags -Wno-typedef-redefinition +add_to nowarn_flags -Wno-tautological-type-limit-compare +add_to nowarn_flags -Wno-psabi + +gcc_flags="$warn_flags $nowarn_flags" + +cc_has_warning_flag() { + write_c_skeleton; + + # Use the positive sense of the flag when testing for -Wno-wombat + # support (gcc will happily accept the -Wno- form of unknown + # warning options). + optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')" + compile_prog "-Werror $optflag" "" +} + +for flag in $gcc_flags; do + if cc_has_warning_flag $flag ; then + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + fi +done + +if test "$stack_protector" != "no"; then + cat > $TMPC << EOF +int main(int argc, char *argv[]) +{ + char arr[64], *p = arr, *c = argv[0]; + while (*c) { + *p++ = *c++; + } + return 0; +} +EOF + gcc_flags="-fstack-protector-strong -fstack-protector-all" + sp_on=0 + for flag in $gcc_flags; do + # We need to check both a compile and a link, since some compiler + # setups fail only on a .c->.o compile and some only at link time + if compile_object "-Werror $flag" && + compile_prog "-Werror $flag" ""; then + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" + sp_on=1 + break + fi + done + if test "$stack_protector" = yes; then + if test $sp_on = 0; then + error_exit "Stack protector not supported" + fi + fi +fi + +# Disable -Wmissing-braces on older compilers that warn even for +# the "universal" C zero initializer {0}. +cat > $TMPC << EOF +struct { + int a[2]; +} x = {0}; +EOF +if compile_object "-Werror" "" ; then + : +else + QEMU_CFLAGS="$QEMU_CFLAGS -Wno-missing-braces" +fi + +# Our module code doesn't support Windows +if test "$modules" = "yes" && test "$mingw32" = "yes" ; then + error_exit "Modules are not available for Windows" +fi + +# module_upgrades is only reasonable if modules are enabled +if test "$modules" = "no" && test "$module_upgrades" = "yes" ; then + error_exit "Can't enable module-upgrades as Modules are not enabled" +fi + +# Static linking is not possible with modules or PIE +if test "$static" = "yes" ; then + if test "$modules" = "yes" ; then + error_exit "static and modules are mutually incompatible" + fi +fi + +# Unconditional check for compiler __thread support + cat > $TMPC << EOF +static __thread int tls_var; +int main(void) { return tls_var; } +EOF + +if ! compile_prog "-Werror" "" ; then + error_exit "Your compiler does not support the __thread specifier for " \ + "Thread-Local Storage (TLS). Please upgrade to a version that does." +fi + +cat > $TMPC << EOF + +#ifdef __linux__ +# define THREAD __thread +#else +# define THREAD +#endif +static THREAD int tls_var; +int main(void) { return tls_var; } +EOF + +# Check we support --no-pie first; we will need this for building ROMs. +if compile_prog "-Werror -fno-pie" "-no-pie"; then + CFLAGS_NOPIE="-fno-pie" + LDFLAGS_NOPIE="-no-pie" +fi + +if test "$static" = "yes"; then + if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then + CFLAGS="-fPIE -DPIE $CFLAGS" + QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS" + pie="yes" + elif test "$pie" = "yes"; then + error_exit "-static-pie not available due to missing toolchain support" + else + QEMU_LDFLAGS="-static $QEMU_LDFLAGS" + pie="no" + fi +elif test "$pie" = "no"; then + CFLAGS="$CFLAGS_NOPIE $CFLAGS" + LDFLAGS="$LDFLAGS_NOPIE $LDFLAGS" +elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then + CFLAGS="-fPIE -DPIE $CFLAGS" + LDFLAGS="-pie $LDFLAGS" + pie="yes" +elif test "$pie" = "yes"; then + error_exit "PIE not available due to missing toolchain support" +else + echo "Disabling PIE due to missing toolchain support" + pie="no" +fi + +# Detect support for PT_GNU_RELRO + DT_BIND_NOW. +# The combination is known as "full relro", because .got.plt is read-only too. +if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then + QEMU_LDFLAGS="-Wl,-z,relro -Wl,-z,now $QEMU_LDFLAGS" +fi + +########################################## +# __sync_fetch_and_and requires at least -march=i486. Many toolchains +# use i686 as default anyway, but for those that don't, an explicit +# specification is necessary + +if test "$cpu" = "i386"; then + cat > $TMPC << EOF +static int sfaa(int *ptr) +{ + return __sync_fetch_and_and(ptr, 0); +} + +int main(void) +{ + int val = 42; + val = __sync_val_compare_and_swap(&val, 0, 1); + sfaa(&val); + return val; +} +EOF + if ! compile_prog "" "" ; then + QEMU_CFLAGS="-march=i486 $QEMU_CFLAGS" + fi +fi + +######################################### +# Solaris specific configure tool chain decisions + +if test "$solaris" = "yes" ; then + if has $install; then + : + else + error_exit "Solaris install program not found. Use --install=/usr/ucb/install or" \ + "install fileutils from www.blastwave.org using pkg-get -i fileutils" \ + "to get ginstall which is used by default (which lives in /opt/csw/bin)" + fi + if test "$(path_of $install)" = "/usr/sbin/install" ; then + error_exit "Solaris /usr/sbin/install is not an appropriate install program." \ + "try ginstall from the GNU fileutils available from www.blastwave.org" \ + "using pkg-get -i fileutils, or use --install=/usr/ucb/install" + fi + if has ar; then + : + else + if test -f /usr/ccs/bin/ar ; then + error_exit "No path includes ar" \ + "Add /usr/ccs/bin to your path and rerun configure" + fi + error_exit "No path includes ar" + fi +fi + +if test -z "${target_list+xxx}" ; then + for target in $default_target_list; do + supported_target $target 2>/dev/null && \ + target_list="$target_list $target" + done + target_list="${target_list# }" +else + target_list=$(echo "$target_list" | sed -e 's/,/ /g') + for target in $target_list; do + # Check that we recognised the target name; this allows a more + # friendly error message than if we let it fall through. + case " $default_target_list " in + *" $target "*) + ;; + *) + error_exit "Unknown target name '$target'" + ;; + esac + supported_target $target || exit 1 + done +fi + +# see if system emulation was really requested +case " $target_list " in + *"-softmmu "*) softmmu=yes + ;; + *) softmmu=no + ;; +esac + +for target in $target_list; do + case "$target" in + arm-softmmu | aarch64-softmmu | i386-softmmu | x86_64-softmmu) + edk2_blobs="yes" + ;; + esac +done +# The EDK2 binaries are compressed with bzip2 +if test "$edk2_blobs" = "yes" && ! has bzip2; then + error_exit "The bzip2 program is required for building QEMU" +fi + +feature_not_found() { + feature=$1 + remedy=$2 + + error_exit "User requested feature $feature" \ + "configure was not able to find it." \ + "$remedy" +} + +# --- +# big/little endian test +cat > $TMPC << EOF +short big_endian[] = { 0x4269, 0x4765, 0x4e64, 0x4961, 0x4e00, 0, }; +short little_endian[] = { 0x694c, 0x7454, 0x654c, 0x6e45, 0x6944, 0x6e41, 0, }; +extern int foo(short *, short *); +int main(int argc, char *argv[]) { + return foo(big_endian, little_endian); +} +EOF + +if compile_object ; then + if strings -a $TMPO | grep -q BiGeNdIaN ; then + bigendian="yes" + elif strings -a $TMPO | grep -q LiTtLeEnDiAn ; then + bigendian="no" + else + echo big/little test failed + fi +else + echo big/little test failed +fi + +########################################## +# system tools +if test -z "$want_tools"; then + if test "$softmmu" = "no"; then + want_tools=no + else + want_tools=yes + fi +fi + +########################################## +# cocoa implies not SDL or GTK +# (the cocoa UI code currently assumes it is always the active UI +# and doesn't interact well with other UI frontend code) +if test "$cocoa" = "yes"; then + if test "$sdl" = "yes"; then + error_exit "Cocoa and SDL UIs cannot both be enabled at once" + fi + if test "$gtk" = "yes"; then + error_exit "Cocoa and GTK UIs cannot both be enabled at once" + fi + gtk=no + sdl=disabled +fi + +# Some versions of Mac OS X incorrectly define SIZE_MAX +cat > $TMPC << EOF +#include +#include +int main(int argc, char *argv[]) { + return printf("%zu", SIZE_MAX); +} +EOF +have_broken_size_max=no +if ! compile_object -Werror ; then + have_broken_size_max=yes +fi + +########################################## +# L2TPV3 probe + +cat > $TMPC < +#include +int main(void) { return sizeof(struct mmsghdr); } +EOF +if compile_prog "" "" ; then + l2tpv3=yes +else + l2tpv3=no +fi + +if check_include "pty.h" ; then + pty_h=yes +else + pty_h=no +fi + +cat > $TMPC < +int main(int argc, char *argv[]) { + return mlockall(MCL_FUTURE); +} +EOF +if compile_prog "" "" ; then + have_mlockall=yes +else + have_mlockall=no +fi + +######################################### +# vhost interdependencies and host support + +# vhost backends +test "$vhost_user" = "" && vhost_user=yes +if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then + error_exit "vhost-user isn't available on win32" +fi +test "$vhost_vdpa" = "" && vhost_vdpa=$linux +if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then + error_exit "vhost-vdpa is only available on Linux" +fi +test "$vhost_kernel" = "" && vhost_kernel=$linux +if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then + error_exit "vhost-kernel is only available on Linux" +fi + +# vhost-kernel devices +test "$vhost_scsi" = "" && vhost_scsi=$vhost_kernel +if test "$vhost_scsi" = "yes" && test "$vhost_kernel" != "yes"; then + error_exit "--enable-vhost-scsi requires --enable-vhost-kernel" +fi +test "$vhost_vsock" = "" && vhost_vsock=$vhost_kernel +if test "$vhost_vsock" = "yes" && test "$vhost_kernel" != "yes"; then + error_exit "--enable-vhost-vsock requires --enable-vhost-kernel" +fi + +# vhost-user backends +test "$vhost_net_user" = "" && vhost_net_user=$vhost_user +if test "$vhost_net_user" = "yes" && test "$vhost_user" = "no"; then + error_exit "--enable-vhost-net-user requires --enable-vhost-user" +fi +test "$vhost_crypto" = "" && vhost_crypto=$vhost_user +if test "$vhost_crypto" = "yes" && test "$vhost_user" = "no"; then + error_exit "--enable-vhost-crypto requires --enable-vhost-user" +fi +test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user +if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then + error_exit "--enable-vhost-user-fs requires --enable-vhost-user" +fi +#vhost-vdpa backends +test "$vhost_net_vdpa" = "" && vhost_net_vdpa=$vhost_vdpa +if test "$vhost_net_vdpa" = "yes" && test "$vhost_vdpa" = "no"; then + error_exit "--enable-vhost-net-vdpa requires --enable-vhost-vdpa" +fi + +# OR the vhost-kernel and vhost-user values for simplicity +if test "$vhost_net" = ""; then + test "$vhost_net_user" = "yes" && vhost_net=yes + test "$vhost_kernel" = "yes" && vhost_net=yes +fi + +########################################## +# MinGW / Mingw-w64 localtime_r/gmtime_r check + +if test "$mingw32" = "yes"; then + # Some versions of MinGW / Mingw-w64 lack localtime_r + # and gmtime_r entirely. + # + # Some versions of Mingw-w64 define a macro for + # localtime_r/gmtime_r. + # + # Some versions of Mingw-w64 will define functions + # for localtime_r/gmtime_r, but only if you have + # _POSIX_THREAD_SAFE_FUNCTIONS defined. For fun + # though, unistd.h and pthread.h both define + # that for you. + # + # So this #undef localtime_r and #include + # are not in fact redundant. +cat > $TMPC << EOF +#include +#include +#undef localtime_r +int main(void) { localtime_r(NULL, NULL); return 0; } +EOF + if compile_prog "" "" ; then + localtime_r="yes" + else + localtime_r="no" + fi +fi + +########################################## +# pkg-config probe + +if ! has "$pkg_config_exe"; then + error_exit "pkg-config binary '$pkg_config_exe' not found" +fi + +########################################## +# NPTL probe + +if test "$linux_user" = "yes"; then + cat > $TMPC < +#include +int main(void) { +#if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT) +#error bork +#endif + return 0; +} +EOF + if ! compile_object ; then + feature_not_found "nptl" "Install glibc and linux kernel headers." + fi +fi + +########################################## +# lzo check + +if test "$lzo" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { lzo_version(); return 0; } +EOF + if compile_prog "" "-llzo2" ; then + lzo_libs="-llzo2" + lzo="yes" + else + if test "$lzo" = "yes"; then + feature_not_found "liblzo2" "Install liblzo2 devel" + fi + lzo="no" + fi +fi + +########################################## +# snappy check + +if test "$snappy" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { snappy_max_compressed_length(4096); return 0; } +EOF + if compile_prog "" "-lsnappy" ; then + snappy_libs='-lsnappy' + snappy="yes" + else + if test "$snappy" = "yes"; then + feature_not_found "libsnappy" "Install libsnappy devel" + fi + snappy="no" + fi +fi + +########################################## +# bzip2 check + +if test "$bzip2" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { BZ2_bzlibVersion(); return 0; } +EOF + if compile_prog "" "-lbz2" ; then + bzip2="yes" + else + if test "$bzip2" = "yes"; then + feature_not_found "libbzip2" "Install libbzip2 devel" + fi + bzip2="no" + fi +fi + +########################################## +# lzfse check + +if test "$lzfse" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { lzfse_decode_scratch_size(); return 0; } +EOF + if compile_prog "" "-llzfse" ; then + lzfse="yes" + else + if test "$lzfse" = "yes"; then + feature_not_found "lzfse" "Install lzfse devel" + fi + lzfse="no" + fi +fi + +########################################## +# zstd check + +if test "$zstd" != "no" ; then + libzstd_minver="1.4.0" + if $pkg_config --atleast-version=$libzstd_minver libzstd ; then + zstd_cflags="$($pkg_config --cflags libzstd)" + zstd_libs="$($pkg_config --libs libzstd)" + zstd="yes" + else + if test "$zstd" = "yes" ; then + feature_not_found "libzstd" "Install libzstd devel" + fi + zstd="no" + fi +fi + +########################################## +# libseccomp check + +if test "$seccomp" != "no" ; then + libseccomp_minver="2.3.0" + if $pkg_config --atleast-version=$libseccomp_minver libseccomp ; then + seccomp_cflags="$($pkg_config --cflags libseccomp)" + seccomp_libs="$($pkg_config --libs libseccomp)" + seccomp="yes" + else + if test "$seccomp" = "yes" ; then + feature_not_found "libseccomp" \ + "Install libseccomp devel >= $libseccomp_minver" + fi + seccomp="no" + fi +fi +########################################## +# xen probe + +if test "$xen" != "no" ; then + # Check whether Xen library path is specified via --extra-ldflags to avoid + # overriding this setting with pkg-config output. If not, try pkg-config + # to obtain all needed flags. + + if ! echo $EXTRA_LDFLAGS | grep tools/libxc > /dev/null && \ + $pkg_config --exists xencontrol ; then + xen_ctrl_version="$(printf '%d%02d%02d' \ + $($pkg_config --modversion xencontrol | sed 's/\./ /g') )" + xen=yes + xen_pc="xencontrol xenstore xenguest xenforeignmemory xengnttab" + xen_pc="$xen_pc xenevtchn xendevicemodel" + if $pkg_config --exists xentoolcore; then + xen_pc="$xen_pc xentoolcore" + fi + QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags $xen_pc)" + xen_cflags="$($pkg_config --cflags $xen_pc)" + xen_libs="$($pkg_config --libs $xen_pc)" + else + + xen_libs="-lxenstore -lxenctrl -lxenguest" + xen_stable_libs="-lxenforeignmemory -lxengnttab -lxenevtchn" + + # First we test whether Xen headers and libraries are available. + # If no, we are done and there is no Xen support. + # If yes, more tests are run to detect the Xen version. + + # Xen (any) + cat > $TMPC < +int main(void) { + return 0; +} +EOF + if ! compile_prog "" "$xen_libs" ; then + # Xen not found + if test "$xen" = "yes" ; then + feature_not_found "xen" "Install xen devel" + fi + xen=no + + # Xen unstable + elif + cat > $TMPC < +#include +int main(void) { + xendevicemodel_handle *xd; + xenforeignmemory_handle *xfmem; + + xd = xendevicemodel_open(0, 0); + xendevicemodel_pin_memory_cacheattr(xd, 0, 0, 0, 0); + + xfmem = xenforeignmemory_open(0, 0); + xenforeignmemory_map_resource(xfmem, 0, 0, 0, 0, 0, NULL, 0, 0); + + return 0; +} +EOF + compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs -lxentoolcore" + then + xen_stable_libs="-lxendevicemodel $xen_stable_libs -lxentoolcore" + xen_ctrl_version=41100 + xen=yes + elif + cat > $TMPC < +#include +int main(void) { + xenforeignmemory_handle *xfmem; + + xfmem = xenforeignmemory_open(0, 0); + xenforeignmemory_map2(xfmem, 0, 0, 0, 0, 0, 0, 0); + xentoolcore_restrict_all(0); + + return 0; +} +EOF + compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs -lxentoolcore" + then + xen_stable_libs="-lxendevicemodel $xen_stable_libs -lxentoolcore" + xen_ctrl_version=41000 + xen=yes + elif + cat > $TMPC < +int main(void) { + xendevicemodel_handle *xd; + + xd = xendevicemodel_open(0, 0); + xendevicemodel_close(xd); + + return 0; +} +EOF + compile_prog "" "$xen_libs -lxendevicemodel $xen_stable_libs" + then + xen_stable_libs="-lxendevicemodel $xen_stable_libs" + xen_ctrl_version=40900 + xen=yes + elif + cat > $TMPC < +#include +#include +#include +#include +#include +#include +#if !defined(HVM_MAX_VCPUS) +# error HVM_MAX_VCPUS not defined +#endif +int main(void) { + xc_interface *xc = NULL; + xenforeignmemory_handle *xfmem; + xenevtchn_handle *xe; + xengnttab_handle *xg; + xengnttab_grant_copy_segment_t* seg = NULL; + + xs_daemon_open(); + + xc = xc_interface_open(0, 0, 0); + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); + + xfmem = xenforeignmemory_open(0, 0); + xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); + + xe = xenevtchn_open(0, 0); + xenevtchn_fd(xe); + + xg = xengnttab_open(0, 0); + xengnttab_grant_copy(xg, 0, seg); + + return 0; +} +EOF + compile_prog "" "$xen_libs $xen_stable_libs" + then + xen_ctrl_version=40800 + xen=yes + elif + cat > $TMPC < +#include +#include +#include +#include +#include +#include +#if !defined(HVM_MAX_VCPUS) +# error HVM_MAX_VCPUS not defined +#endif +int main(void) { + xc_interface *xc = NULL; + xenforeignmemory_handle *xfmem; + xenevtchn_handle *xe; + xengnttab_handle *xg; + + xs_daemon_open(); + + xc = xc_interface_open(0, 0, 0); + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); + + xfmem = xenforeignmemory_open(0, 0); + xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); + + xe = xenevtchn_open(0, 0); + xenevtchn_fd(xe); + + xg = xengnttab_open(0, 0); + xengnttab_map_grant_ref(xg, 0, 0, 0); + + return 0; +} +EOF + compile_prog "" "$xen_libs $xen_stable_libs" + then + xen_ctrl_version=40701 + xen=yes + + # Xen 4.6 + elif + cat > $TMPC < +#include +#include +#include +#if !defined(HVM_MAX_VCPUS) +# error HVM_MAX_VCPUS not defined +#endif +int main(void) { + xc_interface *xc; + xs_daemon_open(); + xc = xc_interface_open(0, 0, 0); + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); + xc_gnttab_open(NULL, 0); + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); + xc_reserved_device_memory_map(xc, 0, 0, 0, 0, NULL, 0); + return 0; +} +EOF + compile_prog "" "$xen_libs" + then + xen_ctrl_version=40600 + xen=yes + + # Xen 4.5 + elif + cat > $TMPC < +#include +#include +#include +#if !defined(HVM_MAX_VCPUS) +# error HVM_MAX_VCPUS not defined +#endif +int main(void) { + xc_interface *xc; + xs_daemon_open(); + xc = xc_interface_open(0, 0, 0); + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); + xc_gnttab_open(NULL, 0); + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); + xc_hvm_create_ioreq_server(xc, 0, 0, NULL); + return 0; +} +EOF + compile_prog "" "$xen_libs" + then + xen_ctrl_version=40500 + xen=yes + + elif + cat > $TMPC < +#include +#include +#include +#if !defined(HVM_MAX_VCPUS) +# error HVM_MAX_VCPUS not defined +#endif +int main(void) { + xc_interface *xc; + xs_daemon_open(); + xc = xc_interface_open(0, 0, 0); + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); + xc_gnttab_open(NULL, 0); + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); + return 0; +} +EOF + compile_prog "" "$xen_libs" + then + xen_ctrl_version=40200 + xen=yes + + else + if test "$xen" = "yes" ; then + feature_not_found "xen (unsupported version)" \ + "Install a supported xen (xen 4.2 or newer)" + fi + xen=no + fi + + if test "$xen" = yes; then + if test $xen_ctrl_version -ge 40701 ; then + xen_libs="$xen_libs $xen_stable_libs " + fi + fi + fi +fi + +if test "$xen_pci_passthrough" != "no"; then + if test "$xen" = "yes" && test "$linux" = "yes"; then + xen_pci_passthrough=yes + else + if test "$xen_pci_passthrough" = "yes"; then + error_exit "User requested feature Xen PCI Passthrough" \ + " but this feature requires /sys from Linux" + fi + xen_pci_passthrough=no + fi +fi + +########################################## +# Windows Hypervisor Platform accelerator (WHPX) check +if test "$whpx" != "no" ; then + if check_include "WinHvPlatform.h" && check_include "WinHvEmulation.h"; then + whpx="yes" + else + if test "$whpx" = "yes"; then + feature_not_found "WinHvPlatform" "WinHvEmulation is not installed" + fi + whpx="no" + fi +fi + +########################################## +# gettext probe +if test "$gettext" != "false" ; then + if has xgettext; then + gettext=true + else + if test "$gettext" = "true" ; then + feature_not_found "gettext" "Install xgettext binary" + fi + gettext=false + fi +fi + +########################################## +# Sparse probe +if test "$sparse" != "no" ; then + if has sparse; then + sparse=yes + else + if test "$sparse" = "yes" ; then + feature_not_found "sparse" "Install sparse binary" + fi + sparse=no + fi +fi + +########################################## +# X11 probe +if $pkg_config --exists "x11"; then + have_x11=yes + x11_cflags=$($pkg_config --cflags x11) + x11_libs=$($pkg_config --libs x11) +fi + +########################################## +# GTK probe + +if test "$gtk" != "no"; then + gtkpackage="gtk+-3.0" + gtkx11package="gtk+-x11-3.0" + gtkversion="3.22.0" + if $pkg_config --exists "$gtkpackage >= $gtkversion"; then + gtk_cflags=$($pkg_config --cflags $gtkpackage) + gtk_libs=$($pkg_config --libs $gtkpackage) + gtk_version=$($pkg_config --modversion $gtkpackage) + if $pkg_config --exists "$gtkx11package >= $gtkversion"; then + need_x11=yes + gtk_cflags="$gtk_cflags $x11_cflags" + gtk_libs="$gtk_libs $x11_libs" + fi + gtk="yes" + elif test "$gtk" = "yes"; then + feature_not_found "gtk" "Install gtk3-devel" + else + gtk="no" + fi +fi + + +########################################## +# GNUTLS probe + +if test "$gnutls" != "no"; then + pass="no" + if $pkg_config --exists "gnutls >= 3.1.18"; then + gnutls_cflags=$($pkg_config --cflags gnutls) + gnutls_libs=$($pkg_config --libs gnutls) + # Packaging for the static libraries is not always correct. + # At least ubuntu 18.04 ships only shared libraries. + write_c_skeleton + if compile_prog "" "$gnutls_libs" ; then + LIBS="$gnutls_libs $LIBS" + QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags" + pass="yes" + fi + fi + if test "$pass" = "no" && test "$gnutls" = "yes"; then + feature_not_found "gnutls" "Install gnutls devel >= 3.1.18" + else + gnutls="$pass" + fi +fi + + +# If user didn't give a --disable/enable-gcrypt flag, +# then mark as disabled if user requested nettle +# explicitly +if test -z "$gcrypt" +then + if test "$nettle" = "yes" + then + gcrypt="no" + fi +fi + +# If user didn't give a --disable/enable-nettle flag, +# then mark as disabled if user requested gcrypt +# explicitly +if test -z "$nettle" +then + if test "$gcrypt" = "yes" + then + nettle="no" + fi +fi + +has_libgcrypt() { + if ! has "libgcrypt-config" + then + return 1 + fi + + if test -n "$cross_prefix" + then + host=$(libgcrypt-config --host) + if test "$host-" != $cross_prefix + then + return 1 + fi + fi + + maj=`libgcrypt-config --version | awk -F . '{print $1}'` + min=`libgcrypt-config --version | awk -F . '{print $2}'` + + if test $maj != 1 || test $min -lt 5 + then + return 1 + fi + + return 0 +} + + +if test "$nettle" != "no"; then + pass="no" + if $pkg_config --exists "nettle >= 2.7.1"; then + nettle_cflags=$($pkg_config --cflags nettle) + nettle_libs=$($pkg_config --libs nettle) + nettle_version=$($pkg_config --modversion nettle) + # Link test to make sure the given libraries work (e.g for static). + write_c_skeleton + if compile_prog "" "$nettle_libs" ; then + LIBS="$nettle_libs $LIBS" + QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags" + if test -z "$gcrypt"; then + gcrypt="no" + fi + pass="yes" + fi + fi + if test "$pass" = "yes" + then + cat > $TMPC << EOF +#include +int main(void) { + return 0; +} +EOF + if compile_prog "$nettle_cflags" "$nettle_libs" ; then + nettle_xts=yes + qemu_private_xts=no + fi + fi + if test "$pass" = "no" && test "$nettle" = "yes"; then + feature_not_found "nettle" "Install nettle devel >= 2.7.1" + else + nettle="$pass" + fi +fi + +if test "$gcrypt" != "no"; then + pass="no" + if has_libgcrypt; then + gcrypt_cflags=$(libgcrypt-config --cflags) + gcrypt_libs=$(libgcrypt-config --libs) + # Debian has removed -lgpg-error from libgcrypt-config + # as it "spreads unnecessary dependencies" which in + # turn breaks static builds... + if test "$static" = "yes" + then + gcrypt_libs="$gcrypt_libs -lgpg-error" + fi + + # Link test to make sure the given libraries work (e.g for static). + write_c_skeleton + if compile_prog "" "$gcrypt_libs" ; then + LIBS="$gcrypt_libs $LIBS" + QEMU_CFLAGS="$QEMU_CFLAGS $gcrypt_cflags" + pass="yes" + fi + fi + if test "$pass" = "yes"; then + gcrypt="yes" + cat > $TMPC << EOF +#include +int main(void) { + gcry_mac_hd_t handle; + gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5, + GCRY_MAC_FLAG_SECURE, NULL); + return 0; +} +EOF + if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then + gcrypt_hmac=yes + fi + cat > $TMPC << EOF +#include +int main(void) { + gcry_cipher_hd_t handle; + gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_XTS, 0); + return 0; +} +EOF + if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then + gcrypt_xts=yes + qemu_private_xts=no + fi + elif test "$gcrypt" = "yes"; then + feature_not_found "gcrypt" "Install gcrypt devel >= 1.5.0" + else + gcrypt="no" + fi +fi + + +if test "$gcrypt" = "yes" && test "$nettle" = "yes" +then + error_exit "Only one of gcrypt & nettle can be enabled" +fi + +########################################## +# libtasn1 - only for the TLS creds/session test suite + +tasn1=yes +tasn1_cflags="" +tasn1_libs="" +if $pkg_config --exists "libtasn1"; then + tasn1_cflags=$($pkg_config --cflags libtasn1) + tasn1_libs=$($pkg_config --libs libtasn1) +else + tasn1=no +fi + + +########################################## +# PAM probe + +if test "$auth_pam" != "no"; then + cat > $TMPC < +#include +int main(void) { + const char *service_name = "qemu"; + const char *user = "frank"; + const struct pam_conv pam_conv = { 0 }; + pam_handle_t *pamh = NULL; + pam_start(service_name, user, &pam_conv, &pamh); + return 0; +} +EOF + if compile_prog "" "-lpam" ; then + auth_pam=yes + else + if test "$auth_pam" = "yes"; then + feature_not_found "PAM" "Install PAM development package" + else + auth_pam=no + fi + fi +fi + +########################################## +# getifaddrs (for tests/test-io-channel-socket ) + +have_ifaddrs_h=yes +if ! check_include "ifaddrs.h" ; then + have_ifaddrs_h=no +fi + +######################################### +# libdrm check +have_drm_h=no +if check_include "libdrm/drm.h" ; then + have_drm_h=yes +fi + +######################################### +# sys/signal.h check +have_sys_signal_h=no +if check_include "sys/signal.h" ; then + have_sys_signal_h=yes +fi + +########################################## +# VTE probe + +if test "$vte" != "no"; then + vteminversion="0.32.0" + if $pkg_config --exists "vte-2.91"; then + vtepackage="vte-2.91" + else + vtepackage="vte-2.90" + fi + if $pkg_config --exists "$vtepackage >= $vteminversion"; then + vte_cflags=$($pkg_config --cflags $vtepackage) + vte_libs=$($pkg_config --libs $vtepackage) + vteversion=$($pkg_config --modversion $vtepackage) + vte="yes" + elif test "$vte" = "yes"; then + feature_not_found "vte" "Install libvte-2.90/2.91 devel" + else + vte="no" + fi +fi + +########################################## +# RDMA needs OpenFabrics libraries +if test "$rdma" != "no" ; then + cat > $TMPC < +int main(void) { return 0; } +EOF + rdma_libs="-lrdmacm -libverbs -libumad" + if compile_prog "" "$rdma_libs" ; then + rdma="yes" + else + if test "$rdma" = "yes" ; then + error_exit \ + " OpenFabrics librdmacm/libibverbs/libibumad not present." \ + " Your options:" \ + " (1) Fast: Install infiniband packages (devel) from your distro." \ + " (2) Cleanest: Install libraries from www.openfabrics.org" \ + " (3) Also: Install softiwarp if you don't have RDMA hardware" + fi + rdma="no" + fi +fi + +########################################## +# PVRDMA detection + +cat > $TMPC < + +int +main(void) +{ + char buf = 0; + void *addr = &buf; + addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED); + + return 0; +} +EOF + +if test "$rdma" = "yes" ; then + case "$pvrdma" in + "") + if compile_prog "" ""; then + pvrdma="yes" + else + pvrdma="no" + fi + ;; + "yes") + if ! compile_prog "" ""; then + error_exit "PVRDMA is not supported since mremap is not implemented" + fi + pvrdma="yes" + ;; + "no") + pvrdma="no" + ;; + esac +else + if test "$pvrdma" = "yes" ; then + error_exit "PVRDMA requires rdma suppport" + fi + pvrdma="no" +fi + +# Let's see if enhanced reg_mr is supported +if test "$pvrdma" = "yes" ; then + +cat > $TMPC < + +int +main(void) +{ + struct ibv_mr *mr; + struct ibv_pd *pd = NULL; + size_t length = 10; + uint64_t iova = 0; + int access = 0; + void *addr = NULL; + + mr = ibv_reg_mr_iova(pd, addr, length, iova, access); + + ibv_dereg_mr(mr); + + return 0; +} +EOF + if ! compile_prog "" "-libverbs"; then + QEMU_CFLAGS="$QEMU_CFLAGS -DLEGACY_RDMA_REG_MR" + fi +fi + +########################################## +# xfsctl() probe, used for file-posix.c +if test "$xfs" != "no" ; then + cat > $TMPC << EOF +#include /* NULL */ +#include +int main(void) +{ + xfsctl(NULL, 0, 0, NULL); + return 0; +} +EOF + if compile_prog "" "" ; then + xfs="yes" + else + if test "$xfs" = "yes" ; then + feature_not_found "xfs" "Instal xfsprogs/xfslibs devel" + fi + xfs=no + fi +fi + +########################################## +# vde libraries probe +if test "$vde" != "no" ; then + vde_libs="-lvdeplug" + cat > $TMPC << EOF +#include +int main(void) +{ + struct vde_open_args a = {0, 0, 0}; + char s[] = ""; + vde_open(s, s, &a); + return 0; +} +EOF + if compile_prog "" "$vde_libs" ; then + vde=yes + else + if test "$vde" = "yes" ; then + feature_not_found "vde" "Install vde (Virtual Distributed Ethernet) devel" + fi + vde=no + fi +fi + +########################################## +# netmap support probe +# Apart from looking for netmap headers, we make sure that the host API version +# supports the netmap backend (>=11). The upper bound (15) is meant to simulate +# a minor/major version number. Minor new features will be marked with values up +# to 15, and if something happens that requires a change to the backend we will +# move above 15, submit the backend fixes and modify this two bounds. +if test "$netmap" != "no" ; then + cat > $TMPC << EOF +#include +#include +#include +#include +#if (NETMAP_API < 11) || (NETMAP_API > 15) +#error +#endif +int main(void) { return 0; } +EOF + if compile_prog "" "" ; then + netmap=yes + else + if test "$netmap" = "yes" ; then + feature_not_found "netmap" + fi + netmap=no + fi +fi + +########################################## +# libcap-ng library probe +if test "$cap_ng" != "no" ; then + cap_libs="-lcap-ng" + cat > $TMPC << EOF +#include +int main(void) +{ + capng_capability_to_name(CAPNG_EFFECTIVE); + return 0; +} +EOF + if compile_prog "" "$cap_libs" ; then + cap_ng=yes + else + if test "$cap_ng" = "yes" ; then + feature_not_found "cap_ng" "Install libcap-ng devel" + fi + cap_ng=no + fi +fi + +########################################## +# Sound support libraries probe + +audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/,/ /g') +for drv in $audio_drv_list; do + case $drv in + alsa | try-alsa) + if $pkg_config alsa --exists; then + alsa_libs=$($pkg_config alsa --libs) + alsa_cflags=$($pkg_config alsa --cflags) + alsa=yes + if test "$drv" = "try-alsa"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-alsa/alsa/') + fi + else + if test "$drv" = "try-alsa"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-alsa//') + else + error_exit "$drv check failed" \ + "Make sure to have the $drv libs and headers installed." + fi + fi + ;; + + pa | try-pa) + if $pkg_config libpulse --exists; then + libpulse=yes + pulse_libs=$($pkg_config libpulse --libs) + pulse_cflags=$($pkg_config libpulse --cflags) + if test "$drv" = "try-pa"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/') + fi + else + if test "$drv" = "try-pa"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa//') + else + error_exit "$drv check failed" \ + "Make sure to have the $drv libs and headers installed." + fi + fi + ;; + + sdl) + if test "$sdl" = "no"; then + error_exit "sdl not found or disabled, can not use sdl audio driver" + fi + ;; + + try-sdl) + if test "$sdl" = "no"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sdl//') + else + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sdl/sdl/') + fi + ;; + + coreaudio) + coreaudio_libs="-framework CoreAudio" + ;; + + dsound) + dsound_libs="-lole32 -ldxguid" + audio_win_int="yes" + ;; + + oss) + oss_libs="$oss_lib" + ;; + + jack | try-jack) + if $pkg_config jack --exists; then + libjack=yes + jack_libs=$($pkg_config jack --libs) + if test "$drv" = "try-jack"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack/jack/') + fi + else + if test "$drv" = "try-jack"; then + audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack//') + else + error_exit "$drv check failed" \ + "Make sure to have the $drv libs and headers installed." + fi + fi + ;; + + *) + echo "$audio_possible_drivers" | grep -q "\<$drv\>" || { + error_exit "Unknown driver '$drv' selected" \ + "Possible drivers are: $audio_possible_drivers" + } + ;; + esac +done + +########################################## +# BrlAPI probe + +if test "$brlapi" != "no" ; then + brlapi_libs="-lbrlapi" + cat > $TMPC << EOF +#include +#include +int main( void ) { return brlapi__openConnection (NULL, NULL, NULL); } +EOF + if compile_prog "" "$brlapi_libs" ; then + brlapi=yes + else + if test "$brlapi" = "yes" ; then + feature_not_found "brlapi" "Install brlapi devel" + fi + brlapi=no + fi +fi + +########################################## +# iconv probe +if test "$iconv" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { + iconv_t conv = iconv_open("WCHAR_T", "UCS-2"); + return conv != (iconv_t) -1; +} +EOF + iconv_prefix_list="/usr/local:/usr" + iconv_lib_list=":-liconv" + IFS=: + for iconv_prefix in $iconv_prefix_list; do + IFS=: + iconv_cflags="-I$iconv_prefix/include" + iconv_ldflags="-L$iconv_prefix/lib" + for iconv_link in $iconv_lib_list; do + unset IFS + iconv_lib="$iconv_ldflags $iconv_link" + echo "looking at iconv in '$iconv_cflags' '$iconv_lib'" >> config.log + if compile_prog "$iconv_cflags" "$iconv_lib" ; then + iconv_found=yes + break + fi + done + if test "$iconv_found" = yes ; then + break + fi + done + if test "$iconv_found" = "yes" ; then + iconv=yes + else + if test "$iconv" = "yes" ; then + feature_not_found "iconv" "Install iconv devel" + fi + iconv=no + fi +fi + +########################################## +# curses probe +if test "$iconv" = "no" ; then + # curses will need iconv + curses=no +fi +if test "$curses" != "no" ; then + if test "$mingw32" = "yes" ; then + curses_inc_list="$($pkg_config --cflags ncurses 2>/dev/null):" + curses_lib_list="$($pkg_config --libs ncurses 2>/dev/null):-lpdcurses" + else + curses_inc_list="$($pkg_config --cflags ncursesw 2>/dev/null):-I/usr/include/ncursesw:" + curses_lib_list="$($pkg_config --libs ncursesw 2>/dev/null):-lncursesw:-lcursesw" + fi + curses_found=no + cat > $TMPC << EOF +#include +#include +#include +#include +int main(void) { + const char *codeset; + wchar_t wch = L'w'; + setlocale(LC_ALL, ""); + resize_term(0, 0); + addwstr(L"wide chars\n"); + addnwstr(&wch, 1); + add_wch(WACS_DEGREE); + codeset = nl_langinfo(CODESET); + return codeset != 0; +} +EOF + IFS=: + for curses_inc in $curses_inc_list; do + # Make sure we get the wide character prototypes + curses_inc="-DNCURSES_WIDECHAR $curses_inc" + IFS=: + for curses_lib in $curses_lib_list; do + unset IFS + if compile_prog "$curses_inc" "$curses_lib" ; then + curses_found=yes + break + fi + done + if test "$curses_found" = yes ; then + break + fi + done + unset IFS + if test "$curses_found" = "yes" ; then + curses=yes + else + if test "$curses" = "yes" ; then + feature_not_found "curses" "Install ncurses devel" + fi + curses=no + fi +fi + +########################################## +# curl probe +if test "$curl" != "no" ; then + if $pkg_config libcurl --exists; then + curlconfig="$pkg_config libcurl" + else + curlconfig=curl-config + fi + cat > $TMPC << EOF +#include +int main(void) { curl_easy_init(); curl_multi_setopt(0, 0, 0); return 0; } +EOF + curl_cflags=$($curlconfig --cflags 2>/dev/null) + curl_libs=$($curlconfig --libs 2>/dev/null) + if compile_prog "$curl_cflags" "$curl_libs" ; then + curl=yes + else + if test "$curl" = "yes" ; then + feature_not_found "curl" "Install libcurl devel" + fi + curl=no + fi +fi # test "$curl" + +########################################## +# glib support probe + +glib_req_ver=2.48 +glib_modules=gthread-2.0 +if test "$modules" = yes; then + glib_modules="$glib_modules gmodule-export-2.0" +fi +if test "$plugins" = yes; then + glib_modules="$glib_modules gmodule-2.0" +fi + +# This workaround is required due to a bug in pkg-config file for glib as it +# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static + +if test "$static" = yes && test "$mingw32" = yes; then + QEMU_CFLAGS="-DGLIB_STATIC_COMPILATION $QEMU_CFLAGS" +fi + +for i in $glib_modules; do + if $pkg_config --atleast-version=$glib_req_ver $i; then + glib_cflags=$($pkg_config --cflags $i) + glib_libs=$($pkg_config --libs $i) + QEMU_CFLAGS="$glib_cflags $QEMU_CFLAGS" + LIBS="$glib_libs $LIBS" + else + error_exit "glib-$glib_req_ver $i is required to compile QEMU" + fi +done + +if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then + gio=yes + gio_cflags=$($pkg_config --cflags gio-2.0) + gio_libs=$($pkg_config --libs gio-2.0) + gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0) + if [ ! -x "$gdbus_codegen" ]; then + gdbus_codegen= + fi +else + gio=no +fi + +if $pkg_config --atleast-version=$glib_req_ver gio-unix-2.0; then + gio_cflags="$gio_cflags $($pkg_config --cflags gio-unix-2.0)" + gio_libs="$gio_libs $($pkg_config --libs gio-unix-2.0)" +fi + +# Sanity check that the current size_t matches the +# size that glib thinks it should be. This catches +# problems on multi-arch where people try to build +# 32-bit QEMU while pointing at 64-bit glib headers +cat > $TMPC < +#include + +#define QEMU_BUILD_BUG_ON(x) \ + typedef char qemu_build_bug_on[(x)?-1:1] __attribute__((unused)); + +int main(void) { + QEMU_BUILD_BUG_ON(sizeof(size_t) != GLIB_SIZEOF_SIZE_T); + return 0; +} +EOF + +if ! compile_prog "$CFLAGS" "$LIBS" ; then + error_exit "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\ + "You probably need to set PKG_CONFIG_LIBDIR"\ + "to point to the right pkg-config files for your"\ + "build target" +fi + +# Silence clang 3.5.0 warnings about glib attribute __alloc_size__ usage +cat > $TMPC << EOF +#include +int main(void) { return 0; } +EOF +if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then + if cc_has_warning_flag "-Wno-unknown-attributes"; then + glib_cflags="-Wno-unknown-attributes $glib_cflags" + QEMU_CFLAGS="-Wno-unknown-attributes $CFLAGS" + fi +fi + +# Silence clang warnings triggered by glib < 2.57.2 +cat > $TMPC << EOF +#include +typedef struct Foo { + int i; +} Foo; +static void foo_free(Foo *f) +{ + g_free(f); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free); +int main(void) { return 0; } +EOF +if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then + if cc_has_warning_flag "-Wno-unused-function"; then + glib_cflags="$glib_cflags -Wno-unused-function" + CFLAGS="$CFLAGS -Wno-unused-function" + fi +fi + +########################################## +# SHA command probe for modules +if test "$modules" = yes; then + shacmd_probe="sha1sum sha1 shasum" + for c in $shacmd_probe; do + if has $c; then + shacmd="$c" + break + fi + done + if test "$shacmd" = ""; then + error_exit "one of the checksum commands is required to enable modules: $shacmd_probe" + fi +fi + +########################################## +# libmpathpersist probe + +if test "$mpath" != "no" ; then + # probe for the new API + cat > $TMPC < +#include +unsigned mpath_mx_alloc_len = 1024; +int logsink; +static struct config *multipath_conf; +extern struct udev *udev; +extern struct config *get_multipath_config(void); +extern void put_multipath_config(struct config *conf); +struct udev *udev; +struct config *get_multipath_config(void) { return multipath_conf; } +void put_multipath_config(struct config *conf) { } + +int main(void) { + udev = udev_new(); + multipath_conf = mpath_lib_init(); + return 0; +} +EOF + if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then + mpathpersist=yes + mpathpersist_new_api=yes + else + # probe for the old API + cat > $TMPC < +#include +unsigned mpath_mx_alloc_len = 1024; +int logsink; +int main(void) { + struct udev *udev = udev_new(); + mpath_lib_init(udev); + return 0; +} +EOF + if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then + mpathpersist=yes + mpathpersist_new_api=no + else + mpathpersist=no + fi + fi +else + mpathpersist=no +fi + +########################################## +# pthread probe +PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2" + +pthread=no +cat > $TMPC << EOF +#include +static void *f(void *p) { return NULL; } +int main(void) { + pthread_t thread; + pthread_create(&thread, 0, f, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + pthread=yes +else + for pthread_lib in $PTHREADLIBS_LIST; do + if compile_prog "" "$pthread_lib" ; then + pthread=yes + found=no + for lib_entry in $LIBS; do + if test "$lib_entry" = "$pthread_lib"; then + found=yes + break + fi + done + if test "$found" = "no"; then + LIBS="$pthread_lib $LIBS" + fi + PTHREAD_LIB="$pthread_lib" + break + fi + done +fi + +if test "$mingw32" != yes && test "$pthread" = no; then + error_exit "pthread check failed" \ + "Make sure to have the pthread libs and headers installed." +fi + +# check for pthread_setname_np with thread id +pthread_setname_np_w_tid=no +cat > $TMPC << EOF +#include + +static void *f(void *p) { return NULL; } +int main(void) +{ + pthread_t thread; + pthread_create(&thread, 0, f, 0); + pthread_setname_np(thread, "QEMU"); + return 0; +} +EOF +if compile_prog "" "$pthread_lib" ; then + pthread_setname_np_w_tid=yes +fi + +# check for pthread_setname_np without thread id +pthread_setname_np_wo_tid=no +cat > $TMPC << EOF +#include + +static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; } +int main(void) +{ + pthread_t thread; + pthread_create(&thread, 0, f, 0); + return 0; +} +EOF +if compile_prog "" "$pthread_lib" ; then + pthread_setname_np_wo_tid=yes +fi + +########################################## +# rbd probe +if test "$rbd" != "no" ; then + cat > $TMPC < +#include +int main(void) { + rados_t cluster; + rados_create(&cluster, NULL); + return 0; +} +EOF + rbd_libs="-lrbd -lrados" + if compile_prog "" "$rbd_libs" ; then + rbd=yes + else + if test "$rbd" = "yes" ; then + feature_not_found "rados block device" "Install librbd/ceph devel" + fi + rbd=no + fi +fi + +########################################## +# libssh probe +if test "$libssh" != "no" ; then + if $pkg_config --exists libssh; then + libssh_cflags=$($pkg_config libssh --cflags) + libssh_libs=$($pkg_config libssh --libs) + libssh=yes + else + if test "$libssh" = "yes" ; then + error_exit "libssh required for --enable-libssh" + fi + libssh=no + fi +fi + +########################################## +# Check for libssh 0.8 +# This is done like this instead of using the LIBSSH_VERSION_* and +# SSH_VERSION_* macros because some distributions in the past shipped +# snapshots of the future 0.8 from Git, and those snapshots did not +# have updated version numbers (still referring to 0.7.0). + +if test "$libssh" = "yes"; then + cat > $TMPC < +int main(void) { return ssh_get_server_publickey(NULL, NULL); } +EOF + if compile_prog "$libssh_cflags" "$libssh_libs"; then + libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags" + fi +fi + +########################################## +# linux-aio probe + +if test "$linux_aio" != "no" ; then + cat > $TMPC < +#include +#include +int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); return 0; } +EOF + if compile_prog "" "-laio" ; then + linux_aio=yes + else + if test "$linux_aio" = "yes" ; then + feature_not_found "linux AIO" "Install libaio devel" + fi + linux_aio=no + fi +fi +########################################## +# linux-io-uring probe + +if test "$linux_io_uring" != "no" ; then + if $pkg_config liburing; then + linux_io_uring_cflags=$($pkg_config --cflags liburing) + linux_io_uring_libs=$($pkg_config --libs liburing) + linux_io_uring=yes + + # io_uring is used in libqemuutil.a where per-file -libs variables are not + # seen by programs linking the archive. It's not ideal, but just add the + # library dependency globally. + LIBS="$linux_io_uring_libs $LIBS" + else + if test "$linux_io_uring" = "yes" ; then + feature_not_found "linux io_uring" "Install liburing devel" + fi + linux_io_uring=no + fi +fi + +########################################## +# TPM emulation is only on POSIX + +if test "$tpm" = ""; then + if test "$mingw32" = "yes"; then + tpm=no + else + tpm=yes + fi +elif test "$tpm" = "yes"; then + if test "$mingw32" = "yes" ; then + error_exit "TPM emulation only available on POSIX systems" + fi +fi + +########################################## +# attr probe + +libattr_libs= +if test "$attr" != "no" ; then + cat > $TMPC < +#include +#ifdef CONFIG_LIBATTR +#include +#else +#include +#endif +int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; } +EOF + if compile_prog "" "" ; then + attr=yes + # Older distros have , and need -lattr: + elif compile_prog "-DCONFIG_LIBATTR" "-lattr" ; then + attr=yes + libattr_libs="-lattr" + LIBS="$libattr_libs $LIBS" + libattr=yes + else + if test "$attr" = "yes" ; then + feature_not_found "ATTR" "Install libc6 or libattr devel" + fi + attr=no + fi +fi + +########################################## +# iovec probe +cat > $TMPC < +#include +#include +int main(void) { return sizeof(struct iovec); } +EOF +iovec=no +if compile_prog "" "" ; then + iovec=yes +fi + +########################################## +# preadv probe +cat > $TMPC < +#include +#include +int main(void) { return preadv(0, 0, 0, 0); } +EOF +preadv=no +if compile_prog "" "" ; then + preadv=yes +fi + +########################################## +# fdt probe +# fdt support is mandatory for at least some target architectures, +# so insist on it if we're building those system emulators. +fdt_required=no +for target in $target_list; do + case $target in + aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu|rx-softmmu) + fdt_required=yes + ;; + esac +done + +if test "$fdt_required" = "yes"; then + if test "$fdt" = "no"; then + error_exit "fdt disabled but some requested targets require it." \ + "You can turn off fdt only if you also disable all the system emulation" \ + "targets which need it (by specifying a cut down --target-list)." + fi + fdt=yes +elif test "$fdt" != "yes" ; then + fdt=no +fi + +# fdt is only required when building softmmu targets +if test -z "$fdt" -a "$softmmu" != "yes" ; then + fdt="no" +fi + +if test "$fdt" != "no" ; then + fdt_libs="-lfdt" + # explicitly check for libfdt_env.h as it is missing in some stable installs + # and test for required functions to make sure we are on a version >= 1.4.2 + cat > $TMPC << EOF +#include +#include +int main(void) { fdt_check_full(NULL, 0); return 0; } +EOF + if compile_prog "" "$fdt_libs" ; then + # system DTC is good - use it + fdt=system + else + # have GIT checkout, so activate dtc submodule + if test -e "${source_path}/.git" ; then + git_submodules="${git_submodules} dtc" + fi + if test -d "${source_path}/dtc/libfdt" || test -e "${source_path}/.git" ; then + fdt=git + mkdir -p dtc + fdt_cflags="-I${source_path}/dtc/libfdt" + fdt_ldflags="-L${build_path}/dtc/libfdt" + fdt_libs="$fdt_libs" + elif test "$fdt" = "yes" ; then + # Not a git build & no libfdt found, prompt for system install + error_exit "DTC (libfdt) version >= 1.4.2 not present." \ + "Please install the DTC (libfdt) devel package" + else + # don't have and don't want + fdt_libs= + fdt=no + fi + fi +fi + +########################################## +# opengl probe (for sdl2, gtk, milkymist-tmu2) + +gbm="no" +if $pkg_config gbm; then + gbm_cflags="$($pkg_config --cflags gbm)" + gbm_libs="$($pkg_config --libs gbm)" + gbm="yes" +fi + +if test "$opengl" != "no" ; then + opengl_pkgs="epoxy gbm" + if $pkg_config $opengl_pkgs; then + opengl_cflags="$($pkg_config --cflags $opengl_pkgs)" + opengl_libs="$($pkg_config --libs $opengl_pkgs)" + opengl=yes + if test "$gtk" = "yes" && $pkg_config --exists "$gtkpackage >= 3.16"; then + gtk_gl="yes" + fi + QEMU_CFLAGS="$QEMU_CFLAGS $opengl_cflags" + else + if test "$opengl" = "yes" ; then + feature_not_found "opengl" "Please install opengl (mesa) devel pkgs: $opengl_pkgs" + fi + opengl_cflags="" + opengl_libs="" + opengl=no + fi +fi + +if test "$opengl" = "yes"; then + cat > $TMPC << EOF +#include +#ifndef EGL_MESA_image_dma_buf_export +# error mesa/epoxy lacks support for dmabufs (mesa 10.6+) +#endif +int main(void) { return 0; } +EOF + if compile_prog "" "" ; then + opengl_dmabuf=yes + fi +fi + +if test "$opengl" = "yes" && test "$have_x11" = "yes"; then + for target in $target_list; do + case $target in + lm32-softmmu) # milkymist-tmu2 requires X11 and OpenGL + need_x11=yes + ;; + esac + done +fi + +########################################## +# libxml2 probe +if test "$libxml2" != "no" ; then + if $pkg_config --exists libxml-2.0; then + libxml2="yes" + libxml2_cflags=$($pkg_config --cflags libxml-2.0) + libxml2_libs=$($pkg_config --libs libxml-2.0) + else + if test "$libxml2" = "yes"; then + feature_not_found "libxml2" "Install libxml2 devel" + fi + libxml2="no" + fi +fi + +########################################## +# glusterfs probe +if test "$glusterfs" != "no" ; then + if $pkg_config --atleast-version=3 glusterfs-api; then + glusterfs="yes" + glusterfs_cflags=$($pkg_config --cflags glusterfs-api) + glusterfs_libs=$($pkg_config --libs glusterfs-api) + if $pkg_config --atleast-version=4 glusterfs-api; then + glusterfs_xlator_opt="yes" + fi + if $pkg_config --atleast-version=5 glusterfs-api; then + glusterfs_discard="yes" + fi + if $pkg_config --atleast-version=6 glusterfs-api; then + glusterfs_fallocate="yes" + glusterfs_zerofill="yes" + fi + cat > $TMPC << EOF +#include + +int +main(void) +{ + /* new glfs_ftruncate() passes two additional args */ + return glfs_ftruncate(NULL, 0, NULL, NULL); +} +EOF + if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then + glusterfs_ftruncate_has_stat="yes" + fi + cat > $TMPC << EOF +#include + +/* new glfs_io_cbk() passes two additional glfs_stat structs */ +static void +glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data) +{} + +int +main(void) +{ + glfs_io_cbk iocb = &glusterfs_iocb; + iocb(NULL, 0 , NULL, NULL, NULL); + return 0; +} +EOF + if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then + glusterfs_iocb_has_stat="yes" + fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ + "Install glusterfs-api devel >= 3" + fi + glusterfs="no" + fi +fi + +# Check for inotify functions when we are building linux-user +# emulator. This is done because older glibc versions don't +# have syscall stubs for these implemented. In that case we +# don't provide them even if kernel supports them. +# +inotify=no +cat > $TMPC << EOF +#include + +int +main(void) +{ + /* try to start inotify */ + return inotify_init(); +} +EOF +if compile_prog "" "" ; then + inotify=yes +fi + +inotify1=no +cat > $TMPC << EOF +#include + +int +main(void) +{ + /* try to start inotify */ + return inotify_init1(0); +} +EOF +if compile_prog "" "" ; then + inotify1=yes +fi + +# check if pipe2 is there +pipe2=no +cat > $TMPC << EOF +#include +#include + +int main(void) +{ + int pipefd[2]; + return pipe2(pipefd, O_CLOEXEC); +} +EOF +if compile_prog "" "" ; then + pipe2=yes +fi + +# check if accept4 is there +accept4=no +cat > $TMPC << EOF +#include +#include + +int main(void) +{ + accept4(0, NULL, NULL, SOCK_CLOEXEC); + return 0; +} +EOF +if compile_prog "" "" ; then + accept4=yes +fi + +# check if tee/splice is there. vmsplice was added same time. +splice=no +cat > $TMPC << EOF +#include +#include +#include + +int main(void) +{ + int len, fd = 0; + len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK); + splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE); + return 0; +} +EOF +if compile_prog "" "" ; then + splice=yes +fi + +########################################## +# libnuma probe + +if test "$numa" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { return numa_available(); } +EOF + + if compile_prog "" "-lnuma" ; then + numa=yes + numa_libs="-lnuma" + else + if test "$numa" = "yes" ; then + feature_not_found "numa" "install numactl devel" + fi + numa=no + fi +fi + +if test "$tcmalloc" = "yes" && test "$jemalloc" = "yes" ; then + echo "ERROR: tcmalloc && jemalloc can't be used at the same time" + exit 1 +fi + +# Even if malloc_trim() is available, these non-libc memory allocators +# do not support it. +if test "$tcmalloc" = "yes" || test "$jemalloc" = "yes" ; then + if test "$malloc_trim" = "yes" ; then + echo "Disabling malloc_trim with non-libc memory allocator" + fi + malloc_trim="no" +fi + +####################################### +# malloc_trim + +if test "$malloc_trim" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { malloc_trim(0); return 0; } +EOF + if compile_prog "" "" ; then + malloc_trim="yes" + else + malloc_trim="no" + fi +fi + +########################################## +# tcmalloc probe + +if test "$tcmalloc" = "yes" ; then + cat > $TMPC << EOF +#include +int main(void) { + void *tmp = malloc(1); + if (tmp != NULL) { + return 0; + } + return 1; +} +EOF + + if compile_prog "" "-ltcmalloc" ; then + LIBS="-ltcmalloc $LIBS" + else + feature_not_found "tcmalloc" "install gperftools devel" + fi +fi + +########################################## +# jemalloc probe + +if test "$jemalloc" = "yes" ; then + cat > $TMPC << EOF +#include +int main(void) { + void *tmp = malloc(1); + if (tmp != NULL) { + return 0; + } + return 1; +} +EOF + + if compile_prog "" "-ljemalloc" ; then + LIBS="-ljemalloc $LIBS" + else + feature_not_found "jemalloc" "install jemalloc devel" + fi +fi + +########################################## +# signalfd probe +signalfd="no" +cat > $TMPC << EOF +#include +#include +#include +int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); } +EOF + +if compile_prog "" "" ; then + signalfd=yes +fi + +# check if optreset global is declared by +optreset="no" +cat > $TMPC << EOF +#include +int main(void) { return optreset; } +EOF + +if compile_prog "" "" ; then + optreset=yes +fi + +# check if eventfd is supported +eventfd=no +cat > $TMPC << EOF +#include + +int main(void) +{ + return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); +} +EOF +if compile_prog "" "" ; then + eventfd=yes +fi + +# check if memfd is supported +memfd=no +cat > $TMPC << EOF +#include + +int main(void) +{ + return memfd_create("foo", MFD_ALLOW_SEALING); +} +EOF +if compile_prog "" "" ; then + memfd=yes +fi + +# check for usbfs +have_usbfs=no +if test "$linux_user" = "yes"; then + cat > $TMPC << EOF +#include + +#ifndef USBDEVFS_GET_CAPABILITIES +#error "USBDEVFS_GET_CAPABILITIES undefined" +#endif + +#ifndef USBDEVFS_DISCONNECT_CLAIM +#error "USBDEVFS_DISCONNECT_CLAIM undefined" +#endif + +int main(void) +{ + return 0; +} +EOF + if compile_prog "" ""; then + have_usbfs=yes + fi +fi + +# check for fallocate +fallocate=no +cat > $TMPC << EOF +#include + +int main(void) +{ + fallocate(0, 0, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + fallocate=yes +fi + +# check for fallocate hole punching +fallocate_punch_hole=no +cat > $TMPC << EOF +#include +#include + +int main(void) +{ + fallocate(0, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + fallocate_punch_hole=yes +fi + +# check that fallocate supports range zeroing inside the file +fallocate_zero_range=no +cat > $TMPC << EOF +#include +#include + +int main(void) +{ + fallocate(0, FALLOC_FL_ZERO_RANGE, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + fallocate_zero_range=yes +fi + +# check for posix_fallocate +posix_fallocate=no +cat > $TMPC << EOF +#include + +int main(void) +{ + posix_fallocate(0, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + posix_fallocate=yes +fi + +# check for sync_file_range +sync_file_range=no +cat > $TMPC << EOF +#include + +int main(void) +{ + sync_file_range(0, 0, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + sync_file_range=yes +fi + +# check for linux/fiemap.h and FS_IOC_FIEMAP +fiemap=no +cat > $TMPC << EOF +#include +#include +#include + +int main(void) +{ + ioctl(0, FS_IOC_FIEMAP, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + fiemap=yes +fi + +# check for dup3 +dup3=no +cat > $TMPC << EOF +#include + +int main(void) +{ + dup3(0, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + dup3=yes +fi + +# check for ppoll support +ppoll=no +cat > $TMPC << EOF +#include + +int main(void) +{ + struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 }; + ppoll(&pfd, 1, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + ppoll=yes +fi + +# check for prctl(PR_SET_TIMERSLACK , ... ) support +prctl_pr_set_timerslack=no +cat > $TMPC << EOF +#include + +int main(void) +{ + prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + prctl_pr_set_timerslack=yes +fi + +# check for epoll support +epoll=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_create(0); + return 0; +} +EOF +if compile_prog "" "" ; then + epoll=yes +fi + +# epoll_create1 is a later addition +# so we must check separately for its presence +epoll_create1=no +cat > $TMPC << EOF +#include + +int main(void) +{ + /* Note that we use epoll_create1 as a value, not as + * a function being called. This is necessary so that on + * old SPARC glibc versions where the function was present in + * the library but not declared in the header file we will + * fail the configure check. (Otherwise we will get a compiler + * warning but not an error, and will proceed to fail the + * qemu compile where we compile with -Werror.) + */ + return (int)(uintptr_t)&epoll_create1; +} +EOF +if compile_prog "" "" ; then + epoll_create1=yes +fi + +# check for sendfile support +sendfile=no +cat > $TMPC << EOF +#include + +int main(void) +{ + return sendfile(0, 0, 0, 0); +} +EOF +if compile_prog "" "" ; then + sendfile=yes +fi + +# check for timerfd support (glibc 2.8 and newer) +timerfd=no +cat > $TMPC << EOF +#include + +int main(void) +{ + return(timerfd_create(CLOCK_REALTIME, 0)); +} +EOF +if compile_prog "" "" ; then + timerfd=yes +fi + +# check for setns and unshare support +setns=no +cat > $TMPC << EOF +#include + +int main(void) +{ + int ret; + ret = setns(0, 0); + ret = unshare(0); + return ret; +} +EOF +if compile_prog "" "" ; then + setns=yes +fi + +# clock_adjtime probe +clock_adjtime=no +cat > $TMPC < + +int main(void) +{ + return clock_adjtime(0, 0); +} +EOF +clock_adjtime=no +if compile_prog "" "" ; then + clock_adjtime=yes +fi + +# syncfs probe +syncfs=no +cat > $TMPC < + +int main(void) +{ + return syncfs(0); +} +EOF +syncfs=no +if compile_prog "" "" ; then + syncfs=yes +fi + +# check for kcov support (kernel must be 4.4+, compiled with certain options) +kcov=no +if check_include sys/kcov.h ; then + kcov=yes +fi + +# If we're making warnings fatal, apply this to Sphinx runs as well +sphinx_werror="" +if test "$werror" = "yes"; then + sphinx_werror="-W" +fi + +# Check we have a new enough version of sphinx-build +has_sphinx_build() { + # This is a bit awkward but works: create a trivial document and + # try to run it with our configuration file (which enforces a + # version requirement). This will fail if either + # sphinx-build doesn't exist at all or if it is too old. + mkdir -p "$TMPDIR1/sphinx" + touch "$TMPDIR1/sphinx/index.rst" + "$sphinx_build" $sphinx_werror -c "$source_path/docs" \ + -b html "$TMPDIR1/sphinx" \ + "$TMPDIR1/sphinx/out" >> config.log 2>&1 +} + +# Check if tools are available to build documentation. +if test "$docs" != "no" ; then + if has_sphinx_build; then + sphinx_ok=yes + else + sphinx_ok=no + fi + if has makeinfo && has pod2man && test "$sphinx_ok" = "yes"; then + docs=yes + else + if test "$docs" = "yes" ; then + if has $sphinx_build && test "$sphinx_ok" != "yes"; then + echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2 + fi + feature_not_found "docs" "Install texinfo, Perl/perl-podlators and a Python 3 version of python-sphinx" + fi + docs=no + fi +fi + +# Search for bswap_32 function +byteswap_h=no +cat > $TMPC << EOF +#include +int main(void) { return bswap_32(0); } +EOF +if compile_prog "" "" ; then + byteswap_h=yes +fi + +# Search for bswap32 function +bswap_h=no +cat > $TMPC << EOF +#include +#include +#include +int main(void) { return bswap32(0); } +EOF +if compile_prog "" "" ; then + bswap_h=yes +fi + +########################################## +# Do we have libiscsi >= 1.9.0 +if test "$libiscsi" != "no" ; then + if $pkg_config --atleast-version=1.9.0 libiscsi; then + libiscsi="yes" + libiscsi_cflags=$($pkg_config --cflags libiscsi) + libiscsi_libs=$($pkg_config --libs libiscsi) + else + if test "$libiscsi" = "yes" ; then + feature_not_found "libiscsi" "Install libiscsi >= 1.9.0" + fi + libiscsi="no" + fi +fi + +########################################## +# Do we need libm +cat > $TMPC << EOF +#include +int main(int argc, char **argv) { return isnan(sin((double)argc)); } +EOF +if compile_prog "" "" ; then + : +elif compile_prog "" "-lm" ; then + LIBS="-lm $LIBS" +else + error_exit "libm check failed" +fi + +########################################## +# Do we need librt +# uClibc provides 2 versions of clock_gettime(), one with realtime +# support and one without. This means that the clock_gettime() don't +# need -lrt. We still need it for timer_create() so we check for this +# function in addition. +cat > $TMPC < +#include +int main(void) { + timer_create(CLOCK_REALTIME, NULL, NULL); + return clock_gettime(CLOCK_REALTIME, NULL); +} +EOF + +if compile_prog "" "" ; then + : +# we need pthread for static linking. use previous pthread test result +elif compile_prog "" "$pthread_lib -lrt" ; then + LIBS="$LIBS -lrt" +fi + +# Check whether we need to link libutil for openpty() +cat > $TMPC << EOF +extern int openpty(int *am, int *as, char *name, void *termp, void *winp); +int main(void) { return openpty(0, 0, 0, 0, 0); } +EOF + +have_openpty="no" +if compile_prog "" "" ; then + have_openpty="yes" +else + if compile_prog "" "-lutil" ; then + libs_tools="-lutil $libs_tools" + have_openpty="yes" + fi +fi + +########################################## +# spice probe +if test "$spice" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { spice_server_new(); return 0; } +EOF + spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null) + spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null) + if $pkg_config --atleast-version=0.12.5 spice-server && \ + $pkg_config --atleast-version=0.12.3 spice-protocol && \ + compile_prog "$spice_cflags" "$spice_libs" ; then + spice="yes" + QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" + else + if test "$spice" = "yes" ; then + feature_not_found "spice" \ + "Install spice-server(>=0.12.5) and spice-protocol(>=0.12.3) devel" + fi + spice="no" + fi +fi + +# check for smartcard support +if test "$smartcard" != "no"; then + if $pkg_config --atleast-version=2.5.1 libcacard; then + libcacard_cflags=$($pkg_config --cflags libcacard) + libcacard_libs=$($pkg_config --libs libcacard) + smartcard="yes" + else + if test "$smartcard" = "yes"; then + feature_not_found "smartcard" "Install libcacard devel" + fi + smartcard="no" + fi +fi + +# check for libusb +if test "$libusb" != "no" ; then + if $pkg_config --atleast-version=1.0.13 libusb-1.0; then + libusb="yes" + libusb_cflags=$($pkg_config --cflags libusb-1.0) + libusb_libs=$($pkg_config --libs libusb-1.0) + else + if test "$libusb" = "yes"; then + feature_not_found "libusb" "Install libusb devel >= 1.0.13" + fi + libusb="no" + fi +fi + +# check for usbredirparser for usb network redirection support +if test "$usb_redir" != "no" ; then + if $pkg_config --atleast-version=0.6 libusbredirparser-0.5; then + usb_redir="yes" + usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5) + usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5) + else + if test "$usb_redir" = "yes"; then + feature_not_found "usb-redir" "Install usbredir devel" + fi + usb_redir="no" + fi +fi + +########################################## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \ + test "$vss_win32_sdk" != "no" ; then + case "$vss_win32_sdk" in + "") vss_win32_include="-isystem $source_path" ;; + *\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we symlink the headers into ".sdk/vss". + vss_win32_include="-isystem $source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; + *) vss_win32_include="-isystem $vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then + guest_agent_with_vss="yes" + QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" + libs_qga="-lole32 -loleaut32 -lshlwapi -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + qga_vss_provider="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb" + else + if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK:" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490" + echo "ERROR: On POSIX-systems, you can extract the SDK headers by:" + echo "ERROR: scripts/extract-vsssdk-headers setup.exe" + echo "ERROR: The headers are extracted in the directory \`inc'." + feature_not_found "VSS support" + fi + guest_agent_with_vss="no" + fi +fi + +########################################## +# lookup Windows platform SDK (if not specified) +# The SDK is needed only to build .tlb (type library) file of guest agent +# VSS provider from the source. It is usually unnecessary because the +# pre-compiled .tlb file is included. + +if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \ + test "$guest_agent_with_vss" = "yes" ; then + if test -z "$win_sdk"; then + programfiles="$PROGRAMFILES" + test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432" + if test -n "$programfiles"; then + win_sdk=$(ls -d "$programfiles/Microsoft SDKs/Windows/v"* | tail -1) 2>/dev/null + else + feature_not_found "Windows SDK" + fi + elif test "$win_sdk" = "no"; then + win_sdk="" + fi +fi + +########################################## +# check if mingw environment provides a recent ntddscsi.h +if test "$mingw32" = "yes" && test "$guest_agent" != "no"; then + cat > $TMPC << EOF +#include +#include +int main(void) { +#if !defined(IOCTL_SCSI_GET_ADDRESS) +#error Missing required ioctl definitions +#endif + SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 }; + return addr.Lun; +} +EOF + if compile_prog "" "" ; then + guest_agent_ntddscsi=yes + libs_qga="-lsetupapi -lcfgmgr32 $libs_qga" + fi +fi + +########################################## +# virgl renderer probe + +if test "$virglrenderer" != "no" ; then + cat > $TMPC << EOF +#include +int main(void) { virgl_renderer_poll(); return 0; } +EOF + virgl_cflags=$($pkg_config --cflags virglrenderer 2>/dev/null) + virgl_libs=$($pkg_config --libs virglrenderer 2>/dev/null) + virgl_version=$($pkg_config --modversion virglrenderer 2>/dev/null) + if $pkg_config virglrenderer >/dev/null 2>&1 && \ + compile_prog "$virgl_cflags" "$virgl_libs" ; then + virglrenderer="yes" + else + if test "$virglrenderer" = "yes" ; then + feature_not_found "virglrenderer" + fi + virglrenderer="no" + fi +fi + +########################################## +# capstone + +case "$capstone" in + "" | yes) + if $pkg_config capstone; then + capstone=system + elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then + capstone=git + elif test -e "${source_path}/capstone/Makefile" ; then + capstone=internal + elif test -z "$capstone" ; then + capstone=no + else + feature_not_found "capstone" "Install capstone devel or git submodule" + fi + ;; + + system) + if ! $pkg_config capstone; then + feature_not_found "capstone" "Install capstone devel" + fi + ;; +esac + +case "$capstone" in + git | internal) + if test "$capstone" = git; then + git_submodules="${git_submodules} capstone" + fi + mkdir -p capstone + QEMU_CFLAGS="$QEMU_CFLAGS -I${source_path}/capstone/include -I${source_path}/capstone/include/capstone" + if test "$mingw32" = "yes"; then + LIBCAPSTONE=capstone.lib + else + LIBCAPSTONE=libcapstone.a + fi + capstone_libs="-L${build_path}/capstone -lcapstone" + capstone_cflags="-I${source_path}/capstone/include -I${source_path}/capstone/include/capstone" + ;; + + system) + capstone_libs="$($pkg_config --libs capstone)" + capstone_cflags="$($pkg_config --cflags capstone)" + QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags capstone)" + ;; + + no) + ;; + *) + error_exit "Unknown state for capstone: $capstone" + ;; +esac + +########################################## +# check if we have fdatasync + +fdatasync=no +cat > $TMPC << EOF +#include +int main(void) { +#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 +return fdatasync(0); +#else +#error Not supported +#endif +} +EOF +if compile_prog "" "" ; then + fdatasync=yes +fi + +########################################## +# check if we have madvise + +madvise=no +cat > $TMPC << EOF +#include +#include +#include +int main(void) { return madvise(NULL, 0, MADV_DONTNEED); } +EOF +if compile_prog "" "" ; then + madvise=yes +fi + +########################################## +# check if we have posix_madvise + +posix_madvise=no +cat > $TMPC << EOF +#include +#include +int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); } +EOF +if compile_prog "" "" ; then + posix_madvise=yes +fi + +########################################## +# check if we have posix_memalign() + +posix_memalign=no +cat > $TMPC << EOF +#include +int main(void) { + void *p; + return posix_memalign(&p, 8, 8); +} +EOF +if compile_prog "" "" ; then + posix_memalign=yes +fi + +########################################## +# check if we have posix_syslog + +posix_syslog=no +cat > $TMPC << EOF +#include +int main(void) { openlog("qemu", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "configure"); return 0; } +EOF +if compile_prog "" "" ; then + posix_syslog=yes +fi + +########################################## +# check if we have sem_timedwait + +sem_timedwait=no +cat > $TMPC << EOF +#include +int main(void) { sem_t s; struct timespec t = {0}; return sem_timedwait(&s, &t); } +EOF +if compile_prog "" "" ; then + sem_timedwait=yes +fi + +########################################## +# check if we have strchrnul + +strchrnul=no +cat > $TMPC << EOF +#include +int main(void); +// Use a haystack that the compiler shouldn't be able to constant fold +char *haystack = (char*)&main; +int main(void) { return strchrnul(haystack, 'x') != &haystack[6]; } +EOF +if compile_prog "" "" ; then + strchrnul=yes +fi + +######################################### +# check if we have st_atim + +st_atim=no +cat > $TMPC << EOF +#include +#include +int main(void) { return offsetof(struct stat, st_atim); } +EOF +if compile_prog "" "" ; then + st_atim=yes +fi + +########################################## +# check if trace backend exists + +$python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends > /dev/null 2> /dev/null +if test "$?" -ne 0 ; then + error_exit "invalid trace backends" \ + "Please choose supported trace backends." +fi + +########################################## +# For 'ust' backend, test if ust headers are present +if have_backend "ust"; then + cat > $TMPC << EOF +#include +int main(void) { return 0; } +EOF + if compile_prog "" "-Wl,--no-as-needed -ldl" ; then + if $pkg_config lttng-ust --exists; then + lttng_ust_libs=$($pkg_config --libs lttng-ust) + else + lttng_ust_libs="-llttng-ust -ldl" + fi + if $pkg_config liburcu-bp --exists; then + urcu_bp_libs=$($pkg_config --libs liburcu-bp) + else + urcu_bp_libs="-lurcu-bp" + fi + + LIBS="$lttng_ust_libs $urcu_bp_libs $LIBS" + else + error_exit "Trace backend 'ust' missing lttng-ust header files" + fi +fi + +########################################## +# For 'dtrace' backend, test if 'dtrace' command is present +if have_backend "dtrace"; then + if ! has 'dtrace' ; then + error_exit "dtrace command is not found in PATH $PATH" + fi + trace_backend_stap="no" + if has 'stap' ; then + trace_backend_stap="yes" + fi +fi + +########################################## +# check and set a backend for coroutine + +# We prefer ucontext, but it's not always possible. The fallback +# is sigcontext. On Windows the only valid backend is the Windows +# specific one. + +ucontext_works=no +if test "$darwin" != "yes"; then + cat > $TMPC << EOF +#include +#ifdef __stub_makecontext +#error Ignoring glibc stub makecontext which will always fail +#endif +int main(void) { makecontext(0, 0, 0); return 0; } +EOF + if compile_prog "" "" ; then + ucontext_works=yes + fi +fi + +if test "$coroutine" = ""; then + if test "$mingw32" = "yes"; then + coroutine=win32 + elif test "$ucontext_works" = "yes"; then + coroutine=ucontext + else + coroutine=sigaltstack + fi +else + case $coroutine in + windows) + if test "$mingw32" != "yes"; then + error_exit "'windows' coroutine backend only valid for Windows" + fi + # Unfortunately the user visible backend name doesn't match the + # coroutine-*.c filename for this case, so we have to adjust it here. + coroutine=win32 + ;; + ucontext) + if test "$ucontext_works" != "yes"; then + feature_not_found "ucontext" + fi + ;; + sigaltstack) + if test "$mingw32" = "yes"; then + error_exit "only the 'windows' coroutine backend is valid for Windows" + fi + ;; + *) + error_exit "unknown coroutine backend $coroutine" + ;; + esac +fi + +if test "$coroutine_pool" = ""; then + coroutine_pool=yes +fi + +if test "$debug_stack_usage" = "yes"; then + if test "$coroutine_pool" = "yes"; then + echo "WARN: disabling coroutine pool for stack usage debugging" + coroutine_pool=no + fi +fi + +################################################## +# SafeStack + + +if test "$safe_stack" = "yes"; then +cat > $TMPC << EOF +int main(int argc, char *argv[]) +{ +#if ! __has_feature(safe_stack) +#error SafeStack Disabled +#endif + return 0; +} +EOF + flag="-fsanitize=safe-stack" + # Check that safe-stack is supported and enabled. + if compile_prog "-Werror $flag" "$flag"; then + # Flag needed both at compilation and at linking + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" + else + error_exit "SafeStack not supported by your compiler" + fi + if test "$coroutine" != "ucontext"; then + error_exit "SafeStack is only supported by the coroutine backend ucontext" + fi +else +cat > $TMPC << EOF +int main(int argc, char *argv[]) +{ +#if defined(__has_feature) +#if __has_feature(safe_stack) +#error SafeStack Enabled +#endif +#endif + return 0; +} +EOF +if test "$safe_stack" = "no"; then + # Make sure that safe-stack is disabled + if ! compile_prog "-Werror" ""; then + # SafeStack was already enabled, try to explicitly remove the feature + flag="-fno-sanitize=safe-stack" + if ! compile_prog "-Werror $flag" "$flag"; then + error_exit "Configure cannot disable SafeStack" + fi + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" + fi +else # "$safe_stack" = "" + # Set safe_stack to yes or no based on pre-existing flags + if compile_prog "-Werror" ""; then + safe_stack="no" + else + safe_stack="yes" + if test "$coroutine" != "ucontext"; then + error_exit "SafeStack is only supported by the coroutine backend ucontext" + fi + fi +fi +fi + +########################################## +# check if we have open_by_handle_at + +open_by_handle_at=no +cat > $TMPC << EOF +#include +#if !defined(AT_EMPTY_PATH) +# error missing definition +#else +int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); } +#endif +EOF +if compile_prog "" "" ; then + open_by_handle_at=yes +fi + +######################################## +# check if we have linux/magic.h + +linux_magic_h=no +cat > $TMPC << EOF +#include +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + linux_magic_h=yes +fi + +######################################## +# check if we have valgrind/valgrind.h + +valgrind_h=no +cat > $TMPC << EOF +#include +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + valgrind_h=yes +fi + +######################################## +# check if environ is declared + +has_environ=no +cat > $TMPC << EOF +#include +int main(void) { + environ = 0; + return 0; +} +EOF +if compile_prog "" "" ; then + has_environ=yes +fi + +######################################## +# check if cpuid.h is usable. + +cat > $TMPC << EOF +#include +int main(void) { + unsigned a, b, c, d; + int max = __get_cpuid_max(0, 0); + + if (max >= 1) { + __cpuid(1, a, b, c, d); + } + + if (max >= 7) { + __cpuid_count(7, 0, a, b, c, d); + } + + return 0; +} +EOF +if compile_prog "" "" ; then + cpuid_h=yes +fi + +########################################## +# avx2 optimization requirement check +# +# There is no point enabling this if cpuid.h is not usable, +# since we won't be able to select the new routines. + +if test "$cpuid_h" = "yes" && test "$avx2_opt" != "no"; then + cat > $TMPC << EOF +#pragma GCC push_options +#pragma GCC target("avx2") +#include +#include +static int bar(void *a) { + __m256i x = *(__m256i *)a; + return _mm256_testz_si256(x, x); +} +int main(int argc, char *argv[]) { return bar(argv[0]); } +EOF + if compile_object "" ; then + avx2_opt="yes" + else + avx2_opt="no" + fi +fi + +########################################## +# avx512f optimization requirement check +# +# There is no point enabling this if cpuid.h is not usable, +# since we won't be able to select the new routines. +# by default, it is turned off. +# if user explicitly want to enable it, check environment + +if test "$cpuid_h" = "yes" && test "$avx512f_opt" = "yes"; then + cat > $TMPC << EOF +#pragma GCC push_options +#pragma GCC target("avx512f") +#include +#include +static int bar(void *a) { + __m512i x = *(__m512i *)a; + return _mm512_test_epi64_mask(x, x); +} +int main(int argc, char *argv[]) +{ + return bar(argv[0]); +} +EOF + if ! compile_object "" ; then + avx512f_opt="no" + fi +else + avx512f_opt="no" +fi + +######################################## +# check if __[u]int128_t is usable. + +int128=no +cat > $TMPC << EOF +__int128_t a; +__uint128_t b; +int main (void) { + a = a + b; + b = a * b; + a = a * a; + return 0; +} +EOF +if compile_prog "" "" ; then + int128=yes +fi + +######################################### +# See if 128-bit atomic operations are supported. + +atomic128=no +if test "$int128" = "yes"; then + cat > $TMPC << EOF +int main(void) +{ + unsigned __int128 x = 0, y = 0; + y = __atomic_load_16(&x, 0); + __atomic_store_16(&x, y, 0); + __atomic_compare_exchange_16(&x, &y, x, 0, 0, 0); + return 0; +} +EOF + if compile_prog "" "" ; then + atomic128=yes + fi +fi + +cmpxchg128=no +if test "$int128" = yes && test "$atomic128" = no; then + cat > $TMPC << EOF +int main(void) +{ + unsigned __int128 x = 0, y = 0; + __sync_val_compare_and_swap_16(&x, y, x); + return 0; +} +EOF + if compile_prog "" "" ; then + cmpxchg128=yes + fi +fi + +######################################### +# See if 64-bit atomic operations are supported. +# Note that without __atomic builtins, we can only +# assume atomic loads/stores max at pointer size. + +cat > $TMPC << EOF +#include +int main(void) +{ + uint64_t x = 0, y = 0; +#ifdef __ATOMIC_RELAXED + y = __atomic_load_8(&x, 0); + __atomic_store_8(&x, y, 0); + __atomic_compare_exchange_8(&x, &y, x, 0, 0, 0); + __atomic_exchange_8(&x, y, 0); + __atomic_fetch_add_8(&x, y, 0); +#else + typedef char is_host64[sizeof(void *) >= sizeof(uint64_t) ? 1 : -1]; + __sync_lock_test_and_set(&x, y); + __sync_val_compare_and_swap(&x, y, 0); + __sync_fetch_and_add(&x, y); +#endif + return 0; +} +EOF +if compile_prog "" "" ; then + atomic64=yes +fi + +######################################### +# See if --dynamic-list is supported by the linker +ld_dynamic_list="no" +if test "$static" = "no" ; then + cat > $TMPTXT < $TMPC < +void foo(void); + +void foo(void) +{ + printf("foo\n"); +} + +int main(void) +{ + foo(); + return 0; +} +EOF + + if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then + ld_dynamic_list="yes" + fi +fi + +######################################### +# See if -exported_symbols_list is supported by the linker + +ld_exported_symbols_list="no" +if test "$static" = "no" ; then + cat > $TMPTXT < $TMPC << EOF +int x = 1; +extern const int y __attribute__((alias("x"))); +int main(void) { return 0; } +EOF +if compile_prog "" "" ; then + attralias=yes +fi + +######################################## +# check if getauxval is available. + +getauxval=no +cat > $TMPC << EOF +#include +int main(void) { + return getauxval(AT_HWCAP) == 0; +} +EOF +if compile_prog "" "" ; then + getauxval=yes +fi + +######################################## +# check if ccache is interfering with +# semantic analysis of macros + +unset CCACHE_CPP2 +ccache_cpp2=no +cat > $TMPC << EOF +static const int Z = 1; +#define fn() ({ Z; }) +#define TAUT(X) ((X) == Z) +#define PAREN(X, Y) (X == Y) +#define ID(X) (X) +int main(int argc, char *argv[]) +{ + int x = 0, y = 0; + x = ID(x); + x = fn(); + fn(); + if (PAREN(x, y)) return 0; + if (TAUT(Z)) return 0; + return 0; +} +EOF + +if ! compile_object "-Werror"; then + ccache_cpp2=yes +fi + +################################################# +# clang does not support glibc + FORTIFY_SOURCE. + +if test "$fortify_source" != "no"; then + if echo | $cc -dM -E - | grep __clang__ > /dev/null 2>&1 ; then + fortify_source="no"; + elif test -n "$cxx" && has $cxx && + echo | $cxx -dM -E - | grep __clang__ >/dev/null 2>&1 ; then + fortify_source="no"; + else + fortify_source="yes" + fi +fi + +############################################### +# Check if copy_file_range is provided by glibc +have_copy_file_range=no +cat > $TMPC << EOF +#include +int main(void) { + copy_file_range(0, NULL, 0, NULL, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + have_copy_file_range=yes +fi + +########################################## +# check if struct fsxattr is available via linux/fs.h + +have_fsxattr=no +cat > $TMPC << EOF +#include +struct fsxattr foo; +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + have_fsxattr=yes +fi + +########################################## +# check for usable membarrier system call +if test "$membarrier" = "yes"; then + have_membarrier=no + if test "$mingw32" = "yes" ; then + have_membarrier=yes + elif test "$linux" = "yes" ; then + cat > $TMPC << EOF + #include + #include + #include + #include + int main(void) { + syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); + syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0); + exit(0); + } +EOF + if compile_prog "" "" ; then + have_membarrier=yes + fi + fi + if test "$have_membarrier" = "no"; then + feature_not_found "membarrier" "membarrier system call not available" + fi +else + # Do not enable it by default even for Mingw32, because it doesn't + # work on Wine. + membarrier=no +fi + +########################################## +# check if rtnetlink.h exists and is useful +have_rtnetlink=no +cat > $TMPC << EOF +#include +int main(void) { + return IFLA_PROTO_DOWN; +} +EOF +if compile_prog "" "" ; then + have_rtnetlink=yes +fi + +########################################## +# check for usable AF_VSOCK environment +have_af_vsock=no +cat > $TMPC << EOF +#include +#include +#include +#if !defined(AF_VSOCK) +# error missing AF_VSOCK flag +#endif +#include +int main(void) { + int sock, ret; + struct sockaddr_vm svm; + socklen_t len = sizeof(svm); + sock = socket(AF_VSOCK, SOCK_STREAM, 0); + ret = getpeername(sock, (struct sockaddr *)&svm, &len); + if ((ret == -1) && (errno == ENOTCONN)) { + return 0; + } + return -1; +} +EOF +if compile_prog "" "" ; then + have_af_vsock=yes +fi + +########################################## +# check for usable AF_ALG environment +have_afalg=no +cat > $TMPC << EOF +#include +#include +#include +#include +int main(void) { + int sock; + sock = socket(AF_ALG, SOCK_SEQPACKET, 0); + return sock; +} +EOF +if compile_prog "" "" ; then + have_afalg=yes +fi +if test "$crypto_afalg" = "yes" +then + if test "$have_afalg" != "yes" + then + error_exit "AF_ALG requested but could not be detected" + fi +fi + + +################################################# +# Check to see if we have the Hypervisor framework +if [ "$darwin" = "yes" ] ; then + cat > $TMPC << EOF +#include +int main() { return 0;} +EOF + if ! compile_object ""; then + hvf='no' + else + hvf='yes' + QEMU_LDFLAGS="-framework Hypervisor $QEMU_LDFLAGS" + fi +fi + +########################################## +# check for sysmacros.h + +have_sysmacros=no +cat > $TMPC << EOF +#include +int main(void) { + return makedev(0, 0); +} +EOF +if compile_prog "" "" ; then + have_sysmacros=yes +fi + +########################################## +# check for _Static_assert() + +have_static_assert=no +cat > $TMPC << EOF +_Static_assert(1, "success"); +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + have_static_assert=yes +fi + +########################################## +# check for utmpx.h, it is missing e.g. on OpenBSD + +have_utmpx=no +cat > $TMPC << EOF +#include +struct utmpx user_info; +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + have_utmpx=yes +fi + +########################################## +# check for getrandom() + +have_getrandom=no +cat > $TMPC << EOF +#include +int main(void) { + return getrandom(0, 0, GRND_NONBLOCK); +} +EOF +if compile_prog "" "" ; then + have_getrandom=yes +fi + +########################################## +# checks for sanitizers + +have_asan=no +have_ubsan=no +have_asan_iface_h=no +have_asan_iface_fiber=no + +if test "$sanitizers" = "yes" ; then + write_c_skeleton + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" ""; then + have_asan=yes + fi + + # we could use a simple skeleton for flags checks, but this also + # detect the static linking issue of ubsan, see also: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285 + cat > $TMPC << EOF +#include +int main(void) { + void *tmp = malloc(10); + if (tmp != NULL) { + return *(int *)(tmp + 2); + } + return 1; +} +EOF + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then + have_ubsan=yes + fi + + if check_include "sanitizer/asan_interface.h" ; then + have_asan_iface_h=yes + fi + + cat > $TMPC << EOF +#include +int main(void) { + __sanitizer_start_switch_fiber(0, 0, 0); + return 0; +} +EOF + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" "" ; then + have_asan_iface_fiber=yes + fi +fi + +########################################## +# checks for fuzzer +if test "$fuzzing" = "yes" ; then + write_c_fuzzer_skeleton + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then + have_fuzzer=yes + else + error_exit "Your compiler doesn't support -fsanitize=fuzzer" + exit 1 + fi +fi + +# Thread sanitizer is, for now, much noisier than the other sanitizers; +# keep it separate until that is not the case. +if test "$tsan" = "yes" && test "$sanitizers" = "yes"; then + error_exit "TSAN is not supported with other sanitiziers." +fi +have_tsan=no +have_tsan_iface_fiber=no +if test "$tsan" = "yes" ; then + write_c_skeleton + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then + have_tsan=yes + fi + cat > $TMPC << EOF +#include +int main(void) { + __tsan_create_fiber(0); + return 0; +} +EOF + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then + have_tsan_iface_fiber=yes + fi +fi + +########################################## +# check for libpmem + +if test "$libpmem" != "no"; then + if $pkg_config --exists "libpmem"; then + libpmem="yes" + libpmem_libs=$($pkg_config --libs libpmem) + libpmem_cflags=$($pkg_config --cflags libpmem) + QEMU_CFLAGS="$QEMU_CFLAGS $libpmem_cflags" + else + if test "$libpmem" = "yes" ; then + feature_not_found "libpmem" "Install nvml or pmdk" + fi + libpmem="no" + fi +fi + +########################################## +# check for libdaxctl + +if test "$libdaxctl" != "no"; then + if $pkg_config --atleast-version=57 "libdaxctl"; then + libdaxctl="yes" + libdaxctl_libs=$($pkg_config --libs libdaxctl) + libdaxctl_cflags=$($pkg_config --cflags libdaxctl) + QEMU_CFLAGS="$QEMU_CFLAGS $libdaxctl_cflags" + else + if test "$libdaxctl" = "yes" ; then + feature_not_found "libdaxctl" "Install libdaxctl" + fi + libdaxctl="no" + fi +fi + +########################################## +# check for slirp + +# slirp is only required when building softmmu targets +if test -z "$slirp" -a "$softmmu" != "yes" ; then + slirp="no" +fi + +case "$slirp" in + "" | yes) + if $pkg_config slirp; then + slirp=system + elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then + slirp=git + elif test -e "${source_path}/slirp/Makefile" ; then + slirp=internal + elif test -z "$slirp" ; then + slirp=no + else + feature_not_found "slirp" "Install slirp devel or git submodule" + fi + ;; + + system) + if ! $pkg_config slirp; then + feature_not_found "slirp" "Install slirp devel" + fi + ;; +esac + +case "$slirp" in + git | internal) + if test "$slirp" = git; then + git_submodules="${git_submodules} slirp" + fi + mkdir -p slirp + slirp_cflags="-I${source_path}/slirp/src -I${build_path}/slirp/src" + slirp_libs="-L${build_path}/slirp -lslirp" + if test "$mingw32" = "yes" ; then + slirp_libs="$slirp_libs -lws2_32 -liphlpapi" + fi + ;; + + system) + slirp_version=$($pkg_config --modversion slirp 2>/dev/null) + slirp_cflags=$($pkg_config --cflags slirp 2>/dev/null) + slirp_libs=$($pkg_config --libs slirp 2>/dev/null) + ;; + + no) + ;; + *) + error_exit "Unknown state for slirp: $slirp" + ;; +esac + +########################################## +# check for usable __NR_keyctl syscall + +if test "$linux" = "yes" ; then + + have_keyring=no + cat > $TMPC << EOF +#include +#include +#include +#include +int main(void) { + return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0); +} +EOF + if compile_prog "" "" ; then + have_keyring=yes + fi +fi +if test "$secret_keyring" != "no" +then + if test "$have_keyring" = "yes" + then + secret_keyring=yes + else + if test "$secret_keyring" = "yes" + then + error_exit "syscall __NR_keyctl requested, \ +but not implemented on your system" + else + secret_keyring=no + fi + fi +fi + +########################################## +# check for usable keyutils.h + +if test "$linux" = "yes" ; then + + have_keyutils=no + cat > $TMPC << EOF +#include +#include +#include +#include +#include +int main(void) { + return request_key("user", NULL, NULL, 0); +} +EOF + if compile_prog "" "-lkeyutils"; then + have_keyutils=yes + fi +fi + + +########################################## +# End of CC checks +# After here, no more $cc or $ld runs + +write_c_skeleton + +if test "$gcov" = "yes" ; then + : +elif test "$fortify_source" = "yes" ; then + QEMU_CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" + debug=no +fi +if test "$debug_info" = "yes"; then + CFLAGS="-g $CFLAGS" + LDFLAGS="-g $LDFLAGS" +fi +if test "$debug" = "no"; then + CFLAGS="-O2 $CFLAGS" +fi + +case "$ARCH" in +alpha) + # Ensure there's only a single GP + QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" +;; +esac + +if test "$gprof" = "yes" ; then + QEMU_CFLAGS="-p $QEMU_CFLAGS" + QEMU_LDFLAGS="-p $QEMU_LDFLAGS" +fi + +if test "$have_asan" = "yes"; then + QEMU_CFLAGS="-fsanitize=address $QEMU_CFLAGS" + QEMU_LDFLAGS="-fsanitize=address $QEMU_LDFLAGS" + if test "$have_asan_iface_h" = "no" ; then + echo "ASAN build enabled, but ASAN header missing." \ + "Without code annotation, the report may be inferior." + elif test "$have_asan_iface_fiber" = "no" ; then + echo "ASAN build enabled, but ASAN header is too old." \ + "Without code annotation, the report may be inferior." + fi +fi +if test "$have_tsan" = "yes" ; then + if test "$have_tsan_iface_fiber" = "yes" ; then + QEMU_CFLAGS="-fsanitize=thread $QEMU_CFLAGS" + QEMU_LDFLAGS="-fsanitize=thread $QEMU_LDFLAGS" + else + error_exit "Cannot enable TSAN due to missing fiber annotation interface." + fi +elif test "$tsan" = "yes" ; then + error_exit "Cannot enable TSAN due to missing sanitize thread interface." +fi +if test "$have_ubsan" = "yes"; then + QEMU_CFLAGS="-fsanitize=undefined $QEMU_CFLAGS" + QEMU_LDFLAGS="-fsanitize=undefined $QEMU_LDFLAGS" +fi + +########################################## +# Do we have libnfs +if test "$libnfs" != "no" ; then + if $pkg_config --atleast-version=1.9.3 libnfs; then + libnfs="yes" + libnfs_libs=$($pkg_config --libs libnfs) + else + if test "$libnfs" = "yes" ; then + feature_not_found "libnfs" "Install libnfs devel >= 1.9.3" + fi + libnfs="no" + fi +fi + +########################################## +# Do we have libudev +if test "$libudev" != "no" ; then + if $pkg_config libudev && test "$static" != "yes"; then + libudev="yes" + libudev_libs=$($pkg_config --libs libudev) + else + libudev="no" + fi +fi + +# Now we've finished running tests it's OK to add -Werror to the compiler flags +if test "$werror" = "yes"; then + QEMU_CFLAGS="-Werror $QEMU_CFLAGS" +fi + +# Exclude --warn-common with TSan to suppress warnings from the TSan libraries. +if test "$solaris" = "no" && test "$tsan" = "no"; then + if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then + QEMU_LDFLAGS="-Wl,--warn-common $QEMU_LDFLAGS" + fi +fi + +# test if pod2man has --utf8 option +if pod2man --help | grep -q utf8; then + POD2MAN="pod2man --utf8" +else + POD2MAN="pod2man" +fi + +# Use ASLR, no-SEH and DEP if available +if test "$mingw32" = "yes" ; then + for flag in --dynamicbase --no-seh --nxcompat; do + if ld_has $flag ; then + QEMU_LDFLAGS="-Wl,$flag $QEMU_LDFLAGS" + fi + done +fi + +# Disable OpenBSD W^X if available +if test "$tcg" = "yes" && test "$targetos" = "OpenBSD"; then + cat > $TMPC <&1 | grep -q "^[[:space:]]*$emu[[:space:]]*$"; then + ld_i386_emulation="$emu" + roms="optionrom" + break + fi + done +fi + +# Only build s390-ccw bios if we're on s390x and the compiler has -march=z900 +if test "$cpu" = "s390x" ; then + write_c_skeleton + if compile_prog "-march=z900" ""; then + roms="$roms s390-ccw" + # SLOF is required for building the s390-ccw firmware on s390x, + # since it is using the libnet code from SLOF for network booting. + if test -e "${source_path}/.git" ; then + git_submodules="${git_submodules} roms/SLOF" + fi + fi +fi + +if test $git_update = 'yes' ; then + (cd "${source_path}" && GIT="$git" "./scripts/git-submodule.sh" update "$git_submodules") + + if test "$fdt" = "git" ; then + if [ "$pwd_is_source_path" != "y" ] ; then + symlink "$source_path/dtc/Makefile" "dtc/Makefile" + fi + fi +fi + +# Check that the C++ compiler exists and works with the C compiler. +# All the QEMU_CXXFLAGS are based on QEMU_CFLAGS. Keep this at the end to don't miss any other that could be added. +if has $cxx; then + cat > $TMPC < $TMPCXX <config-all-disas.mak + +echo "# Automatically generated by configure - do not modify" > $config_host_mak +echo >> $config_host_mak + +echo all: >> $config_host_mak +echo "prefix=$prefix" >> $config_host_mak +echo "bindir=$bindir" >> $config_host_mak +echo "libdir=$libdir" >> $config_host_mak +echo "libexecdir=$libexecdir" >> $config_host_mak +echo "includedir=$includedir" >> $config_host_mak +echo "sysconfdir=$sysconfdir" >> $config_host_mak +echo "qemu_confdir=$qemu_confdir" >> $config_host_mak +echo "qemu_datadir=$qemu_datadir" >> $config_host_mak +echo "qemu_firmwarepath=$firmwarepath" >> $config_host_mak +echo "qemu_moddir=$qemu_moddir" >> $config_host_mak +if test "$mingw32" = "no" ; then + echo "qemu_localstatedir=$local_statedir" >> $config_host_mak +fi +echo "qemu_helperdir=$libexecdir" >> $config_host_mak +echo "qemu_localedir=$qemu_localedir" >> $config_host_mak +echo "qemu_icondir=$qemu_icondir" >> $config_host_mak +echo "qemu_desktopdir=$qemu_desktopdir" >> $config_host_mak +echo "GIT=$git" >> $config_host_mak +echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak +echo "GIT_UPDATE=$git_update" >> $config_host_mak + +echo "ARCH=$ARCH" >> $config_host_mak + +if test "$default_devices" = "yes" ; then + echo "CONFIG_MINIKCONF_MODE=--defconfig" >> $config_host_mak +else + echo "CONFIG_MINIKCONF_MODE=--allnoconfig" >> $config_host_mak +fi +if test "$debug_tcg" = "yes" ; then + echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak +fi +if test "$strip_opt" = "yes" ; then + echo "STRIP=${strip}" >> $config_host_mak +fi +if test "$bigendian" = "yes" ; then + echo "HOST_WORDS_BIGENDIAN=y" >> $config_host_mak +fi +if test "$mingw32" = "yes" ; then + echo "CONFIG_WIN32=y" >> $config_host_mak + rc_version=$(cat $source_path/VERSION) + version_major=${rc_version%%.*} + rc_version=${rc_version#*.} + version_minor=${rc_version%%.*} + rc_version=${rc_version#*.} + version_subminor=${rc_version%%.*} + version_micro=0 + echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak + echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak + if test "$guest_agent_with_vss" = "yes" ; then + echo "CONFIG_QGA_VSS=y" >> $config_host_mak + echo "QGA_VSS_PROVIDER=$qga_vss_provider" >> $config_host_mak + echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak + fi + if test "$guest_agent_ntddscsi" = "yes" ; then + echo "CONFIG_QGA_NTDDSCSI=y" >> $config_host_mak + fi + if test "$guest_agent_msi" = "yes"; then + echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak + echo "QEMU_GA_MSI_MINGW_DLL_PATH=${QEMU_GA_MSI_MINGW_DLL_PATH}" >> $config_host_mak + echo "QEMU_GA_MSI_WITH_VSS=${QEMU_GA_MSI_WITH_VSS}" >> $config_host_mak + echo "QEMU_GA_MSI_ARCH=${QEMU_GA_MSI_ARCH}" >> $config_host_mak + echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER}" >> $config_host_mak + echo "QEMU_GA_DISTRO=${QEMU_GA_DISTRO}" >> $config_host_mak + echo "QEMU_GA_VERSION=${QEMU_GA_VERSION}" >> $config_host_mak + fi +else + echo "CONFIG_POSIX=y" >> $config_host_mak +fi + +if test "$linux" = "yes" ; then + echo "CONFIG_LINUX=y" >> $config_host_mak +fi + +if test "$darwin" = "yes" ; then + echo "CONFIG_DARWIN=y" >> $config_host_mak +fi + +if test "$solaris" = "yes" ; then + echo "CONFIG_SOLARIS=y" >> $config_host_mak +fi +if test "$haiku" = "yes" ; then + echo "CONFIG_HAIKU=y" >> $config_host_mak +fi +if test "$static" = "yes" ; then + echo "CONFIG_STATIC=y" >> $config_host_mak +fi +if test "$profiler" = "yes" ; then + echo "CONFIG_PROFILER=y" >> $config_host_mak +fi +if test "$want_tools" = "yes" ; then + echo "CONFIG_TOOLS=y" >> $config_host_mak +fi +if test "$guest_agent" = "yes" ; then + echo "CONFIG_GUEST_AGENT=y" >> $config_host_mak +fi +if test "$slirp" != "no"; then + echo "CONFIG_SLIRP=y" >> $config_host_mak + echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak + echo "SLIRP_CFLAGS=$slirp_cflags" >> $config_host_mak + echo "SLIRP_LIBS=$slirp_libs" >> $config_host_mak +fi +subdirs= +if [ "$slirp" = "git" -o "$slirp" = "internal" ]; then + subdirs="$subdirs slirp" +fi +if test "$vde" = "yes" ; then + echo "CONFIG_VDE=y" >> $config_host_mak + echo "VDE_LIBS=$vde_libs" >> $config_host_mak +fi +if test "$netmap" = "yes" ; then + echo "CONFIG_NETMAP=y" >> $config_host_mak +fi +if test "$l2tpv3" = "yes" ; then + echo "CONFIG_L2TPV3=y" >> $config_host_mak +fi +if test "$gprof" = "yes" ; then + echo "CONFIG_GPROF=y" >> $config_host_mak +fi +if test "$cap_ng" = "yes" ; then + echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak + echo "LIBCAP_NG_LIBS=$cap_libs" >> $config_host_mak +fi +echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak +for drv in $audio_drv_list; do + def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]') + echo "$def=y" >> $config_host_mak +done +if test "$alsa" = "yes" ; then + echo "CONFIG_ALSA=y" >> $config_host_mak +fi +echo "ALSA_LIBS=$alsa_libs" >> $config_host_mak +echo "ALSA_CFLAGS=$alsa_cflags" >> $config_host_mak +if test "$libpulse" = "yes" ; then + echo "CONFIG_LIBPULSE=y" >> $config_host_mak +fi +echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak +echo "PULSE_CFLAGS=$pulse_cflags" >> $config_host_mak +echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak +echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak +echo "OSS_LIBS=$oss_libs" >> $config_host_mak +if test "$libjack" = "yes" ; then + echo "CONFIG_LIBJACK=y" >> $config_host_mak +fi +echo "JACK_LIBS=$jack_libs" >> $config_host_mak +if test "$audio_win_int" = "yes" ; then + echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak +fi +echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak +echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak +if test "$xfs" = "yes" ; then + echo "CONFIG_XFS=y" >> $config_host_mak +fi +qemu_version=$(head $source_path/VERSION) +echo "PKGVERSION=$pkgversion" >>$config_host_mak +echo "SRC_PATH=$source_path" >> $config_host_mak +echo "TARGET_DIRS=$target_list" >> $config_host_mak +if [ "$docs" = "yes" ] ; then + echo "BUILD_DOCS=yes" >> $config_host_mak +fi +if test "$modules" = "yes"; then + # $shacmd can generate a hash started with digit, which the compiler doesn't + # like as an symbol. So prefix it with an underscore + echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak + echo "CONFIG_MODULES=y" >> $config_host_mak +fi +if test "$module_upgrades" = "yes"; then + echo "CONFIG_MODULE_UPGRADES=y" >> $config_host_mak +fi +if test "$have_x11" = "yes" && test "$need_x11" = "yes"; then + echo "CONFIG_X11=y" >> $config_host_mak + echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak + echo "X11_LIBS=$x11_libs" >> $config_host_mak +fi +if test "$cocoa" = "yes" ; then + echo "CONFIG_COCOA=y" >> $config_host_mak +fi +if test "$iconv" = "yes" ; then + echo "CONFIG_ICONV=y" >> $config_host_mak + echo "ICONV_CFLAGS=$iconv_cflags" >> $config_host_mak + echo "ICONV_LIBS=$iconv_lib" >> $config_host_mak +fi +if test "$curses" = "yes" ; then + echo "CONFIG_CURSES=y" >> $config_host_mak + echo "CURSES_CFLAGS=$curses_inc" >> $config_host_mak + echo "CURSES_LIBS=$curses_lib" >> $config_host_mak +fi +if test "$pipe2" = "yes" ; then + echo "CONFIG_PIPE2=y" >> $config_host_mak +fi +if test "$accept4" = "yes" ; then + echo "CONFIG_ACCEPT4=y" >> $config_host_mak +fi +if test "$splice" = "yes" ; then + echo "CONFIG_SPLICE=y" >> $config_host_mak +fi +if test "$eventfd" = "yes" ; then + echo "CONFIG_EVENTFD=y" >> $config_host_mak +fi +if test "$memfd" = "yes" ; then + echo "CONFIG_MEMFD=y" >> $config_host_mak +fi +if test "$have_usbfs" = "yes" ; then + echo "CONFIG_USBFS=y" >> $config_host_mak +fi +if test "$fallocate" = "yes" ; then + echo "CONFIG_FALLOCATE=y" >> $config_host_mak +fi +if test "$fallocate_punch_hole" = "yes" ; then + echo "CONFIG_FALLOCATE_PUNCH_HOLE=y" >> $config_host_mak +fi +if test "$fallocate_zero_range" = "yes" ; then + echo "CONFIG_FALLOCATE_ZERO_RANGE=y" >> $config_host_mak +fi +if test "$posix_fallocate" = "yes" ; then + echo "CONFIG_POSIX_FALLOCATE=y" >> $config_host_mak +fi +if test "$sync_file_range" = "yes" ; then + echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak +fi +if test "$fiemap" = "yes" ; then + echo "CONFIG_FIEMAP=y" >> $config_host_mak +fi +if test "$dup3" = "yes" ; then + echo "CONFIG_DUP3=y" >> $config_host_mak +fi +if test "$ppoll" = "yes" ; then + echo "CONFIG_PPOLL=y" >> $config_host_mak +fi +if test "$prctl_pr_set_timerslack" = "yes" ; then + echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak +fi +if test "$epoll" = "yes" ; then + echo "CONFIG_EPOLL=y" >> $config_host_mak +fi +if test "$epoll_create1" = "yes" ; then + echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak +fi +if test "$sendfile" = "yes" ; then + echo "CONFIG_SENDFILE=y" >> $config_host_mak +fi +if test "$timerfd" = "yes" ; then + echo "CONFIG_TIMERFD=y" >> $config_host_mak +fi +if test "$setns" = "yes" ; then + echo "CONFIG_SETNS=y" >> $config_host_mak +fi +if test "$clock_adjtime" = "yes" ; then + echo "CONFIG_CLOCK_ADJTIME=y" >> $config_host_mak +fi +if test "$syncfs" = "yes" ; then + echo "CONFIG_SYNCFS=y" >> $config_host_mak +fi +if test "$kcov" = "yes" ; then + echo "CONFIG_KCOV=y" >> $config_host_mak +fi +if test "$inotify" = "yes" ; then + echo "CONFIG_INOTIFY=y" >> $config_host_mak +fi +if test "$inotify1" = "yes" ; then + echo "CONFIG_INOTIFY1=y" >> $config_host_mak +fi +if test "$sem_timedwait" = "yes" ; then + echo "CONFIG_SEM_TIMEDWAIT=y" >> $config_host_mak +fi +if test "$strchrnul" = "yes" ; then + echo "HAVE_STRCHRNUL=y" >> $config_host_mak +fi +if test "$st_atim" = "yes" ; then + echo "HAVE_STRUCT_STAT_ST_ATIM=y" >> $config_host_mak +fi +if test "$byteswap_h" = "yes" ; then + echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak +fi +if test "$bswap_h" = "yes" ; then + echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak +fi +if test "$curl" = "yes" ; then + echo "CONFIG_CURL=y" >> $config_host_mak + echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak + echo "CURL_LIBS=$curl_libs" >> $config_host_mak +fi +if test "$brlapi" = "yes" ; then + echo "CONFIG_BRLAPI=y" >> $config_host_mak + echo "BRLAPI_LIBS=$brlapi_libs" >> $config_host_mak +fi +if test "$gtk" = "yes" ; then + echo "CONFIG_GTK=y" >> $config_host_mak + echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak + echo "GTK_LIBS=$gtk_libs" >> $config_host_mak + if test "$gtk_gl" = "yes" ; then + echo "CONFIG_GTK_GL=y" >> $config_host_mak + fi +fi +if test "$gio" = "yes" ; then + echo "CONFIG_GIO=y" >> $config_host_mak + echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak + echo "GIO_LIBS=$gio_libs" >> $config_host_mak + echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak +fi +echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak +if test "$gnutls" = "yes" ; then + echo "CONFIG_GNUTLS=y" >> $config_host_mak + echo "GNUTLS_CFLAGS=$gnutls_cflags" >> $config_host_mak + echo "GNUTLS_LIBS=$gnutls_libs" >> $config_host_mak +fi +if test "$gcrypt" = "yes" ; then + echo "CONFIG_GCRYPT=y" >> $config_host_mak + if test "$gcrypt_hmac" = "yes" ; then + echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak + fi +fi +if test "$nettle" = "yes" ; then + echo "CONFIG_NETTLE=y" >> $config_host_mak + echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak + echo "NETTLE_CFLAGS=$nettle_cflags" >> $config_host_mak + echo "NETTLE_LIBS=$nettle_libs" >> $config_host_mak +fi +if test "$qemu_private_xts" = "yes" ; then + echo "CONFIG_QEMU_PRIVATE_XTS=y" >> $config_host_mak +fi +if test "$tasn1" = "yes" ; then + echo "CONFIG_TASN1=y" >> $config_host_mak +fi +if test "$auth_pam" = "yes" ; then + echo "CONFIG_AUTH_PAM=y" >> $config_host_mak +fi +if test "$have_ifaddrs_h" = "yes" ; then + echo "HAVE_IFADDRS_H=y" >> $config_host_mak +fi +if test "$have_drm_h" = "yes" ; then + echo "HAVE_DRM_H=y" >> $config_host_mak +fi +if test "$have_broken_size_max" = "yes" ; then + echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak +fi +if test "$have_openpty" = "yes" ; then + echo "HAVE_OPENPTY=y" >> $config_host_mak +fi +if test "$have_sys_signal_h" = "yes" ; then + echo "HAVE_SYS_SIGNAL_H=y" >> $config_host_mak +fi + +# Work around a system header bug with some kernel/XFS header +# versions where they both try to define 'struct fsxattr': +# xfs headers will not try to redefine structs from linux headers +# if this macro is set. +if test "$have_fsxattr" = "yes" ; then + echo "HAVE_FSXATTR=y" >> $config_host_mak +fi +if test "$have_copy_file_range" = "yes" ; then + echo "HAVE_COPY_FILE_RANGE=y" >> $config_host_mak +fi +if test "$vte" = "yes" ; then + echo "CONFIG_VTE=y" >> $config_host_mak + echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak + echo "VTE_LIBS=$vte_libs" >> $config_host_mak +fi +if test "$virglrenderer" = "yes" ; then + echo "CONFIG_VIRGL=y" >> $config_host_mak + echo "VIRGL_CFLAGS=$virgl_cflags" >> $config_host_mak + echo "VIRGL_LIBS=$virgl_libs" >> $config_host_mak +fi +if test "$xen" = "yes" ; then + echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak + echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak + echo "XEN_CFLAGS=$xen_cflags" >> $config_host_mak + echo "XEN_LIBS=$xen_libs" >> $config_host_mak +fi +if test "$linux_aio" = "yes" ; then + echo "CONFIG_LINUX_AIO=y" >> $config_host_mak +fi +if test "$linux_io_uring" = "yes" ; then + echo "CONFIG_LINUX_IO_URING=y" >> $config_host_mak + echo "LINUX_IO_URING_CFLAGS=$linux_io_uring_cflags" >> $config_host_mak + echo "LINUX_IO_URING_LIBS=$linux_io_uring_libs" >> $config_host_mak +fi +if test "$attr" = "yes" ; then + echo "CONFIG_ATTR=y" >> $config_host_mak + echo "LIBATTR_LIBS=$libattr_libs" >> $config_host_mak +fi +if test "$libattr" = "yes" ; then + echo "CONFIG_LIBATTR=y" >> $config_host_mak +fi +if test "$virtfs" = "yes" ; then + echo "CONFIG_VIRTFS=y" >> $config_host_mak +fi +if test "$mpath" = "yes" ; then + echo "CONFIG_MPATH=y" >> $config_host_mak + if test "$mpathpersist_new_api" = "yes"; then + echo "CONFIG_MPATH_NEW_API=y" >> $config_host_mak + fi +fi +if test "$vhost_scsi" = "yes" ; then + echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak +fi +if test "$vhost_net" = "yes" ; then + echo "CONFIG_VHOST_NET=y" >> $config_host_mak +fi +if test "$vhost_net_user" = "yes" ; then + echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak +fi +if test "$vhost_net_vdpa" = "yes" ; then + echo "CONFIG_VHOST_NET_VDPA=y" >> $config_host_mak +fi +if test "$vhost_crypto" = "yes" ; then + echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak +fi +if test "$vhost_vsock" = "yes" ; then + echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak + if test "$vhost_user" = "yes" ; then + echo "CONFIG_VHOST_USER_VSOCK=y" >> $config_host_mak + fi +fi +if test "$vhost_kernel" = "yes" ; then + echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak +fi +if test "$vhost_user" = "yes" ; then + echo "CONFIG_VHOST_USER=y" >> $config_host_mak +fi +if test "$vhost_vdpa" = "yes" ; then + echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak +fi +if test "$vhost_user_fs" = "yes" ; then + echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak +fi +if test "$blobs" = "yes" ; then + echo "INSTALL_BLOBS=yes" >> $config_host_mak +fi +if test "$iovec" = "yes" ; then + echo "CONFIG_IOVEC=y" >> $config_host_mak +fi +if test "$preadv" = "yes" ; then + echo "CONFIG_PREADV=y" >> $config_host_mak +fi +if test "$fdt" != "no" ; then + echo "CONFIG_FDT=y" >> $config_host_mak + echo "FDT_CFLAGS=$fdt_cflags" >> $config_host_mak + echo "FDT_LIBS=$fdt_ldflags $fdt_libs" >> $config_host_mak +fi +if test "$membarrier" = "yes" ; then + echo "CONFIG_MEMBARRIER=y" >> $config_host_mak +fi +if test "$signalfd" = "yes" ; then + echo "CONFIG_SIGNALFD=y" >> $config_host_mak +fi +if test "$optreset" = "yes" ; then + echo "HAVE_OPTRESET=y" >> $config_host_mak +fi +if test "$tcg" = "yes"; then + echo "CONFIG_TCG=y" >> $config_host_mak + if test "$tcg_interpreter" = "yes" ; then + echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak + fi +fi +if test "$fdatasync" = "yes" ; then + echo "CONFIG_FDATASYNC=y" >> $config_host_mak +fi +if test "$madvise" = "yes" ; then + echo "CONFIG_MADVISE=y" >> $config_host_mak +fi +if test "$posix_madvise" = "yes" ; then + echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak +fi +if test "$posix_memalign" = "yes" ; then + echo "CONFIG_POSIX_MEMALIGN=y" >> $config_host_mak +fi +if test "$spice" = "yes" ; then + echo "CONFIG_SPICE=y" >> $config_host_mak + echo "SPICE_CFLAGS=$spice_cflags" >> $config_host_mak + echo "SPICE_LIBS=$spice_libs" >> $config_host_mak +fi + +if test "$smartcard" = "yes" ; then + echo "CONFIG_SMARTCARD=y" >> $config_host_mak + echo "SMARTCARD_CFLAGS=$libcacard_cflags" >> $config_host_mak + echo "SMARTCARD_LIBS=$libcacard_libs" >> $config_host_mak +fi + +if test "$libusb" = "yes" ; then + echo "CONFIG_USB_LIBUSB=y" >> $config_host_mak + echo "LIBUSB_CFLAGS=$libusb_cflags" >> $config_host_mak + echo "LIBUSB_LIBS=$libusb_libs" >> $config_host_mak +fi + +if test "$usb_redir" = "yes" ; then + echo "CONFIG_USB_REDIR=y" >> $config_host_mak + echo "USB_REDIR_CFLAGS=$usb_redir_cflags" >> $config_host_mak + echo "USB_REDIR_LIBS=$usb_redir_libs" >> $config_host_mak +fi + +if test "$opengl" = "yes" ; then + echo "CONFIG_OPENGL=y" >> $config_host_mak + echo "OPENGL_LIBS=$opengl_libs" >> $config_host_mak + if test "$opengl_dmabuf" = "yes" ; then + echo "CONFIG_OPENGL_DMABUF=y" >> $config_host_mak + fi +fi + +if test "$gbm" = "yes" ; then + echo "CONFIG_GBM=y" >> $config_host_mak + echo "GBM_LIBS=$gbm_libs" >> $config_host_mak + echo "GBM_CFLAGS=$gbm_cflags" >> $config_host_mak +fi + + +if test "$malloc_trim" = "yes" ; then + echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak +fi + +if test "$avx2_opt" = "yes" ; then + echo "CONFIG_AVX2_OPT=y" >> $config_host_mak +fi + +if test "$avx512f_opt" = "yes" ; then + echo "CONFIG_AVX512F_OPT=y" >> $config_host_mak +fi + +if test "$lzo" = "yes" ; then + echo "CONFIG_LZO=y" >> $config_host_mak + echo "LZO_LIBS=$lzo_libs" >> $config_host_mak +fi + +if test "$snappy" = "yes" ; then + echo "CONFIG_SNAPPY=y" >> $config_host_mak + echo "SNAPPY_LIBS=$snappy_libs" >> $config_host_mak +fi + +if test "$bzip2" = "yes" ; then + echo "CONFIG_BZIP2=y" >> $config_host_mak + echo "BZIP2_LIBS=-lbz2" >> $config_host_mak +fi + +if test "$lzfse" = "yes" ; then + echo "CONFIG_LZFSE=y" >> $config_host_mak + echo "LZFSE_LIBS=-llzfse" >> $config_host_mak +fi + +if test "$zstd" = "yes" ; then + echo "CONFIG_ZSTD=y" >> $config_host_mak + echo "ZSTD_CFLAGS=$zstd_cflags" >> $config_host_mak + echo "ZSTD_LIBS=$zstd_libs" >> $config_host_mak +fi + +if test "$libiscsi" = "yes" ; then + echo "CONFIG_LIBISCSI=y" >> $config_host_mak + echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak + echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak +fi + +if test "$libnfs" = "yes" ; then + echo "CONFIG_LIBNFS=y" >> $config_host_mak + echo "LIBNFS_LIBS=$libnfs_libs" >> $config_host_mak +fi + +if test "$seccomp" = "yes"; then + echo "CONFIG_SECCOMP=y" >> $config_host_mak + echo "SECCOMP_CFLAGS=$seccomp_cflags" >> $config_host_mak + echo "SECCOMP_LIBS=$seccomp_libs" >> $config_host_mak +fi + +# XXX: suppress that +if [ "$bsd" = "yes" ] ; then + echo "CONFIG_BSD=y" >> $config_host_mak +fi + +if test "$localtime_r" = "yes" ; then + echo "CONFIG_LOCALTIME_R=y" >> $config_host_mak +fi +if test "$qom_cast_debug" = "yes" ; then + echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak +fi +if test "$rbd" = "yes" ; then + echo "CONFIG_RBD=y" >> $config_host_mak + echo "RBD_LIBS=$rbd_libs" >> $config_host_mak +fi + +echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak +if test "$coroutine_pool" = "yes" ; then + echo "CONFIG_COROUTINE_POOL=1" >> $config_host_mak +else + echo "CONFIG_COROUTINE_POOL=0" >> $config_host_mak +fi + +if test "$debug_stack_usage" = "yes" ; then + echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak +fi + +if test "$crypto_afalg" = "yes" ; then + echo "CONFIG_AF_ALG=y" >> $config_host_mak +fi + +if test "$open_by_handle_at" = "yes" ; then + echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak +fi + +if test "$linux_magic_h" = "yes" ; then + echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak +fi + +if test "$valgrind_h" = "yes" ; then + echo "CONFIG_VALGRIND_H=y" >> $config_host_mak +fi + +if test "$have_asan_iface_fiber" = "yes" ; then + echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak +fi + +if test "$have_tsan" = "yes" && test "$have_tsan_iface_fiber" = "yes" ; then + echo "CONFIG_TSAN=y" >> $config_host_mak +fi + +if test "$has_environ" = "yes" ; then + echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak +fi + +if test "$cpuid_h" = "yes" ; then + echo "CONFIG_CPUID_H=y" >> $config_host_mak +fi + +if test "$int128" = "yes" ; then + echo "CONFIG_INT128=y" >> $config_host_mak +fi + +if test "$atomic128" = "yes" ; then + echo "CONFIG_ATOMIC128=y" >> $config_host_mak +fi + +if test "$cmpxchg128" = "yes" ; then + echo "CONFIG_CMPXCHG128=y" >> $config_host_mak +fi + +if test "$atomic64" = "yes" ; then + echo "CONFIG_ATOMIC64=y" >> $config_host_mak +fi + +if test "$attralias" = "yes" ; then + echo "CONFIG_ATTRIBUTE_ALIAS=y" >> $config_host_mak +fi + +if test "$getauxval" = "yes" ; then + echo "CONFIG_GETAUXVAL=y" >> $config_host_mak +fi + +if test "$glusterfs" = "yes" ; then + echo "CONFIG_GLUSTERFS=y" >> $config_host_mak + echo "GLUSTERFS_CFLAGS=$glusterfs_cflags" >> $config_host_mak + echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak +fi + +if test "$glusterfs_xlator_opt" = "yes" ; then + echo "CONFIG_GLUSTERFS_XLATOR_OPT=y" >> $config_host_mak +fi + +if test "$glusterfs_discard" = "yes" ; then + echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak +fi + +if test "$glusterfs_fallocate" = "yes" ; then + echo "CONFIG_GLUSTERFS_FALLOCATE=y" >> $config_host_mak +fi + +if test "$glusterfs_zerofill" = "yes" ; then + echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak +fi + +if test "$glusterfs_ftruncate_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak +fi + +if test "$glusterfs_iocb_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak +fi + +if test "$libssh" = "yes" ; then + echo "CONFIG_LIBSSH=y" >> $config_host_mak + echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak + echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak +fi + +if test "$live_block_migration" = "yes" ; then + echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak +fi + +if test "$tpm" = "yes"; then + echo 'CONFIG_TPM=y' >> $config_host_mak +fi + +echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak +if have_backend "nop"; then + echo "CONFIG_TRACE_NOP=y" >> $config_host_mak +fi +if have_backend "simple"; then + echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak + # Set the appropriate trace file. + trace_file="\"$trace_file-\" FMT_pid" +fi +if have_backend "log"; then + echo "CONFIG_TRACE_LOG=y" >> $config_host_mak +fi +if have_backend "ust"; then + echo "CONFIG_TRACE_UST=y" >> $config_host_mak + echo "LTTNG_UST_LIBS=$lttng_ust_libs" >> $config_host_mak + echo "URCU_BP_LIBS=$urcu_bp_libs" >> $config_host_mak +fi +if have_backend "dtrace"; then + echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak + if test "$trace_backend_stap" = "yes" ; then + echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak + fi +fi +if have_backend "ftrace"; then + if test "$linux" = "yes" ; then + echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak + else + feature_not_found "ftrace(trace backend)" "ftrace requires Linux" + fi +fi +if have_backend "syslog"; then + if test "$posix_syslog" = "yes" ; then + echo "CONFIG_TRACE_SYSLOG=y" >> $config_host_mak + else + feature_not_found "syslog(trace backend)" "syslog not available" + fi +fi +echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak + +if test "$rdma" = "yes" ; then + echo "CONFIG_RDMA=y" >> $config_host_mak + echo "RDMA_LIBS=$rdma_libs" >> $config_host_mak +fi + +if test "$pvrdma" = "yes" ; then + echo "CONFIG_PVRDMA=y" >> $config_host_mak +fi + +if test "$have_rtnetlink" = "yes" ; then + echo "CONFIG_RTNETLINK=y" >> $config_host_mak +fi + +if test "$libxml2" = "yes" ; then + echo "CONFIG_LIBXML2=y" >> $config_host_mak + echo "LIBXML2_CFLAGS=$libxml2_cflags" >> $config_host_mak + echo "LIBXML2_LIBS=$libxml2_libs" >> $config_host_mak +fi + +if test "$replication" = "yes" ; then + echo "CONFIG_REPLICATION=y" >> $config_host_mak +fi + +if test "$have_af_vsock" = "yes" ; then + echo "CONFIG_AF_VSOCK=y" >> $config_host_mak +fi + +if test "$have_sysmacros" = "yes" ; then + echo "CONFIG_SYSMACROS=y" >> $config_host_mak +fi + +if test "$have_static_assert" = "yes" ; then + echo "CONFIG_STATIC_ASSERT=y" >> $config_host_mak +fi + +if test "$have_utmpx" = "yes" ; then + echo "HAVE_UTMPX=y" >> $config_host_mak +fi +if test "$have_getrandom" = "yes" ; then + echo "CONFIG_GETRANDOM=y" >> $config_host_mak +fi +if test "$ivshmem" = "yes" ; then + echo "CONFIG_IVSHMEM=y" >> $config_host_mak +fi +if test "$capstone" != "no" ; then + echo "CONFIG_CAPSTONE=y" >> $config_host_mak + echo "CAPSTONE_CFLAGS=$capstone_cflags" >> $config_host_mak + echo "CAPSTONE_LIBS=$capstone_libs" >> $config_host_mak +fi +if test "$debug_mutex" = "yes" ; then + echo "CONFIG_DEBUG_MUTEX=y" >> $config_host_mak +fi + +# Hold two types of flag: +# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on +# a thread we have a handle to +# CONFIG_PTHREAD_SETNAME_NP_W_TID - A way of doing it on a particular +# platform +if test "$pthread_setname_np_w_tid" = "yes" ; then + echo "CONFIG_THREAD_SETNAME_BYTHREAD=y" >> $config_host_mak + echo "CONFIG_PTHREAD_SETNAME_NP_W_TID=y" >> $config_host_mak +elif test "$pthread_setname_np_wo_tid" = "yes" ; then + echo "CONFIG_THREAD_SETNAME_BYTHREAD=y" >> $config_host_mak + echo "CONFIG_PTHREAD_SETNAME_NP_WO_TID=y" >> $config_host_mak +fi + +if test "$libpmem" = "yes" ; then + echo "CONFIG_LIBPMEM=y" >> $config_host_mak + echo "LIBPMEM_LIBS=$libpmem_libs" >> $config_host_mak + echo "LIBPMEM_CFLAGS=$libpmem_cflags" >> $config_host_mak +fi + +if test "$libdaxctl" = "yes" ; then + echo "CONFIG_LIBDAXCTL=y" >> $config_host_mak + echo "LIBDAXCTL_LIBS=$libdaxctl_libs" >> $config_host_mak +fi + +if test "$bochs" = "yes" ; then + echo "CONFIG_BOCHS=y" >> $config_host_mak +fi +if test "$cloop" = "yes" ; then + echo "CONFIG_CLOOP=y" >> $config_host_mak +fi +if test "$dmg" = "yes" ; then + echo "CONFIG_DMG=y" >> $config_host_mak +fi +if test "$qcow1" = "yes" ; then + echo "CONFIG_QCOW1=y" >> $config_host_mak +fi +if test "$vdi" = "yes" ; then + echo "CONFIG_VDI=y" >> $config_host_mak +fi +if test "$vvfat" = "yes" ; then + echo "CONFIG_VVFAT=y" >> $config_host_mak +fi +if test "$qed" = "yes" ; then + echo "CONFIG_QED=y" >> $config_host_mak +fi +if test "$parallels" = "yes" ; then + echo "CONFIG_PARALLELS=y" >> $config_host_mak +fi +if test "$sheepdog" = "yes" ; then + echo "CONFIG_SHEEPDOG=y" >> $config_host_mak +fi +if test "$pty_h" = "yes" ; then + echo "HAVE_PTY_H=y" >> $config_host_mak +fi +if test "$have_mlockall" = "yes" ; then + echo "HAVE_MLOCKALL=y" >> $config_host_mak +fi +if test "$fuzzing" = "yes" ; then + QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer-no-link" +fi + +if test "$plugins" = "yes" ; then + echo "CONFIG_PLUGIN=y" >> $config_host_mak + LIBS="-ldl $LIBS" + # Copy the export object list to the build dir + if test "$ld_dynamic_list" = "yes" ; then + echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak + ld_symbols=qemu-plugins-ld.symbols + cp "$source_path/plugins/qemu-plugins.symbols" $ld_symbols + elif test "$ld_exported_symbols_list" = "yes" ; then + echo "CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST=yes" >> $config_host_mak + ld64_symbols=qemu-plugins-ld64.symbols + echo "# Automatically generated by configure - do not modify" > $ld64_symbols + grep 'qemu_' "$source_path/plugins/qemu-plugins.symbols" | sed 's/;//g' | \ + sed -E 's/^[[:space:]]*(.*)/_\1/' >> $ld64_symbols + else + error_exit \ + "If \$plugins=yes, either \$ld_dynamic_list or " \ + "\$ld_exported_symbols_list should have been set to 'yes'." + fi +fi + +if test -n "$gdb_bin" ; then + echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak +fi + +if test "$secret_keyring" = "yes" ; then + echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak + if test "$have_keyutils" = "yes" ; then + echo "CONFIG_TEST_SECRET_KEYRING=y" >> $config_host_mak + fi +fi + +if test "$tcg_interpreter" = "yes"; then + QEMU_INCLUDES="-iquote ${source_path}/tcg/tci $QEMU_INCLUDES" +elif test "$ARCH" = "sparc64" ; then + QEMU_INCLUDES="-iquote ${source_path}/tcg/sparc $QEMU_INCLUDES" +elif test "$ARCH" = "s390x" ; then + QEMU_INCLUDES="-iquote ${source_path}/tcg/s390 $QEMU_INCLUDES" +elif test "$ARCH" = "x86_64" || test "$ARCH" = "x32" ; then + QEMU_INCLUDES="-iquote ${source_path}/tcg/i386 $QEMU_INCLUDES" +elif test "$ARCH" = "ppc64" ; then + QEMU_INCLUDES="-iquote ${source_path}/tcg/ppc $QEMU_INCLUDES" +elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then + QEMU_INCLUDES="-I${source_path}/tcg/riscv $QEMU_INCLUDES" +else + QEMU_INCLUDES="-iquote ${source_path}/tcg/${ARCH} $QEMU_INCLUDES" +fi + +echo "ROMS=$roms" >> $config_host_mak +echo "MAKE=$make" >> $config_host_mak +echo "INSTALL=$install" >> $config_host_mak +echo "INSTALL_DIR=$install -d -m 0755" >> $config_host_mak +echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak +echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak +echo "INSTALL_LIB=$install -c -m 0644" >> $config_host_mak +echo "PYTHON=$python" >> $config_host_mak +echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak +echo "GENISOIMAGE=$genisoimage" >> $config_host_mak +echo "MESON=$meson" >> $config_host_mak +echo "CC=$cc" >> $config_host_mak +if $iasl -h > /dev/null 2>&1; then + echo "CONFIG_IASL=$iasl" >> $config_host_mak +fi +echo "CXX=$cxx" >> $config_host_mak +echo "OBJCC=$objcc" >> $config_host_mak +echo "AR=$ar" >> $config_host_mak +echo "ARFLAGS=$ARFLAGS" >> $config_host_mak +echo "AS=$as" >> $config_host_mak +echo "CCAS=$ccas" >> $config_host_mak +echo "CPP=$cpp" >> $config_host_mak +echo "OBJCOPY=$objcopy" >> $config_host_mak +echo "LD=$ld" >> $config_host_mak +echo "RANLIB=$ranlib" >> $config_host_mak +echo "NM=$nm" >> $config_host_mak +echo "PKG_CONFIG=$pkg_config_exe" >> $config_host_mak +echo "WINDRES=$windres" >> $config_host_mak +echo "CFLAGS=$CFLAGS" >> $config_host_mak +echo "CXXFLAGS=$CXXFLAGS" >> $config_host_mak +echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak +echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak +echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak +echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak +echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak +echo "GLIB_LIBS=$glib_libs" >> $config_host_mak +if test "$sparse" = "yes" ; then + echo "SPARSE_CFLAGS = -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak +fi +echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak +echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak +echo "LD_REL_FLAGS=$LD_REL_FLAGS" >> $config_host_mak +echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak +echo "LIBS+=$LIBS" >> $config_host_mak +echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak +echo "PTHREAD_LIB=$PTHREAD_LIB" >> $config_host_mak +echo "EXESUF=$EXESUF" >> $config_host_mak +echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak +echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak +echo "LIBS_QGA=$libs_qga" >> $config_host_mak +echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak +echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak +echo "POD2MAN=$POD2MAN" >> $config_host_mak +if test "$gcov" = "yes" ; then + echo "CONFIG_GCOV=y" >> $config_host_mak +fi + +if test "$libudev" != "no"; then + echo "CONFIG_LIBUDEV=y" >> $config_host_mak + echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak +fi +if test "$fuzzing" != "no"; then + echo "CONFIG_FUZZ=y" >> $config_host_mak +fi + +if test "$edk2_blobs" = "yes" ; then + echo "DECOMPRESS_EDK2_BLOBS=y" >> $config_host_mak +fi + +if test "$rng_none" = "yes"; then + echo "CONFIG_RNG_NONE=y" >> $config_host_mak +fi + +# use included Linux headers +if test "$linux" = "yes" ; then + mkdir -p linux-headers + case "$cpu" in + i386|x86_64|x32) + linux_arch=x86 + ;; + ppc|ppc64|ppc64le) + linux_arch=powerpc + ;; + s390x) + linux_arch=s390 + ;; + aarch64) + linux_arch=arm64 + ;; + mips64) + linux_arch=mips + ;; + *) + # For most CPUs the kernel architecture name and QEMU CPU name match. + linux_arch="$cpu" + ;; + esac + # For non-KVM architectures we will not have asm headers + if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then + symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm + fi +fi + +for target in $target_list; do +target_dir="$target" +config_target_mak=$target_dir/config-target.mak +target_name=$(echo $target | cut -d '-' -f 1) +target_aligned_only="no" +case "$target_name" in + alpha|hppa|mips64el|mips64|mipsel|mips|mipsn32|mipsn32el|sh4|sh4eb|sparc|sparc64|sparc32plus|xtensa|xtensaeb) + target_aligned_only="yes" + ;; +esac +target_bigendian="no" +case "$target_name" in + armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb) + target_bigendian="yes" + ;; +esac +target_softmmu="no" +target_user_only="no" +target_linux_user="no" +target_bsd_user="no" +case "$target" in + ${target_name}-softmmu) + target_softmmu="yes" + ;; + ${target_name}-linux-user) + target_user_only="yes" + target_linux_user="yes" + ;; + ${target_name}-bsd-user) + target_user_only="yes" + target_bsd_user="yes" + ;; + *) + error_exit "Target '$target' not recognised" + exit 1 + ;; +esac + +mkdir -p $target_dir +echo "# Automatically generated by configure - do not modify" > $config_target_mak + +bflt="no" +mttcg="no" +interp_prefix1=$(echo "$interp_prefix" | sed "s/%M/$target_name/g") +gdb_xml_files="" + +TARGET_ARCH="$target_name" +TARGET_BASE_ARCH="" +TARGET_ABI_DIR="" +TARGET_SYSTBL_ABI="" +TARGET_SYSTBL="" + +case "$target_name" in + i386) + mttcg="yes" + gdb_xml_files="i386-32bit.xml" + TARGET_SYSTBL_ABI=i386 + TARGET_SYSTBL=syscall_32.tbl + ;; + x86_64) + TARGET_BASE_ARCH=i386 + TARGET_SYSTBL_ABI=common,64 + TARGET_SYSTBL=syscall_64.tbl + mttcg="yes" + gdb_xml_files="i386-64bit.xml" + ;; + alpha) + mttcg="yes" + TARGET_SYSTBL_ABI=common + ;; + arm|armeb) + TARGET_ARCH=arm + TARGET_SYSTBL_ABI=common,oabi + bflt="yes" + mttcg="yes" + gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" + ;; + aarch64|aarch64_be) + TARGET_ARCH=aarch64 + TARGET_BASE_ARCH=arm + bflt="yes" + mttcg="yes" + gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" + ;; + avr) + gdb_xml_files="avr-cpu.xml" + target_compiler=$cross_cc_avr + ;; + cris) + ;; + hppa) + mttcg="yes" + TARGET_SYSTBL_ABI=common,32 + ;; + lm32) + ;; + m68k) + bflt="yes" + gdb_xml_files="cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml" + TARGET_SYSTBL_ABI=common + ;; + microblaze|microblazeel) + TARGET_ARCH=microblaze + TARGET_SYSTBL_ABI=common + mttcg="yes" + bflt="yes" + echo "TARGET_ABI32=y" >> $config_target_mak + ;; + mips|mipsel) + mttcg="yes" + TARGET_ARCH=mips + echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak + TARGET_SYSTBL_ABI=o32 + TARGET_SYSTBL=syscall_o32.tbl + ;; + mipsn32|mipsn32el) + mttcg="yes" + TARGET_ARCH=mips64 + TARGET_BASE_ARCH=mips + echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak + echo "TARGET_ABI32=y" >> $config_target_mak + TARGET_SYSTBL_ABI=n32 + TARGET_SYSTBL=syscall_n32.tbl + ;; + mips64|mips64el) + mttcg="no" + TARGET_ARCH=mips64 + TARGET_BASE_ARCH=mips + echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak + TARGET_SYSTBL_ABI=n64 + TARGET_SYSTBL=syscall_n64.tbl + ;; + moxie) + ;; + nios2) + ;; + or1k) + TARGET_ARCH=openrisc + TARGET_BASE_ARCH=openrisc + ;; + ppc) + gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" + TARGET_SYSTBL_ABI=common,nospu,32 + ;; + ppc64) + TARGET_BASE_ARCH=ppc + TARGET_ABI_DIR=ppc + TARGET_SYSTBL_ABI=common,nospu,64 + mttcg=yes + gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" + ;; + ppc64le) + TARGET_ARCH=ppc64 + TARGET_BASE_ARCH=ppc + TARGET_ABI_DIR=ppc + TARGET_SYSTBL_ABI=common,nospu,64 + mttcg=yes + gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" + ;; + ppc64abi32) + TARGET_ARCH=ppc64 + TARGET_BASE_ARCH=ppc + TARGET_ABI_DIR=ppc + TARGET_SYSTBL_ABI=common,nospu,32 + echo "TARGET_ABI32=y" >> $config_target_mak + gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" + ;; + riscv32) + TARGET_BASE_ARCH=riscv + TARGET_ABI_DIR=riscv + mttcg=yes + gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-csr.xml riscv-32bit-virtual.xml" + ;; + riscv64) + TARGET_BASE_ARCH=riscv + TARGET_ABI_DIR=riscv + mttcg=yes + gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml" + ;; + rx) + TARGET_ARCH=rx + bflt="yes" + target_compiler=$cross_cc_rx + gdb_xml_files="rx-core.xml" + ;; + sh4|sh4eb) + TARGET_ARCH=sh4 + TARGET_SYSTBL_ABI=common + bflt="yes" + ;; + sparc) + TARGET_SYSTBL_ABI=common,32 + ;; + sparc64) + TARGET_BASE_ARCH=sparc + TARGET_SYSTBL_ABI=common,64 + ;; + sparc32plus) + TARGET_ARCH=sparc64 + TARGET_BASE_ARCH=sparc + TARGET_ABI_DIR=sparc + TARGET_SYSTBL_ABI=common,32 + echo "TARGET_ABI32=y" >> $config_target_mak + ;; + s390x) + TARGET_SYSTBL_ABI=common,64 + mttcg=yes + gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml s390-gs.xml" + ;; + tilegx) + ;; + tricore) + ;; + unicore32) + ;; + xtensa|xtensaeb) + TARGET_ARCH=xtensa + TARGET_SYSTBL_ABI=common + bflt="yes" + mttcg="yes" + ;; + *) + error_exit "Unsupported target CPU" + ;; +esac +# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH +if [ "$TARGET_BASE_ARCH" = "" ]; then + TARGET_BASE_ARCH=$TARGET_ARCH +fi +if [ "$TARGET_SYSTBL_ABI" != "" ] && [ "$TARGET_SYSTBL" = "" ]; then + TARGET_SYSTBL=syscall.tbl +fi + +upper() { + echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' +} + +target_arch_name="$(upper $TARGET_ARCH)" +echo "TARGET_$target_arch_name=y" >> $config_target_mak +echo "TARGET_NAME=$target_name" >> $config_target_mak +echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak +if [ "$TARGET_ABI_DIR" = "" ]; then + TARGET_ABI_DIR=$TARGET_ARCH +fi +echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak +if [ "$HOST_VARIANT_DIR" != "" ]; then + echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak +fi +if [ "$TARGET_SYSTBL_ABI" != "" ]; then + echo "TARGET_SYSTBL_ABI=$TARGET_SYSTBL_ABI" >> $config_target_mak + echo "TARGET_SYSTBL=$TARGET_SYSTBL" >> $config_target_mak +fi + +if supported_xen_target $target; then + echo "CONFIG_XEN=y" >> $config_target_mak + if test "$xen_pci_passthrough" = yes; then + echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak" + fi +fi +if supported_kvm_target $target; then + echo "CONFIG_KVM=y" >> $config_target_mak +fi +if supported_hax_target $target; then + echo "CONFIG_HAX=y" >> $config_target_mak +fi +if supported_hvf_target $target; then + echo "CONFIG_HVF=y" >> $config_target_mak +fi +if supported_whpx_target $target; then + echo "CONFIG_WHPX=y" >> $config_target_mak +fi +if test "$target_aligned_only" = "yes" ; then + echo "TARGET_ALIGNED_ONLY=y" >> $config_target_mak +fi +if test "$target_bigendian" = "yes" ; then + echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak +fi +if test "$target_softmmu" = "yes" ; then + echo "CONFIG_SOFTMMU=y" >> $config_target_mak + if test "$mttcg" = "yes" ; then + echo "TARGET_SUPPORTS_MTTCG=y" >> $config_target_mak + fi +fi +if test "$target_user_only" = "yes" ; then + echo "CONFIG_USER_ONLY=y" >> $config_target_mak + echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak + symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" +else + symlink "../qemu-system-$target_name" "$target_dir/qemu-system-$target_name" +fi +if test "$target_linux_user" = "yes" ; then + echo "CONFIG_LINUX_USER=y" >> $config_target_mak +fi +list="" +if test ! -z "$gdb_xml_files" ; then + for x in $gdb_xml_files; do + list="$list gdb-xml/$x" + done + echo "TARGET_XML_FILES=$list" >> $config_target_mak +fi + +if test "$target_user_only" = "yes" && test "$bflt" = "yes"; then + echo "TARGET_HAS_BFLT=y" >> $config_target_mak +fi +if test "$target_bsd_user" = "yes" ; then + echo "CONFIG_BSD_USER=y" >> $config_target_mak +fi + + +# generate QEMU_CFLAGS/QEMU_LDFLAGS for targets + +disas_config() { + echo "CONFIG_${1}_DIS=y" >> $config_target_mak + echo "CONFIG_${1}_DIS=y" >> config-all-disas.mak +} + +for i in $ARCH $TARGET_BASE_ARCH ; do + case "$i" in + alpha) + disas_config "ALPHA" + ;; + aarch64) + if test -n "${cxx}"; then + disas_config "ARM_A64" + fi + ;; + arm) + disas_config "ARM" + if test -n "${cxx}"; then + disas_config "ARM_A64" + fi + ;; + avr) + disas_config "AVR" + ;; + cris) + disas_config "CRIS" + ;; + hppa) + disas_config "HPPA" + ;; + i386|x86_64|x32) + disas_config "I386" + ;; + lm32) + disas_config "LM32" + ;; + m68k) + disas_config "M68K" + ;; + microblaze*) + disas_config "MICROBLAZE" + ;; + mips*) + disas_config "MIPS" + if test -n "${cxx}"; then + disas_config "NANOMIPS" + fi + ;; + moxie*) + disas_config "MOXIE" + ;; + nios2) + disas_config "NIOS2" + ;; + or1k) + disas_config "OPENRISC" + ;; + ppc*) + disas_config "PPC" + ;; + riscv*) + disas_config "RISCV" + ;; + rx) + disas_config "RX" + ;; + s390*) + disas_config "S390" + ;; + sh4) + disas_config "SH4" + ;; + sparc*) + disas_config "SPARC" + ;; + xtensa*) + disas_config "XTENSA" + ;; + esac +done +if test "$tcg_interpreter" = "yes" ; then + disas_config "TCI" +fi + +done # for target in $targets + +if [ "$fdt" = "git" ]; then + subdirs="$subdirs dtc" +fi +if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then + subdirs="$subdirs capstone" +fi +echo "SUBDIRS=$subdirs" >> $config_host_mak +if test -n "$LIBCAPSTONE"; then + echo "LIBCAPSTONE=$LIBCAPSTONE" >> $config_host_mak +fi + +if test "$numa" = "yes"; then + echo "CONFIG_NUMA=y" >> $config_host_mak + echo "NUMA_LIBS=$numa_libs" >> $config_host_mak +fi + +if test "$ccache_cpp2" = "yes"; then + echo "export CCACHE_CPP2=y" >> $config_host_mak +fi + +if test "$safe_stack" = "yes"; then + echo "CONFIG_SAFESTACK=y" >> $config_host_mak +fi + +# If we're using a separate build tree, set it up now. +# DIRS are directories which we simply mkdir in the build tree; +# LINKS are things to symlink back into the source tree +# (these can be both files and directories). +# Caution: do not add files or directories here using wildcards. This +# will result in problems later if a new file matching the wildcard is +# added to the source tree -- nothing will cause configure to be rerun +# so the build tree will be missing the link back to the new file, and +# tests might fail. Prefer to keep the relevant files in their own +# directory and symlink the directory instead. +DIRS="tests tests/tcg tests/tcg/lm32 tests/qapi-schema tests/qtest/libqos" +DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph" +DIRS="$DIRS docs docs/interop fsdev scsi" +DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw" +DIRS="$DIRS roms/seabios" +LINKS="Makefile" +LINKS="$LINKS tests/tcg/lm32/Makefile" +LINKS="$LINKS tests/tcg/Makefile.target" +LINKS="$LINKS pc-bios/optionrom/Makefile" +LINKS="$LINKS pc-bios/s390-ccw/Makefile" +LINKS="$LINKS roms/seabios/Makefile" +LINKS="$LINKS pc-bios/qemu-icon.bmp" +LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit +LINKS="$LINKS tests/acceptance tests/data" +LINKS="$LINKS tests/qemu-iotests/check" +LINKS="$LINKS python" +for bios_file in \ + $source_path/pc-bios/*.bin \ + $source_path/pc-bios/*.elf \ + $source_path/pc-bios/*.lid \ + $source_path/pc-bios/*.rom \ + $source_path/pc-bios/*.dtb \ + $source_path/pc-bios/*.img \ + $source_path/pc-bios/openbios-* \ + $source_path/pc-bios/u-boot.* \ + $source_path/pc-bios/edk2-*.fd.bz2 \ + $source_path/pc-bios/palcode-* +do + LINKS="$LINKS pc-bios/$(basename $bios_file)" +done +mkdir -p $DIRS +for f in $LINKS ; do + if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then + symlink "$source_path/$f" "$f" + fi +done + +(for i in $cross_cc_vars; do + export $i +done +export target_list source_path use_containers +$source_path/tests/tcg/configure.sh) + +# temporary config to build submodules +for rom in seabios; do + config_mak=roms/$rom/config.mak + echo "# Automatically generated by configure - do not modify" > $config_mak + echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak + echo "AS=$as" >> $config_mak + echo "CCAS=$ccas" >> $config_mak + echo "CC=$cc" >> $config_mak + echo "BCC=bcc" >> $config_mak + echo "CPP=$cpp" >> $config_mak + echo "OBJCOPY=objcopy" >> $config_mak + echo "IASL=$iasl" >> $config_mak + echo "LD=$ld" >> $config_mak + echo "RANLIB=$ranlib" >> $config_mak +done + +# set up qemu-iotests in this build directory +iotests_common_env="tests/qemu-iotests/common.env" + +echo "# Automatically generated by configure - do not modify" > "$iotests_common_env" +echo >> "$iotests_common_env" +echo "export PYTHON='$python'" >> "$iotests_common_env" + +if test "$skip_meson" = no; then +cross="config-meson.cross.new" +meson_quote() { + echo "['$(echo $* | sed "s/ /','/g")']" +} + +echo "# Automatically generated by configure - do not modify" > $cross +echo "[properties]" >> $cross +test -z "$cxx" && echo "link_language = 'c'" >> $cross +echo "[binaries]" >> $cross +echo "c = $(meson_quote $cc)" >> $cross +test -n "$cxx" && echo "cpp = $(meson_quote $cxx)" >> $cross +echo "ar = $(meson_quote $ar)" >> $cross +echo "nm = $(meson_quote $nm)" >> $cross +echo "pkgconfig = $(meson_quote $pkg_config_exe)" >> $cross +echo "ranlib = $(meson_quote $ranlib)" >> $cross +echo "strip = $(meson_quote $strip)" >> $cross +echo "windres = $(meson_quote $windres)" >> $cross +if test -n "$cross_prefix"; then + cross_arg="--cross-file config-meson.cross" + # Hack: Meson expects an absolute path for the *build* machine + # for the prefix, so add a slash in front of a Windows path that + # includes a drive letter. + # + # See https://github.com/mesonbuild/meson/issues/7577. + echo "[host_machine]" >> $cross + if test "$mingw32" = "yes" ; then + echo "system = 'windows'" >> $cross + case $prefix in + ?:*) pre_prefix=/ ;; + esac + fi + case "$ARCH" in + i386|x86_64) + echo "cpu_family = 'x86'" >> $cross + ;; + ppc64le) + echo "cpu_family = 'ppc64'" >> $cross + ;; + *) + echo "cpu_family = '$ARCH'" >> $cross + ;; + esac + echo "cpu = '$cpu'" >> $cross + if test "$bigendian" = "yes" ; then + echo "endian = 'big'" >> $cross + else + echo "endian = 'little'" >> $cross + fi +else + cross_arg="--native-file config-meson.cross" +fi +mv $cross config-meson.cross + +rm -rf meson-private meson-info meson-logs +NINJA=${ninja:-${build_path}/ninjatool} $meson setup \ + --prefix "${pre_prefix}$prefix" \ + --libdir "${pre_prefix}$libdir" \ + --libexecdir "${pre_prefix}$libexecdir" \ + --bindir "${pre_prefix}$bindir" \ + --includedir "${pre_prefix}$includedir" \ + --datadir "${pre_prefix}$datadir" \ + --mandir "${pre_prefix}$mandir" \ + --sysconfdir "${pre_prefix}$sysconfdir" \ + --localstatedir "${pre_prefix}$local_statedir" \ + -Ddocdir="${pre_prefix}$docdir" \ + -Dqemu_suffix="$qemu_suffix" \ + -Doptimization=$(if test "$debug" = yes; then echo 0; else echo 2; fi) \ + -Ddebug=$(if test "$debug_info" = yes; then echo true; else echo false; fi) \ + -Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \ + -Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \ + -Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \ + -Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \ + -Dsdl=$sdl -Dsdl_image=$sdl_image \ + -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ + -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f\ + $cross_arg \ + "$build_path" "$source_path" + +if test "$?" -ne 0 ; then + error_exit "meson setup failed" +fi +touch ninjatool.stamp +fi + +# Save the configure command line for later reuse. +cat <config.status +#!/bin/sh +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. +EOD + +preserve_env() { + envname=$1 + + eval envval=\$$envname + + if test -n "$envval" + then + echo "$envname='$envval'" >> config.status + echo "export $envname" >> config.status + else + echo "unset $envname" >> config.status + fi +} + +# Preserve various env variables that influence what +# features/build target configure will detect +preserve_env AR +preserve_env AS +preserve_env CC +preserve_env CPP +preserve_env CXX +preserve_env INSTALL +preserve_env LD +preserve_env LD_LIBRARY_PATH +preserve_env LIBTOOL +preserve_env MAKE +preserve_env NM +preserve_env OBJCOPY +preserve_env PATH +preserve_env PKG_CONFIG +preserve_env PKG_CONFIG_LIBDIR +preserve_env PKG_CONFIG_PATH +preserve_env PYTHON +preserve_env SDL2_CONFIG +preserve_env SMBD +preserve_env STRIP +preserve_env WINDRES + +printf "exec" >>config.status +for i in "$0" "$@"; do + test "$i" = --skip-meson || printf " '%s'" "$i" >>config.status +done +echo ' "$@"' >>config.status +chmod +x config.status + +rm -r "$TMPDIR1" From patchwork Thu Sep 3 07:43:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752587 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D63D4739 for ; Thu, 3 Sep 2020 07:48:50 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A9FDE206C0 for ; Thu, 3 Sep 2020 07:48:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="V+ZGx1cU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A9FDE206C0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:60080 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjzF-0008FI-S2 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:48:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43432) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuZ-0000Pk-T0 for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:59 -0400 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]:37570) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuY-0003uI-86 for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:43:59 -0400 Received: by mail-pj1-x1043.google.com with SMTP id mw10so1063515pjb.2 for ; Thu, 03 Sep 2020 00:43:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iUIJV0NrJHasWSyZnY8jh25seOv6g5EICBiDlFuRKr4=; b=V+ZGx1cU4OTfefyAApcuukQl4R7vN5YN202dFspHVkDeN4atRmT84tPnUf4xeYAAIa I+mVUzMGV0w3qTrNFn4JwaDQeBLInW2k07SzNOt3jAh0KWui0iqXy7clGiTj6Hd9ysEA EDhuZ9DV6Zlbyo+PcUVhiR/cspXLwAQwYWfXIK7i4VNwaAZs6EZk0FU5Iryi/GtxsI5c eTbi0s9UpJZqhBqnGvXMZwetX2ALCzcRdQJPOlOm419DnNOiqFTE2nT51n7K/A2yYHrb jPXF6yr0+2v7EKieQzK5frmTuDmqeXnRGErolA3Zfsjzxzg1/Pe+YjO1NxxsPRD800i6 Hh+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iUIJV0NrJHasWSyZnY8jh25seOv6g5EICBiDlFuRKr4=; b=NJ54UvRL7bi9gkbi+wNg14MtTbRtSi0q7875lt65fK6ky8jdewnwwo7cbX5alw6dz9 8EDw1Z1Du7g1SJXcl3JM9+ufO7ew6/Q1ZT3qT+EoylKSmjI5jqwVQvJBCuOvqhSYmrEe syUBv3WCR59RHZ76ifak8oVqW+qgFLIZeL77ez6cPTUYwwqo7ytVKkve+c+NAizMRYOJ ggFmQF/V83TA16U1pDmPK9kJxq+gVz9DiEJyd1y+Qy1dne+oODNgdESzdfzqyHsTE4Q9 MqI2PSFpcMoMR1yeJqdkO4DCgSypm2Lk6eI3kVI3Cd8f6XHy88db/6e1LslYCAyWOx81 QlaA== X-Gm-Message-State: AOAM533jFGZWRACIpB2Lpz4vLnKBCYdBkIJgF4YGi1SLreRtfewyv5gc lxF37vJN0/6HxzQ5OsLeq/piw/2XPyfKle2n X-Google-Smtp-Source: ABdhPJyieuTP3xXoHaWWtLkYgv+toiYfOcMJ/F2wZzEn5itdl2Rkpwy6TLkWSE5O5ma8hcEs733b5A== X-Received: by 2002:a17:90a:c255:: with SMTP id d21mr2126386pjx.212.1599119036513; Thu, 03 Sep 2020 00:43:56 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:55 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 09/12] stubs: qemu_notify_event have no need to stub Date: Thu, 3 Sep 2020 15:43:10 +0800 Message-Id: <20200903074313.1498-10-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1043; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1043.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" LINK tests/test-qdev-global-props.exe LINK tests/test-timed-average.exe C:/CI-Tools/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: libqemuutil.a(util_main-loop.c.obj): in function `qemu_notify_event': C:\work\xemu\qemu-build/../qemu/util/main-loop.c:139: multiple definition of `qemu_notify_event'; libqemuutil.a(stubs_notify-event.c.obj):C:\work\xemu\qemu-build/../qemu/stubs/notify-event.c:6: first defined here collect2.exe: error: ld returned 1 exit status make: *** [C:/work/xemu/qemu/rules.mak:88:tests/test-timed-average.exe] 错误 1 Signed-off-by: Yonggang Luo --- stubs/notify-event.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/stubs/notify-event.c b/stubs/notify-event.c index 827bb52d1a..59935db11e 100644 --- a/stubs/notify-event.c +++ b/stubs/notify-event.c @@ -1,6 +1,2 @@ -#include "qemu/osdep.h" -#include "qemu/main-loop.h" - -void qemu_notify_event(void) -{ -} +#include "qemu/osdep.h" +#include "qemu/main-loop.h" From patchwork Thu Sep 3 07:43:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752589 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 18442739 for ; Thu, 3 Sep 2020 07:48:53 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CA89D206C0 for ; Thu, 3 Sep 2020 07:48:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ew7MLk6c" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CA89D206C0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:60242 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDjzH-0008JJ-TT for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:48:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43454) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjud-0000Zt-KZ for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:03 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]:43758) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjua-0003uY-Th for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:03 -0400 Received: by mail-pf1-x42b.google.com with SMTP id f18so1600906pfa.10 for ; Thu, 03 Sep 2020 00:44:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XFDBLTs60eOSYLuVLk2iUO8fBuKWazdIEw2K2TmK4fE=; b=Ew7MLk6cVRSkPPzhU/SRj272x7jfPI26WW2HSUmCs4ePq8HwHpiFw0cnaDiSQjxliF neMZ+u2S2YnvMsuNsZJmHTSVHzmTZu7FGbW2Vr0dzfqftTDhu+YGaQlP+EU0SXil6agk PRxt/C+3BDOiImWXHtKrO372w+HOzbdzOmIWBYZhi8tEnoGDa3Kpot5tyaT3iNOU91+E hseG68hZY4MFmR1OBFUIXkFgRHU/7eD+G0Ds7oSUWzdftiTAO1/jMBMGDcahgr8sjRPh D5o24qnvG9RI5/Y4eGoEDmjLMxcuUWRi82lii7jX8V7m7ExftlQo3t2BHqLyNfjfD4i0 HITg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XFDBLTs60eOSYLuVLk2iUO8fBuKWazdIEw2K2TmK4fE=; b=h4LWEehsvomjQgFjYDnOmDBC/0tvesujDZy4uZRObKYKITqQvMuFWMSKOocd8q0z0i S2DVeopGGwwY1La8gA1G16IzLtK4bIbyBjZewifh7GvG1mpYcEWqwb/3uSfqztSUn8Y9 QAAqAB84AUurCHIJ9JaQkgmWGvdc92NtiKeHBBBSEwpelmvSSeZ2Cx5m5Z3V+YtLXcvY aj+6WYIWgIS5+suZRskRrWv8/97WNiTC4LrWKgxFSBvURuhlI1DsLOI8qblWkSLGoOq7 an1ehrKe9a8iyheRgCVPzI+7lwYMy5t4T3RlIVr39x2Wz1O7FVnsJhSVS1MnKtxCqlYE CPZQ== X-Gm-Message-State: AOAM532zPvqKaxWc+3twFlA+Lamj1Dyyw/LbYHEX77Gz0QIuFnPnnfnY GtcV9O71i+zNPv6MBwmg/baFeb300W7JETHI X-Google-Smtp-Source: ABdhPJzdldktEhDoJEnR8tSsBVjo5PhA8Hc7nWa3dgpX+JgAWsjbv8gvIAvxaK17vsfyjhlXGN7bqQ== X-Received: by 2002:a63:ba49:: with SMTP id l9mr1983782pgu.101.1599119038878; Thu, 03 Sep 2020 00:43:58 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:43:58 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 10/12] meson: Fixes qapi tests. Date: Thu, 3 Sep 2020 15:43:11 +0800 Message-Id: <20200903074313.1498-11-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42b; envelope-from=luoyonggang@gmail.com; helo=mail-pf1-x42b.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The error are: +@end table + +@end deftypefn + make: *** [Makefile.mtest:63: check-qapi-schema] Error 1 Signed-off-by: Yonggang Luo --- tests/qapi-schema/meson.build | 451 +++++++++++++++++----------------- 1 file changed, 226 insertions(+), 225 deletions(-) diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build index c87d141417..67ba0a5ebd 100644 --- a/tests/qapi-schema/meson.build +++ b/tests/qapi-schema/meson.build @@ -1,225 +1,226 @@ -test_env = environment() -test_env.set('PYTHONPATH', meson.source_root() / 'scripts') -test_env.set('PYTHONIOENCODING', 'utf-8') - -schemas = [ - 'alternate-any.json', - 'alternate-array.json', - 'alternate-base.json', - 'alternate-branch-if-invalid.json', - 'alternate-clash.json', - 'alternate-conflict-dict.json', - 'alternate-conflict-enum-bool.json', - 'alternate-conflict-enum-int.json', - 'alternate-conflict-string.json', - 'alternate-conflict-bool-string.json', - 'alternate-conflict-num-string.json', - 'alternate-empty.json', - 'alternate-invalid-dict.json', - 'alternate-nested.json', - 'alternate-unknown.json', - 'args-alternate.json', - 'args-any.json', - 'args-array-empty.json', - 'args-array-unknown.json', - 'args-bad-boxed.json', - 'args-boxed-anon.json', - 'args-boxed-string.json', - 'args-int.json', - 'args-invalid.json', - 'args-member-array-bad.json', - 'args-member-case.json', - 'args-member-unknown.json', - 'args-name-clash.json', - 'args-union.json', - 'args-unknown.json', - 'bad-base.json', - 'bad-data.json', - 'bad-ident.json', - 'bad-if.json', - 'bad-if-empty.json', - 'bad-if-empty-list.json', - 'bad-if-list.json', - 'bad-type-bool.json', - 'bad-type-dict.json', - 'bad-type-int.json', - 'base-cycle-direct.json', - 'base-cycle-indirect.json', - 'command-int.json', - 'comments.json', - 'doc-bad-alternate-member.json', - 'doc-bad-boxed-command-arg.json', - 'doc-bad-command-arg.json', - 'doc-bad-enum-member.json', - 'doc-bad-event-arg.json', - 'doc-bad-feature.json', - 'doc-bad-section.json', - 'doc-bad-symbol.json', - 'doc-bad-union-member.json', - 'doc-before-include.json', - 'doc-before-pragma.json', - 'doc-duplicated-arg.json', - 'doc-duplicated-return.json', - 'doc-duplicated-since.json', - 'doc-empty-arg.json', - 'doc-empty-section.json', - 'doc-empty-symbol.json', - 'doc-good.json', - 'doc-interleaved-section.json', - 'doc-invalid-end.json', - 'doc-invalid-end2.json', - 'doc-invalid-return.json', - 'doc-invalid-section.json', - 'doc-invalid-start.json', - 'doc-missing-colon.json', - 'doc-missing-expr.json', - 'doc-missing-space.json', - 'doc-missing.json', - 'doc-no-symbol.json', - 'doc-undoc-feature.json', - 'double-type.json', - 'duplicate-key.json', - 'empty.json', - 'enum-bad-member.json', - 'enum-bad-name.json', - 'enum-bad-prefix.json', - 'enum-clash-member.json', - 'enum-dict-member-unknown.json', - 'enum-if-invalid.json', - 'enum-int-member.json', - 'enum-member-case.json', - 'enum-missing-data.json', - 'enum-wrong-data.json', - 'event-boxed-empty.json', - 'event-case.json', - 'event-member-invalid-dict.json', - 'event-nest-struct.json', - 'features-bad-type.json', - 'features-deprecated-type.json', - 'features-duplicate-name.json', - 'features-if-invalid.json', - 'features-missing-name.json', - 'features-name-bad-type.json', - 'features-no-list.json', - 'features-unknown-key.json', - 'flat-union-array-branch.json', - 'flat-union-bad-base.json', - 'flat-union-bad-discriminator.json', - 'flat-union-base-any.json', - 'flat-union-base-union.json', - 'flat-union-clash-member.json', - 'flat-union-discriminator-bad-name.json', - 'flat-union-empty.json', - 'flat-union-inline.json', - 'flat-union-inline-invalid-dict.json', - 'flat-union-int-branch.json', - 'flat-union-invalid-branch-key.json', - 'flat-union-invalid-discriminator.json', - 'flat-union-invalid-if-discriminator.json', - 'flat-union-no-base.json', - 'flat-union-optional-discriminator.json', - 'flat-union-string-discriminator.json', - 'funny-char.json', - 'funny-word.json', - 'ident-with-escape.json', - 'include-before-err.json', - 'include-cycle.json', - 'include-extra-junk.json', - 'include-nested-err.json', - 'include-no-file.json', - 'include-non-file.json', - 'include-repetition.json', - 'include-self-cycle.json', - 'include-simple.json', - 'indented-expr.json', - 'leading-comma-list.json', - 'leading-comma-object.json', - 'missing-colon.json', - 'missing-comma-list.json', - 'missing-comma-object.json', - 'missing-type.json', - 'nested-struct-data.json', - 'nested-struct-data-invalid-dict.json', - 'non-objects.json', - 'oob-test.json', - 'allow-preconfig-test.json', - 'pragma-doc-required-crap.json', - 'pragma-extra-junk.json', - 'pragma-name-case-whitelist-crap.json', - 'pragma-non-dict.json', - 'pragma-unknown.json', - 'pragma-returns-whitelist-crap.json', - 'qapi-schema-test.json', - 'quoted-structural-chars.json', - 'redefined-builtin.json', - 'redefined-command.json', - 'redefined-event.json', - 'redefined-type.json', - 'reserved-command-q.json', - 'reserved-enum-q.json', - 'reserved-member-has.json', - 'reserved-member-q.json', - 'reserved-member-u.json', - 'reserved-member-underscore.json', - 'reserved-type-kind.json', - 'reserved-type-list.json', - 'returns-alternate.json', - 'returns-array-bad.json', - 'returns-dict.json', - 'returns-unknown.json', - 'returns-whitelist.json', - 'string-code-point-31.json', - 'string-code-point-127.json', - 'struct-base-clash-deep.json', - 'struct-base-clash.json', - 'struct-data-invalid.json', - 'struct-member-if-invalid.json', - 'struct-member-invalid-dict.json', - 'struct-member-invalid.json', - 'trailing-comma-list.json', - 'trailing-comma-object.json', - 'type-bypass-bad-gen.json', - 'unclosed-list.json', - 'unclosed-object.json', - 'unclosed-string.json', - 'union-base-empty.json', - 'union-base-no-discriminator.json', - 'union-branch-case.json', - 'union-branch-if-invalid.json', - 'union-branch-invalid-dict.json', - 'union-clash-branches.json', - 'union-empty.json', - 'union-invalid-base.json', - 'union-optional-branch.json', - 'union-unknown.json', - 'unknown-escape.json', - 'unknown-expr-key.json', -] - -# Because people may want to use test-qapi.py from the command line, we -# are not using the "#! /usr/bin/env python3" trick here. See -# docs/devel/build-system.txt -test('QAPI schema regression tests', python, args: files('test-qapi.py', schemas), - env: test_env, suite: ['qapi-schema', 'qapi-frontend']) - -diff = find_program('diff') - -qapi_doc = custom_target('QAPI doc', - output: ['doc-good-qapi-doc.texi', - 'doc-good-qapi-commands.c', 'doc-good-qapi-commands.h', - 'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h', - 'doc-good-qapi-events.c', 'doc-good-qapi-events.h', - 'doc-good-qapi-init-commands.c', 'doc-good-qapi-init-commands.h', - 'doc-good-qapi-introspect.c', 'doc-good-qapi-introspect.h', - 'doc-good-qapi-types.c', 'doc-good-qapi-types.h', - 'doc-good-qapi-visit.c', 'doc-good-qapi-visit.h' ], - input: files('doc-good.json'), - command: [ qapi_gen, '-o', meson.current_build_dir(), - '-p', 'doc-good-', '@INPUT0@' ], - depend_files: qapi_gen_depends) - -# "full_path()" needed here to work around -# https://github.com/mesonbuild/meson/issues/7585 -test('QAPI doc', diff, args: ['-u', files('doc-good.texi'), qapi_doc[0].full_path()], - depends: qapi_doc, - suite: ['qapi-schema', 'qapi-doc']) +test_env = environment() +test_env.set('PYTHONPATH', meson.source_root() / 'scripts') +test_env.set('PYTHONIOENCODING', 'utf-8') + +schemas = [ + 'alternate-any.json', + 'alternate-array.json', + 'alternate-base.json', + 'alternate-branch-if-invalid.json', + 'alternate-clash.json', + 'alternate-conflict-dict.json', + 'alternate-conflict-enum-bool.json', + 'alternate-conflict-enum-int.json', + 'alternate-conflict-string.json', + 'alternate-conflict-bool-string.json', + 'alternate-conflict-num-string.json', + 'alternate-empty.json', + 'alternate-invalid-dict.json', + 'alternate-nested.json', + 'alternate-unknown.json', + 'args-alternate.json', + 'args-any.json', + 'args-array-empty.json', + 'args-array-unknown.json', + 'args-bad-boxed.json', + 'args-boxed-anon.json', + 'args-boxed-string.json', + 'args-int.json', + 'args-invalid.json', + 'args-member-array-bad.json', + 'args-member-case.json', + 'args-member-unknown.json', + 'args-name-clash.json', + 'args-union.json', + 'args-unknown.json', + 'bad-base.json', + 'bad-data.json', + 'bad-ident.json', + 'bad-if.json', + 'bad-if-empty.json', + 'bad-if-empty-list.json', + 'bad-if-list.json', + 'bad-type-bool.json', + 'bad-type-dict.json', + 'bad-type-int.json', + 'base-cycle-direct.json', + 'base-cycle-indirect.json', + 'command-int.json', + 'comments.json', + 'doc-bad-alternate-member.json', + 'doc-bad-boxed-command-arg.json', + 'doc-bad-command-arg.json', + 'doc-bad-enum-member.json', + 'doc-bad-event-arg.json', + 'doc-bad-feature.json', + 'doc-bad-section.json', + 'doc-bad-symbol.json', + 'doc-bad-union-member.json', + 'doc-before-include.json', + 'doc-before-pragma.json', + 'doc-duplicated-arg.json', + 'doc-duplicated-return.json', + 'doc-duplicated-since.json', + 'doc-empty-arg.json', + 'doc-empty-section.json', + 'doc-empty-symbol.json', + 'doc-good.json', + 'doc-interleaved-section.json', + 'doc-invalid-end.json', + 'doc-invalid-end2.json', + 'doc-invalid-return.json', + 'doc-invalid-section.json', + 'doc-invalid-start.json', + 'doc-missing-colon.json', + 'doc-missing-expr.json', + 'doc-missing-space.json', + 'doc-missing.json', + 'doc-no-symbol.json', + 'doc-undoc-feature.json', + 'double-type.json', + 'duplicate-key.json', + 'empty.json', + 'enum-bad-member.json', + 'enum-bad-name.json', + 'enum-bad-prefix.json', + 'enum-clash-member.json', + 'enum-dict-member-unknown.json', + 'enum-if-invalid.json', + 'enum-int-member.json', + 'enum-member-case.json', + 'enum-missing-data.json', + 'enum-wrong-data.json', + 'event-boxed-empty.json', + 'event-case.json', + 'event-member-invalid-dict.json', + 'event-nest-struct.json', + 'features-bad-type.json', + 'features-deprecated-type.json', + 'features-duplicate-name.json', + 'features-if-invalid.json', + 'features-missing-name.json', + 'features-name-bad-type.json', + 'features-no-list.json', + 'features-unknown-key.json', + 'flat-union-array-branch.json', + 'flat-union-bad-base.json', + 'flat-union-bad-discriminator.json', + 'flat-union-base-any.json', + 'flat-union-base-union.json', + 'flat-union-clash-member.json', + 'flat-union-discriminator-bad-name.json', + 'flat-union-empty.json', + 'flat-union-inline.json', + 'flat-union-inline-invalid-dict.json', + 'flat-union-int-branch.json', + 'flat-union-invalid-branch-key.json', + 'flat-union-invalid-discriminator.json', + 'flat-union-invalid-if-discriminator.json', + 'flat-union-no-base.json', + 'flat-union-optional-discriminator.json', + 'flat-union-string-discriminator.json', + 'funny-char.json', + 'funny-word.json', + 'ident-with-escape.json', + 'include-before-err.json', + 'include-cycle.json', + 'include-extra-junk.json', + 'include-nested-err.json', + 'include-no-file.json', + 'include-non-file.json', + 'include-repetition.json', + 'include-self-cycle.json', + 'include-simple.json', + 'indented-expr.json', + 'leading-comma-list.json', + 'leading-comma-object.json', + 'missing-colon.json', + 'missing-comma-list.json', + 'missing-comma-object.json', + 'missing-type.json', + 'nested-struct-data.json', + 'nested-struct-data-invalid-dict.json', + 'non-objects.json', + 'oob-test.json', + 'allow-preconfig-test.json', + 'pragma-doc-required-crap.json', + 'pragma-extra-junk.json', + 'pragma-name-case-whitelist-crap.json', + 'pragma-non-dict.json', + 'pragma-unknown.json', + 'pragma-returns-whitelist-crap.json', + 'qapi-schema-test.json', + 'quoted-structural-chars.json', + 'redefined-builtin.json', + 'redefined-command.json', + 'redefined-event.json', + 'redefined-type.json', + 'reserved-command-q.json', + 'reserved-enum-q.json', + 'reserved-member-has.json', + 'reserved-member-q.json', + 'reserved-member-u.json', + 'reserved-member-underscore.json', + 'reserved-type-kind.json', + 'reserved-type-list.json', + 'returns-alternate.json', + 'returns-array-bad.json', + 'returns-dict.json', + 'returns-unknown.json', + 'returns-whitelist.json', + 'string-code-point-31.json', + 'string-code-point-127.json', + 'struct-base-clash-deep.json', + 'struct-base-clash.json', + 'struct-data-invalid.json', + 'struct-member-if-invalid.json', + 'struct-member-invalid-dict.json', + 'struct-member-invalid.json', + 'trailing-comma-list.json', + 'trailing-comma-object.json', + 'type-bypass-bad-gen.json', + 'unclosed-list.json', + 'unclosed-object.json', + 'unclosed-string.json', + 'union-base-empty.json', + 'union-base-no-discriminator.json', + 'union-branch-case.json', + 'union-branch-if-invalid.json', + 'union-branch-invalid-dict.json', + 'union-clash-branches.json', + 'union-empty.json', + 'union-invalid-base.json', + 'union-optional-branch.json', + 'union-unknown.json', + 'unknown-escape.json', + 'unknown-expr-key.json', +] + +# Because people may want to use test-qapi.py from the command line, we +# are not using the "#! /usr/bin/env python3" trick here. See +# docs/devel/build-system.txt +test('QAPI schema regression tests', python, args: files('test-qapi.py', schemas), + env: test_env, suite: ['qapi-schema', 'qapi-frontend']) + +diff = find_program('diff') + +qapi_doc = custom_target('QAPI doc', + output: ['doc-good-qapi-doc.texi', + 'doc-good-qapi-commands.c', 'doc-good-qapi-commands.h', + 'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h', + 'doc-good-qapi-events.c', 'doc-good-qapi-events.h', + 'doc-good-qapi-init-commands.c', 'doc-good-qapi-init-commands.h', + 'doc-good-qapi-introspect.c', 'doc-good-qapi-introspect.h', + 'doc-good-qapi-types.c', 'doc-good-qapi-types.h', + 'doc-good-qapi-visit.c', 'doc-good-qapi-visit.h' ], + input: files('doc-good.json'), + command: [ qapi_gen, '-o', meson.current_build_dir(), + '-p', 'doc-good-', '@INPUT0@' ], + depend_files: qapi_gen_depends) + +# "full_path()" needed here to work around +# https://github.com/mesonbuild/meson/issues/7585 +test('QAPI doc', diff, args: ['--strip-trailing-cr', + '-u', files('doc-good.texi'), qapi_doc[0].full_path()], + depends: qapi_doc, + suite: ['qapi-schema', 'qapi-doc']) From patchwork Thu Sep 3 07:43:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752595 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B38E314E3 for ; Thu, 3 Sep 2020 07:52:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4B6B720775 for ; Thu, 3 Sep 2020 07:52:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="uR8f6+8w" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4B6B720775 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:42394 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDk3C-0004Bl-Ah for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:52:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43486) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuk-0000rh-DJ for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:10 -0400 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]:42721) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjuf-0003uu-GO for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:10 -0400 Received: by mail-pf1-x444.google.com with SMTP id 17so1603923pfw.9 for ; Thu, 03 Sep 2020 00:44:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=J7jnwobGRIDUa/em/2YcJoKe5IITUTAYh0YoCe/oM4I=; b=uR8f6+8wxQiGuKMusQHfs3q1NgCVppHtYIUFOl5Zu77r16bQ6nTuLTcF4LbIqSr0j0 lYtvzIVps59TwS23a3V0u16vxf4uezmOSohKYXOJi+OtMG23iXJXVOBOFAtBf7wFkvzc ty2F03Msk4Yd+E8A7txfI8VQMNiEj4HC6rGnSvuiY2qHZvBZA1MD8m/sAT5K9gahcOUZ 0LRDX9HyUsIumkgWZm5Czm4Fbin2vA9D1630Cl+6bxnaSx9BcdRh38O9Iuz86DYqPHJK zR5rb0d8kFOqOc3OQZcy3g8h7XMiaeuB/L1YQQhZsRTbJY23kXezlz25Qhf5WYnEXVZ8 S96w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=J7jnwobGRIDUa/em/2YcJoKe5IITUTAYh0YoCe/oM4I=; b=rDwoIwBWsMSju6b28gnLw52jsoSwSNhROGASZHKrah9PLW+333DWo1CWxGPWXaC6Ge EZ3LI2WMF+IX0GfSWiNe9zrr0lG2O8ESkGMSP5Eu+RPsy5AniO6BVY66NHg19om60+LJ LCdwHrqUMV6BQry+ZiXEz0Fm9hgDWcJ6yI+ZzUvmwN1ii0NrbIbeUV30oY9UK78gORTb f6wD4yuwovnpBgU3Qk4p1mEL7HWe/mlbFCpZuqQGRxRh7l7uSZ2SrccTRTzyDuSuisum fu6E0ENTI4QdbET6sFgY2QTeAaOHHxkQlvgDa1qmhvoldfplCKeuv/ekufpgnl5cZdLm Mhtw== X-Gm-Message-State: AOAM530phdNVkupwwMocPsGgBmG9M1oqf+Xpj2ldml7mcLhUho1JEb0x q3gS+o8UeDHOOZnnTpzJ8vLZcZYZlLiT8IVn X-Google-Smtp-Source: ABdhPJzaJVwJVMkVpCrTVXmdc4w6tnDyJND6q4wPE1faO9V/tRjsoO+pAuXRRcFGGTlTLenoZq4kpg== X-Received: by 2002:a65:66c4:: with SMTP id c4mr1991372pgw.442.1599119042329; Thu, 03 Sep 2020 00:44:02 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.43.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:44:01 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 11/12] tests: Disable test-image-locking that not works under Win32 Date: Thu, 3 Sep 2020 15:43:12 +0800 Message-Id: <20200903074313.1498-12-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::444; envelope-from=luoyonggang@gmail.com; helo=mail-pf1-x444.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yonggang Luo --- tests/Makefile.include | 1086 ++++++++++++++++++++-------------------- 1 file changed, 544 insertions(+), 542 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 9ac8f5b86a..497f1f21ff 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -1,542 +1,544 @@ -# -*- Mode: makefile -*- - -.PHONY: check-help -check-help: - @echo "Regression testing targets:" - @echo - @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests" - @echo - @echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target" - @echo " $(MAKE) check-qtest Run qtest tests" - @echo " $(MAKE) check-unit Run qobject tests" - @echo " $(MAKE) check-speed Run qobject speed tests" - @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" - @echo " $(MAKE) check-block Run block tests" -ifeq ($(CONFIG_TCG),y) - @echo " $(MAKE) check-tcg Run TCG tests" - @echo " $(MAKE) check-softfloat Run FPU emulation tests" -endif - @echo " $(MAKE) check-acceptance Run all acceptance (functional) tests" - @echo - @echo " $(MAKE) check-report.tap Generates an aggregated TAP test report" - @echo " $(MAKE) check-venv Creates a Python venv for tests" - @echo " $(MAKE) check-clean Clean the tests and related data" - @echo - @echo "The following are useful for CI builds" - @echo " $(MAKE) check-build Build most test binaris" - @echo " $(MAKE) get-vm-images Downloads all images used by acceptance tests, according to configured targets (~350 MB each, 1.5 GB max)" - @echo - @echo - @echo "The variable SPEED can be set to control the gtester speed setting." - @echo "Default options are -k and (for $(MAKE) V=1) --verbose; they can be" - @echo "changed with variable GTESTER_OPTIONS." - -ifneq ($(wildcard config-host.mak),) -export SRC_PATH - -# TODO don't duplicate $(SRC_PATH)/Makefile's qapi-py here -qapi-py = $(SRC_PATH)/scripts/qapi/__init__.py \ -$(SRC_PATH)/scripts/qapi/commands.py \ -$(SRC_PATH)/scripts/qapi/common.py \ -$(SRC_PATH)/scripts/qapi/doc.py \ -$(SRC_PATH)/scripts/qapi/error.py \ -$(SRC_PATH)/scripts/qapi/events.py \ -$(SRC_PATH)/scripts/qapi/expr.py \ -$(SRC_PATH)/scripts/qapi/gen.py \ -$(SRC_PATH)/scripts/qapi/introspect.py \ -$(SRC_PATH)/scripts/qapi/parser.py \ -$(SRC_PATH)/scripts/qapi/schema.py \ -$(SRC_PATH)/scripts/qapi/source.py \ -$(SRC_PATH)/scripts/qapi/types.py \ -$(SRC_PATH)/scripts/qapi/visit.py \ -$(SRC_PATH)/scripts/qapi-gen.py - -# Get the list of all supported sysemu targets -SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \ - $(wildcard $(SRC_PATH)/default-configs/*-softmmu.mak))) - -check-unit-y += tests/check-qdict$(EXESUF) -check-unit-y += tests/check-block-qdict$(EXESUF) -check-unit-y += tests/check-qnum$(EXESUF) -check-unit-y += tests/check-qstring$(EXESUF) -check-unit-y += tests/check-qlist$(EXESUF) -check-unit-y += tests/check-qnull$(EXESUF) -check-unit-y += tests/check-qobject$(EXESUF) -check-unit-y += tests/check-qjson$(EXESUF) -check-unit-y += tests/check-qlit$(EXESUF) -check-unit-y += tests/test-qobject-output-visitor$(EXESUF) -check-unit-y += tests/test-clone-visitor$(EXESUF) -check-unit-y += tests/test-qobject-input-visitor$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-qmp-cmds$(EXESUF) -check-unit-y += tests/test-string-input-visitor$(EXESUF) -check-unit-y += tests/test-string-output-visitor$(EXESUF) -check-unit-y += tests/test-qmp-event$(EXESUF) -check-unit-y += tests/test-opts-visitor$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-coroutine$(EXESUF) -check-unit-y += tests/test-visitor-serialization$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-iov$(EXESUF) -check-unit-y += tests/test-bitmap$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-aio$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-aio-multithread$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-throttle$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-thread-pool$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-hbitmap$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-drain$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-graph-mod$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-blockjob$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-blockjob-txn$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-block-backend$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-block-iothread$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-image-locking$(EXESUF) -check-unit-y += tests/test-x86-cpuid$(EXESUF) -# all code tested by test-x86-cpuid is inside topology.h -ifeq ($(CONFIG_SOFTMMU),y) -check-unit-y += tests/test-xbzrle$(EXESUF) -check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF) -endif -check-unit-y += tests/test-cutils$(EXESUF) -check-unit-y += tests/test-shift128$(EXESUF) -check-unit-y += tests/test-mul64$(EXESUF) -check-unit-y += tests/test-int128$(EXESUF) -# all code tested by test-int128 is inside int128.h -check-unit-y += tests/rcutorture$(EXESUF) -check-unit-y += tests/test-rcu-list$(EXESUF) -check-unit-y += tests/test-rcu-simpleq$(EXESUF) -check-unit-y += tests/test-rcu-tailq$(EXESUF) -check-unit-y += tests/test-rcu-slist$(EXESUF) -check-unit-y += tests/test-qdist$(EXESUF) -check-unit-y += tests/test-qht$(EXESUF) -check-unit-y += tests/test-qht-par$(EXESUF) -check-unit-y += tests/test-bitops$(EXESUF) -check-unit-y += tests/test-bitcnt$(EXESUF) -check-unit-y += tests/test-qgraph$(EXESUF) -check-unit-y += tests/check-qom-interface$(EXESUF) -check-unit-y += tests/check-qom-proplist$(EXESUF) -check-unit-y += tests/test-qemu-opts$(EXESUF) -check-unit-y += tests/test-keyval$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-write-threshold$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hash$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hash$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hmac$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hmac$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-cipher$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-cipher$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-secret$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlscredsx509$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlssession$(EXESUF) -ifndef CONFIG_TSAN -# Some tests: test-char, test-qdev-global-props, and test-qga, -# are not runnable under TSan due to a known issue. -# https://github.com/google/sanitizers/issues/1116 -check-unit-$(CONFIG_SOFTMMU) += tests/test-char$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-qdev-global-props$(EXESUF) -ifeq ($(CONFIG_GUEST_AGENT),y) -check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF) -endif -endif -check-unit-$(CONFIG_SOFTMMU) += tests/test-timed-average$(EXESUF) -check-unit-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_INOTIFY1)) += tests/test-util-filemonitor$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-util-sockets$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-simple$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-list$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-listfile$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_AUTH_PAM)) += tests/test-authz-pam$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-task$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-socket$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-file$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-io-channel-tls$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-command$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-buffer$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-base64$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(if $(CONFIG_NETTLE),y,$(CONFIG_GCRYPT))) += tests/test-crypto-pbkdf$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-ivgen$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-afsplit$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_QEMU_PRIVATE_XTS)) += tests/test-crypto-xts$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-block$(EXESUF) -check-unit-y += tests/test-logging$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_REPLICATION)) += tests/test-replication$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-bufferiszero$(EXESUF) -check-unit-y += tests/test-uuid$(EXESUF) -check-unit-y += tests/ptimer-test$(EXESUF) -check-unit-y += tests/test-qapi-util$(EXESUF) - -generated-files-y += tests/test-qapi-types.h -generated-files-y += tests/include/test-qapi-types-sub-module.h -generated-files-y += tests/test-qapi-types-sub-sub-module.h -generated-files-y += tests/test-qapi-visit.h -generated-files-y += tests/include/test-qapi-visit-sub-module.h -generated-files-y += tests/test-qapi-visit-sub-sub-module.h -generated-files-y += tests/test-qapi-commands.h -generated-files-y += tests/test-qapi-init-commands.h -generated-files-y += tests/include/test-qapi-commands-sub-module.h -generated-files-y += tests/test-qapi-commands-sub-sub-module.h -generated-files-y += tests/test-qapi-emit-events.h -generated-files-y += tests/test-qapi-events.h -generated-files-y += tests/include/test-qapi-events-sub-module.h -generated-files-y += tests/test-qapi-events-sub-sub-module.h -generated-files-y += tests/test-qapi-introspect.h - -QEMU_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest - - -# Deps that are common to various different sets of tests below -test-util-obj-y = libqemuutil.a -test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y) -test-qapi-obj-y = tests/test-qapi-types.o \ - tests/include/test-qapi-types-sub-module.o \ - tests/test-qapi-types-sub-sub-module.o \ - tests/test-qapi-visit.o \ - tests/include/test-qapi-visit-sub-module.o \ - tests/test-qapi-visit-sub-sub-module.o \ - tests/test-qapi-introspect.o \ - $(test-qom-obj-y) -benchmark-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) -test-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) -test-io-obj-$(CONFIG_BLOCK) = $(io-obj-y) $(test-crypto-obj-y) -test-authz-obj-$(CONFIG_BLOCK) = $(test-qom-obj-y) $(authz-obj-y) -test-block-obj-$(CONFIG_BLOCK) = $(block-obj-y) $(test-io-obj-y) tests/iothread.o - -tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y) -tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y) -tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y) -tests/check-block-qdict$(EXESUF): tests/check-block-qdict.o $(test-util-obj-y) -tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y) -tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) -tests/check-qobject$(EXESUF): tests/check-qobject.o $(test-util-obj-y) -tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y) -tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y) -tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y) -tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y) - -tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(test-io-obj-y) $(chardev-obj-y) tests/socket-helpers.o -tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y) -tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y) -tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y) -tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y) -tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-block-iothread$(EXESUF): tests/test-block-iothread.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) -tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) -tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) -tests/test-bitmap$(EXESUF): tests/test-bitmap.o $(test-util-obj-y) -tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o -tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/libmigration.fa $(test-util-obj-y) \ - $(test-io-obj-y) -tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o $(test-util-obj-y) -tests/test-int128$(EXESUF): tests/test-int128.o -tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) -tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y) -tests/test-rcu-simpleq$(EXESUF): tests/test-rcu-simpleq.o $(test-util-obj-y) -tests/test-rcu-tailq$(EXESUF): tests/test-rcu-tailq.o $(test-util-obj-y) -tests/test-rcu-slist$(EXESUF): tests/test-rcu-slist.o $(test-util-obj-y) -tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y) -tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y) -tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y) -tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) -tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y) -tests/atomic_add-bench$(EXESUF): tests/atomic_add-bench.o $(test-util-obj-y) -tests/atomic64-bench$(EXESUF): tests/atomic64-bench.o $(test-util-obj-y) - -tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o hw/core/libhwcore.fa \ - $(test-qapi-obj-y) -tests/test-vmstate$(EXESUF): tests/test-vmstate.o migration/libmigration.fa \ - $(test-io-obj-y) -tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y) -tests/test-base64$(EXESUF): tests/test-base64.o $(test-util-obj-y) -tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o -tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) -tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) -tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y) -tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y) -tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) - -tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y) - -tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \ - $(test-block-obj-y) - -tests/test-qapi-types.c tests/test-qapi-types.h \ -tests/include/test-qapi-types-sub-module.c \ -tests/include/test-qapi-types-sub-module.h \ -tests/test-qapi-types-sub-sub-module.c \ -tests/test-qapi-types-sub-sub-module.h \ -tests/test-qapi-visit.c tests/test-qapi-visit.h \ -tests/include/test-qapi-visit-sub-module.c \ -tests/include/test-qapi-visit-sub-module.h \ -tests/test-qapi-visit-sub-sub-module.c \ -tests/test-qapi-visit-sub-sub-module.h \ -tests/test-qapi-commands.h tests/test-qapi-commands.c \ -tests/include/test-qapi-commands-sub-module.h \ -tests/include/test-qapi-commands-sub-module.c \ -tests/test-qapi-commands-sub-sub-module.h \ -tests/test-qapi-commands-sub-sub-module.c \ -tests/test-qapi-emit-events.c tests/test-qapi-emit-events.h \ -tests/test-qapi-events.c tests/test-qapi-events.h \ -tests/test-qapi-init-commands.c \ -tests/test-qapi-init-commands.h \ -tests/include/test-qapi-events-sub-module.c \ -tests/include/test-qapi-events-sub-module.h \ -tests/test-qapi-events-sub-sub-module.c \ -tests/test-qapi-events-sub-sub-module.h \ -tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \ -tests/test-qapi-gen-timestamp ; -tests/test-qapi-gen-timestamp: \ - $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json \ - $(SRC_PATH)/tests/qapi-schema/include/sub-module.json \ - $(SRC_PATH)/tests/qapi-schema/sub-sub-module.json \ - $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o tests -p "test-" $<, \ - "GEN","$(@:%-timestamp=%)") - @rm -f tests/test-qapi-doc.texi - @>$@ - -tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) -tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) -tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) tests/test-qapi-emit-events.o tests/test-qapi-events.o -tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y) -tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y) -tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y) -tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o tests/test-qapi-init-commands.o $(test-qapi-obj-y) -tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) -tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) - -tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y) -tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) -tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) -tests/test-bitcnt$(EXESUF): tests/test-bitcnt.o $(test-util-obj-y) -tests/test-qgraph$(EXESUF): tests/test-qgraph.o tests/qtest/libqos/qgraph.o $(test-util-obj-y) -tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y) -tests/benchmark-crypto-hash$(EXESUF): tests/benchmark-crypto-hash.o $(test-crypto-obj-y) -tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y) -tests/benchmark-crypto-hmac$(EXESUF): tests/benchmark-crypto-hmac.o $(test-crypto-obj-y) -tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y) -tests/benchmark-crypto-cipher$(EXESUF): tests/benchmark-crypto-cipher.o $(test-crypto-obj-y) -tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y) -tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y) - -ifeq ($(CONFIG_TEST_SECRET_KEYRING),y) -tests/test-crypto-secret.o-libs := -lkeyutils -endif - -tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS) -tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS) -tests/pkix_asn1_tab.o-cflags := $(TASN1_CFLAGS) - -tests/test-crypto-tlscredsx509.o-cflags := $(TASN1_CFLAGS) -tests/test-crypto-tlscredsx509$(EXESUF): tests/test-crypto-tlscredsx509.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y) - -tests/test-crypto-tlssession.o-cflags := $(TASN1_CFLAGS) -tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ - tests/crypto-tls-psk-helpers.o \ - $(test-crypto-obj-y) -tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \ - $(test-util-obj-y) -tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \ - tests/socket-helpers.o $(test-util-obj-y) -tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y) -tests/test-authz-list$(EXESUF): tests/test-authz-list.o $(test-authz-obj-y) -tests/test-authz-listfile$(EXESUF): tests/test-authz-listfile.o $(test-authz-obj-y) -tests/test-authz-pam$(EXESUF): tests/test-authz-pam.o $(test-authz-obj-y) -tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) -tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ - tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y) -tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-command$(EXESUF): tests/test-io-channel-command.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-buffer$(EXESUF): tests/test-io-channel-buffer.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-crypto-pbkdf$(EXESUF): tests/test-crypto-pbkdf.o $(test-crypto-obj-y) -tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o $(test-crypto-obj-y) -tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o $(test-crypto-obj-y) -tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y) - -tests/migration/stress$(EXESUF): tests/migration/stress.o - $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@") - -INITRD_WORK_DIR=tests/migration/initrd - -tests/migration/initrd-stress.img: tests/migration/stress$(EXESUF) - mkdir -p $(INITRD_WORK_DIR) - cp $< $(INITRD_WORK_DIR)/init - (cd $(INITRD_WORK_DIR) && (find | cpio --quiet -o -H newc | gzip -9)) > $@ - rm $(INITRD_WORK_DIR)/init - rmdir $(INITRD_WORK_DIR) - -tests/test-qga$(EXESUF): qga/qemu-ga$(EXESUF) -tests/test-qga$(EXESUF): tests/test-qga.o tests/qtest/libqtest.o $(test-util-obj-y) -tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a -tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o - -SPEED = quick - -# gtester tests, possibly with verbose output -# do_test_tap runs all tests, even if some of them fail, while do_test_human -# stops at the first failure unless -k is given on the command line - -define do_test_human_k - $(quiet-@)rc=0; $(foreach COMMAND, $1, \ - $(call quiet-command-run, \ - export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only) \ - || rc=$$?;, "TEST", "$@: $(COMMAND)")) exit $$rc -endef -define do_test_human_no_k - $(foreach COMMAND, $1, \ - $(call quiet-command, \ - MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2 \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only), \ - "TEST", "$@: $(COMMAND)") -) -endef -do_test_human = \ - $(if $(findstring k, $(MAKEFLAGS)), $(do_test_human_k), $(do_test_human_no_k)) - -define do_test_tap - $(call quiet-command, \ - { export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ - $(foreach COMMAND, $1, \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | sed "s/^\(not \)\?ok [0-9]* /&$(notdir $(COMMAND)) /" || true; ) } \ - | ./scripts/tap-merge.pl | tee "$@" \ - | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only), \ - "TAP","$@") -endef - -build-unit: $(check-unit-y) - -check-unit: $(check-unit-y) - $(call do_test_human, $^) - -check-speed: $(check-speed-y) - $(call do_test_human, $^) - -# gtester tests with TAP output - -check-report-unit.tap: $(check-unit-y) - $(call do_test_tap,$^) - -# Per guest TCG tests - -BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGET_DIRS)) -CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGET_DIRS)) -RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGET_DIRS)) - -# Probe for the Docker Builds needed for each build -$(foreach PROBE_TARGET,$(TARGET_DIRS), \ - $(eval -include $(SRC_PATH)/tests/tcg/Makefile.prereqs)) - -build-tcg-tests-%: $(if $(CONFIG_PLUGIN),plugins) - $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ - -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ - SRC_PATH=$(SRC_PATH) \ - V="$(V)" TARGET="$*" guest-tests, \ - "BUILD", "TCG tests for $*") - -run-tcg-tests-%: build-tcg-tests-% all - $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ - -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ - SRC_PATH=$(SRC_PATH) SPEED="$(SPEED)" \ - V="$(V)" TARGET="$*" run-guest-tests, \ - "RUN", "TCG tests for $*") - -clean-tcg-tests-%: - $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ - -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ - SRC_PATH=$(SRC_PATH) TARGET="$*" clean-guest-tests, \ - "CLEAN", "TCG tests for $*") - -.PHONY: build-tcg -build-tcg: $(BUILD_TCG_TARGET_RULES) - -.PHONY: check-tcg -check-tcg: $(RUN_TCG_TARGET_RULES) - -.PHONY: clean-tcg -clean-tcg: $(CLEAN_TCG_TARGET_RULES) - - -# Python venv for running tests - -.PHONY: check-venv check-acceptance - -TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv -TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt -TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results -# Controls the output generated by Avocado when running tests. -# Any number of command separated loggers are accepted. For more -# information please refer to "avocado --help". -AVOCADO_SHOW=app -AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGET_DIRS))) - -$(TESTS_VENV_DIR): $(TESTS_VENV_REQ) - $(call quiet-command, \ - $(PYTHON) -m venv --system-site-packages $@, \ - VENV, $@) - $(call quiet-command, \ - $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ - PIP, $(TESTS_VENV_REQ)) - $(call quiet-command, touch $@) - -$(TESTS_RESULTS_DIR): - $(call quiet-command, mkdir -p $@, \ - MKDIR, $@) - -check-venv: $(TESTS_VENV_DIR) - -FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(TARGETS)) -FEDORA_31_ARCHES := x86_64 aarch64 ppc64le s390x -FEDORA_31_DOWNLOAD=$(filter $(FEDORA_31_ARCHES),$(FEDORA_31_ARCHES_CANDIDATES)) - -# download one specific Fedora 31 image -get-vm-image-fedora-31-%: check-venv - $(call quiet-command, \ - $(TESTS_VENV_DIR)/bin/python -m avocado vmimage get \ - --distro=fedora --distro-version=31 --arch=$*, \ - "AVOCADO", "Downloading acceptance tests VM image for $*") - -# download all vm images, according to defined targets -get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOWNLOAD)) - -check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images - $(call quiet-command, \ - $(TESTS_VENV_DIR)/bin/python -m avocado \ - --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ - --filter-by-tags-include-empty --filter-by-tags-include-empty-key \ - $(AVOCADO_TAGS) \ - $(if $(GITLAB_CI),,--failfast=on) tests/acceptance, \ - "AVOCADO", "tests/acceptance") - -# Consolidated targets - -.PHONY: check-block check-unit check check-clean get-vm-images -check-block: -check-build: build-unit - -check-clean: - rm -rf $(check-unit-y) tests/*.o tests/*/*.o $(QEMU_IOTESTS_HELPERS-y) - rm -f tests/test-qapi-gen-timestamp - rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR) - -check: check-unit - -clean: check-clean - -# Build the help program automatically - --include $(wildcard tests/*.d) - -endif +# -*- Mode: makefile -*- + +.PHONY: check-help +check-help: + @echo "Regression testing targets:" + @echo + @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests" + @echo + @echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target" + @echo " $(MAKE) check-qtest Run qtest tests" + @echo " $(MAKE) check-unit Run qobject tests" + @echo " $(MAKE) check-speed Run qobject speed tests" + @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" + @echo " $(MAKE) check-block Run block tests" +ifeq ($(CONFIG_TCG),y) + @echo " $(MAKE) check-tcg Run TCG tests" + @echo " $(MAKE) check-softfloat Run FPU emulation tests" +endif + @echo " $(MAKE) check-acceptance Run all acceptance (functional) tests" + @echo + @echo " $(MAKE) check-report.tap Generates an aggregated TAP test report" + @echo " $(MAKE) check-venv Creates a Python venv for tests" + @echo " $(MAKE) check-clean Clean the tests and related data" + @echo + @echo "The following are useful for CI builds" + @echo " $(MAKE) check-build Build most test binaris" + @echo " $(MAKE) get-vm-images Downloads all images used by acceptance tests, according to configured targets (~350 MB each, 1.5 GB max)" + @echo + @echo + @echo "The variable SPEED can be set to control the gtester speed setting." + @echo "Default options are -k and (for $(MAKE) V=1) --verbose; they can be" + @echo "changed with variable GTESTER_OPTIONS." + +ifneq ($(wildcard config-host.mak),) +export SRC_PATH + +# TODO don't duplicate $(SRC_PATH)/Makefile's qapi-py here +qapi-py = $(SRC_PATH)/scripts/qapi/__init__.py \ +$(SRC_PATH)/scripts/qapi/commands.py \ +$(SRC_PATH)/scripts/qapi/common.py \ +$(SRC_PATH)/scripts/qapi/doc.py \ +$(SRC_PATH)/scripts/qapi/error.py \ +$(SRC_PATH)/scripts/qapi/events.py \ +$(SRC_PATH)/scripts/qapi/expr.py \ +$(SRC_PATH)/scripts/qapi/gen.py \ +$(SRC_PATH)/scripts/qapi/introspect.py \ +$(SRC_PATH)/scripts/qapi/parser.py \ +$(SRC_PATH)/scripts/qapi/schema.py \ +$(SRC_PATH)/scripts/qapi/source.py \ +$(SRC_PATH)/scripts/qapi/types.py \ +$(SRC_PATH)/scripts/qapi/visit.py \ +$(SRC_PATH)/scripts/qapi-gen.py + +# Get the list of all supported sysemu targets +SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \ + $(wildcard $(SRC_PATH)/default-configs/*-softmmu.mak))) + +check-unit-y += tests/check-qdict$(EXESUF) +check-unit-y += tests/check-block-qdict$(EXESUF) +check-unit-y += tests/check-qnum$(EXESUF) +check-unit-y += tests/check-qstring$(EXESUF) +check-unit-y += tests/check-qlist$(EXESUF) +check-unit-y += tests/check-qnull$(EXESUF) +check-unit-y += tests/check-qobject$(EXESUF) +check-unit-y += tests/check-qjson$(EXESUF) +check-unit-y += tests/check-qlit$(EXESUF) +check-unit-y += tests/test-qobject-output-visitor$(EXESUF) +check-unit-y += tests/test-clone-visitor$(EXESUF) +check-unit-y += tests/test-qobject-input-visitor$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-qmp-cmds$(EXESUF) +check-unit-y += tests/test-string-input-visitor$(EXESUF) +check-unit-y += tests/test-string-output-visitor$(EXESUF) +check-unit-y += tests/test-qmp-event$(EXESUF) +check-unit-y += tests/test-opts-visitor$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-coroutine$(EXESUF) +check-unit-y += tests/test-visitor-serialization$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-iov$(EXESUF) +check-unit-y += tests/test-bitmap$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-aio$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-aio-multithread$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-throttle$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-thread-pool$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-hbitmap$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-drain$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-graph-mod$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-blockjob$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-blockjob-txn$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-block-backend$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-block-iothread$(EXESUF) +ifeq ($(CONFIG_POSIX),y) +check-unit-$(CONFIG_BLOCK) += tests/test-image-locking$(EXESUF) +endif +check-unit-y += tests/test-x86-cpuid$(EXESUF) +# all code tested by test-x86-cpuid is inside topology.h +ifeq ($(CONFIG_SOFTMMU),y) +check-unit-y += tests/test-xbzrle$(EXESUF) +check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF) +endif +check-unit-y += tests/test-cutils$(EXESUF) +check-unit-y += tests/test-shift128$(EXESUF) +check-unit-y += tests/test-mul64$(EXESUF) +check-unit-y += tests/test-int128$(EXESUF) +# all code tested by test-int128 is inside int128.h +check-unit-y += tests/rcutorture$(EXESUF) +check-unit-y += tests/test-rcu-list$(EXESUF) +check-unit-y += tests/test-rcu-simpleq$(EXESUF) +check-unit-y += tests/test-rcu-tailq$(EXESUF) +check-unit-y += tests/test-rcu-slist$(EXESUF) +check-unit-y += tests/test-qdist$(EXESUF) +check-unit-y += tests/test-qht$(EXESUF) +check-unit-y += tests/test-qht-par$(EXESUF) +check-unit-y += tests/test-bitops$(EXESUF) +check-unit-y += tests/test-bitcnt$(EXESUF) +check-unit-y += tests/test-qgraph$(EXESUF) +check-unit-y += tests/check-qom-interface$(EXESUF) +check-unit-y += tests/check-qom-proplist$(EXESUF) +check-unit-y += tests/test-qemu-opts$(EXESUF) +check-unit-y += tests/test-keyval$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-write-threshold$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hash$(EXESUF) +check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hash$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hmac$(EXESUF) +check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hmac$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-cipher$(EXESUF) +check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-cipher$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-secret$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlscredsx509$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlssession$(EXESUF) +ifndef CONFIG_TSAN +# Some tests: test-char, test-qdev-global-props, and test-qga, +# are not runnable under TSan due to a known issue. +# https://github.com/google/sanitizers/issues/1116 +check-unit-$(CONFIG_SOFTMMU) += tests/test-char$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-qdev-global-props$(EXESUF) +ifeq ($(CONFIG_GUEST_AGENT),y) +check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF) +endif +endif +check-unit-$(CONFIG_SOFTMMU) += tests/test-timed-average$(EXESUF) +check-unit-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_INOTIFY1)) += tests/test-util-filemonitor$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-util-sockets$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-authz-simple$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-authz-list$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-authz-listfile$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_AUTH_PAM)) += tests/test-authz-pam$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-io-task$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-socket$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-file$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-io-channel-tls$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-command$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-buffer$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-base64$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(if $(CONFIG_NETTLE),y,$(CONFIG_GCRYPT))) += tests/test-crypto-pbkdf$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-ivgen$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-afsplit$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_QEMU_PRIVATE_XTS)) += tests/test-crypto-xts$(EXESUF) +check-unit-$(CONFIG_BLOCK) += tests/test-crypto-block$(EXESUF) +check-unit-y += tests/test-logging$(EXESUF) +check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_REPLICATION)) += tests/test-replication$(EXESUF) +check-unit-$(CONFIG_SOFTMMU) += tests/test-bufferiszero$(EXESUF) +check-unit-y += tests/test-uuid$(EXESUF) +check-unit-y += tests/ptimer-test$(EXESUF) +check-unit-y += tests/test-qapi-util$(EXESUF) + +generated-files-y += tests/test-qapi-types.h +generated-files-y += tests/include/test-qapi-types-sub-module.h +generated-files-y += tests/test-qapi-types-sub-sub-module.h +generated-files-y += tests/test-qapi-visit.h +generated-files-y += tests/include/test-qapi-visit-sub-module.h +generated-files-y += tests/test-qapi-visit-sub-sub-module.h +generated-files-y += tests/test-qapi-commands.h +generated-files-y += tests/test-qapi-init-commands.h +generated-files-y += tests/include/test-qapi-commands-sub-module.h +generated-files-y += tests/test-qapi-commands-sub-sub-module.h +generated-files-y += tests/test-qapi-emit-events.h +generated-files-y += tests/test-qapi-events.h +generated-files-y += tests/include/test-qapi-events-sub-module.h +generated-files-y += tests/test-qapi-events-sub-sub-module.h +generated-files-y += tests/test-qapi-introspect.h + +QEMU_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest + + +# Deps that are common to various different sets of tests below +test-util-obj-y = libqemuutil.a +test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y) +test-qapi-obj-y = tests/test-qapi-types.o \ + tests/include/test-qapi-types-sub-module.o \ + tests/test-qapi-types-sub-sub-module.o \ + tests/test-qapi-visit.o \ + tests/include/test-qapi-visit-sub-module.o \ + tests/test-qapi-visit-sub-sub-module.o \ + tests/test-qapi-introspect.o \ + $(test-qom-obj-y) +benchmark-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) +test-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) +test-io-obj-$(CONFIG_BLOCK) = $(io-obj-y) $(test-crypto-obj-y) +test-authz-obj-$(CONFIG_BLOCK) = $(test-qom-obj-y) $(authz-obj-y) +test-block-obj-$(CONFIG_BLOCK) = $(block-obj-y) $(test-io-obj-y) tests/iothread.o + +tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y) +tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y) +tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y) +tests/check-block-qdict$(EXESUF): tests/check-block-qdict.o $(test-util-obj-y) +tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y) +tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) +tests/check-qobject$(EXESUF): tests/check-qobject.o $(test-util-obj-y) +tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y) +tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y) +tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y) +tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y) + +tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(test-io-obj-y) $(chardev-obj-y) tests/socket-helpers.o +tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y) +tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y) +tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y) +tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y) +tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-block-iothread$(EXESUF): tests/test-block-iothread.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y) +tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) +tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) +tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) +tests/test-bitmap$(EXESUF): tests/test-bitmap.o $(test-util-obj-y) +tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o +tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/libmigration.fa $(test-util-obj-y) \ + $(test-io-obj-y) +tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o $(test-util-obj-y) +tests/test-int128$(EXESUF): tests/test-int128.o +tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) +tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y) +tests/test-rcu-simpleq$(EXESUF): tests/test-rcu-simpleq.o $(test-util-obj-y) +tests/test-rcu-tailq$(EXESUF): tests/test-rcu-tailq.o $(test-util-obj-y) +tests/test-rcu-slist$(EXESUF): tests/test-rcu-slist.o $(test-util-obj-y) +tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y) +tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y) +tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y) +tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) +tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y) +tests/atomic_add-bench$(EXESUF): tests/atomic_add-bench.o $(test-util-obj-y) +tests/atomic64-bench$(EXESUF): tests/atomic64-bench.o $(test-util-obj-y) + +tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o hw/core/libhwcore.fa \ + $(test-qapi-obj-y) +tests/test-vmstate$(EXESUF): tests/test-vmstate.o migration/libmigration.fa \ + $(test-io-obj-y) +tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y) +tests/test-base64$(EXESUF): tests/test-base64.o $(test-util-obj-y) +tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o +tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) +tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) +tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y) +tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y) +tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) + +tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y) + +tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \ + $(test-block-obj-y) + +tests/test-qapi-types.c tests/test-qapi-types.h \ +tests/include/test-qapi-types-sub-module.c \ +tests/include/test-qapi-types-sub-module.h \ +tests/test-qapi-types-sub-sub-module.c \ +tests/test-qapi-types-sub-sub-module.h \ +tests/test-qapi-visit.c tests/test-qapi-visit.h \ +tests/include/test-qapi-visit-sub-module.c \ +tests/include/test-qapi-visit-sub-module.h \ +tests/test-qapi-visit-sub-sub-module.c \ +tests/test-qapi-visit-sub-sub-module.h \ +tests/test-qapi-commands.h tests/test-qapi-commands.c \ +tests/include/test-qapi-commands-sub-module.h \ +tests/include/test-qapi-commands-sub-module.c \ +tests/test-qapi-commands-sub-sub-module.h \ +tests/test-qapi-commands-sub-sub-module.c \ +tests/test-qapi-emit-events.c tests/test-qapi-emit-events.h \ +tests/test-qapi-events.c tests/test-qapi-events.h \ +tests/test-qapi-init-commands.c \ +tests/test-qapi-init-commands.h \ +tests/include/test-qapi-events-sub-module.c \ +tests/include/test-qapi-events-sub-module.h \ +tests/test-qapi-events-sub-sub-module.c \ +tests/test-qapi-events-sub-sub-module.h \ +tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \ +tests/test-qapi-gen-timestamp ; +tests/test-qapi-gen-timestamp: \ + $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json \ + $(SRC_PATH)/tests/qapi-schema/include/sub-module.json \ + $(SRC_PATH)/tests/qapi-schema/sub-sub-module.json \ + $(qapi-py) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ + -o tests -p "test-" $<, \ + "GEN","$(@:%-timestamp=%)") + @rm -f tests/test-qapi-doc.texi + @>$@ + +tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) +tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) +tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) tests/test-qapi-emit-events.o tests/test-qapi-events.o +tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y) +tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y) +tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y) +tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o tests/test-qapi-init-commands.o $(test-qapi-obj-y) +tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) +tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) + +tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y) +tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) +tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) +tests/test-bitcnt$(EXESUF): tests/test-bitcnt.o $(test-util-obj-y) +tests/test-qgraph$(EXESUF): tests/test-qgraph.o tests/qtest/libqos/qgraph.o $(test-util-obj-y) +tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y) +tests/benchmark-crypto-hash$(EXESUF): tests/benchmark-crypto-hash.o $(test-crypto-obj-y) +tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y) +tests/benchmark-crypto-hmac$(EXESUF): tests/benchmark-crypto-hmac.o $(test-crypto-obj-y) +tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y) +tests/benchmark-crypto-cipher$(EXESUF): tests/benchmark-crypto-cipher.o $(test-crypto-obj-y) +tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y) +tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y) + +ifeq ($(CONFIG_TEST_SECRET_KEYRING),y) +tests/test-crypto-secret.o-libs := -lkeyutils +endif + +tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS) +tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS) +tests/pkix_asn1_tab.o-cflags := $(TASN1_CFLAGS) + +tests/test-crypto-tlscredsx509.o-cflags := $(TASN1_CFLAGS) +tests/test-crypto-tlscredsx509$(EXESUF): tests/test-crypto-tlscredsx509.o \ + tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y) + +tests/test-crypto-tlssession.o-cflags := $(TASN1_CFLAGS) +tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \ + tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ + tests/crypto-tls-psk-helpers.o \ + $(test-crypto-obj-y) +tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \ + $(test-util-obj-y) +tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \ + tests/socket-helpers.o $(test-util-obj-y) +tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y) +tests/test-authz-list$(EXESUF): tests/test-authz-list.o $(test-authz-obj-y) +tests/test-authz-listfile$(EXESUF): tests/test-authz-listfile.o $(test-authz-obj-y) +tests/test-authz-pam$(EXESUF): tests/test-authz-pam.o $(test-authz-obj-y) +tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) +tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ + tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y) +tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ + tests/io-channel-helpers.o $(test-io-obj-y) +tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ + tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ + tests/io-channel-helpers.o $(test-io-obj-y) +tests/test-io-channel-command$(EXESUF): tests/test-io-channel-command.o \ + tests/io-channel-helpers.o $(test-io-obj-y) +tests/test-io-channel-buffer$(EXESUF): tests/test-io-channel-buffer.o \ + tests/io-channel-helpers.o $(test-io-obj-y) +tests/test-crypto-pbkdf$(EXESUF): tests/test-crypto-pbkdf.o $(test-crypto-obj-y) +tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o $(test-crypto-obj-y) +tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o $(test-crypto-obj-y) +tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y) + +tests/migration/stress$(EXESUF): tests/migration/stress.o + $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@") + +INITRD_WORK_DIR=tests/migration/initrd + +tests/migration/initrd-stress.img: tests/migration/stress$(EXESUF) + mkdir -p $(INITRD_WORK_DIR) + cp $< $(INITRD_WORK_DIR)/init + (cd $(INITRD_WORK_DIR) && (find | cpio --quiet -o -H newc | gzip -9)) > $@ + rm $(INITRD_WORK_DIR)/init + rmdir $(INITRD_WORK_DIR) + +tests/test-qga$(EXESUF): qga/qemu-ga$(EXESUF) +tests/test-qga$(EXESUF): tests/test-qga.o tests/qtest/libqtest.o $(test-util-obj-y) +tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a +tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o + +SPEED = quick + +# gtester tests, possibly with verbose output +# do_test_tap runs all tests, even if some of them fail, while do_test_human +# stops at the first failure unless -k is given on the command line + +define do_test_human_k + $(quiet-@)rc=0; $(foreach COMMAND, $1, \ + $(call quiet-command-run, \ + export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ + $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ + | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only) \ + || rc=$$?;, "TEST", "$@: $(COMMAND)")) exit $$rc +endef +define do_test_human_no_k + $(foreach COMMAND, $1, \ + $(call quiet-command, \ + MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2 \ + $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ + | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only), \ + "TEST", "$@: $(COMMAND)") +) +endef +do_test_human = \ + $(if $(findstring k, $(MAKEFLAGS)), $(do_test_human_k), $(do_test_human_no_k)) + +define do_test_tap + $(call quiet-command, \ + { export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ + $(foreach COMMAND, $1, \ + $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ + | sed "s/^\(not \)\?ok [0-9]* /&$(notdir $(COMMAND)) /" || true; ) } \ + | ./scripts/tap-merge.pl | tee "$@" \ + | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only), \ + "TAP","$@") +endef + +build-unit: $(check-unit-y) + +check-unit: $(check-unit-y) + $(call do_test_human, $^) + +check-speed: $(check-speed-y) + $(call do_test_human, $^) + +# gtester tests with TAP output + +check-report-unit.tap: $(check-unit-y) + $(call do_test_tap,$^) + +# Per guest TCG tests + +BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGET_DIRS)) +CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGET_DIRS)) +RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGET_DIRS)) + +# Probe for the Docker Builds needed for each build +$(foreach PROBE_TARGET,$(TARGET_DIRS), \ + $(eval -include $(SRC_PATH)/tests/tcg/Makefile.prereqs)) + +build-tcg-tests-%: $(if $(CONFIG_PLUGIN),plugins) + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ + -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ + SRC_PATH=$(SRC_PATH) \ + V="$(V)" TARGET="$*" guest-tests, \ + "BUILD", "TCG tests for $*") + +run-tcg-tests-%: build-tcg-tests-% all + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ + -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ + SRC_PATH=$(SRC_PATH) SPEED="$(SPEED)" \ + V="$(V)" TARGET="$*" run-guest-tests, \ + "RUN", "TCG tests for $*") + +clean-tcg-tests-%: + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ + -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ + SRC_PATH=$(SRC_PATH) TARGET="$*" clean-guest-tests, \ + "CLEAN", "TCG tests for $*") + +.PHONY: build-tcg +build-tcg: $(BUILD_TCG_TARGET_RULES) + +.PHONY: check-tcg +check-tcg: $(RUN_TCG_TARGET_RULES) + +.PHONY: clean-tcg +clean-tcg: $(CLEAN_TCG_TARGET_RULES) + + +# Python venv for running tests + +.PHONY: check-venv check-acceptance + +TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv +TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt +TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results +# Controls the output generated by Avocado when running tests. +# Any number of command separated loggers are accepted. For more +# information please refer to "avocado --help". +AVOCADO_SHOW=app +AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGET_DIRS))) + +$(TESTS_VENV_DIR): $(TESTS_VENV_REQ) + $(call quiet-command, \ + $(PYTHON) -m venv --system-site-packages $@, \ + VENV, $@) + $(call quiet-command, \ + $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ + PIP, $(TESTS_VENV_REQ)) + $(call quiet-command, touch $@) + +$(TESTS_RESULTS_DIR): + $(call quiet-command, mkdir -p $@, \ + MKDIR, $@) + +check-venv: $(TESTS_VENV_DIR) + +FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(TARGETS)) +FEDORA_31_ARCHES := x86_64 aarch64 ppc64le s390x +FEDORA_31_DOWNLOAD=$(filter $(FEDORA_31_ARCHES),$(FEDORA_31_ARCHES_CANDIDATES)) + +# download one specific Fedora 31 image +get-vm-image-fedora-31-%: check-venv + $(call quiet-command, \ + $(TESTS_VENV_DIR)/bin/python -m avocado vmimage get \ + --distro=fedora --distro-version=31 --arch=$*, \ + "AVOCADO", "Downloading acceptance tests VM image for $*") + +# download all vm images, according to defined targets +get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOWNLOAD)) + +check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images + $(call quiet-command, \ + $(TESTS_VENV_DIR)/bin/python -m avocado \ + --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ + --filter-by-tags-include-empty --filter-by-tags-include-empty-key \ + $(AVOCADO_TAGS) \ + $(if $(GITLAB_CI),,--failfast=on) tests/acceptance, \ + "AVOCADO", "tests/acceptance") + +# Consolidated targets + +.PHONY: check-block check-unit check check-clean get-vm-images +check-block: +check-build: build-unit + +check-clean: + rm -rf $(check-unit-y) tests/*.o tests/*/*.o $(QEMU_IOTESTS_HELPERS-y) + rm -f tests/test-qapi-gen-timestamp + rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR) + +check: check-unit + +clean: check-clean + +# Build the help program automatically + +-include $(wildcard tests/*.d) + +endif From patchwork Thu Sep 3 07:43:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonggang Luo X-Patchwork-Id: 11752591 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4C5FC739 for ; Thu, 3 Sep 2020 07:49:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 17F9220897 for ; Thu, 3 Sep 2020 07:49:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iUfHbyJF" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 17F9220897 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:35572 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDk0E-0001J4-6v for patchwork-qemu-devel@patchwork.kernel.org; Thu, 03 Sep 2020 03:49:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43482) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDjuj-0000oN-4k for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:09 -0400 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]:34870) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDjug-0003v6-VB for qemu-devel@nongnu.org; Thu, 03 Sep 2020 03:44:08 -0400 Received: by mail-pj1-x1044.google.com with SMTP id g6so1068250pjl.0 for ; Thu, 03 Sep 2020 00:44:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RPs3RoSh234lXncrsywCpA+V5get783NAhmcnU+hzlo=; b=iUfHbyJFHXe9LOF3xQaeLRQn4G6OacWh0s0spzv8StMBdYin+zMqcZELjT54/WJvMq Ik+H8tbvrDcXzdr6XSvYQcMm/Sq2/zEHVnA28JTjWFWWjiz+H5cCTMqkqPmm/5PLnbTH hDnBIHN4UJhOC5u+jQOEn7al370Oc7RsSdf/R+Tum0mY8cR9iuC33g8Uej9gSf48kZbv OXz47zU6JzsTnW7bEDGrWGUmJPhl8AKBWhiKCHCSGcSqCs6TJBrGhSFBPLF6TbhkL/D1 7pimML4XQXtD4nVzoTNVKlpGK97M7Acy2vLYy+wykYTxrQOpUyuqpqISfClCiZq7E2QZ AE3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RPs3RoSh234lXncrsywCpA+V5get783NAhmcnU+hzlo=; b=bnRovbYHtPDLsI4PU7Y0430qeIALnUh3ZzKP/OTu3l8YmVGUhpkCQMrPAtnK9jBF2K PModdWfvkEzlGmmW0uVvDVf3qwQ6nW90+1lnavXBrkudg9amkvr/gz0QTy2/Gyomwa8a aNfvJi58YBU0xlJ/YVEp8HPmyb/xs8kpbbBckyTxYPXDrgjBsoFgt+tmIkdRujN7XCbq GaASVn5PfmBRvWBrasnpq/kRBcOaXD9UvpwdGeY83A1m6OLfMaB2CblQrR4K1bDrttAp g8jXoOUwKE5PvJG0BinBZp6Mor3ii1vwYvl37iCa0WqBGhGF5J8FwcIxg8rS+86FZ1W5 a0PA== X-Gm-Message-State: AOAM53373l2hu5yqWe+B2je9TQYcByGQWFZfm4iJ/LXXC6/5Z+l9/8Au ZZlOcgfgmLWhoOUD0flAShVzy0c3IxE+oc7g X-Google-Smtp-Source: ABdhPJwaJblHbAYFES+QR4WRfz3ya+TkSfDAneXGmFAaT9gtylJ1ZjpInma0B83+NxkJiMweIwV3tQ== X-Received: by 2002:a17:90a:8589:: with SMTP id m9mr2074589pjn.109.1599119045126; Thu, 03 Sep 2020 00:44:05 -0700 (PDT) Received: from localhost.localdomain ([222.95.248.6]) by smtp.googlemail.com with ESMTPSA id o6sm1512472pju.25.2020.09.03.00.44.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2020 00:44:03 -0700 (PDT) From: Yonggang Luo To: qemu-devel@nongnu.org Subject: [PATCH v3 12/12] ci: Enable msys2 ci in cirrus Date: Thu, 3 Sep 2020 15:43:13 +0800 Message-Id: <20200903074313.1498-13-luoyonggang@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200903074313.1498-1-luoyonggang@gmail.com> References: <20200903074313.1498-1-luoyonggang@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1044; envelope-from=luoyonggang@gmail.com; helo=mail-pj1-x1044.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Yonggang Luo Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Install msys2 in a proper way refer to https://github.com/cirruslabs/cirrus-ci-docs/issues/699 The https://wiki.qemu.org/Hosts/W32#Native_builds_with_MSYS2 need to be updated. There is no need of --cross-prefix, open mingw64.exe instead of msys2.exe then we don't need the --cross-prefix, besides using ENV MSYS: winsymlinks:nativestrict MSYSTEM: MINGW64 CHERE_INVOKING: 1 to opening mingw64 native shell. Signed-off-by: Yonggang Luo --- .cirrus.yml | 108 +++++++++++++++++----------- scripts/ci/windows/msys2_build.sh | 33 +++++++++ scripts/ci/windows/msys2_install.sh | 31 ++++++++ 3 files changed, 130 insertions(+), 42 deletions(-) create mode 100644 scripts/ci/windows/msys2_build.sh create mode 100644 scripts/ci/windows/msys2_install.sh diff --git a/.cirrus.yml b/.cirrus.yml index f287d23c5b..0bfb465193 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,42 +1,66 @@ -env: - CIRRUS_CLONE_DEPTH: 1 - -freebsd_12_task: - freebsd_instance: - image_family: freebsd-12-1 - cpu: 8 - memory: 8G - install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y - bash curl cyrus-sasl git glib gmake gnutls gsed - nettle perl5 pixman pkgconf png usbredir - script: - - mkdir build - - cd build - - ../configure || { cat config.log; exit 1; } - - gmake -j8 - - gmake V=1 check - -macos_task: - osx_instance: - image: mojave-base - install_script: - - brew install pkg-config python gnu-sed glib pixman make sdl2 bash - script: - - mkdir build - - cd build - - ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; } - - gmake -j$(sysctl -n hw.ncpu) - - gmake check - -macos_xcode_task: - osx_instance: - # this is an alias for the latest Xcode - image: mojave-xcode - install_script: - - brew install pkg-config gnu-sed glib pixman make sdl2 bash - script: - - mkdir build - - cd build - - ../configure --cc=clang || { cat config.log; exit 1; } - - gmake -j$(sysctl -n hw.ncpu) - - gmake check +env: + CIRRUS_CLONE_DEPTH: 1 + +freebsd_12_task: + freebsd_instance: + image_family: freebsd-12-1 + cpu: 8 + memory: 8G + install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y + bash curl cyrus-sasl git glib gmake gnutls gsed + nettle perl5 pixman pkgconf png usbredir + script: + - mkdir build + - cd build + - ../configure || { cat config.log; exit 1; } + - gmake -j8 + - gmake V=1 check + +macos_task: + osx_instance: + image: mojave-base + install_script: + - brew install pkg-config python gnu-sed glib pixman make sdl2 bash + script: + - mkdir build + - cd build + - ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; } + - gmake -j$(sysctl -n hw.ncpu) + - gmake check + +macos_xcode_task: + osx_instance: + # this is an alias for the latest Xcode + image: mojave-xcode + install_script: + - brew install pkg-config gnu-sed glib pixman make sdl2 bash + script: + - mkdir build + - cd build + - ../configure --cc=clang || { cat config.log; exit 1; } + - gmake -j$(sysctl -n hw.ncpu) + - gmake check + +windows_msys2_task: + windows_container: + image: cirrusci/windowsservercore:cmake + os_version: 2019 + cpu: 8 + memory: 8G + env: + MSYS: winsymlinks:nativestrict + MSYSTEM: MINGW64 + CHERE_INVOKING: 1 + printenv_script: + - C:\tools\msys64\usr\bin\bash.exe -lc 'printenv' + install_script: + - C:\tools\msys64\usr\bin\bash.exe -lc "cd /c/tools && curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - C:\tools\msys64\usr\bin\bash.exe -lc "cd /c/tools && curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - C:\tools\msys64\usr\bin\bash.exe -lc "cd /c/tools && pacman -U --noconfirm msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sy --noconfirm" + - C:\tools\msys64\usr\bin\bash.exe -lc "pacman --needed --noconfirm -S bash pacman pacman-mirrors msys2-runtime" + - taskkill /F /IM gpg-agent.exe + - C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Su" + - C:\tools\msys64\usr\bin\bash.exe -lc "sh scripts/ci/windows/msys2_install.sh" + script: + - C:\tools\msys64\usr\bin\bash.exe -lc "sh scripts/ci/windows/msys2_build.sh" diff --git a/scripts/ci/windows/msys2_build.sh b/scripts/ci/windows/msys2_build.sh new file mode 100644 index 0000000000..3ba89a4206 --- /dev/null +++ b/scripts/ci/windows/msys2_build.sh @@ -0,0 +1,33 @@ +mkdir build +cd build +../configure \ + --python=python3 \ + --enable-gtk --enable-sdl \ + --enable-capstone=git \ + --enable-stack-protector \ + --ninja=ninja \ + --enable-gnutls \ + --enable-nettle \ + --enable-vnc \ + --enable-vnc-sasl \ + --enable-vnc-jpeg \ + --enable-vnc-png \ + --enable-membarrier \ + --enable-slirp=git \ + --disable-kvm \ + --enable-hax \ + --enable-whpx \ + --disable-spice \ + --enable-lzo \ + --enable-snappy \ + --enable-bzip2 \ + --enable-vdi \ + --enable-qcow1 \ + --enable-tools \ + --enable-libusb \ + --enable-usb-redir \ + --enable-libnfs \ + --enable-libssh \ + --disable-pie +make -j$NUMBER_OF_PROCESSORS +# make check diff --git a/scripts/ci/windows/msys2_install.sh b/scripts/ci/windows/msys2_install.sh new file mode 100644 index 0000000000..ff35b73ef2 --- /dev/null +++ b/scripts/ci/windows/msys2_install.sh @@ -0,0 +1,31 @@ +pacman --noconfirm -S --needed \ +base-devel \ +git \ +mingw-w64-x86_64-python \ +mingw-w64-x86_64-python-setuptools \ +mingw-w64-x86_64-toolchain \ +mingw-w64-x86_64-SDL2 \ +mingw-w64-x86_64-SDL2_image \ +mingw-w64-x86_64-gtk3 \ +mingw-w64-x86_64-ninja \ +mingw-w64-x86_64-make \ +mingw-w64-x86_64-lzo2 \ +mingw-w64-x86_64-libjpeg-turbo \ +mingw-w64-x86_64-pixman \ +mingw-w64-x86_64-libgcrypt \ +mingw-w64-x86_64-capstone \ +mingw-w64-x86_64-libpng \ +mingw-w64-x86_64-libssh \ +mingw-w64-x86_64-libxml2 \ +mingw-w64-x86_64-snappy \ +mingw-w64-x86_64-libusb \ +mingw-w64-x86_64-usbredir \ +mingw-w64-x86_64-libtasn1 \ +mingw-w64-x86_64-libnfs \ +mingw-w64-x86_64-nettle \ +mingw-w64-x86_64-cyrus-sasl \ +mingw-w64-x86_64-curl \ +mingw-w64-x86_64-gnutls \ +mingw-w64-x86_64-zstd \ +mingw-w64-x86_64-glib2 +