diff options
96 files changed, 3609 insertions, 1206 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index f4bf49b704..02c43a074a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,61 +1,6 @@ env: CIRRUS_CLONE_DEPTH: 1 -freebsd_12_task: - freebsd_instance: - image_family: freebsd-12-2 - 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 ninja - script: - - mkdir build - - cd build - # TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed - # See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71 - - ../configure --enable-werror --disable-gnutls - || { cat config.log meson-logs/meson-log.txt; exit 1; } - - gmake -j$(sysctl -n hw.ncpu) - - gmake -j$(sysctl -n hw.ncpu) check V=1 - -macos_task: - osx_instance: - image: catalina-base - install_script: - - brew install pkg-config python gnu-sed glib pixman make sdl2 bash ninja - script: - - mkdir build - - cd build - - ../configure --python=/usr/local/bin/python3 --enable-werror - --extra-cflags='-Wno-error=deprecated-declarations' - || { cat config.log meson-logs/meson-log.txt; exit 1; } - - gmake -j$(sysctl -n hw.ncpu) - - gmake check-unit V=1 - - gmake check-block V=1 - - gmake check-qapi-schema V=1 - - gmake check-softfloat V=1 - - gmake check-qtest-x86_64 V=1 - -macos_xcode_task: - osx_instance: - # this is an alias for the latest Xcode - image: catalina-xcode - install_script: - - brew install pkg-config gnu-sed glib pixman make sdl2 bash ninja - script: - - mkdir build - - cd build - - ../configure --extra-cflags='-Wno-error=deprecated-declarations' --enable-modules - --enable-werror --cc=clang || { cat config.log meson-logs/meson-log.txt; exit 1; } - - gmake -j$(sysctl -n hw.ncpu) - - gmake check-unit V=1 - - gmake check-block V=1 - - gmake check-qapi-schema V=1 - - gmake check-softfloat V=1 - - gmake check-qtest-x86_64 V=1 - windows_msys2_task: timeout_in: 90m windows_container: diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index d9b834c848..89df51517c 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -354,29 +354,6 @@ build-some-softmmu: TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu MAKE_CHECK_ARGS: check-tcg -# Run check-tcg against linux-user (with plugins) -# we skip sparc64-linux-user until it has been fixed somewhat -# we skip cris-linux-user as it doesn't use the common run loop -build-user-plugins: - extends: .native_build_job_template - needs: - job: amd64-debian-user-cross-container - variables: - IMAGE: debian-all-test-cross - CONFIGURE_ARGS: --disable-tools --disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user - MAKE_CHECK_ARGS: check-tcg - timeout: 1h 30m - -build-some-softmmu-plugins: - extends: .native_build_job_template - needs: - job: amd64-debian-user-cross-container - variables: - IMAGE: debian-all-test-cross - CONFIGURE_ARGS: --disable-tools --disable-user --enable-plugins --enable-debug-tcg - TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu - MAKE_CHECK_ARGS: check-tcg - clang-system: extends: .native_build_job_template needs: diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml new file mode 100644 index 0000000000..60b13ed83f --- /dev/null +++ b/.gitlab-ci.d/cirrus.yml @@ -0,0 +1,102 @@ +# Jobs that we delegate to Cirrus CI because they require an operating +# system other than Linux. These jobs will only run if the required +# setup has been performed on the GitLab account. +# +# The Cirrus CI configuration is generated by replacing target-specific +# variables in a generic template: some of these variables are provided +# when the GitLab CI job is defined, others are taken from a shell +# snippet generated using lcitool. +# +# Note that the $PATH environment variable has to be treated with +# special care, because we can't just override it at the GitLab CI job +# definition level or we risk breaking it completely. +.cirrus_build_job: + stage: build + image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master + needs: [] + allow_failure: true + script: + - source .gitlab-ci.d/cirrus/$NAME.vars + - sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g" + -e "s|[@]CI_COMMIT_REF_NAME@|$CI_COMMIT_REF_NAME|g" + -e "s|[@]CI_COMMIT_SHA@|$CI_COMMIT_SHA|g" + -e "s|[@]CIRRUS_VM_INSTANCE_TYPE@|$CIRRUS_VM_INSTANCE_TYPE|g" + -e "s|[@]CIRRUS_VM_IMAGE_SELECTOR@|$CIRRUS_VM_IMAGE_SELECTOR|g" + -e "s|[@]CIRRUS_VM_IMAGE_NAME@|$CIRRUS_VM_IMAGE_NAME|g" + -e "s|[@]CIRRUS_VM_CPUS@|$CIRRUS_VM_CPUS|g" + -e "s|[@]CIRRUS_VM_RAM@|$CIRRUS_VM_RAM|g" + -e "s|[@]UPDATE_COMMAND@|$UPDATE_COMMAND|g" + -e "s|[@]INSTALL_COMMAND@|$INSTALL_COMMAND|g" + -e "s|[@]PATH@|$PATH_EXTRA${PATH_EXTRA:+:}\$PATH|g" + -e "s|[@]PKG_CONFIG_PATH@|$PKG_CONFIG_PATH|g" + -e "s|[@]PKGS@|$PKGS|g" + -e "s|[@]MAKE@|$MAKE|g" + -e "s|[@]PYTHON@|$PYTHON|g" + -e "s|[@]PIP3@|$PIP3|g" + -e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g" + -e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g" + -e "s|[@]TEST_TARGETSS@|$TEST_TARGETSS|g" + <.gitlab-ci.d/cirrus/build.yml >.gitlab-ci.d/cirrus/$NAME.yml + - cat .gitlab-ci.d/cirrus/$NAME.yml + - cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml + rules: + - if: "$CIRRUS_GITHUB_REPO && $CIRRUS_API_TOKEN" + +x64-freebsd-12-build: + extends: .cirrus_build_job + variables: + NAME: freebsd-12 + CIRRUS_VM_INSTANCE_TYPE: freebsd_instance + CIRRUS_VM_IMAGE_SELECTOR: image_family + CIRRUS_VM_IMAGE_NAME: freebsd-12-2 + CIRRUS_VM_CPUS: 8 + CIRRUS_VM_RAM: 8G + UPDATE_COMMAND: pkg update + INSTALL_COMMAND: pkg install -y + # TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed + # See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71 + CONFIGURE_ARGS: --disable-gnutls + TEST_TARGETS: check + +x64-freebsd-13-build: + extends: .cirrus_build_job + variables: + NAME: freebsd-13 + CIRRUS_VM_INSTANCE_TYPE: freebsd_instance + CIRRUS_VM_IMAGE_SELECTOR: image_family + CIRRUS_VM_IMAGE_NAME: freebsd-13-0 + CIRRUS_VM_CPUS: 8 + CIRRUS_VM_RAM: 8G + UPDATE_COMMAND: pkg update + INSTALL_COMMAND: pkg install -y + TEST_TARGETS: check + +x64-macos-11-base-build: + extends: .cirrus_build_job + variables: + NAME: macos-11 + CIRRUS_VM_INSTANCE_TYPE: osx_instance + CIRRUS_VM_IMAGE_SELECTOR: image + CIRRUS_VM_IMAGE_NAME: big-sur-base + CIRRUS_VM_CPUS: 12 + CIRRUS_VM_RAM: 24G + UPDATE_COMMAND: brew update + INSTALL_COMMAND: brew install + PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin + PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig + TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64 + +x64-macos-11-xcode-build: + extends: .cirrus_build_job + variables: + NAME: macos-11 + CIRRUS_VM_INSTANCE_TYPE: osx_instance + CIRRUS_VM_IMAGE_SELECTOR: image + CIRRUS_VM_IMAGE_NAME: big-sur-xcode + CIRRUS_VM_CPUS: 12 + CIRRUS_VM_RAM: 24G + UPDATE_COMMAND: brew update + INSTALL_COMMAND: brew install + PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin + PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig + TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64 diff --git a/.gitlab-ci.d/cirrus/README.rst b/.gitlab-ci.d/cirrus/README.rst new file mode 100644 index 0000000000..657b0706d7 --- /dev/null +++ b/.gitlab-ci.d/cirrus/README.rst @@ -0,0 +1,54 @@ +Cirrus CI integration +===================== + +GitLab CI shared runners only provide a docker environment running on Linux. +While it is possible to provide private runners for non-Linux platforms this +is not something most contributors/maintainers will wish to do. + +To work around this limitation, we take advantage of `Cirrus CI`_'s free +offering: more specifically, we use the `cirrus-run`_ script to trigger Cirrus +CI jobs from GitLab CI jobs so that Cirrus CI job output is integrated into +the main GitLab CI pipeline dashboard. + +There is, however, some one-time setup required. If you want FreeBSD and macOS +builds to happen when you push to your GitLab repository, you need to + +* set up a GitHub repository for the project, eg. ``yourusername/qemu``. + This repository needs to exist for cirrus-run to work, but it doesn't need to + be kept up to date, so you can create it and then forget about it; + +* enable the `Cirrus CI GitHub app`_ for your GitHub account; + +* sign up for Cirrus CI. It's enough to log into the website using your GitHub + account; + +* grab an API token from the `Cirrus CI settings`_ page; + +* it may be necessary to push an empty ``.cirrus.yml`` file to your github fork + for Cirrus CI to properly recognize the project. You can check whether + Cirrus CI knows about your project by navigating to: + + ``https://cirrus-ci.com/yourusername/qemu`` + +* in the *CI/CD / Variables* section of the settings page for your GitLab + repository, create two new variables: + + * ``CIRRUS_GITHUB_REPO``, containing the name of the GitHub repository + created earlier, eg. ``yourusername/qemu``; + + * ``CIRRUS_API_TOKEN``, containing the Cirrus CI API token generated earlier. + This variable **must** be marked as *Masked*, because anyone with knowledge + of it can impersonate you as far as Cirrus CI is concerned. + + Neither of these variables should be marked as *Protected*, because in + general you'll want to be able to trigger Cirrus CI builds from non-protected + branches. + +Once this one-time setup is complete, you can just keep pushing to your GitLab +repository as usual and you'll automatically get the additional CI coverage. + + +.. _Cirrus CI GitHub app: https://github.com/marketplace/cirrus-ci +.. _Cirrus CI settings: https://cirrus-ci.com/settings/profile/ +.. _Cirrus CI: https://cirrus-ci.com/ +.. _cirrus-run: https://github.com/sio/cirrus-run/ diff --git a/.gitlab-ci.d/cirrus/build.yml b/.gitlab-ci.d/cirrus/build.yml new file mode 100644 index 0000000000..857bdc5536 --- /dev/null +++ b/.gitlab-ci.d/cirrus/build.yml @@ -0,0 +1,35 @@ +@CIRRUS_VM_INSTANCE_TYPE@: + @CIRRUS_VM_IMAGE_SELECTOR@: @CIRRUS_VM_IMAGE_NAME@ + cpu: @CIRRUS_VM_CPUS@ + memory: @CIRRUS_VM_RAM@ + +env: + CIRRUS_CLONE_DEPTH: 1 + CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@" + CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@" + CI_COMMIT_SHA: "@CI_COMMIT_SHA@" + PATH: "@PATH@" + PKG_CONFIG_PATH: "@PKG_CONFIG_PATH@" + PYTHON: "@PYTHON@" + MAKE: "@MAKE@" + CONFIGURE_ARGS: "@CONFIGURE_ARGS@" + +build_task: + install_script: + - @UPDATE_COMMAND@ + - @INSTALL_COMMAND@ @PKGS@ + - if test -n "@PYPI_PKGS@" ; then @PIP3@ install @PYPI_PKGS@ ; fi + clone_script: + - git clone --depth 100 "$CI_REPOSITORY_URL" . + - git fetch origin "$CI_COMMIT_REF_NAME" + - git reset --hard "$CI_COMMIT_SHA" + build_script: + - mkdir build + - cd build + - ../configure --enable-werror $CONFIGURE_ARGS + || { cat config.log meson-logs/meson-log.txt; exit 1; } + - $MAKE -j$(sysctl -n hw.ncpu) + - for TARGET in $TEST_TARGETS ; + do + $MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ; + done diff --git a/.gitlab-ci.d/cirrus/freebsd-12.vars b/.gitlab-ci.d/cirrus/freebsd-12.vars new file mode 100644 index 0000000000..2099b21354 --- /dev/null +++ b/.gitlab-ci.d/cirrus/freebsd-12.vars @@ -0,0 +1,13 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool variables freebsd-12 qemu +# +# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 + +PACKAGING_COMMAND='pkg' +CCACHE='/usr/local/bin/ccache' +MAKE='/usr/local/bin/gmake' +NINJA='/usr/local/bin/ninja' +PYTHON='/usr/local/bin/python3' +PIP3='/usr/local/bin/pip-3.8' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars new file mode 100644 index 0000000000..323fe806d5 --- /dev/null +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -0,0 +1,13 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool variables freebsd-13 qemu +# +# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 + +PACKAGING_COMMAND='pkg' +CCACHE='/usr/local/bin/ccache' +MAKE='/usr/local/bin/gmake' +NINJA='/usr/local/bin/ninja' +PYTHON='/usr/local/bin/python3' +PIP3='/usr/local/bin/pip-3.8' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' diff --git a/.gitlab-ci.d/cirrus/macos-11.vars b/.gitlab-ci.d/cirrus/macos-11.vars new file mode 100644 index 0000000000..cbec8a44a3 --- /dev/null +++ b/.gitlab-ci.d/cirrus/macos-11.vars @@ -0,0 +1,15 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool variables macos-11 qemu +# +# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 + +PACKAGING_COMMAND='brew' +CCACHE='/usr/local/bin/ccache' +MAKE='/usr/local/bin/gmake' +NINJA='/usr/local/bin/ninja' +PYTHON='/usr/local/bin/python3' +PIP3='/usr/local/bin/pip3' +PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb libxml2 llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' +PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme virtualenv' +CPAN_PKGS='Test::Harness' diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml new file mode 100644 index 0000000000..061d3cdfed --- /dev/null +++ b/.gitlab-ci.d/custom-runners.yml @@ -0,0 +1,222 @@ +# The CI jobs defined here require GitLab runners installed and +# registered on machines that match their operating system names, +# versions and architectures. This is in contrast to the other CI +# jobs that are intended to run on GitLab's "shared" runners. + +# Different than the default approach on "shared" runners, based on +# containers, the custom runners have no such *requirement*, as those +# jobs should be capable of running on operating systems with no +# compatible container implementation, or no support from +# gitlab-runner. To avoid problems that gitlab-runner can cause while +# reusing the GIT repository, let's enable the clone strategy, which +# guarantees a fresh repository on each job run. +variables: + GIT_STRATEGY: clone + +# All ubuntu-18.04 jobs should run successfully in an environment +# setup by the scripts/ci/setup/build-environment.yml task +# "Install basic packages to build QEMU on Ubuntu 18.04/20.04" +ubuntu-18.04-s390x-all-linux-static: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + # --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763 + # --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages + - mkdir build + - cd build + - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc` check-tcg V=1 + +ubuntu-18.04-s390x-all: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --disable-libssh + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-18.04-s390x-alldbg: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --enable-debug --disable-libssh + - make clean + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-18.04-s390x-clang: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + when: manual + script: + - mkdir build + - cd build + - ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-18.04-s390x-tci: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --disable-libssh --enable-tcg-interpreter + - make --output-sync -j`nproc` + +ubuntu-18.04-s390x-notcg: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_18.04 + - s390x + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + when: manual + script: + - mkdir build + - cd build + - ../configure --disable-libssh --disable-tcg + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +# All ubuntu-20.04 jobs should run successfully in an environment +# setup by the scripts/ci/setup/qemu/build-environment.yml task +# "Install basic packages to build QEMU on Ubuntu 18.04/20.04" +ubuntu-20.04-aarch64-all-linux-static: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + # --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763 + # --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages + - mkdir build + - cd build + - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc` check-tcg V=1 + +ubuntu-20.04-aarch64-all: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --disable-libssh + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-20.04-aarch64-alldbg: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --enable-debug --disable-libssh + - make clean + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-20.04-aarch64-clang: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + when: manual + script: + - mkdir build + - cd build + - ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 + +ubuntu-20.04-aarch64-tci: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + script: + - mkdir build + - cd build + - ../configure --disable-libssh --enable-tcg-interpreter + - make --output-sync -j`nproc` + +ubuntu-20.04-aarch64-notcg: + allow_failure: true + needs: [] + stage: build + tags: + - ubuntu_20.04 + - aarch64 + rules: + - if: '$CI_COMMIT_BRANCH =~ /^staging/' + when: manual + script: + - mkdir build + - cd build + - ../configure --disable-libssh --disable-tcg + - make --output-sync -j`nproc` + - make --output-sync -j`nproc` check V=1 diff --git a/.gitlab-ci.d/edk2.yml b/.gitlab-ci.d/edk2.yml index ba7280605c..aae2f7ad88 100644 --- a/.gitlab-ci.d/edk2.yml +++ b/.gitlab-ci.d/edk2.yml @@ -1,10 +1,22 @@ -docker-edk2: - stage: containers - rules: # Only run this job when the Dockerfile is modified +# All jobs needing docker-edk2 must use the same rules it uses. +.edk2_job_rules: + rules: # Only run this job when ... - changes: + # this file is modified - .gitlab-ci.d/edk2.yml + # or the Dockerfile is modified - .gitlab-ci.d/edk2/Dockerfile + # or roms/edk2/ is modified (submodule updated) + - roms/edk2/* when: always + - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' + when: always + - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' + when: always + +docker-edk2: + extends: .edk2_job_rules + stage: containers image: docker:19.03.1 services: - docker:19.03.1-dind @@ -24,16 +36,9 @@ docker-edk2: - docker push $IMAGE_TAG build-edk2: + extends: .edk2_job_rules stage: build needs: ['docker-edk2'] - rules: # Only run this job when ... - - changes: # ... roms/edk2/ is modified (submodule updated) - - roms/edk2/* - when: always - - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' - when: always - - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' - when: always artifacts: paths: # 'artifacts.zip' will contains the following files: - pc-bios/edk2*bz2 diff --git a/.gitlab-ci.d/qemu-project.yml b/.gitlab-ci.d/qemu-project.yml index 64cb2ba1da..b3d79bc429 100644 --- a/.gitlab-ci.d/qemu-project.yml +++ b/.gitlab-ci.d/qemu-project.yml @@ -9,3 +9,5 @@ include: - local: '/.gitlab-ci.d/crossbuilds.yml' - local: '/.gitlab-ci.d/buildtest.yml' - local: '/.gitlab-ci.d/static_checks.yml' + - local: '/.gitlab-ci.d/custom-runners.yml' + - local: '/.gitlab-ci.d/cirrus.yml' diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml index b01f6ec231..96dbd9e310 100644 --- a/.gitlab-ci.d/static_checks.yml +++ b/.gitlab-ci.d/static_checks.yml @@ -43,6 +43,7 @@ check-python-tox: - make -C python check-tox variables: GIT_DEPTH: 1 + QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false needs: job: python-container allow_failure: true diff --git a/.travis.yml b/.travis.yml index 4609240b5a..0faddf7b4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ addons: - libattr1-dev - libbrlapi-dev - libcap-ng-dev + - libcacard-dev - libgcc-7-dev - libgnutls28-dev - libgtk-3-dev @@ -34,7 +35,6 @@ addons: - liblttng-ust-dev - libncurses5-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libpng-dev - librados-dev @@ -129,6 +129,7 @@ jobs: - libaio-dev - libattr1-dev - libbrlapi-dev + - libcacard-dev - libcap-ng-dev - libgcrypt20-dev - libgnutls28-dev @@ -137,7 +138,6 @@ jobs: - liblttng-ust-dev - libncurses5-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libpng-dev - librados-dev @@ -163,6 +163,7 @@ jobs: - libaio-dev - libattr1-dev - libbrlapi-dev + - libcacard-dev - libcap-ng-dev - libgcrypt20-dev - libgnutls28-dev @@ -171,7 +172,6 @@ jobs: - liblttng-ust-dev - libncurses5-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libpng-dev - librados-dev @@ -196,6 +196,7 @@ jobs: - libaio-dev - libattr1-dev - libbrlapi-dev + - libcacard-dev - libcap-ng-dev - libgcrypt20-dev - libgnutls28-dev @@ -204,7 +205,6 @@ jobs: - liblttng-ust-dev - libncurses5-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libpng-dev - librados-dev @@ -238,6 +238,7 @@ jobs: apt_packages: - libaio-dev - libattr1-dev + - libcacard-dev - libcap-ng-dev - libgnutls28-dev - libiscsi-dev @@ -245,7 +246,6 @@ jobs: - liblzo2-dev - libncurses-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libsdl2-dev - libsdl2-image-dev @@ -281,6 +281,7 @@ jobs: - libaio-dev - libattr1-dev - libbrlapi-dev + - libcacard-dev - libcap-ng-dev - libgcrypt20-dev - libgnutls28-dev @@ -289,7 +290,6 @@ jobs: - liblttng-ust-dev - libncurses5-dev - libnfs-dev - - libnss3-dev - libpixman-1-dev - libpng-dev - librados-dev diff --git a/MAINTAINERS b/MAINTAINERS index c340bb02b0..9100f9a043 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -171,6 +171,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/arm/smmu* F: include/hw/arm/smmu* +F: tests/acceptance/smmu.py AVR TCG CPUs M: Michael Rolnik <mrolnik@gmail.com> @@ -2201,7 +2202,6 @@ F: include/hw/southbridge/piix.h Firmware configuration (fw_cfg) M: Philippe Mathieu-Daudé <philmd@redhat.com> -R: Laszlo Ersek <lersek@redhat.com> R: Gerd Hoffmann <kraxel@redhat.com> S: Supported F: docs/specs/fw_cfg.txt @@ -2933,7 +2933,6 @@ F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h Firmware schema specifications -M: Laszlo Ersek <lersek@redhat.com> M: Philippe Mathieu-Daudé <philmd@redhat.com> R: Daniel P. Berrange <berrange@redhat.com> R: Kashyap Chamarthy <kchamart@redhat.com> @@ -2941,9 +2940,9 @@ S: Maintained F: docs/interop/firmware.json EDK2 Firmware -M: Laszlo Ersek <lersek@redhat.com> M: Philippe Mathieu-Daudé <philmd@redhat.com> S: Supported +F: hw/i386/*ovmf* F: pc-bios/descriptors/??-edk2-*.json F: pc-bios/edk2-* F: roms/Makefile.edk2 @@ -3017,6 +3016,8 @@ F: include/tcg/ TCG Plugins M: Alex Bennée <alex.bennee@linaro.org> +R: Alexandre Iooss <erdnaxe@crans.org> +R: Mahmoud Mandour <ma.mandourr@gmail.com> S: Maintained F: docs/devel/tcg-plugins.rst F: plugins/ diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index b6d5fc6326..b4e15b6aad 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1728,7 +1728,7 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, data->v.io.offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr; } else { data->is_io = false; - data->v.ram.hostaddr = addr + tlbe->addend; + data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend); } return true; } else { diff --git a/configure b/configure index 4d0a2bfdd8..49b5481139 100755 --- a/configure +++ b/configure @@ -429,7 +429,7 @@ libxml2="auto" debug_mutex="no" libpmem="auto" default_devices="true" -plugins="no" +plugins="$default_feature" fuzzing="no" rng_none="no" secret_keyring="$default_feature" @@ -708,6 +708,7 @@ MINGW32*) audio_drv_list="" fi supported_os="yes" + plugins="no" pie="no" ;; GNU/kFreeBSD) @@ -1110,6 +1111,7 @@ for opt do --enable-cap-ng) cap_ng="enabled" ;; --disable-tcg) tcg="disabled" + plugins="no" ;; --enable-tcg) tcg="enabled" ;; @@ -1521,7 +1523,11 @@ for opt do ;; --disable-xkbcommon) xkbcommon="disabled" ;; - --enable-plugins) plugins="yes" + --enable-plugins) if test "$mingw32" = "yes"; then + error_exit "TCG plugins not currently supported on Windows platforms" + else + plugins="yes" + fi ;; --disable-plugins) plugins="no" ;; @@ -1575,6 +1581,11 @@ for opt do esac done +# test for any invalid configuration combinations +if test "$plugins" = "yes" -a "$tcg" = "disabled"; then + error_exit "Can't enable plugins on non-TCG builds" +fi + case $git_submodules_action in update|validate) if test ! -e "$source_path/.git"; then @@ -2191,11 +2202,16 @@ 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 +# Static linking is not possible with plugins, modules or PIE if test "$static" = "yes" ; then if test "$modules" = "yes" ; then error_exit "static and modules are mutually incompatible" fi + if test "$plugins" = "yes"; then + error_exit "static and plugins are mutually incompatible" + else + plugins="no" + fi fi # Unconditional check for compiler __thread support @@ -3089,6 +3105,69 @@ for drv in $audio_drv_list; do done ########################################## +# plugin linker support probe + +if test "$plugins" != "no"; then + + ######################################### + # See if --dynamic-list is supported by the linker + + ld_dynamic_list="no" + cat > $TMPTXT <<EOF +{ + foo; +}; +EOF + + cat > $TMPC <<EOF +#include <stdio.h> +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 + + ######################################### + # See if -exported_symbols_list is supported by the linker + + ld_exported_symbols_list="no" + cat > $TMPTXT <<EOF + _foo +EOF + + if compile_prog "" "-Wl,-exported_symbols_list,$TMPTXT" ; then + ld_exported_symbols_list="yes" + fi + + if test "$ld_dynamic_list" = "no" && + test "$ld_exported_symbols_list" = "no" ; then + if test "$plugins" = "yes"; then + error_exit \ + "Plugin support requires dynamic linking and specifying a set of symbols " \ + "that are exported to plugins. Unfortunately your linker doesn't " \ + "support the flag (--dynamic-list or -exported_symbols_list) used " \ + "for this purpose." + else + plugins="no" + fi + else + plugins="yes" + fi +fi + +########################################## # glib support probe glib_req_ver=2.56 @@ -3096,7 +3175,7 @@ glib_modules=gthread-2.0 if test "$modules" = yes; then glib_modules="$glib_modules gmodule-export-2.0" fi -if test "$plugins" = yes; then +if test "$plugins" = "yes"; then glib_modules="$glib_modules gmodule-2.0" fi @@ -3921,61 +4000,6 @@ 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 <<EOF -{ - foo; -}; -EOF - - cat > $TMPC <<EOF -#include <stdio.h> -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 <<EOF - _foo -EOF - - if compile_prog "" "-Wl,-exported_symbols_list,$TMPTXT" ; then - ld_exported_symbols_list="yes" - fi -fi - -if test "$plugins" = "yes" && - test "$ld_dynamic_list" = "no" && - test "$ld_exported_symbols_list" = "no" ; then - error_exit \ - "Plugin support requires dynamic linking and specifying a set of symbols " \ - "that are exported to plugins. Unfortunately your linker doesn't " \ - "support the flag (--dynamic-list or -exported_symbols_list) used " \ - "for this purpose. You can't build with --static." -fi - ######################################## # check if getauxval is available. diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile index b9d7935e5e..54ac5ccd9f 100644 --- a/contrib/plugins/Makefile +++ b/contrib/plugins/Makefile @@ -13,18 +13,20 @@ include $(BUILD_DIR)/config-host.mak VPATH += $(SRC_PATH)/contrib/plugins NAMES := +NAMES += execlog NAMES += hotblocks NAMES += hotpages NAMES += howvec NAMES += lockstep NAMES += hwprofile +NAMES += cache SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES))) # The main QEMU uses Glib extensively so it's perfectly fine to use it # in plugins (which many example do). CFLAGS = $(GLIB_CFLAGS) -CFLAGS += -fPIC +CFLAGS += -fPIC -Wall $(filter -W%, $(QEMU_CFLAGS)) CFLAGS += $(if $(findstring no-psabi,$(QEMU_CFLAGS)),-Wpsabi) CFLAGS += -I$(SRC_PATH)/include/qemu diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c new file mode 100644 index 0000000000..bf0d2f6097 --- /dev/null +++ b/contrib/plugins/cache.c @@ -0,0 +1,641 @@ +/* + * Copyright (C) 2021, Mahmoud Mandour <ma.mandourr@gmail.com> + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <inttypes.h> +#include <stdio.h> +#include <glib.h> + +#include <qemu-plugin.h> + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW; + +static GHashTable *miss_ht; + +static GMutex mtx; +static GRand *rng; + +static int limit; +static bool sys; + +static uint64_t dmem_accesses; +static uint64_t dmisses; + +static uint64_t imem_accesses; +static uint64_t imisses; + +enum EvictionPolicy { + LRU, + FIFO, + RAND, +}; + +enum EvictionPolicy policy; + +/* + * A CacheSet is a set of cache blocks. A memory block that maps to a set can be + * put in any of the blocks inside the set. The number of block per set is + * called the associativity (assoc). + * + * Each block contains the the stored tag and a valid bit. Since this is not + * a functional simulator, the data itself is not stored. We only identify + * whether a block is in the cache or not by searching for its tag. + * + * In order to search for memory data in the cache, the set identifier and tag + * are extracted from the address and the set is probed to see whether a tag + * match occur. + * + * An address is logically divided into three portions: The block offset, + * the set number, and the tag. + * + * The set number is used to identify the set in which the block may exist. + * The tag is compared against all the tags of a set to search for a match. If a + * match is found, then the access is a hit. + * + * The CacheSet also contains bookkeaping information about eviction details. + */ + +typedef struct { + uint64_t tag; + bool valid; +} CacheBlock; + +typedef struct { + CacheBlock *blocks; + uint64_t *lru_priorities; + uint64_t lru_gen_counter; + GQueue *fifo_queue; +} CacheSet; + +typedef struct { + CacheSet *sets; + int num_sets; + int cachesize; + int assoc; + int blksize_shift; + uint64_t set_mask; + uint64_t tag_mask; +} Cache; + +typedef struct { + char *disas_str; + const char *symbol; + uint64_t addr; + uint64_t dmisses; + uint64_t imisses; +} InsnData; + +void (*update_hit)(Cache *cache, int set, int blk); +void (*update_miss)(Cache *cache, int set, int blk); + +void (*metadata_init)(Cache *cache); +void (*metadata_destroy)(Cache *cache); + +Cache *dcache, *icache; + +static int pow_of_two(int num) +{ + g_assert((num & (num - 1)) == 0); + int ret = 0; + while (num /= 2) { + ret++; + } + return ret; +} + +/* + * LRU evection policy: For each set, a generation counter is maintained + * alongside a priority array. + * + * On each set access, the generation counter is incremented. + * + * On a cache hit: The hit-block is assigned the current generation counter, + * indicating that it is the most recently used block. + * + * On a cache miss: The block with the least priority is searched and replaced + * with the newly-cached block, of which the priority is set to the current + * generation number. + */ + +static void lru_priorities_init(Cache *cache) +{ + int i; + + for (i = 0; i < cache->num_sets; i++) { + cache->sets[i].lru_priorities = g_new0(uint64_t, cache->assoc); + cache->sets[i].lru_gen_counter = 0; + } +} + +static void lru_update_blk(Cache *cache, int set_idx, int blk_idx) +{ + CacheSet *set = &cache->sets[set_idx]; + set->lru_priorities[blk_idx] = cache->sets[set_idx].lru_gen_counter; + set->lru_gen_counter++; +} + +static int lru_get_lru_block(Cache *cache, int set_idx) +{ + int i, min_idx, min_priority; + + min_priority = cache->sets[set_idx].lru_priorities[0]; + min_idx = 0; + + for (i = 1; i < cache->assoc; i++) { + if (cache->sets[set_idx].lru_priorities[i] < min_priority) { + min_priority = cache->sets[set_idx].lru_priorities[i]; + min_idx = i; + } + } + return min_idx; +} + +static void lru_priorities_destroy(Cache *cache) +{ + int i; + + for (i = 0; i < cache->num_sets; i++) { + g_free(cache->sets[i].lru_priorities); + } +} + +/* + * FIFO eviction policy: a FIFO queue is maintained for each CacheSet that + * stores accesses to the cache. + * + * On a compulsory miss: The block index is enqueued to the fifo_queue to + * indicate that it's the latest cached block. + * + * On a conflict miss: The first-in block is removed from the cache and the new + * block is put in its place and enqueued to the FIFO queue. + */ + +static void fifo_init(Cache *cache) +{ + int i; + + for (i = 0; i < cache->num_sets; i++) { + cache->sets[i].fifo_queue = g_queue_new(); + } +} + +static int fifo_get_first_block(Cache *cache, int set) +{ + GQueue *q = cache->sets[set].fifo_queue; + return GPOINTER_TO_INT(g_queue_pop_tail(q)); +} + +static void fifo_update_on_miss(Cache *cache, int set, int blk_idx) +{ + GQueue *q = cache->sets[set].fifo_queue; + g_queue_push_head(q, GINT_TO_POINTER(blk_idx)); +} + +static void fifo_destroy(Cache *cache) +{ + int i; + + for (i = 0; i < cache->assoc; i++) { + g_queue_free(cache->sets[i].fifo_queue); + } +} + +static inline uint64_t extract_tag(Cache *cache, uint64_t addr) +{ + return addr & cache->tag_mask; +} + +static inline uint64_t extract_set(Cache *cache, uint64_t addr) +{ + return (addr & cache->set_mask) >> cache->blksize_shift; +} + +static const char *cache_config_error(int blksize, int assoc, int cachesize) +{ + if (cachesize % blksize != 0) { + return "cache size must be divisible by block size"; + } else if (cachesize % (blksize * assoc) != 0) { + return "cache size must be divisible by set size (assoc * block size)"; + } else { + return NULL; + } +} + +static bool bad_cache_params(int blksize, int assoc, int cachesize) +{ + return (cachesize % blksize) != 0 || (cachesize % (blksize * assoc) != 0); +} + +static Cache *cache_init(int blksize, int assoc, int cachesize) +{ + if (bad_cache_params(blksize, assoc, cachesize)) { + return NULL; + } + + Cache *cache; + int i; + uint64_t blk_mask; + + cache = g_new(Cache, 1); + cache->assoc = assoc; + cache->cachesize = cachesize; + cache->num_sets = cachesize / (blksize * assoc); + cache->sets = g_new(CacheSet, cache->num_sets); + cache->blksize_shift = pow_of_two(blksize); + + for (i = 0; i < cache->num_sets; i++) { + cache->sets[i].blocks = g_new0(CacheBlock, assoc); + } + + blk_mask = blksize - 1; + cache->set_mask = ((cache->num_sets - 1) << cache->blksize_shift); + cache->tag_mask = ~(cache->set_mask | blk_mask); + + if (metadata_init) { + metadata_init(cache); + } + + return cache; +} + +static int get_invalid_block(Cache *cache, uint64_t set) +{ + int i; + + for (i = 0; i < cache->assoc; i++) { + if (!cache->sets[set].blocks[i].valid) { + return i; + } + } + + return -1; +} + +static int get_replaced_block(Cache *cache, int set) +{ + switch (policy) { + case RAND: + return g_rand_int_range(rng, 0, cache->assoc); + case LRU: + return lru_get_lru_block(cache, set); + case FIFO: + return fifo_get_first_block(cache, set); + default: + g_assert_not_reached(); + } +} + +static int in_cache(Cache *cache, uint64_t addr) +{ + int i; + uint64_t tag, set; + + tag = extract_tag(cache, addr); + set = extract_set(cache, addr); + + for (i = 0; i < cache->assoc; i++) { + if (cache->sets[set].blocks[i].tag == tag && + cache->sets[set].blocks[i].valid) { + return i; + } + } + + return -1; +} + +/** + * access_cache(): Simulate a cache access + * @cache: The cache under simulation + * @addr: The address of the requested memory location + * + * Returns true if the requsted data is hit in the cache and false when missed. + * The cache is updated on miss for the next access. + */ +static bool access_cache(Cache *cache, uint64_t addr) +{ + int hit_blk, replaced_blk; + uint64_t tag, set; + + tag = extract_tag(cache, addr); + set = extract_set(cache, addr); + + hit_blk = in_cache(cache, addr); + if (hit_blk != -1) { + if (update_hit) { + update_hit(cache, set, hit_blk); + } + return true; + } + + replaced_blk = get_invalid_block(cache, set); + + if (replaced_blk == -1) { + replaced_blk = get_replaced_block(cache, set); + } + + if (update_miss) { + update_miss(cache, set, replaced_blk); + } + + cache->sets[set].blocks[replaced_blk].tag = tag; + cache->sets[set].blocks[replaced_blk].valid = true; + + return false; +} + +static void vcpu_mem_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, + uint64_t vaddr, void *userdata) +{ + uint64_t effective_addr; + struct qemu_plugin_hwaddr *hwaddr; + InsnData *insn; + + g_mutex_lock(&mtx); + hwaddr = qemu_plugin_get_hwaddr(info, vaddr); + if (hwaddr && qemu_plugin_hwaddr_is_io(hwaddr)) { + g_mutex_unlock(&mtx); + return; + } + + effective_addr = hwaddr ? qemu_plugin_hwaddr_phys_addr(hwaddr) : vaddr; + + if (!access_cache(dcache, effective_addr)) { + insn = (InsnData *) userdata; + insn->dmisses++; + dmisses++; + } + dmem_accesses++; + g_mutex_unlock(&mtx); +} + +static void vcpu_insn_exec(unsigned int vcpu_index, void *userdata) +{ + uint64_t insn_addr; + InsnData *insn; + + g_mutex_lock(&mtx); + insn_addr = ((InsnData *) userdata)->addr; + + if (!access_cache(icache, insn_addr)) { + insn = (InsnData *) userdata; + insn->imisses++; + imisses++; + } + imem_accesses++; + g_mutex_unlock(&mtx); +} + +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + size_t n_insns; + size_t i; + InsnData *data; + + n_insns = qemu_plugin_tb_n_insns(tb); + for (i = 0; i < n_insns; i++) { + struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); + uint64_t effective_addr; + + if (sys) { + effective_addr = (uint64_t) qemu_plugin_insn_haddr(insn); + } else { + effective_addr = (uint64_t) qemu_plugin_insn_vaddr(insn); + } + + /* + * Instructions might get translated multiple times, we do not create + * new entries for those instructions. Instead, we fetch the same + * entry from the hash table and register it for the callback again. + */ + g_mutex_lock(&mtx); + data = g_hash_table_lookup(miss_ht, GUINT_TO_POINTER(effective_addr)); + if (data == NULL) { + data = g_new0(InsnData, 1); + data->disas_str = qemu_plugin_insn_disas(insn); + data->symbol = qemu_plugin_insn_symbol(insn); + data->addr = effective_addr; + g_hash_table_insert(miss_ht, GUINT_TO_POINTER(effective_addr), + (gpointer) data); + } + g_mutex_unlock(&mtx); + + qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem_access, + QEMU_PLUGIN_CB_NO_REGS, + rw, data); + + qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec, + QEMU_PLUGIN_CB_NO_REGS, data); + } +} + +static void insn_free(gpointer data) +{ + InsnData *insn = (InsnData *) data; + g_free(insn->disas_str); + g_free(insn); +} + +static void cache_free(Cache *cache) +{ + for (int i = 0; i < cache->num_sets; i++) { + g_free(cache->sets[i].blocks); + } + + if (metadata_destroy) { + metadata_destroy(cache); + } + + g_free(cache->sets); + g_free(cache); +} + +static int dcmp(gconstpointer a, gconstpointer b) +{ + InsnData *insn_a = (InsnData *) a; + InsnData *insn_b = (InsnData *) b; + + return insn_a->dmisses < insn_b->dmisses ? 1 : -1; +} + +static int icmp(gconstpointer a, gconstpointer b) +{ + InsnData *insn_a = (InsnData *) a; + InsnData *insn_b = (InsnData *) b; + + return insn_a->imisses < insn_b->imisses ? 1 : -1; +} + +static void log_stats() +{ + g_autoptr(GString) rep = g_string_new(""); + g_string_append_printf(rep, + "Data accesses: %lu, Misses: %lu\nMiss rate: %lf%%\n\n", + dmem_accesses, + dmisses, + ((double) dmisses / (double) dmem_accesses) * 100.0); + + g_string_append_printf(rep, + "Instruction accesses: %lu, Misses: %lu\nMiss rate: %lf%%\n\n", + imem_accesses, + imisses, + ((double) imisses / (double) imem_accesses) * 100.0); + + qemu_plugin_outs(rep->str); +} + +static void log_top_insns() +{ + int i; + GList *curr, *miss_insns; + InsnData *insn; + + miss_insns = g_hash_table_get_values(miss_ht); + miss_insns = g_list_sort(miss_insns, dcmp); + g_autoptr(GString) rep = g_string_new(""); + g_string_append_printf(rep, "%s", "address, data misses, instruction\n"); + + for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) { + insn = (InsnData *) curr->data; + g_string_append_printf(rep, "0x%" PRIx64, insn->addr); + if (insn->symbol) { + g_string_append_printf(rep, " (%s)", insn->symbol); + } + g_string_append_printf(rep, ", %ld, %s\n", insn->dmisses, + insn->disas_str); + } + + miss_insns = g_list_sort(miss_insns, icmp); + g_string_append_printf(rep, "%s", "\naddress, fetch misses, instruction\n"); + + for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) { + insn = (InsnData *) curr->data; + g_string_append_printf(rep, "0x%" PRIx64, insn->addr); + if (insn->symbol) { + g_string_append_printf(rep, " (%s)", insn->symbol); + } + g_string_append_printf(rep, ", %ld, %s\n", insn->imisses, + insn->disas_str); + } + + qemu_plugin_outs(rep->str); + g_list_free(miss_insns); +} + +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + log_stats(); + log_top_insns(); + + cache_free(dcache); + cache_free(icache); + + g_hash_table_destroy(miss_ht); +} + +static void policy_init() +{ + switch (policy) { + case LRU: + update_hit = lru_update_blk; + update_miss = lru_update_blk; + metadata_init = lru_priorities_init; + metadata_destroy = lru_priorities_destroy; + break; + case FIFO: + update_miss = fifo_update_on_miss; + metadata_init = fifo_init; + metadata_destroy = fifo_destroy; + break; + case RAND: + rng = g_rand_new(); + break; + default: + g_assert_not_reached(); + } +} + +QEMU_PLUGIN_EXPORT +int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, + int argc, char **argv) +{ + int i; + int iassoc, iblksize, icachesize; + int dassoc, dblksize, dcachesize; + + limit = 32; + sys = info->system_emulation; + + dassoc = 8; + dblksize = 64; + dcachesize = dblksize * dassoc * 32; + + iassoc = 8; + iblksize = 64; + icachesize = iblksize * iassoc * 32; + + policy = LRU; + + for (i = 0; i < argc; i++) { + char *opt = argv[i]; + if (g_str_has_prefix(opt, "iblksize=")) { + iblksize = g_ascii_strtoll(opt + 9, NULL, 10); + } else if (g_str_has_prefix(opt, "iassoc=")) { + iassoc = g_ascii_strtoll(opt + 7, NULL, 10); + } else if (g_str_has_prefix(opt, "icachesize=")) { + icachesize = g_ascii_strtoll(opt + 11, NULL, 10); + } else if (g_str_has_prefix(opt, "dblksize=")) { + dblksize = g_ascii_strtoll(opt + 9, NULL, 10); + } else if (g_str_has_prefix(opt, "dassoc=")) { + dassoc = g_ascii_strtoll(opt + 7, NULL, 10); + } else if (g_str_has_prefix(opt, "dcachesize=")) { + dcachesize = g_ascii_strtoll(opt + 11, NULL, 10); + } else if (g_str_has_prefix(opt, "limit=")) { + limit = g_ascii_strtoll(opt + 6, NULL, 10); + } else if (g_str_has_prefix(opt, "evict=")) { + gchar *p = opt + 6; + if (g_strcmp0(p, "rand") == 0) { + policy = RAND; + } else if (g_strcmp0(p, "lru") == 0) { + policy = LRU; + } else if (g_strcmp0(p, "fifo") == 0) { + policy = FIFO; + } else { + fprintf(stderr, "invalid eviction policy: %s\n", opt); + return -1; + } + } else { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } + } + + policy_init(); + + dcache = cache_init(dblksize, dassoc, dcachesize); + if (!dcache) { + const char *err = cache_config_error(dblksize, dassoc, dcachesize); + fprintf(stderr, "dcache cannot be constructed from given parameters\n"); + fprintf(stderr, "%s\n", err); + return -1; + } + + icache = cache_init(iblksize, iassoc, icachesize); + if (!icache) { + const char *err = cache_config_error(iblksize, iassoc, icachesize); + fprintf(stderr, "icache cannot be constructed from given parameters\n"); + fprintf(stderr, "%s\n", err); + return -1; + } + + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); + + miss_ht = g_hash_table_new_full(NULL, g_direct_equal, NULL, insn_free); + + return 0; +} diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c new file mode 100644 index 0000000000..2de9f0d7d4 --- /dev/null +++ b/contrib/plugins/execlog.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2021, Alexandre Iooss <erdnaxe@crans.org> + * + * Log instruction execution with memory access. + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include <glib.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <qemu-plugin.h> + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +/* Store last executed instruction on each vCPU as a GString */ +GArray *last_exec; + +/** + * Add memory read or write information to current instruction log + */ +static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, + uint64_t vaddr, void *udata) +{ + GString *s; + + /* Find vCPU in array */ + g_assert(cpu_index < last_exec->len); + s = g_array_index(last_exec, GString *, cpu_index); + + /* Indicate type of memory access */ + if (qemu_plugin_mem_is_store(info)) { + g_string_append(s, ", store"); + } else { + g_string_append(s, ", load"); + } + + /* If full system emulation log physical address and device name */ + struct qemu_plugin_hwaddr *hwaddr = qemu_plugin_get_hwaddr(info, vaddr); + if (hwaddr) { + uint64_t addr = qemu_plugin_hwaddr_phys_addr(hwaddr); + const char *name = qemu_plugin_hwaddr_device_name(hwaddr); + g_string_append_printf(s, ", 0x%08"PRIx64", %s", addr, name); + } else { + g_string_append_printf(s, ", 0x%08"PRIx64, vaddr); + } +} + +/** + * Log instruction execution + */ +static void vcpu_insn_exec(unsigned int cpu_index, void *udata) +{ + GString *s; + + /* Find or create vCPU in array */ + while (cpu_index >= last_exec->len) { + s = g_string_new(NULL); + g_array_append_val(last_exec, s); + } + s = g_array_index(last_exec, GString *, cpu_index); + + /* Print previous instruction in cache */ + if (s->len) { + qemu_plugin_outs(s->str); + qemu_plugin_outs("s\n"); + } + + /* Store new instruction in cache */ + /* vcpu_mem will add memory access information to last_exec */ + g_string_printf(s, "%u, ", cpu_index); + g_string_append(s, (char *)udata); +} + +/** + * On translation block new translation + * + * QEMU convert code by translation block (TB). By hooking here we can then hook + * a callback on each instruction and memory access. + */ +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + struct qemu_plugin_insn *insn; + uint64_t insn_vaddr; + uint32_t insn_opcode; + char *insn_disas; + + size_t n = qemu_plugin_tb_n_insns(tb); + for (size_t i = 0; i < n; i++) { + /* + * `insn` is shared between translations in QEMU, copy needed data here. + * `output` is never freed as it might be used multiple times during + * the emulation lifetime. + * We only consider the first 32 bits of the instruction, this may be + * a limitation for CISC architectures. + */ + insn = qemu_plugin_tb_get_insn(tb, i); + insn_vaddr = qemu_plugin_insn_vaddr(insn); + insn_opcode = *((uint32_t *)qemu_plugin_insn_data(insn)); + insn_disas = qemu_plugin_insn_disas(insn); + char *output = g_strdup_printf("0x%"PRIx64", 0x%"PRIx32", \"%s\"", + insn_vaddr, insn_opcode, insn_disas); + + /* Register callback on memory read or write */ + qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, + QEMU_PLUGIN_CB_NO_REGS, + QEMU_PLUGIN_MEM_RW, NULL); + + /* Register callback on instruction */ + qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec, + QEMU_PLUGIN_CB_NO_REGS, output); + } +} + +/** + * On plugin exit, print last instruction in cache + */ +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + guint i; + GString *s; + for (i = 0; i < last_exec->len; i++) { + s = g_array_index(last_exec, GString *, i); + if (s->str) { + qemu_plugin_outs(s->str); + qemu_plugin_outs("\n"); + } + } +} + +/** + * Install the plugin + */ +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, int argc, + char **argv) +{ + /* + * Initialize dynamic array to cache vCPU instruction. In user mode + * we don't know the size before emulation. + */ + last_exec = g_array_new(FALSE, FALSE, sizeof(GString *)); + + /* Register translation block and exit callbacks */ + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); + + return 0; +} diff --git a/docs/ccid.txt b/docs/ccid.txt index c97fbd2de0..2b85b1bd42 100644 --- a/docs/ccid.txt +++ b/docs/ccid.txt @@ -34,15 +34,14 @@ reader and smart card (i.e. not backed by a physical device) using this device. 2. Building -The cryptographic functions and access to the physical card is done via NSS. - -Installing NSS: +The cryptographic functions and access to the physical card is done via the +libcacard library, whose development package must be installed prior to +building QEMU: In redhat/fedora: - yum install nss-devel -In ubuntu/debian: - apt-get install libnss3-dev - (not tested on ubuntu) + yum install libcacard-devel +In ubuntu: + apt-get install libcacard-dev Configuring and building: ./configure --enable-smartcard && make @@ -51,7 +50,7 @@ Configuring and building: 3. Using ccid-card-emulated with hardware Assuming you have a working smartcard on the host with the current -user, using NSS, qemu acts as another NSS client using ccid-card-emulated: +user, using libcacard, QEMU acts as another client using ccid-card-emulated: qemu -usb -device usb-ccid -device ccid-card-emulated diff --git a/docs/devel/ci.rst b/docs/devel/ci.rst new file mode 100644 index 0000000000..b3bf3ef615 --- /dev/null +++ b/docs/devel/ci.rst @@ -0,0 +1,127 @@ +== +CI +== + +QEMU has configurations enabled for a number of different CI services. +The most up to date information about them and their status can be +found at:: + + https://wiki.qemu.org/Testing/CI + +Jobs on Custom Runners +====================== + +Besides the jobs run under the various CI systems listed before, there +are a number additional jobs that will run before an actual merge. +These use the same GitLab CI's service/framework already used for all +other GitLab based CI jobs, but rely on additional systems, not the +ones provided by GitLab as "shared runners". + +The architecture of GitLab's CI service allows different machines to +be set up with GitLab's "agent", called gitlab-runner, which will take +care of running jobs created by events such as a push to a branch. +Here, the combination of a machine, properly configured with GitLab's +gitlab-runner, is called a "custom runner". + +The GitLab CI jobs definition for the custom runners are located under:: + + .gitlab-ci.d/custom-runners.yml + +Custom runners entail custom machines. To see a list of the machines +currently deployed in the QEMU GitLab CI and their maintainers, please +refer to the QEMU `wiki <https://wiki.qemu.org/AdminContacts>`__. + +Machine Setup Howto +------------------- + +For all Linux based systems, the setup can be mostly automated by the +execution of two Ansible playbooks. Create an ``inventory`` file +under ``scripts/ci/setup``, such as this:: + + fully.qualified.domain + other.machine.hostname + +You may need to set some variables in the inventory file itself. One +very common need is to tell Ansible to use a Python 3 interpreter on +those hosts. This would look like:: + + fully.qualified.domain ansible_python_interpreter=/usr/bin/python3 + other.machine.hostname ansible_python_interpreter=/usr/bin/python3 + +Build environment +~~~~~~~~~~~~~~~~~ + +The ``scripts/ci/setup/build-environment.yml`` Ansible playbook will +set up machines with the environment needed to perform builds and run +QEMU tests. This playbook consists on the installation of various +required packages (and a general package update while at it). It +currently covers a number of different Linux distributions, but it can +be expanded to cover other systems. + +The minimum required version of Ansible successfully tested in this +playbook is 2.8.0 (a version check is embedded within the playbook +itself). To run the playbook, execute:: + + cd scripts/ci/setup + ansible-playbook -i inventory build-environment.yml + +Please note that most of the tasks in the playbook require superuser +privileges, such as those from the ``root`` account or those obtained +by ``sudo``. If necessary, please refer to ``ansible-playbook`` +options such as ``--become``, ``--become-method``, ``--become-user`` +and ``--ask-become-pass``. + +gitlab-runner setup and registration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The gitlab-runner agent needs to be installed on each machine that +will run jobs. The association between a machine and a GitLab project +happens with a registration token. To find the registration token for +your repository/project, navigate on GitLab's web UI to: + + * Settings (the gears-like icon at the bottom of the left hand side + vertical toolbar), then + * CI/CD, then + * Runners, and click on the "Expand" button, then + * Under "Set up a specific Runner manually", look for the value under + "And this registration token:" + +Copy the ``scripts/ci/setup/vars.yml.template`` file to +``scripts/ci/setup/vars.yml``. Then, set the +``gitlab_runner_registration_token`` variable to the value obtained +earlier. + +To run the playbook, execute:: + + cd scripts/ci/setup + ansible-playbook -i inventory gitlab-runner.yml + +Following the registration, it's necessary to configure the runner tags, +and optionally other configurations on the GitLab UI. Navigate to: + + * Settings (the gears like icon), then + * CI/CD, then + * Runners, and click on the "Expand" button, then + * "Runners activated for this project", then + * Click on the "Edit" icon (next to the "Lock" Icon) + +Tags are very important as they are used to route specific jobs to +specific types of runners, so it's a good idea to double check that +the automatically created tags are consistent with the OS and +architecture. For instance, an Ubuntu 20.04 aarch64 system should +have tags set as:: + + ubuntu_20.04,aarch64 + +Because the job definition at ``.gitlab-ci.d/custom-runners.yml`` +would contain:: + + ubuntu-20.04-aarch64-all: + tags: + - ubuntu_20.04 + - aarch64 + +It's also recommended to: + + * increase the "Maximum job timeout" to something like ``2h`` + * give it a better Description diff --git a/docs/devel/index.rst b/docs/devel/index.rst index ba90badbbd..40a7e2ee6f 100644 --- a/docs/devel/index.rst +++ b/docs/devel/index.rst @@ -27,6 +27,7 @@ Contents: migration atomics stable-process + ci qtest decodetree secure-coding-practices diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 18c6581d85..7e54f12837 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -71,7 +71,8 @@ API Usage ===== -The QEMU binary needs to be compiled for plugin support:: +Any QEMU binary with TCG support has plugins enabled by default. +Earlier releases needed to be explicitly enabled with:: configure --enable-plugins @@ -319,3 +320,86 @@ the user to see what hardware is accessed how often. It has a number of options: off:0000001c, 1, 2 off:00000020, 1, 2 ... + +- contrib/plugins/execlog.c + +The execlog tool traces executed instructions with memory access. It can be used +for debugging and security analysis purposes. +Please be aware that this will generate a lot of output. + +The plugin takes no argument:: + + qemu-system-arm $(QEMU_ARGS) \ + -plugin ./contrib/plugins/libexeclog.so -d plugin + +which will output an execution trace following this structure:: + + # vCPU, vAddr, opcode, disassembly[, load/store, memory addr, device]... + 0, 0xa12, 0xf8012400, "movs r4, #0" + 0, 0xa14, 0xf87f42b4, "cmp r4, r6" + 0, 0xa16, 0xd206, "bhs #0xa26" + 0, 0xa18, 0xfff94803, "ldr r0, [pc, #0xc]", load, 0x00010a28, RAM + 0, 0xa1a, 0xf989f000, "bl #0xd30" + 0, 0xd30, 0xfff9b510, "push {r4, lr}", store, 0x20003ee0, RAM, store, 0x20003ee4, RAM + 0, 0xd32, 0xf9893014, "adds r0, #0x14" + 0, 0xd34, 0xf9c8f000, "bl #0x10c8" + 0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM + +- contrib/plugins/cache + +Cache modelling plugin that measures the performance of a given cache +configuration when a given working set is run:: + + qemu-x86_64 -plugin ./contrib/plugins/libcache.so \ + -d plugin -D cache.log ./tests/tcg/x86_64-linux-user/float_convs + +will report the following:: + + Data accesses: 996479, Misses: 507 + Miss rate: 0.050879% + + Instruction accesses: 2641737, Misses: 18617 + Miss rate: 0.704726% + + address, data misses, instruction + 0x424f1e (_int_malloc), 109, movq %rax, 8(%rcx) + 0x41f395 (_IO_default_xsputn), 49, movb %dl, (%rdi, %rax) + 0x42584d (ptmalloc_init.part.0), 33, movaps %xmm0, (%rax) + 0x454d48 (__tunables_init), 20, cmpb $0, (%r8) + ... + + address, fetch misses, instruction + 0x4160a0 (__vfprintf_internal), 744, movl $1, %ebx + 0x41f0a0 (_IO_setb), 744, endbr64 + 0x415882 (__vfprintf_internal), 744, movq %r12, %rdi + 0x4268a0 (__malloc), 696, andq $0xfffffffffffffff0, %rax + ... + +The plugin has a number of arguments, all of them are optional: + + * arg="limit=N" + + Print top N icache and dcache thrashing instructions along with their + address, number of misses, and its disassembly. (default: 32) + + * arg="icachesize=N" + * arg="iblksize=B" + * arg="iassoc=A" + + Instruction cache configuration arguments. They specify the cache size, block + size, and associativity of the instruction cache, respectively. + (default: N = 16384, B = 64, A = 8) + + * arg="dcachesize=N" + * arg="dblksize=B" + * arg="dassoc=A" + + Data cache configuration arguments. They specify the cache size, block size, + and associativity of the data cache, respectively. + (default: N = 16384, B = 64, A = 8) + + * arg="evict=POLICY" + + Sets the eviction policy to POLICY. Available policies are: :code:`lru`, + :code:`fifo`, and :code:`rand`. The plugin will use the specified policy for + both instruction and data caches. (default: POLICY = :code:`lru`) diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 4e42392810..8f572255d3 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -904,6 +904,17 @@ name. If one is not given explicitly, it will either be set to ``None``, or, if the test is tagged with one (and only one) ``:avocado: tags=arch:VALUE`` tag, it will be set to ``VALUE``. +cpu +~~~ + +The cpu model that will be set to all QEMUMachine instances created +by the test. + +The ``cpu`` attribute will be set to the test parameter of the same +name. If one is not given explicitly, it will either be set to +``None ``, or, if the test is tagged with one (and only one) +``:avocado: tags=cpu:VALUE`` tag, it will be set to ``VALUE``. + machine ~~~~~~~ @@ -922,6 +933,39 @@ The preserved value of the ``qemu_bin`` parameter or the result of the dynamic probe for a QEMU binary in the current working directory or source tree. +LinuxTest +~~~~~~~~~ + +Besides the attributes present on the ``avocado_qemu.Test`` base +class, the ``avocado_qemu.LinuxTest`` adds the following attributes: + +distro +...... + +The name of the Linux distribution used as the guest image for the +test. The name should match the **Provider** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_version +.............. + +The version of the Linux distribution as the guest image for the +test. The name should match the **Version** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_checksum +............... + +The sha256 hash of the guest image file used for the test. + +If this value is not set in the code or by a test parameter (with the +same name), no validation on the integrity of the image will be +performed. + Parameter reference ------------------- @@ -950,6 +994,12 @@ architecture of a kernel or disk image to boot a VM with. This parameter has a direct relation with the ``arch`` attribute. If not given, it will default to None. +cpu +~~~ + +The cpu model that will be set to all QEMUMachine instances created +by the test. + machine ~~~~~~~ @@ -962,6 +1012,38 @@ qemu_bin The exact QEMU binary to be used on QEMUMachine. +LinuxTest +~~~~~~~~~ + +Besides the parameters present on the ``avocado_qemu.Test`` base +class, the ``avocado_qemu.LinuxTest`` adds the following parameters: + +distro +...... + +The name of the Linux distribution used as the guest image for the +test. The name should match the **Provider** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_version +.............. + +The version of the Linux distribution as the guest image for the +test. The name should match the **Version** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_checksum +............... + +The sha256 hash of the guest image file used for the test. + +If this value is not set in the code or by this parameter no +validation on the integrity of the image will be performed. + Skipping tests -------------- The Avocado framework provides Python decorators which allow for easily skip diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index aacb6f6d96..bad6cf5b4e 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -1,5 +1,9 @@ +config X86_FW_OVMF + bool + config SEV bool + select X86_FW_OVMF depends on KVM config PC diff --git a/hw/i386/meson.build b/hw/i386/meson.build index e5d109f5c6..80dad29f2b 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -24,6 +24,8 @@ i386_ss.add(when: 'CONFIG_PC', if_true: files( 'pc_sysfw.c', 'acpi-build.c', 'port92.c')) +i386_ss.add(when: 'CONFIG_X86_FW_OVMF', if_true: files('pc_sysfw_ovmf.c'), + if_false: files('pc_sysfw_ovmf-stubs.c')) subdir('kvm') subdir('xen') diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 6ce37a2b05..68d6b1f783 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -124,113 +124,6 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms) } } -#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" - -static uint8_t *ovmf_table; -static int ovmf_table_len; - -static void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) -{ - uint8_t *ptr; - QemuUUID guid; - int tot_len; - - /* should only be called once */ - if (ovmf_table) { - return; - } - - if (flash_size < TARGET_PAGE_SIZE) { - return; - } - - /* - * if this is OVMF there will be a table footer - * guid 48 bytes before the end of the flash file. If it's - * not found, silently abort the flash parsing. - */ - qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); - guid = qemu_uuid_bswap(guid); /* guids are LE */ - ptr = flash_ptr + flash_size - 48; - if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { - return; - } - - /* if found, just before is two byte table length */ - ptr -= sizeof(uint16_t); - tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); - - if (tot_len <= 0) { - return; - } - - ovmf_table = g_malloc(tot_len); - ovmf_table_len = tot_len; - - /* - * ptr is the foot of the table, so copy it all to the newly - * allocated ovmf_table and then set the ovmf_table pointer - * to the table foot - */ - memcpy(ovmf_table, ptr - tot_len, tot_len); - ovmf_table += tot_len; -} - -bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, - int *data_len) -{ - uint8_t *ptr = ovmf_table; - int tot_len = ovmf_table_len; - QemuUUID entry_guid; - - if (qemu_uuid_parse(entry, &entry_guid) < 0) { - return false; - } - - if (!ptr) { - return false; - } - - entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ - while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { - int len; - QemuUUID *guid; - - /* - * The data structure is - * arbitrary length data - * 2 byte length of entire entry - * 16 byte guid - */ - guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); - len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - - sizeof(uint16_t))); - - /* - * just in case the table is corrupt, wouldn't want to spin in - * the zero case - */ - if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { - return false; - } else if (len > tot_len) { - return false; - } - - ptr -= len; - tot_len -= len; - if (qemu_uuid_is_equal(guid, &entry_guid)) { - if (data) { - *data = ptr; - } - if (data_len) { - *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); - } - return true; - } - } - return false; -} - /* * Map the pcms->flash[] from 4GiB downward, and realize. * Map them in descending order, i.e. pcms->flash[0] at the top, diff --git a/hw/i386/pc_sysfw_ovmf-stubs.c b/hw/i386/pc_sysfw_ovmf-stubs.c new file mode 100644 index 0000000000..aabe78b271 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf-stubs.c @@ -0,0 +1,26 @@ +/* + * QEMU PC System Firmware (OVMF stubs) + * + * Copyright (c) 2021 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé <philmd@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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 "hw/i386/pc.h" + +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len) +{ + g_assert_not_reached(); +} + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + g_assert_not_reached(); +} diff --git a/hw/i386/pc_sysfw_ovmf.c b/hw/i386/pc_sysfw_ovmf.c new file mode 100644 index 0000000000..f4dd92c588 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf.c @@ -0,0 +1,151 @@ +/* + * QEMU PC System Firmware (OVMF specific) + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2011-2012 Intel Corporation + * + * 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 "hw/i386/pc.h" +#include "cpu.h" + +#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" + +static bool ovmf_flash_parsed; +static uint8_t *ovmf_table; +static int ovmf_table_len; + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + uint8_t *ptr; + QemuUUID guid; + int tot_len; + + /* should only be called once */ + if (ovmf_flash_parsed) { + return; + } + + ovmf_flash_parsed = true; + + if (flash_size < TARGET_PAGE_SIZE) { + return; + } + + /* + * if this is OVMF there will be a table footer + * guid 48 bytes before the end of the flash file. If it's + * not found, silently abort the flash parsing. + */ + qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); + guid = qemu_uuid_bswap(guid); /* guids are LE */ + ptr = flash_ptr + flash_size - 48; + if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { + return; + } + + /* if found, just before is two byte table length */ + ptr -= sizeof(uint16_t); + tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); + + if (tot_len <= 0) { + return; + } + + ovmf_table = g_malloc(tot_len); + ovmf_table_len = tot_len; + + /* + * ptr is the foot of the table, so copy it all to the newly + * allocated ovmf_table and then set the ovmf_table pointer + * to the table foot + */ + memcpy(ovmf_table, ptr - tot_len, tot_len); + ovmf_table += tot_len; +} + +/** + * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's + * reset vector GUIDed table. + * + * @entry: GUID string of the entry to lookup + * @data: Filled with a pointer to the entry's value (if not NULL) + * @data_len: Filled with the length of the entry's value (if not NULL). Pass + * NULL here if the length of data is known. + * + * Return: true if the entry was found in the OVMF table; false otherwise. + */ +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, + int *data_len) +{ + uint8_t *ptr = ovmf_table; + int tot_len = ovmf_table_len; + QemuUUID entry_guid; + + assert(ovmf_flash_parsed); + + if (qemu_uuid_parse(entry, &entry_guid) < 0) { + return false; + } + + if (!ptr) { + return false; + } + + entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ + while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { + int len; + QemuUUID *guid; + + /* + * The data structure is + * arbitrary length data + * 2 byte length of entire entry + * 16 byte guid + */ + guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); + len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - + sizeof(uint16_t))); + + /* + * just in case the table is corrupt, wouldn't want to spin in + * the zero case + */ + if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { + return false; + } else if (len > tot_len) { + return false; + } + + ptr -= len; + tot_len -= len; + if (qemu_uuid_is_equal(guid, &entry_guid)) { + if (data) { + *data = ptr; + } + if (data_len) { + *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); + } + return true; + } + } + return false; +} diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 87294f2632..0775f945d7 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -188,6 +188,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms); void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory); bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len); +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size); /* acpi-build.c */ diff --git a/include/qemu/plugin-memory.h b/include/qemu/plugin-memory.h index b36def27d7..0f59226727 100644 --- a/include/qemu/plugin-memory.h +++ b/include/qemu/plugin-memory.h @@ -18,7 +18,7 @@ struct qemu_plugin_hwaddr { hwaddr offset; } io; struct { - uint64_t hostaddr; + void *hostaddr; } ram; } v; }; diff --git a/meson.build b/meson.build index 073269c59f..6e4d2d8034 100644 --- a/meson.build +++ b/meson.build @@ -92,7 +92,11 @@ if cpu in ['x86', 'x86_64'] } endif -modular_tcg = ['i386-softmmu', 'x86_64-softmmu'] +modular_tcg = [] +# Darwin does not support references to thread-local variables in modules +if targetos != 'darwin' + modular_tcg = ['i386-softmmu', 'x86_64-softmmu'] +endif edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ] install_edk2_blobs = false @@ -451,7 +455,10 @@ endif rt = cc.find_library('rt', required: false) libdl = not_found if 'CONFIG_PLUGIN' in config_host - libdl = cc.find_library('dl', required: true) + libdl = cc.find_library('dl', required: false) + if not cc.has_function('dlopen', dependencies: libdl) + error('dlopen not found') + endif endif libiscsi = not_found if not get_option('libiscsi').auto() or have_block @@ -1681,6 +1688,19 @@ if capstone_opt in ['enabled', 'auto', 'system'] kwargs: static_kwargs, method: 'pkg-config', required: capstone_opt == 'system' or capstone_opt == 'enabled' and not have_internal) + + # Some versions of capstone have broken pkg-config file + # that reports a wrong -I path, causing the #include to + # fail later. If the system has such a broken version + # do not use it. + if capstone.found() and not cc.compiles('#include <capstone.h>', + dependencies: [capstone]) + capstone = not_found + if capstone_opt == 'system' + error('system capstone requested, it does not appear to work') + endif + endif + if capstone.found() capstone_opt = 'system' elif have_internal @@ -2844,7 +2864,6 @@ 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 += {'plugin support': config_host.has_key('CONFIG_PLUGIN')} summary_info += {'fuzzing support': config_host.has_key('CONFIG_FUZZ')} if have_system summary_info += {'Audio drivers': config_host['CONFIG_AUDIO_DRIVERS']} @@ -2960,6 +2979,7 @@ if config_all.has_key('CONFIG_TCG') else summary_info += {'TCG backend': 'native (@0@)'.format(cpu)} endif + summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')} summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')} endif summary_info += {'target list': ' '.join(target_dirs)} diff --git a/plugins/api.c b/plugins/api.c index 332e2c60e2..78b563c5c5 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -308,11 +308,11 @@ uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) if (!haddr->is_io) { RAMBlock *block; ram_addr_t offset; - void *hostaddr = (void *) haddr->v.ram.hostaddr; + void *hostaddr = haddr->v.ram.hostaddr; block = qemu_ram_block_from_host(hostaddr, false, &offset); if (!block) { - error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr); + error_report("Bad host ram pointer %p", haddr->v.ram.hostaddr); abort(); } diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols index 4bdb381f48..40b4ff3821 100644 --- a/plugins/qemu-plugins.symbols +++ b/plugins/qemu-plugins.symbols @@ -8,9 +8,7 @@ qemu_plugin_register_vcpu_insn_exec_cb; qemu_plugin_register_vcpu_insn_exec_inline; qemu_plugin_register_vcpu_mem_cb; - qemu_plugin_register_vcpu_mem_haddr_cb; qemu_plugin_register_vcpu_mem_inline; - qemu_plugin_ram_addr_from_host; qemu_plugin_register_vcpu_tb_trans_cb; qemu_plugin_register_vcpu_tb_exec_cb; qemu_plugin_register_vcpu_tb_exec_inline; @@ -32,7 +30,6 @@ qemu_plugin_mem_is_store; qemu_plugin_get_hwaddr; qemu_plugin_hwaddr_is_io; - qemu_plugin_hwaddr_to_raddr; qemu_plugin_vcpu_for_each; qemu_plugin_n_vcpus; qemu_plugin_n_max_vcpus; diff --git a/python/Makefile b/python/Makefile index ac46ae33e7..fe27a3e12e 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,4 +1,5 @@ QEMU_VENV_DIR=.dev-venv +QEMU_TOX_EXTRA_ARGS ?= .PHONY: help help: @@ -15,6 +16,8 @@ help: @echo " These tests use the newest dependencies." @echo " Requires: Python 3.6 - 3.10, and tox." @echo " Hint (Fedora): 'sudo dnf install python3-tox python3.10'" + @echo " The variable QEMU_TOX_EXTRA_ARGS can be use to pass extra" + @echo " arguments to tox". @echo "" @echo "make check-dev:" @echo " Run tests in a venv against your default python3 version." @@ -87,7 +90,7 @@ check: .PHONY: check-tox check-tox: - @tox + @tox $(QEMU_TOX_EXTRA_ARGS) .PHONY: clean clean: diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index d47ab3d896..971ed7e8c6 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -96,7 +96,8 @@ class QEMUMachine: socket_scm_helper: Optional[str] = None, sock_dir: Optional[str] = None, drain_console: bool = False, - console_log: Optional[str] = None): + console_log: Optional[str] = None, + log_dir: Optional[str] = None): ''' Initialize a QEMUMachine @@ -110,6 +111,7 @@ class QEMUMachine: @param sock_dir: where to create socket (defaults to base_temp_dir) @param drain_console: (optional) True to drain console socket to buffer @param console_log: (optional) path to console log file + @param log_dir: where to create and keep log files @note: Qemu process is not started until launch() is used. ''' # pylint: disable=too-many-arguments @@ -123,6 +125,7 @@ class QEMUMachine: self._name = name or "qemu-%d" % os.getpid() self._base_temp_dir = base_temp_dir self._sock_dir = sock_dir or self._base_temp_dir + self._log_dir = log_dir self._socket_scm_helper = socket_scm_helper if monitor_address is not None: @@ -313,9 +316,12 @@ class QEMUMachine: args.extend(['-device', device]) return args - def _pre_launch(self) -> None: - self._qemu_log_path = os.path.join(self.temp_dir, self._name + ".log") + @property + def args(self) -> List[str]: + """Returns the list of arguments given to the QEMU binary.""" + return self._args + def _pre_launch(self) -> None: if self._console_set: self._remove_files.append(self._console_address) @@ -332,6 +338,7 @@ class QEMUMachine: # NOTE: Make sure any opened resources are *definitely* freed in # _post_shutdown()! # pylint: disable=consider-using-with + self._qemu_log_path = os.path.join(self.log_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') def _post_launch(self) -> None: @@ -770,3 +777,12 @@ class QEMUMachine: self._temp_dir = tempfile.mkdtemp(prefix="qemu-machine-", dir=self._base_temp_dir) return self._temp_dir + + @property + def log_dir(self) -> str: + """ + Returns a directory to be used for writing logs + """ + if self._log_dir is None: + return self.temp_dir + return self._log_dir diff --git a/python/setup.cfg b/python/setup.cfg index 11f71d5312..14bab90288 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -121,6 +121,7 @@ multi_line_output=3 [tox:tox] envlist = py36, py37, py38, py39, py310 +skip_missing_interpreters = true [testenv] allowlist_externals = make diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 27baf17d6c..a099acb34d 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2166,9 +2166,10 @@ typedef struct _ga_win_10_0_server_t { char const *version_id; } ga_win_10_0_server_t; -static ga_win_10_0_server_t const WIN_10_0_SERVER_VERSION_MATRIX[3] = { +static ga_win_10_0_server_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = { {14393, "Microsoft Windows Server 2016", "2016"}, {17763, "Microsoft Windows Server 2019", "2019"}, + {20344, "Microsoft Windows Server 2022", "2022"}, {0, 0} }; diff --git a/scripts/ci/setup/.gitignore b/scripts/ci/setup/.gitignore new file mode 100644 index 0000000000..f4a6183f1f --- /dev/null +++ b/scripts/ci/setup/.gitignore @@ -0,0 +1,2 @@ +inventory +vars.yml diff --git a/scripts/ci/setup/build-environment.yml b/scripts/ci/setup/build-environment.yml new file mode 100644 index 0000000000..581c1c75d1 --- /dev/null +++ b/scripts/ci/setup/build-environment.yml @@ -0,0 +1,116 @@ +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa <crosa@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +# +# This is an ansible playbook file. Run it to set up systems with the +# environment needed to build QEMU. +--- +- name: Installation of basic packages to build QEMU + hosts: all + tasks: + - name: Check for suitable ansible version + delegate_to: localhost + assert: + that: + - '((ansible_version.major == 2) and (ansible_version.minor >= 8)) or (ansible_version.major >= 3)' + msg: "Unsuitable ansible version, please use version 2.8.0 or later" + + - name: Update apt cache / upgrade packages via apt + apt: + update_cache: yes + upgrade: yes + when: + - ansible_facts['distribution'] == 'Ubuntu' + + - name: Install basic packages to build QEMU on Ubuntu 18.04/20.04 + package: + name: + # Originally from tests/docker/dockerfiles/ubuntu1804.docker + - ccache + - gcc + - gettext + - git + - glusterfs-common + - libaio-dev + - libattr1-dev + - libbrlapi-dev + - libbz2-dev + - libcacard-dev + - libcap-ng-dev + - libcurl4-gnutls-dev + - libdrm-dev + - libepoxy-dev + - libfdt-dev + - libgbm-dev + - libgtk-3-dev + - libibverbs-dev + - libiscsi-dev + - libjemalloc-dev + - libjpeg-turbo8-dev + - liblzo2-dev + - libncurses5-dev + - libncursesw5-dev + - libnfs-dev + - libnss3-dev + - libnuma-dev + - libpixman-1-dev + - librados-dev + - librbd-dev + - librdmacm-dev + - libsasl2-dev + - libsdl2-dev + - libseccomp-dev + - libsnappy-dev + - libspice-protocol-dev + - libssh-dev + - libusb-1.0-0-dev + - libusbredirhost-dev + - libvdeplug-dev + - libvte-2.91-dev + - libzstd-dev + - make + - python3-yaml + - python3-sphinx + - python3-sphinx-rtd-theme + - ninja-build + - sparse + - xfslibs-dev + state: present + when: + - ansible_facts['distribution'] == 'Ubuntu' + + - name: Install packages to build QEMU on Ubuntu 18.04/20.04 on non-s390x + package: + name: + - libspice-server-dev + - libxen-dev + state: present + when: + - ansible_facts['distribution'] == 'Ubuntu' + - ansible_facts['architecture'] != 's390x' + + - name: Install basic packages to build QEMU on Ubuntu 18.04 + package: + name: + # Originally from tests/docker/dockerfiles/ubuntu1804.docker + - clang + when: + - ansible_facts['distribution'] == 'Ubuntu' + - ansible_facts['distribution_version'] == '18.04' + + - name: Install basic packages to build QEMU on Ubuntu 20.04 + package: + name: + # Originally from tests/docker/dockerfiles/ubuntu2004.docker + - clang-10 + - genisoimage + - liblttng-ust-dev + - libslirp-dev + - netcat-openbsd + when: + - ansible_facts['distribution'] == 'Ubuntu' + - ansible_facts['distribution_version'] == '20.04' diff --git a/scripts/ci/setup/gitlab-runner.yml b/scripts/ci/setup/gitlab-runner.yml new file mode 100644 index 0000000000..1127db516f --- /dev/null +++ b/scripts/ci/setup/gitlab-runner.yml @@ -0,0 +1,71 @@ +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa <crosa@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +# +# This is an ansible playbook file. Run it to set up systems with the +# gitlab-runner agent. +--- +- name: Installation of gitlab-runner + hosts: all + vars_files: + - vars.yml + tasks: + - debug: + msg: 'Checking for a valid GitLab registration token' + failed_when: "gitlab_runner_registration_token == 'PLEASE_PROVIDE_A_VALID_TOKEN'" + + - name: Create a group for the gitlab-runner service + group: + name: gitlab-runner + + - name: Create a user for the gitlab-runner service + user: + user: gitlab-runner + group: gitlab-runner + comment: GitLab Runner + home: /home/gitlab-runner + shell: /bin/bash + + - name: Remove the .bash_logout file when on Ubuntu systems + file: + path: /home/gitlab-runner/.bash_logout + state: absent + when: "ansible_facts['distribution'] == 'Ubuntu'" + + - name: Set the Operating System for gitlab-runner + set_fact: + gitlab_runner_os: "{{ ansible_facts[\"system\"]|lower }}" + - debug: + msg: gitlab-runner OS is {{ gitlab_runner_os }} + + - name: Set the architecture for gitlab-runner + set_fact: + gitlab_runner_arch: "{{ ansible_to_gitlab_arch[ansible_facts[\"architecture\"]] }}" + - debug: + msg: gitlab-runner arch is {{ gitlab_runner_arch }} + + - name: Download the matching gitlab-runner + get_url: + dest: /usr/local/bin/gitlab-runner + url: "https://s3.amazonaws.com/gitlab-runner-downloads/v{{ gitlab_runner_version }}/binaries/gitlab-runner-{{ gitlab_runner_os }}-{{ gitlab_runner_arch }}" + owner: gitlab-runner + group: gitlab-runner + mode: u=rwx,g=rwx,o=rx + + - name: Register the gitlab-runner + command: "/usr/local/bin/gitlab-runner register --non-interactive --url {{ gitlab_runner_server_url }} --registration-token {{ gitlab_runner_registration_token }} --executor shell --tag-list {{ ansible_facts[\"architecture\"] }},{{ ansible_facts[\"distribution\"]|lower }}_{{ ansible_facts[\"distribution_version\"] }} --description '{{ ansible_facts[\"distribution\"] }} {{ ansible_facts[\"distribution_version\"] }} {{ ansible_facts[\"architecture\"] }} ({{ ansible_facts[\"os_family\"] }})'" + + - name: Install the gitlab-runner service using its own functionality + command: /usr/local/bin/gitlab-runner install --user gitlab-runner --working-directory /home/gitlab-runner + register: gitlab_runner_install_service_result + failed_when: "gitlab_runner_install_service_result.rc != 0 and \"already exists\" not in gitlab_runner_install_service_result.stderr" + + - name: Enable the gitlab-runner service + service: + name: gitlab-runner + state: started + enabled: yes diff --git a/scripts/ci/setup/inventory.template b/scripts/ci/setup/inventory.template new file mode 100644 index 0000000000..2fbb50c4a8 --- /dev/null +++ b/scripts/ci/setup/inventory.template @@ -0,0 +1 @@ +localhost diff --git a/scripts/ci/setup/vars.yml.template b/scripts/ci/setup/vars.yml.template new file mode 100644 index 0000000000..e48089761f --- /dev/null +++ b/scripts/ci/setup/vars.yml.template @@ -0,0 +1,12 @@ +# The version of the gitlab-runner to use +gitlab_runner_version: 13.12.0 +# The URL of the gitlab server to use, usually https://gitlab.com unless you're +# using a private GitLab instance +gitlab_runner_server_url: https://gitlab.com +# A mapping of the ansible to gitlab architecture nomenclature +ansible_to_gitlab_arch: + x86_64: amd64 + aarch64: arm64 + s390x: s390x +# A unique token made available by GitLab to your project for registering runners +gitlab_runner_registration_token: PLEASE_PROVIDE_A_VALID_TOKEN diff --git a/scripts/coverity-scan/coverity-scan.docker b/scripts/coverity-scan/coverity-scan.docker index 501ac67233..ecff6ac5b4 100644 --- a/scripts/coverity-scan/coverity-scan.docker +++ b/scripts/coverity-scan/coverity-scan.docker @@ -93,7 +93,6 @@ ENV PACKAGES \ mingw64-SDL2 \ ncurses-devel \ nettle-devel \ - nss-devel \ numactl-devel \ perl \ perl-Test-Harness \ diff --git a/stubs/meson.build b/stubs/meson.build index 2e79ff9f4d..d3fa8646b3 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -15,7 +15,9 @@ stub_ss.add(files('fdset.c')) stub_ss.add(files('fw_cfg.c')) stub_ss.add(files('gdbstub.c')) stub_ss.add(files('get-vm-name.c')) -stub_ss.add(when: 'CONFIG_LINUX_IO_URING', if_true: files('io_uring.c')) +if linux_io_uring.found() + stub_ss.add(files('io_uring.c')) +endif stub_ss.add(files('iothread-lock.c')) stub_ss.add(files('isa-bus.c')) stub_ss.add(files('is-daemonized.c')) diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 833d3baa7b..103c6326a2 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -66,8 +66,6 @@ struct DisasContext { /* Temporaries for $31 and $f31 as source and destination. */ TCGv zero; TCGv sink; - /* Temporary for immediate constants. */ - TCGv lit; }; /* Target-specific return values from translate_one, indicating the @@ -157,7 +155,7 @@ void alpha_translate_init(void) static TCGv load_zero(DisasContext *ctx) { if (!ctx->zero) { - ctx->zero = tcg_const_i64(0); + ctx->zero = tcg_constant_i64(0); } return ctx->zero; } @@ -177,14 +175,6 @@ static void free_context_temps(DisasContext *ctx) tcg_temp_free(ctx->sink); ctx->sink = NULL; } - if (ctx->zero) { - tcg_temp_free(ctx->zero); - ctx->zero = NULL; - } - if (ctx->lit) { - tcg_temp_free(ctx->lit); - ctx->lit = NULL; - } } static TCGv load_gpr(DisasContext *ctx, unsigned reg) @@ -200,8 +190,7 @@ static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg, uint8_t lit, bool islit) { if (islit) { - ctx->lit = tcg_const_i64(lit); - return ctx->lit; + return tcg_constant_i64(lit); } else if (likely(reg < 31)) { return ctx->ir[reg]; } else { @@ -261,11 +250,9 @@ static void gen_excp_1(int exception, int error_code) { TCGv_i32 tmp1, tmp2; - tmp1 = tcg_const_i32(exception); - tmp2 = tcg_const_i32(error_code); + tmp1 = tcg_constant_i32(exception); + tmp2 = tcg_constant_i32(error_code); gen_helper_excp(cpu_env, tmp1, tmp2); - tcg_temp_free_i32(tmp2); - tcg_temp_free_i32(tmp1); } static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code) @@ -485,15 +472,11 @@ static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, return DISAS_NORETURN; } else { - TCGv_i64 z = tcg_const_i64(0); - TCGv_i64 d = tcg_const_i64(dest); - TCGv_i64 p = tcg_const_i64(ctx->base.pc_next); + TCGv_i64 z = load_zero(ctx); + TCGv_i64 d = tcg_constant_i64(dest); + TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next); tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p); - - tcg_temp_free_i64(z); - tcg_temp_free_i64(d); - tcg_temp_free_i64(p); return DISAS_PC_UPDATED; } } @@ -695,22 +678,19 @@ static void gen_fp_exc_raise(int rc, int fn11) if (!(fn11 & QUAL_I)) { ignore |= FPCR_INE; } - ign = tcg_const_i32(ignore); + ign = tcg_constant_i32(ignore); /* ??? Pass in the regno of the destination so that the helper can set EXC_MASK, which contains a bitmask of destination registers that have caused arithmetic traps. A simple userspace emulation does not require this. We do need it for a guest kernel's entArith, or if we were to do something clever with imprecise exceptions. */ - reg = tcg_const_i32(rc + 32); + reg = tcg_constant_i32(rc + 32); if (fn11 & QUAL_S) { gen_helper_fp_exc_raise_s(cpu_env, ign, reg); } else { gen_helper_fp_exc_raise(cpu_env, ign, reg); } - - tcg_temp_free_i32(reg); - tcg_temp_free_i32(ign); } static void gen_cvtlq(TCGv vc, TCGv vb) @@ -803,7 +783,7 @@ IEEE_INTCVT(cvtqt) static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask) { - TCGv vmask = tcg_const_i64(mask); + TCGv vmask = tcg_constant_i64(mask); TCGv tmp = tcg_temp_new_i64(); if (inv_a) { @@ -815,7 +795,6 @@ static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask) tcg_gen_andc_i64(vc, vb, vmask); tcg_gen_or_i64(vc, vc, tmp); - tcg_temp_free(vmask); tcg_temp_free(tmp); } @@ -1084,15 +1063,11 @@ static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, static void gen_rx(DisasContext *ctx, int ra, int set) { - TCGv tmp; - if (ra != 31) { ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT); } - tmp = tcg_const_i64(set); - st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT); - tcg_temp_free(tmp); + st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT); } static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) @@ -1193,12 +1168,9 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) case 0x3E: /* WTINT */ - { - TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); - } + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + -offsetof(AlphaCPU, env) + + offsetof(CPUState, halted)); tcg_gen_movi_i64(ctx->ir[IR_V0], 0); return gen_excp(ctx, EXCP_HALTED, 0); @@ -1349,12 +1321,8 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno) case 253: /* WAIT */ - { - TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); - } + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + -offsetof(AlphaCPU, env) + offsetof(CPUState, halted)); return gen_excp(ctx, EXCP_HALTED, 0); case 252: @@ -2721,15 +2689,14 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return address from EXC_ADDR. This turns out to be useful for our emulation PALcode, so continue to accept it. */ - ctx->lit = vb = tcg_temp_new(); + vb = dest_sink(ctx); tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr)); } else { vb = load_gpr(ctx, rb); } tcg_gen_movi_i64(cpu_lock_addr, -1); + st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT); tmp = tcg_temp_new(); - tcg_gen_movi_i64(tmp, 0); - st_flag_byte(tmp, ENV_FLAG_RX_SHIFT); tcg_gen_andi_i64(tmp, vb, 1); st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT); tcg_temp_free(tmp); @@ -2996,7 +2963,6 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) ctx->zero = NULL; ctx->sink = NULL; - ctx->lit = NULL; /* Bound the number of insns to execute to those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 835120c038..2552747138 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -144,6 +144,7 @@ #define tcg_gen_sextract_reg tcg_gen_sextract_i64 #define tcg_const_reg tcg_const_i64 #define tcg_const_local_reg tcg_const_local_i64 +#define tcg_constant_reg tcg_constant_i64 #define tcg_gen_movcond_reg tcg_gen_movcond_i64 #define tcg_gen_add2_reg tcg_gen_add2_i64 #define tcg_gen_sub2_reg tcg_gen_sub2_i64 @@ -238,6 +239,7 @@ #define tcg_gen_sextract_reg tcg_gen_sextract_i32 #define tcg_const_reg tcg_const_i32 #define tcg_const_local_reg tcg_const_local_i32 +#define tcg_constant_reg tcg_constant_i32 #define tcg_gen_movcond_reg tcg_gen_movcond_i32 #define tcg_gen_add2_reg tcg_gen_add2_i32 #define tcg_gen_sub2_reg tcg_gen_sub2_i32 @@ -250,8 +252,6 @@ typedef struct DisasCond { TCGCond c; TCGv_reg a0, a1; - bool a0_is_n; - bool a1_is_0; } DisasCond; typedef struct DisasContext { @@ -446,9 +446,7 @@ static DisasCond cond_make_n(void) return (DisasCond){ .c = TCG_COND_NE, .a0 = cpu_psw_n, - .a0_is_n = true, - .a1 = NULL, - .a1_is_0 = true + .a1 = tcg_constant_reg(0) }; } @@ -456,7 +454,7 @@ static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0) { assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); return (DisasCond){ - .c = c, .a0 = a0, .a1_is_0 = true + .c = c, .a0 = a0, .a1 = tcg_constant_reg(0) }; } @@ -480,26 +478,14 @@ static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1) return r; } -static void cond_prep(DisasCond *cond) -{ - if (cond->a1_is_0) { - cond->a1_is_0 = false; - cond->a1 = tcg_const_reg(0); - } -} - static void cond_free(DisasCond *cond) { switch (cond->c) { default: - if (!cond->a0_is_n) { + if (cond->a0 != cpu_psw_n) { tcg_temp_free(cond->a0); } - if (!cond->a1_is_0) { - tcg_temp_free(cond->a1); - } - cond->a0_is_n = false; - cond->a1_is_0 = false; + tcg_temp_free(cond->a1); cond->a0 = NULL; cond->a1 = NULL; /* fallthru */ @@ -557,9 +543,8 @@ static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg) static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t) { if (ctx->null_cond.c != TCG_COND_NEVER) { - cond_prep(&ctx->null_cond); tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0, - ctx->null_cond.a1, dest, t); + ctx->null_cond.a1, dest, t); } else { tcg_gen_mov_reg(dest, t); } @@ -666,11 +651,9 @@ static void nullify_over(DisasContext *ctx) assert(ctx->null_cond.c != TCG_COND_ALWAYS); ctx->null_lab = gen_new_label(); - cond_prep(&ctx->null_cond); /* If we're using PSW[N], copy it to a temp because... */ - if (ctx->null_cond.a0_is_n) { - ctx->null_cond.a0_is_n = false; + if (ctx->null_cond.a0 == cpu_psw_n) { ctx->null_cond.a0 = tcg_temp_new(); tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n); } @@ -683,7 +666,7 @@ static void nullify_over(DisasContext *ctx) } tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0, - ctx->null_cond.a1, ctx->null_lab); + ctx->null_cond.a1, ctx->null_lab); cond_free(&ctx->null_cond); } } @@ -697,10 +680,9 @@ static void nullify_save(DisasContext *ctx) } return; } - if (!ctx->null_cond.a0_is_n) { - cond_prep(&ctx->null_cond); + if (ctx->null_cond.a0 != cpu_psw_n) { tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n, - ctx->null_cond.a0, ctx->null_cond.a1); + ctx->null_cond.a0, ctx->null_cond.a1); ctx->psw_n_nonzero = true; } cond_free(&ctx->null_cond); @@ -771,9 +753,7 @@ static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp) static void gen_excp_1(int exception) { - TCGv_i32 t = tcg_const_i32(exception); - gen_helper_excp(cpu_env, t); - tcg_temp_free_i32(t); + gen_helper_excp(cpu_env, tcg_constant_i32(exception)); } static void gen_excp(DisasContext *ctx, int exception) @@ -787,12 +767,9 @@ static void gen_excp(DisasContext *ctx, int exception) static bool gen_excp_iir(DisasContext *ctx, int exc) { - TCGv_reg tmp; - nullify_over(ctx); - tmp = tcg_const_reg(ctx->insn); - tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR])); - tcg_temp_free(tmp); + tcg_gen_st_reg(tcg_constant_reg(ctx->insn), + cpu_env, offsetof(CPUHPPAState, cr[CR_IIR])); gen_excp(ctx, exc); return nullify_end(ctx); } @@ -1150,13 +1127,12 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, } if (!is_l || cond_need_cb(c)) { - TCGv_reg zero = tcg_const_reg(0); + TCGv_reg zero = tcg_constant_reg(0); cb_msb = get_temp(ctx); tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero); if (is_c) { tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero); } - tcg_temp_free(zero); if (!is_l) { cb = get_temp(ctx); tcg_gen_xor_reg(cb, in1, in2); @@ -1182,7 +1158,6 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, /* Emit any conditional trap before any writeback. */ cond = do_cond(cf, dest, cb_msb, sv); if (is_tc) { - cond_prep(&cond); tmp = tcg_temp_new(); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); @@ -1242,7 +1217,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, cb = tcg_temp_new(); cb_msb = tcg_temp_new(); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); if (is_b) { /* DEST,C = IN1 + ~IN2 + C. */ tcg_gen_not_reg(cb, in2); @@ -1258,7 +1233,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, tcg_gen_eqv_reg(cb, in1, in2); tcg_gen_xor_reg(cb, cb, dest); } - tcg_temp_free(zero); /* Compute signed overflow if required. */ sv = NULL; @@ -1278,7 +1252,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, /* Emit any conditional trap before any writeback. */ if (is_tc) { - cond_prep(&cond); tmp = tcg_temp_new(); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); @@ -1404,7 +1377,6 @@ static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, if (is_tc) { TCGv_reg tmp = tcg_temp_new(); - cond_prep(&cond); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); tcg_temp_free(tmp); @@ -1860,7 +1832,6 @@ static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n, } taken = gen_new_label(); - cond_prep(cond); tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken); cond_free(cond); @@ -1957,7 +1928,6 @@ static bool do_ibranch(DisasContext *ctx, TCGv_reg dest, tcg_gen_lookup_and_goto_ptr(); return nullify_end(ctx); } else { - cond_prep(&ctx->null_cond); c = ctx->null_cond.c; a0 = ctx->null_cond.a0; a1 = ctx->null_cond.a1; @@ -2449,17 +2419,16 @@ static bool trans_probe(DisasContext *ctx, arg_probe *a) form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false); if (a->imm) { - level = tcg_const_i32(a->ri); + level = tcg_constant_i32(a->ri); } else { level = tcg_temp_new_i32(); tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri)); tcg_gen_andi_i32(level, level, 3); } - want = tcg_const_i32(a->write ? PAGE_WRITE : PAGE_READ); + want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ); gen_helper_probe(dest, cpu_env, addr, level, want); - tcg_temp_free_i32(want); tcg_temp_free_i32(level); save_gpr(ctx, a->t, dest); @@ -2599,17 +2568,13 @@ static bool trans_lpa(DisasContext *ctx, arg_ldst *a) static bool trans_lci(DisasContext *ctx, arg_lci *a) { - TCGv_reg ci; - CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); /* The Coherence Index is an implementation-defined function of the physical address. Two addresses with the same CI have a coherent view of the cache. Our implementation is to return 0 for all, since the entire address space is coherent. */ - ci = tcg_const_reg(0); - save_gpr(ctx, a->t, ci); - tcg_temp_free(ci); + save_gpr(ctx, a->t, tcg_constant_reg(0)); cond_free(&ctx->null_cond); return true; @@ -2710,8 +2675,6 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a) * currently implemented as idle. */ if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */ - TCGv_i32 tmp; - /* No need to check for supervisor, as userland can only pause until the next timer interrupt. */ nullify_over(ctx); @@ -2722,10 +2685,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a) nullify_set(ctx, 0); /* Tell the qemu main loop to halt until this cpu has work. */ - tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + offsetof(CPUState, halted) - offsetof(HPPACPU, env)); gen_excp_1(EXCP_HALTED); ctx->base.is_jmp = DISAS_NORETURN; @@ -2833,7 +2794,7 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a) add2 = tcg_temp_new(); addc = tcg_temp_new(); dest = tcg_temp_new(); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); /* Form R1 << 1 | PSW[CB]{8}. */ tcg_gen_add_reg(add1, in1, in1); @@ -2851,7 +2812,6 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a) tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero); tcg_temp_free(addc); - tcg_temp_free(zero); /* Write back the result register. */ save_gpr(ctx, a->t, dest); @@ -2967,9 +2927,8 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a) */ gen_helper_ldc_check(addr); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop); - tcg_temp_free(zero); if (a->m) { save_gpr(ctx, a->b, ofs); @@ -3882,15 +3841,13 @@ static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a) ta = load_frw0_i32(a->r1); tb = load_frw0_i32(a->r2); - ty = tcg_const_i32(a->y); - tc = tcg_const_i32(a->c); + ty = tcg_constant_i32(a->y); + tc = tcg_constant_i32(a->c); gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc); tcg_temp_free_i32(ta); tcg_temp_free_i32(tb); - tcg_temp_free_i32(ty); - tcg_temp_free_i32(tc); return nullify_end(ctx); } @@ -3904,15 +3861,13 @@ static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a) ta = load_frd0(a->r1); tb = load_frd0(a->r2); - ty = tcg_const_i32(a->y); - tc = tcg_const_i32(a->c); + ty = tcg_constant_i32(a->y); + tc = tcg_constant_i32(a->c); gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc); tcg_temp_free_i64(ta); tcg_temp_free_i64(tb); - tcg_temp_free_i32(ty); - tcg_temp_free_i32(tc); return nullify_end(ctx); } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 950a991a71..5d98a4e7c0 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1437,6 +1437,8 @@ typedef struct CPUX86State { FPReg fpregs[8]; /* KVM-only so far */ uint16_t fpop; + uint16_t fpcs; + uint16_t fpds; uint64_t fpip; uint64_t fpdp; diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index 74bbe94b80..cdd8e9f947 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -727,10 +727,14 @@ void helper_fwait(CPUX86State *env) } } -void helper_fninit(CPUX86State *env) +static void do_fninit(CPUX86State *env) { env->fpus = 0; env->fpstt = 0; + env->fpcs = 0; + env->fpds = 0; + env->fpip = 0; + env->fpdp = 0; cpu_set_fpuc(env, 0x37f); env->fptags[0] = 1; env->fptags[1] = 1; @@ -742,6 +746,11 @@ void helper_fninit(CPUX86State *env) env->fptags[7] = 1; } +void helper_fninit(CPUX86State *env) +{ + do_fninit(env); +} + /* BCD ops */ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) @@ -2373,19 +2382,19 @@ static void do_fstenv(CPUX86State *env, target_ulong ptr, int data32, cpu_stl_data_ra(env, ptr, env->fpuc, retaddr); cpu_stl_data_ra(env, ptr + 4, fpus, retaddr); cpu_stl_data_ra(env, ptr + 8, fptag, retaddr); - cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */ - cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */ - cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */ - cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */ + cpu_stl_data_ra(env, ptr + 12, env->fpip, retaddr); /* fpip */ + cpu_stl_data_ra(env, ptr + 16, env->fpcs, retaddr); /* fpcs */ + cpu_stl_data_ra(env, ptr + 20, env->fpdp, retaddr); /* fpoo */ + cpu_stl_data_ra(env, ptr + 24, env->fpds, retaddr); /* fpos */ } else { /* 16 bit */ cpu_stw_data_ra(env, ptr, env->fpuc, retaddr); cpu_stw_data_ra(env, ptr + 2, fpus, retaddr); cpu_stw_data_ra(env, ptr + 4, fptag, retaddr); - cpu_stw_data_ra(env, ptr + 6, 0, retaddr); - cpu_stw_data_ra(env, ptr + 8, 0, retaddr); - cpu_stw_data_ra(env, ptr + 10, 0, retaddr); - cpu_stw_data_ra(env, ptr + 12, 0, retaddr); + cpu_stw_data_ra(env, ptr + 6, env->fpip, retaddr); + cpu_stw_data_ra(env, ptr + 8, env->fpcs, retaddr); + cpu_stw_data_ra(env, ptr + 10, env->fpdp, retaddr); + cpu_stw_data_ra(env, ptr + 12, env->fpds, retaddr); } } @@ -2451,18 +2460,7 @@ static void do_fsave(CPUX86State *env, target_ulong ptr, int data32, ptr += 10; } - /* fninit */ - env->fpus = 0; - env->fpstt = 0; - cpu_set_fpuc(env, 0x37f); - env->fptags[0] = 1; - env->fptags[1] = 1; - env->fptags[2] = 1; - env->fptags[3] = 1; - env->fptags[4] = 1; - env->fptags[5] = 1; - env->fptags[6] = 1; - env->fptags[7] = 1; + do_fninit(env); } void helper_fsave(CPUX86State *env, target_ulong ptr, int data32) @@ -2834,7 +2832,7 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm) if (xstate_bv & XSTATE_FP_MASK) { do_xrstor_fpu(env, ptr, ra); } else { - helper_fninit(env); + do_fninit(env); memset(env->fpregs, 0, sizeof(env->fpregs)); } } diff --git a/target/i386/tcg/sysemu/bpt_helper.c b/target/i386/tcg/sysemu/bpt_helper.c index 624f90b789..4d96a48a3c 100644 --- a/target/i386/tcg/sysemu/bpt_helper.c +++ b/target/i386/tcg/sysemu/bpt_helper.c @@ -109,9 +109,9 @@ static void hw_breakpoint_remove(CPUX86State *env, int index) case DR7_TYPE_DATA_WR: case DR7_TYPE_DATA_RW: - if (env->cpu_breakpoint[index]) { + if (env->cpu_watchpoint[index]) { cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]); - env->cpu_breakpoint[index] = NULL; + env->cpu_watchpoint[index] = NULL; } break; diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 3814ce2a3e..8520d5a1e2 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -5919,503 +5919,555 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /************************/ /* floats */ case 0xd8 ... 0xdf: - if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { - /* if CR0.EM or CR0.TS are set, generate an FPU exception */ - /* XXX: what to do if illegal op ? */ - gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); - break; - } - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = modrm & 7; - op = ((b & 7) << 3) | ((modrm >> 3) & 7); - if (mod != 3) { - /* memory op */ - gen_lea_modrm(env, s, modrm); - switch(op) { - case 0x00 ... 0x07: /* fxxxs */ - case 0x10 ... 0x17: /* fixxxl */ - case 0x20 ... 0x27: /* fxxxl */ - case 0x30 ... 0x37: /* fixxx */ - { - int op1; - op1 = op & 7; + { + bool update_fip = true; + + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { + /* if CR0.EM or CR0.TS are set, generate an FPU exception */ + /* XXX: what to do if illegal op ? */ + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); + break; + } + modrm = x86_ldub_code(env, s); + mod = (modrm >> 6) & 3; + rm = modrm & 7; + op = ((b & 7) << 3) | ((modrm >> 3) & 7); + if (mod != 3) { + /* memory op */ + AddressParts a = gen_lea_modrm_0(env, s, modrm); + TCGv ea = gen_lea_modrm_1(s, a); + TCGv last_addr = tcg_temp_new(); + bool update_fdp = true; + + tcg_gen_mov_tl(last_addr, ea); + gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override); + + switch (op) { + case 0x00 ... 0x07: /* fxxxs */ + case 0x10 ... 0x17: /* fixxxl */ + case 0x20 ... 0x27: /* fxxxl */ + case 0x30 ... 0x37: /* fixxx */ + { + int op1; + op1 = op & 7; + + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_FT0(cpu_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + break; + } - switch(op >> 4) { + gen_helper_fp_arith_ST0_FT0(op1); + if (op1 == 3) { + /* fcomp needs pop */ + gen_helper_fpop(cpu_env); + } + } + break; + case 0x08: /* flds */ + case 0x0a: /* fsts */ + case 0x0b: /* fstps */ + case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ + case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ + case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ + switch (op & 7) { case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_FT0(cpu_env, s->tmp2_i32); + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_ST0(cpu_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + break; + } break; case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); - break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); - gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); + /* XXX: the corresponding CPUID bit must be tested ! */ + switch (op >> 4) { + case 1: + gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + break; + case 3: + default: + gen_helper_fistt_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + gen_helper_fpop(cpu_env); break; - case 3: default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + switch (op >> 4) { + case 0: + gen_helper_fsts_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 1: + gen_helper_fistl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + break; + case 3: + default: + gen_helper_fist_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + if ((op & 7) == 3) { + gen_helper_fpop(cpu_env); + } break; } + break; + case 0x0c: /* fldenv mem */ + gen_helper_fldenv(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0d: /* fldcw mem */ + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + gen_helper_fldcw(cpu_env, s->tmp2_i32); + update_fip = update_fdp = false; + break; + case 0x0e: /* fnstenv mem */ + gen_helper_fstenv(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0f: /* fnstcw mem */ + gen_helper_fnstcw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x1d: /* fldt mem */ + gen_helper_fldt_ST0(cpu_env, s->A0); + break; + case 0x1f: /* fstpt mem */ + gen_helper_fstt_ST0(cpu_env, s->A0); + gen_helper_fpop(cpu_env); + break; + case 0x2c: /* frstor mem */ + gen_helper_frstor(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2e: /* fnsave mem */ + gen_helper_fsave(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2f: /* fnstsw mem */ + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x3c: /* fbld */ + gen_helper_fbld_ST0(cpu_env, s->A0); + break; + case 0x3e: /* fbstp */ + gen_helper_fbst_ST0(cpu_env, s->A0); + gen_helper_fpop(cpu_env); + break; + case 0x3d: /* fildll */ + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); + break; + case 0x3f: /* fistpll */ + gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fpop(cpu_env); + break; + default: + goto unknown_op; + } - gen_helper_fp_arith_ST0_FT0(op1); - if (op1 == 3) { - /* fcomp needs pop */ - gen_helper_fpop(cpu_env); - } + if (update_fdp) { + int last_seg = s->override >= 0 ? s->override : a.def_seg; + + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, + segs[last_seg].selector)); + tcg_gen_st16_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, fpds)); + tcg_gen_st_tl(last_addr, cpu_env, + offsetof(CPUX86State, fpdp)); } - break; - case 0x08: /* flds */ - case 0x0a: /* fsts */ - case 0x0b: /* fstps */ - case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ - case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ - case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ - switch(op & 7) { - case 0: - switch(op >> 4) { - case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_ST0(cpu_env, s->tmp2_i32); + tcg_temp_free(last_addr); + } else { + /* register float ops */ + opreg = rm; + + switch (op) { + case 0x08: /* fld sti */ + gen_helper_fpush(cpu_env); + gen_helper_fmov_ST0_STN(cpu_env, + tcg_const_i32((opreg + 1) & 7)); + break; + case 0x09: /* fxchg sti */ + case 0x29: /* fxchg4 sti, undocumented op */ + case 0x39: /* fxchg7 sti, undocumented op */ + gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg)); + break; + case 0x0a: /* grp d9/2 */ + switch (rm) { + case 0: /* fnop */ + /* check exceptions (FreeBSD FPU probe) */ + gen_helper_fwait(cpu_env); + update_fip = false; break; - case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + default: + goto unknown_op; + } + break; + case 0x0c: /* grp d9/4 */ + switch (rm) { + case 0: /* fchs */ + gen_helper_fchs_ST0(cpu_env); break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); - gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); + case 1: /* fabs */ + gen_helper_fabs_ST0(cpu_env); break; - case 3: - default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + case 4: /* ftst */ + gen_helper_fldz_FT0(cpu_env); + gen_helper_fcom_ST0_FT0(cpu_env); break; + case 5: /* fxam */ + gen_helper_fxam_ST0(cpu_env); + break; + default: + goto unknown_op; } break; - case 1: - /* XXX: the corresponding CPUID bit must be tested ! */ - switch(op >> 4) { - case 1: - gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 0x0d: /* grp d9/5 */ + { + switch (rm) { + case 0: + gen_helper_fpush(cpu_env); + gen_helper_fld1_ST0(cpu_env); + break; + case 1: + gen_helper_fpush(cpu_env); + gen_helper_fldl2t_ST0(cpu_env); + break; + case 2: + gen_helper_fpush(cpu_env); + gen_helper_fldl2e_ST0(cpu_env); + break; + case 3: + gen_helper_fpush(cpu_env); + gen_helper_fldpi_ST0(cpu_env); + break; + case 4: + gen_helper_fpush(cpu_env); + gen_helper_fldlg2_ST0(cpu_env); + break; + case 5: + gen_helper_fpush(cpu_env); + gen_helper_fldln2_ST0(cpu_env); + break; + case 6: + gen_helper_fpush(cpu_env); + gen_helper_fldz_ST0(cpu_env); + break; + default: + goto unknown_op; + } + } + break; + case 0x0e: /* grp d9/6 */ + switch (rm) { + case 0: /* f2xm1 */ + gen_helper_f2xm1(cpu_env); break; - case 2: - gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + case 1: /* fyl2x */ + gen_helper_fyl2x(cpu_env); + break; + case 2: /* fptan */ + gen_helper_fptan(cpu_env); + break; + case 3: /* fpatan */ + gen_helper_fpatan(cpu_env); + break; + case 4: /* fxtract */ + gen_helper_fxtract(cpu_env); + break; + case 5: /* fprem1 */ + gen_helper_fprem1(cpu_env); + break; + case 6: /* fdecstp */ + gen_helper_fdecstp(cpu_env); break; - case 3: default: - gen_helper_fistt_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); + case 7: /* fincstp */ + gen_helper_fincstp(cpu_env); break; } - gen_helper_fpop(cpu_env); break; - default: - switch(op >> 4) { - case 0: - gen_helper_fsts_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 0x0f: /* grp d9/7 */ + switch (rm) { + case 0: /* fprem */ + gen_helper_fprem(cpu_env); break; - case 1: - gen_helper_fistl_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 1: /* fyl2xp1 */ + gen_helper_fyl2xp1(cpu_env); break; - case 2: - gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + case 2: /* fsqrt */ + gen_helper_fsqrt(cpu_env); + break; + case 3: /* fsincos */ + gen_helper_fsincos(cpu_env); + break; + case 5: /* fscale */ + gen_helper_fscale(cpu_env); + break; + case 4: /* frndint */ + gen_helper_frndint(cpu_env); + break; + case 6: /* fsin */ + gen_helper_fsin(cpu_env); break; - case 3: default: - gen_helper_fist_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); + case 7: /* fcos */ + gen_helper_fcos(cpu_env); break; } - if ((op & 7) == 3) - gen_helper_fpop(cpu_env); - break; - } - break; - case 0x0c: /* fldenv mem */ - gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x0d: /* fldcw mem */ - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - gen_helper_fldcw(cpu_env, s->tmp2_i32); - break; - case 0x0e: /* fnstenv mem */ - gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x0f: /* fnstcw mem */ - gen_helper_fnstcw(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - case 0x1d: /* fldt mem */ - gen_helper_fldt_ST0(cpu_env, s->A0); - break; - case 0x1f: /* fstpt mem */ - gen_helper_fstt_ST0(cpu_env, s->A0); - gen_helper_fpop(cpu_env); - break; - case 0x2c: /* frstor mem */ - gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x2e: /* fnsave mem */ - gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x2f: /* fnstsw mem */ - gen_helper_fnstsw(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - case 0x3c: /* fbld */ - gen_helper_fbld_ST0(cpu_env, s->A0); - break; - case 0x3e: /* fbstp */ - gen_helper_fbst_ST0(cpu_env, s->A0); - gen_helper_fpop(cpu_env); - break; - case 0x3d: /* fildll */ - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); - break; - case 0x3f: /* fistpll */ - gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fpop(cpu_env); - break; - default: - goto unknown_op; - } - } else { - /* register float ops */ - opreg = rm; - - switch(op) { - case 0x08: /* fld sti */ - gen_helper_fpush(cpu_env); - gen_helper_fmov_ST0_STN(cpu_env, - tcg_const_i32((opreg + 1) & 7)); - break; - case 0x09: /* fxchg sti */ - case 0x29: /* fxchg4 sti, undocumented op */ - case 0x39: /* fxchg7 sti, undocumented op */ - gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg)); - break; - case 0x0a: /* grp d9/2 */ - switch(rm) { - case 0: /* fnop */ - /* check exceptions (FreeBSD FPU probe) */ - gen_helper_fwait(cpu_env); - break; - default: - goto unknown_op; - } - break; - case 0x0c: /* grp d9/4 */ - switch(rm) { - case 0: /* fchs */ - gen_helper_fchs_ST0(cpu_env); break; - case 1: /* fabs */ - gen_helper_fabs_ST0(cpu_env); + case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ + case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ + case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ + { + int op1; + + op1 = op & 7; + if (op >= 0x20) { + gen_helper_fp_arith_STN_ST0(op1, opreg); + if (op >= 0x30) { + gen_helper_fpop(cpu_env); + } + } else { + gen_helper_fmov_FT0_STN(cpu_env, + tcg_const_i32(opreg)); + gen_helper_fp_arith_ST0_FT0(op1); + } + } break; - case 4: /* ftst */ - gen_helper_fldz_FT0(cpu_env); + case 0x02: /* fcom */ + case 0x22: /* fcom2, undocumented op */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fcom_ST0_FT0(cpu_env); break; - case 5: /* fxam */ - gen_helper_fxam_ST0(cpu_env); + case 0x03: /* fcomp */ + case 0x23: /* fcomp3, undocumented op */ + case 0x32: /* fcomp5, undocumented op */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); break; - default: - goto unknown_op; - } - break; - case 0x0d: /* grp d9/5 */ - { - switch(rm) { - case 0: - gen_helper_fpush(cpu_env); - gen_helper_fld1_ST0(cpu_env); - break; - case 1: - gen_helper_fpush(cpu_env); - gen_helper_fldl2t_ST0(cpu_env); + case 0x15: /* da/5 */ + switch (rm) { + case 1: /* fucompp */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fucom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); break; - case 2: - gen_helper_fpush(cpu_env); - gen_helper_fldl2e_ST0(cpu_env); + default: + goto unknown_op; + } + break; + case 0x1c: + switch (rm) { + case 0: /* feni (287 only, just do nop here) */ break; - case 3: - gen_helper_fpush(cpu_env); - gen_helper_fldpi_ST0(cpu_env); + case 1: /* fdisi (287 only, just do nop here) */ break; - case 4: - gen_helper_fpush(cpu_env); - gen_helper_fldlg2_ST0(cpu_env); + case 2: /* fclex */ + gen_helper_fclex(cpu_env); + update_fip = false; break; - case 5: - gen_helper_fpush(cpu_env); - gen_helper_fldln2_ST0(cpu_env); + case 3: /* fninit */ + gen_helper_fninit(cpu_env); + update_fip = false; break; - case 6: - gen_helper_fpush(cpu_env); - gen_helper_fldz_ST0(cpu_env); + case 4: /* fsetpm (287 only, just do nop here) */ break; default: goto unknown_op; } - } - break; - case 0x0e: /* grp d9/6 */ - switch(rm) { - case 0: /* f2xm1 */ - gen_helper_f2xm1(cpu_env); - break; - case 1: /* fyl2x */ - gen_helper_fyl2x(cpu_env); - break; - case 2: /* fptan */ - gen_helper_fptan(cpu_env); - break; - case 3: /* fpatan */ - gen_helper_fpatan(cpu_env); - break; - case 4: /* fxtract */ - gen_helper_fxtract(cpu_env); - break; - case 5: /* fprem1 */ - gen_helper_fprem1(cpu_env); - break; - case 6: /* fdecstp */ - gen_helper_fdecstp(cpu_env); break; - default: - case 7: /* fincstp */ - gen_helper_fincstp(cpu_env); - break; - } - break; - case 0x0f: /* grp d9/7 */ - switch(rm) { - case 0: /* fprem */ - gen_helper_fprem(cpu_env); - break; - case 1: /* fyl2xp1 */ - gen_helper_fyl2xp1(cpu_env); - break; - case 2: /* fsqrt */ - gen_helper_fsqrt(cpu_env); + case 0x1d: /* fucomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - case 3: /* fsincos */ - gen_helper_fsincos(cpu_env); + case 0x1e: /* fcomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - case 5: /* fscale */ - gen_helper_fscale(cpu_env); + case 0x28: /* ffree sti */ + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); break; - case 4: /* frndint */ - gen_helper_frndint(cpu_env); + case 0x2a: /* fst sti */ + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); break; - case 6: /* fsin */ - gen_helper_fsin(cpu_env); + case 0x2b: /* fstp sti */ + case 0x0b: /* fstp1 sti, undocumented op */ + case 0x3a: /* fstp8 sti, undocumented op */ + case 0x3b: /* fstp9 sti, undocumented op */ + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; - default: - case 7: /* fcos */ - gen_helper_fcos(cpu_env); + case 0x2c: /* fucom st(i) */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucom_ST0_FT0(cpu_env); break; - } - break; - case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ - case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ - case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ - { - int op1; - - op1 = op & 7; - if (op >= 0x20) { - gen_helper_fp_arith_STN_ST0(op1, opreg); - if (op >= 0x30) - gen_helper_fpop(cpu_env); - } else { - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fp_arith_ST0_FT0(op1); - } - } - break; - case 0x02: /* fcom */ - case 0x22: /* fcom2, undocumented op */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(cpu_env); - break; - case 0x03: /* fcomp */ - case 0x23: /* fcomp3, undocumented op */ - case 0x32: /* fcomp5, undocumented op */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - break; - case 0x15: /* da/5 */ - switch(rm) { - case 1: /* fucompp */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + case 0x2d: /* fucomp st(i) */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fucom_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); - gen_helper_fpop(cpu_env); break; - default: - goto unknown_op; - } - break; - case 0x1c: - switch(rm) { - case 0: /* feni (287 only, just do nop here) */ - break; - case 1: /* fdisi (287 only, just do nop here) */ - break; - case 2: /* fclex */ - gen_helper_fclex(cpu_env); + case 0x33: /* de/3 */ + switch (rm) { + case 1: /* fcompp */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); + break; + default: + goto unknown_op; + } break; - case 3: /* fninit */ - gen_helper_fninit(cpu_env); + case 0x38: /* ffreep sti, undocumented op */ + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; - case 4: /* fsetpm (287 only, just do nop here) */ + case 0x3c: /* df/4 */ + switch (rm) { + case 0: + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + break; + default: + goto unknown_op; + } break; - default: - goto unknown_op; - } - break; - case 0x1d: /* fucomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x1e: /* fcomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x28: /* ffree sti */ - gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); - break; - case 0x2a: /* fst sti */ - gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); - break; - case 0x2b: /* fstp sti */ - case 0x0b: /* fstp1 sti, undocumented op */ - case 0x3a: /* fstp8 sti, undocumented op */ - case 0x3b: /* fstp9 sti, undocumented op */ - gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); - gen_helper_fpop(cpu_env); - break; - case 0x2c: /* fucom st(i) */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(cpu_env); - break; - case 0x2d: /* fucomp st(i) */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - break; - case 0x33: /* de/3 */ - switch(rm) { - case 1: /* fcompp */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); - gen_helper_fcom_ST0_FT0(cpu_env); + case 0x3d: /* fucomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x3e: /* fcomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - default: - goto unknown_op; - } - break; - case 0x38: /* ffreep sti, undocumented op */ - gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fpop(cpu_env); - break; - case 0x3c: /* df/4 */ - switch(rm) { - case 0: - gen_helper_fnstsw(s->tmp2_i32, cpu_env); - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + case 0x10 ... 0x13: /* fcmovxx */ + case 0x18 ... 0x1b: + { + int op1; + TCGLabel *l1; + static const uint8_t fcmov_cc[8] = { + (JCC_B << 1), + (JCC_Z << 1), + (JCC_BE << 1), + (JCC_P << 1), + }; + + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); + l1 = gen_new_label(); + gen_jcc1_noeob(s, op1, l1); + gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg)); + gen_set_label(l1); + } break; default: goto unknown_op; } - break; - case 0x3d: /* fucomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x3e: /* fcomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x10 ... 0x13: /* fcmovxx */ - case 0x18 ... 0x1b: - { - int op1; - TCGLabel *l1; - static const uint8_t fcmov_cc[8] = { - (JCC_B << 1), - (JCC_Z << 1), - (JCC_BE << 1), - (JCC_P << 1), - }; + } - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); - l1 = gen_new_label(); - gen_jcc1_noeob(s, op1, l1); - gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg)); - gen_set_label(l1); - } - break; - default: - goto unknown_op; + if (update_fip) { + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, segs[R_CS].selector)); + tcg_gen_st16_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, fpcs)); + tcg_gen_st_tl(tcg_constant_tl(pc_start - s->cs_base), + cpu_env, offsetof(CPUX86State, fpip)); } } break; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 37c3e3e0a3..059da48475 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -52,6 +52,8 @@ typedef struct DisasContext { /* The temporary corresponding to register 0 for this compilation. */ TCGv R0; + /* The constant zero. */ + TCGv zero; } DisasContext; static inline bool is_user(DisasContext *dc) @@ -129,9 +131,7 @@ void openrisc_translate_init(void) static void gen_exception(DisasContext *dc, unsigned int excp) { - TCGv_i32 tmp = tcg_const_i32(excp); - gen_helper_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); + gen_helper_exception(cpu_env, tcg_constant_i32(excp)); } static void gen_illegal_exception(DisasContext *dc) @@ -199,10 +199,10 @@ static void gen_ove_cyov(DisasContext *dc) static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv t0 = tcg_const_tl(0); + TCGv t0 = tcg_temp_new(); TCGv res = tcg_temp_new(); - tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero); tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); @@ -216,11 +216,11 @@ static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv t0 = tcg_const_tl(0); + TCGv t0 = tcg_temp_new(); TCGv res = tcg_temp_new(); - tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); - tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero); + tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero); tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); @@ -538,13 +538,9 @@ static bool trans_l_extbz(DisasContext *dc, arg_da *a) static bool trans_l_cmov(DisasContext *dc, arg_dab *a) { - TCGv zero; - check_r0_write(dc, a->d); - zero = tcg_const_tl(0); - tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, + tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero, cpu_R(dc, a->a), cpu_R(dc, a->b)); - tcg_temp_free(zero); return true; } @@ -632,15 +628,10 @@ static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) { target_ulong tmp_pc = dc->base.pc_next + a->n * 4; - TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); - TCGv t_true = tcg_const_tl(tmp_pc); - TCGv t_zero = tcg_const_tl(0); - - tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); + TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8); + TCGv t_true = tcg_constant_tl(tmp_pc); - tcg_temp_free(t_next); - tcg_temp_free(t_true); - tcg_temp_free(t_zero); + tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next); dc->delayed_branch = 2; } @@ -740,12 +731,6 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a) ea = tcg_temp_new(); tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); - /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned - to cpu_regs[0]. Since l.swa is quite often immediately followed by a - branch, don't bother reallocating; finish the TB using the "real" R0. - This also takes care of RB input across the branch. */ - dc->R0 = cpu_regs[0]; - lab_fail = gen_new_label(); lab_done = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); @@ -753,7 +738,7 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a) val = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, - cpu_regs[a->b], dc->mem_idx, MO_TEUL); + cpu_R(dc, a->b), dc->mem_idx, MO_TEUL); tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); tcg_temp_free(val); @@ -813,44 +798,28 @@ static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a) static bool trans_l_addi(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_addic(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_muli(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) { - TCGv t0; - - t0 = tcg_const_tl(a->i); - gen_mac(dc, cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } @@ -1624,8 +1593,9 @@ static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) /* Allow the TCG optimizer to see that R0 == 0, when it's true, which is the common case. */ + dc->zero = tcg_constant_tl(0); if (dc->tb_flags & TB_FLAGS_R0_0) { - dc->R0 = tcg_const_tl(0); + dc->R0 = dc->zero; } else { dc->R0 = cpu_regs[0]; } diff --git a/tests/Makefile.include b/tests/Makefile.include index e4dcb17329..6e16c05f10 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -96,7 +96,7 @@ AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS))) $(TESTS_VENV_DIR): $(TESTS_VENV_REQ) $(call quiet-command, \ - $(PYTHON) -m venv --system-site-packages $@, \ + $(PYTHON) -m venv $@, \ VENV, $@) $(call quiet-command, \ $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 93c4b9851f..2c4fef3e14 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -86,14 +86,17 @@ def _console_interaction(test, success_message, failure_message, assert not keep_sending or send_string if vm is None: vm = test.vm - console = vm.console_socket.makefile() + console = vm.console_socket.makefile(mode='rb', encoding='utf-8') console_logger = logging.getLogger('console') while True: if send_string: vm.console_socket.sendall(send_string.encode()) if not keep_sending: send_string = None # send only once - msg = console.readline().strip() + try: + msg = console.readline().decode().strip() + except UnicodeDecodeError: + msg = None if not msg: continue console_logger.debug(msg) @@ -210,6 +213,9 @@ class Test(avocado.Test): self.arch = self.params.get('arch', default=self._get_unique_tag_val('arch')) + self.cpu = self.params.get('cpu', + default=self._get_unique_tag_val('cpu')) + self.machine = self.params.get('machine', default=self._get_unique_tag_val('machine')) @@ -219,9 +225,13 @@ class Test(avocado.Test): if self.qemu_bin is None: self.cancel("No QEMU binary defined or found in the build tree") - def _new_vm(self, *args): + def _new_vm(self, name, *args): self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") - vm = QEMUMachine(self.qemu_bin, sock_dir=self._sd.name) + vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, + sock_dir=self._sd.name, log_dir=self.logdir) + self.log.debug('QEMUMachine "%s" created', name) + self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir) + self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir) if args: vm.add_args(*args) return vm @@ -234,11 +244,34 @@ class Test(avocado.Test): if not name: name = str(uuid.uuid4()) if self._vms.get(name) is None: - self._vms[name] = self._new_vm(*args) + self._vms[name] = self._new_vm(name, *args) + if self.cpu is not None: + self._vms[name].add_args('-cpu', self.cpu) if self.machine is not None: self._vms[name].set_machine(self.machine) return self._vms[name] + def set_vm_arg(self, arg, value): + """ + Set an argument to list of extra arguments to be given to the QEMU + binary. If the argument already exists then its value is replaced. + + :param arg: the QEMU argument, such as "-cpu" in "-cpu host" + :type arg: str + :param value: the argument value, such as "host" in "-cpu host" + :type value: str + """ + if not arg or not value: + return + if arg not in self.vm.args: + self.vm.args.extend([arg, value]) + else: + idx = self.vm.args.index(arg) + 1 + if idx < len(self.vm.args): + self.vm.args[idx] = value + else: + self.vm.args.append(value) + def tearDown(self): for vm in self._vms.values(): vm.shutdown() @@ -299,6 +332,103 @@ class LinuxSSHMixIn: f'Guest command failed: {command}') return stdout_lines, stderr_lines +class LinuxDistro: + """Represents a Linux distribution + + Holds information of known distros. + """ + #: A collection of known distros and their respective image checksum + KNOWN_DISTROS = { + 'fedora': { + '31': { + 'x86_64': + {'checksum': ('e3c1b309d9203604922d6e255c2c5d09' + '8a309c2d46215d8fc026954f3c5c27a0'), + 'pxeboot_url': ('https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/x86_64/os/images/pxeboot/'), + 'kernel_params': ('root=UUID=b1438b9b-2cab-4065-a99a-' + '08a96687f73c ro no_timer_check ' + 'net.ifnames=0 console=tty1 ' + 'console=ttyS0,115200n8'), + }, + 'aarch64': + {'checksum': ('1e18d9c0cf734940c4b5d5ec592facae' + 'd2af0ad0329383d5639c997fdf16fe49'), + 'pxeboot_url': 'https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/aarch64/os/images/pxeboot/', + 'kernel_params': ('root=UUID=b6950a44-9f3c-4076-a9c2-' + '355e8475b0a7 ro earlyprintk=pl011,0x9000000' + ' ignore_loglevel no_timer_check' + ' printk.time=1 rd_NO_PLYMOUTH' + ' console=ttyAMA0'), + }, + 'ppc64': + {'checksum': ('7c3528b85a3df4b2306e892199a9e1e4' + '3f991c506f2cc390dc4efa2026ad2f58')}, + 's390x': + {'checksum': ('4caaab5a434fd4d1079149a072fdc789' + '1e354f834d355069ca982fdcaf5a122d')}, + }, + '32': { + 'aarch64': + {'checksum': ('b367755c664a2d7a26955bbfff985855' + 'adfa2ca15e908baf15b4b176d68d3967'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/32/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=3df75b65-be8d-4db4-8655-' + '14d95c0e90c5 ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8'), + }, + }, + '33': { + 'aarch64': + {'checksum': ('e7f75cdfd523fe5ac2ca9eeece68edc1' + 'a81f386a17f969c1d1c7c87031008a6b'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/33/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=d20b3ffa-6397-4a63-a734-' + '1126a0208f8a ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8' + ' console=tty0'), + }, + }, + } + } + + def __init__(self, name, version, arch): + self.name = name + self.version = version + self.arch = arch + try: + info = self.KNOWN_DISTROS.get(name).get(version).get(arch) + except AttributeError: + # Unknown distro + info = None + self._info = info or {} + + @property + def checksum(self): + """Gets the cloud-image file checksum""" + return self._info.get('checksum', None) + + @checksum.setter + def checksum(self, value): + self._info['checksum'] = value + + @property + def pxeboot_url(self): + """Gets the repository url where pxeboot files can be found""" + return self._info.get('pxeboot_url', None) + + @property + def default_kernel_params(self): + """Gets the default kernel parameters""" + return self._info.get('kernel_params', None) + class LinuxTest(Test, LinuxSSHMixIn): """Facilitates having a cloud-image Linux based available. @@ -308,12 +438,39 @@ class LinuxTest(Test, LinuxSSHMixIn): """ timeout = 900 - chksum = None + distro = None username = 'root' password = 'password' + def _set_distro(self): + distro_name = self.params.get( + 'distro', + default=self._get_unique_tag_val('distro')) + if not distro_name: + distro_name = 'fedora' + + distro_version = self.params.get( + 'distro_version', + default=self._get_unique_tag_val('distro_version')) + if not distro_version: + distro_version = '31' + + self.distro = LinuxDistro(distro_name, distro_version, self.arch) + + # The distro checksum behaves differently than distro name and + # version. First, it does not respect a tag with the same + # name, given that it's not expected to be used for filtering + # (distro name versions are the natural choice). Second, the + # order of precedence is: parameter, attribute and then value + # from KNOWN_DISTROS. + distro_checksum = self.params.get('distro_checksum', + default=None) + if distro_checksum: + self.distro.checksum = distro_checksum + def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): super(LinuxTest, self).setUp() + self._set_distro() self.vm.add_args('-smp', '2') self.vm.add_args('-m', '1024') # The following network device allows for SSH connections @@ -351,12 +508,14 @@ class LinuxTest(Test, LinuxSSHMixIn): self.log.info('Downloading/preparing boot image') # Fedora 31 only provides ppc64le images image_arch = self.arch - if image_arch == 'ppc64': - image_arch = 'ppc64le' + if self.distro.name == 'fedora': + if image_arch == 'ppc64': + image_arch = 'ppc64le' + try: boot = vmimage.get( - 'fedora', arch=image_arch, version='31', - checksum=self.chksum, + self.distro.name, arch=image_arch, version=self.distro.version, + checksum=self.distro.checksum, algorithm='sha256', cache_dir=self.cache_dirs[0], snapshot_dir=self.workdir) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index 4c8a5994b2..ab19146d1e 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -20,8 +20,6 @@ class BootLinuxX8664(LinuxTest): :avocado: tags=arch:x86_64 """ - chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0' - def test_pc_i440fx_tcg(self): """ :avocado: tags=machine:pc @@ -66,8 +64,6 @@ class BootLinuxAarch64(LinuxTest): :avocado: tags=machine:gic-version=2 """ - chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49' - def add_common_args(self): self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', @@ -83,7 +79,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "max") self.vm.add_args("-machine", "virt,gic-version=2") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -96,7 +91,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "max") self.vm.add_args("-machine", "virt,gic-version=3") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -108,7 +102,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("kvm") self.vm.add_args("-accel", "kvm") - self.vm.add_args("-cpu", "host") self.vm.add_args("-machine", "virt,gic-version=host") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -119,8 +112,6 @@ class BootLinuxPPC64(LinuxTest): :avocado: tags=arch:ppc64 """ - chksum = '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58' - def test_pseries_tcg(self): """ :avocado: tags=machine:pseries @@ -136,8 +127,6 @@ class BootLinuxS390X(LinuxTest): :avocado: tags=arch:s390x """ - chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d' - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_s390_ccw_virtio_tcg(self): """ diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 3ae11a7a8f..5248c8097d 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -239,6 +239,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mips64el :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:5KEc """ kernel_url = ('https://github.com/philmd/qemu-testing-blob/' 'raw/9ad2df38/mips/malta/mips64el/' @@ -258,8 +259,7 @@ class BootLinuxConsole(LinuxKernelTest): kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-cpu', '5KEc', - '-kernel', kernel_path, + self.vm.add_args('-kernel', kernel_path, '-initrd', initrd_path, '-append', kernel_command_line, '-no-reboot') @@ -287,7 +287,6 @@ class BootLinuxConsole(LinuxKernelTest): + 'mem=256m@@0x0 ' + 'console=ttyS0') self.vm.add_args('-no-reboot', - '-cpu', 'I7200', '-kernel', kernel_path, '-append', kernel_command_line) self.vm.launch() @@ -299,6 +298,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -311,6 +311,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -323,6 +324,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -335,6 +337,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:aarch64 :avocado: tags=machine:virt :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a53 """ kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/29/Everything/aarch64/os/images/pxeboot' @@ -905,6 +908,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc :avocado: tags=device:sd + :avocado: tags=os:netbsd """ # This test download a 304MB compressed image and expand it to 2GB deb_url = ('http://snapshot.debian.org/archive/debian/' @@ -1167,9 +1171,9 @@ class BootLinuxConsole(LinuxKernelTest): """ :avocado: tags=arch:ppc64 :avocado: tags=machine:ppce500 + :avocado: tags=cpu:e5500 """ tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' - self.vm.add_args('-cpu', 'e5500') self.do_test_advcal_2018('19', tar_hash, 'uImage') def test_ppc_g3beige(self): @@ -1211,7 +1215,7 @@ class BootLinuxConsole(LinuxKernelTest): """ :avocado: tags=arch:xtensa :avocado: tags=machine:lx60 + :avocado: tags=cpu:dc233c """ tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' - self.vm.add_args('-cpu', 'dc233c') self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf') diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py index 75c2d44492..3479b5233b 100644 --- a/tests/acceptance/boot_xen.py +++ b/tests/acceptance/boot_xen.py @@ -48,7 +48,6 @@ class BootXenBase(LinuxKernelTest): xen_command_line = self.XEN_COMMON_COMMAND_LINE self.vm.add_args('-machine', 'virtualization=on', - '-cpu', 'cortex-a57', '-m', '768', '-kernel', xen_path, '-append', xen_command_line, diff --git a/tests/acceptance/cpu_queries.py b/tests/acceptance/cpu_queries.py index 293dccb89a..cc9e380cc7 100644 --- a/tests/acceptance/cpu_queries.py +++ b/tests/acceptance/cpu_queries.py @@ -8,8 +8,6 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -import logging - from avocado_qemu import Test class QueryCPUModelExpansion(Test): @@ -27,7 +25,7 @@ class QueryCPUModelExpansion(Test): cpus = self.vm.command('query-cpu-definitions') for c in cpus: - print(repr(c)) + self.log.info("Checking CPU: %s", c) self.assertNotIn('', c['unavailable-features'], c['name']) for c in cpus: diff --git a/tests/acceptance/intel_iommu.py b/tests/acceptance/intel_iommu.py new file mode 100644 index 0000000000..474d62f6bf --- /dev/null +++ b/tests/acceptance/intel_iommu.py @@ -0,0 +1,119 @@ +# INTEL_IOMMU Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger <eric.auger@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class IntelIOMMU(LinuxTest): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=distro:fedora + :avocado: tags=distro_version:31 + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + :avocado: tags=intel_iommu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(IntelIOMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def add_common_args(self): + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + def common_vm_setup(self, custom_kernel=None): + self.require_accelerator("kvm") + self.add_common_args() + self.vm.add_args("-accel", "kvm") + + if custom_kernel is None: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dmesg | grep -e DMAR -e IOMMU') + self.ssh_command('find /sys/kernel/iommu_groups/ -type l') + self.ssh_command('dnf -y install numactl-devel') + + def test_intel_iommu(self): + """ + :avocado: tags=intel_iommu_intremap + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on') + self.run_and_check() + + def test_intel_iommu_strict(self): + """ + :avocado: tags=intel_iommu_strict + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_strict_cm(self): + """ + :avocado: tags=intel_iommu_strict_cm + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_pt(self): + """ + :avocado: tags=intel_iommu_pt + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on iommu=pt') + self.run_and_check() diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py index 61c9079d04..4de1947418 100644 --- a/tests/acceptance/linux_ssh_mips_malta.py +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -19,6 +19,8 @@ from avocado.utils import archive from avocado.utils import ssh +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') class LinuxSSH(Test, LinuxSSHMixIn): timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' @@ -65,11 +67,6 @@ class LinuxSSH(Test, LinuxSSHMixIn): kernel_hash = self.IMAGE_INFO[endianess]['kernel_hash'][wordsize] return kernel_url, kernel_hash - @skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') - def setUp(self): - super(LinuxSSH, self).setUp() - def ssh_disconnect_vm(self): self.ssh_session.quit() diff --git a/tests/acceptance/machine_mips_malta.py b/tests/acceptance/machine_mips_malta.py index 7c9a4ee4d2..b67d8cb141 100644 --- a/tests/acceptance/machine_mips_malta.py +++ b/tests/acceptance/machine_mips_malta.py @@ -62,7 +62,6 @@ class MaltaMachineFramebuffer(Test): kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'clocksource=GIC console=tty0 console=ttyS0') self.vm.add_args('-kernel', kernel_path, - '-cpu', 'I6400', '-smp', '%u' % cpu_cores_count, '-vga', 'std', '-append', kernel_command_line) @@ -96,7 +95,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 """ self.do_test_i6400_framebuffer_logo(1) @@ -105,7 +104,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 :avocado: tags=mips:smp """ self.do_test_i6400_framebuffer_logo(7) @@ -115,7 +114,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 :avocado: tags=mips:smp """ self.do_test_i6400_framebuffer_logo(8) diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py index f48f68fc6b..2e86d5017a 100644 --- a/tests/acceptance/pc_cpu_hotplug_props.py +++ b/tests/acceptance/pc_cpu_hotplug_props.py @@ -25,11 +25,11 @@ from avocado_qemu import Test class OmittedCPUProps(Test): """ :avocado: tags=arch:x86_64 + :avocado: tags=cpu:qemu64 """ def test_no_die_id(self): self.vm.add_args('-nodefaults', '-S') self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') - self.vm.add_args('-cpu', 'qemu64') self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') self.vm.launch() self.assertEquals(len(self.vm.command('query-cpus-fast')), 2) diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py index 96ba13b894..2993ee3b07 100644 --- a/tests/acceptance/ppc_prep_40p.py +++ b/tests/acceptance/ppc_prep_40p.py @@ -27,6 +27,7 @@ class IbmPrep40pMachine(Test): """ :avocado: tags=arch:ppc :avocado: tags=machine:40p + :avocado: tags=os:netbsd :avocado: tags=slowness:high """ bios_url = ('http://ftpmirror.your.org/pub/misc/' @@ -64,6 +65,7 @@ class IbmPrep40pMachine(Test): """ :avocado: tags=arch:ppc :avocado: tags=machine:40p + :avocado: tags=os:netbsd """ drive_url = ('https://cdn.netbsd.org/pub/NetBSD/iso/7.1.2/' 'NetBSD-7.1.2-prep.iso') diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py index 71facdaa75..bb32b31240 100644 --- a/tests/acceptance/replay_kernel.py +++ b/tests/acceptance/replay_kernel.py @@ -156,8 +156,7 @@ class ReplayKernelNormal(ReplayKernelBase): 'console=ttyAMA0') console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern, - args=('-cpu', 'cortex-a53')) + self.run_rr(kernel_path, kernel_command_line, console_pattern) def test_arm_virt(self): """ @@ -301,7 +300,7 @@ class ReplayKernelNormal(ReplayKernelBase): tar_url = ('https://www.qemu-advent-calendar.org' '/2018/download/day19.tar.xz') file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'uImage', ('-cpu', 'e5500')) + self.do_test_advcal_2018(file_path, 'uImage') def test_ppc_g3beige(self): """ @@ -348,8 +347,7 @@ class ReplayKernelNormal(ReplayKernelBase): tar_url = ('https://www.qemu-advent-calendar.org' '/2018/download/day02.tar.xz') file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf', - args=('-cpu', 'dc233c')) + self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf') @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') class ReplayKernelSlow(ReplayKernelBase): @@ -394,6 +392,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=machine:malta :avocado: tags=endian:little :avocado: tags=slowness:high + :avocado: tags=cpu:5KEc """ kernel_url = ('https://github.com/philmd/qemu-testing-blob/' 'raw/9ad2df38/mips/malta/mips64el/' @@ -414,7 +413,7 @@ class ReplayKernelSlow(ReplayKernelBase): 'rdinit=/sbin/init noreboot') console_pattern = 'Boot successful.' self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path, '-cpu', '5KEc')) + args=('-initrd', initrd_path)) def do_test_mips_malta32el_nanomips(self, kernel_path_xz): kernel_path = self.workdir + "kernel" @@ -426,14 +425,14 @@ class ReplayKernelSlow(ReplayKernelBase): 'mem=256m@@0x0 ' 'console=ttyS0') console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-cpu', 'I7200')) + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) def test_mips_malta32el_nanomips_4k(self): """ :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -447,6 +446,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -460,6 +460,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' diff --git a/tests/acceptance/reverse_debugging.py b/tests/acceptance/reverse_debugging.py index be01aca217..d2921e70c3 100644 --- a/tests/acceptance/reverse_debugging.py +++ b/tests/acceptance/reverse_debugging.py @@ -207,4 +207,4 @@ class ReverseDebugging_AArch64(ReverseDebugging): kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) self.reverse_debugging( - args=('-kernel', kernel_path, '-cpu', 'cortex-a53')) + args=('-kernel', kernel_path)) diff --git a/tests/acceptance/smmu.py b/tests/acceptance/smmu.py new file mode 100644 index 0000000000..b3c4de6bf4 --- /dev/null +++ b/tests/acceptance/smmu.py @@ -0,0 +1,137 @@ +# SMMUv3 Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger <eric.auger@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest, BUILD_DIR + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class SMMU(LinuxTest): + """ + :avocado: tags=accel:kvm + :avocado: tags=cpu:host + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=distro:fedora + :avocado: tags=smmu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(SMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def common_vm_setup(self, custom_kernel=False): + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-cpu", "host") + self.vm.add_args("-machine", "iommu=smmuv3") + self.vm.add_args("-d", "guest_errors") + self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + if custom_kernel is False: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dnf -y install numactl-devel') + + + # 5.3 kernel without RIL # + + def test_smmu_noril(self): + """ + :avocado: tags=smmu_noril + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_noril_passthrough(self): + """ + :avocado: tags=smmu_noril_passthrough + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_noril_nostrict(self): + """ + :avocado: tags=smmu_noril_nostrict + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() + + # 5.8 kernel featuring range invalidation + # >= v5.7 kernel + + def test_smmu_ril(self): + """ + :avocado: tags=smmu_ril + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_ril_passthrough(self): + """ + :avocado: tags=smmu_ril_passthrough + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_ril_nostrict(self): + """ + :avocado: tags=smmu_ril_nostrict + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() diff --git a/tests/acceptance/tcg_plugins.py b/tests/acceptance/tcg_plugins.py index c21bf9e52a..9ca1515c3b 100644 --- a/tests/acceptance/tcg_plugins.py +++ b/tests/acceptance/tcg_plugins.py @@ -25,7 +25,7 @@ class PluginKernelBase(LinuxKernelTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' def run_vm(self, kernel_path, kernel_command_line, - plugin, plugin_log, console_pattern, args): + plugin, plugin_log, console_pattern, args=None): vm = self.get_vm() vm.set_console() @@ -68,7 +68,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -80,8 +80,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libinsn.so", plugin_log.name, - console_pattern, - args=('-cpu', 'cortex-a53')) + console_pattern) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: @@ -95,7 +94,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -108,7 +107,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libinsn.so", plugin_log.name, console_pattern, - args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + args=('-icount', 'shift=1')) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: @@ -121,7 +120,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -134,7 +133,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libmem.so,arg=both", plugin_log.name, console_pattern, - args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + args=('-icount', 'shift=1')) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: diff --git a/tests/acceptance/virtio-gpu.py b/tests/acceptance/virtio-gpu.py index e7979343e9..589332c1b7 100644 --- a/tests/acceptance/virtio-gpu.py +++ b/tests/acceptance/virtio-gpu.py @@ -60,6 +60,7 @@ class VirtioGPUx86(Test): """ :avocado: tags=arch:x86_64 :avocado: tags=device:virtio-vga + :avocado: tags=cpu:host """ kernel_command_line = ( self.KERNEL_COMMON_COMMAND_LINE + "console=ttyS0 rdinit=/bin/bash" @@ -72,7 +73,6 @@ class VirtioGPUx86(Test): initrd_path = self.fetch_asset(self.INITRD_URL) self.vm.set_console() - self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-machine", "pc,accel=kvm") self.vm.add_args("-device", "virtio-vga,virgl=on") @@ -101,6 +101,7 @@ class VirtioGPUx86(Test): """ :avocado: tags=arch:x86_64 :avocado: tags=device:vhost-user-vga + :avocado: tags=cpu:host """ kernel_command_line = ( self.KERNEL_COMMON_COMMAND_LINE + "console=ttyS0 rdinit=/bin/bash" @@ -140,7 +141,6 @@ class VirtioGPUx86(Test): ) self.vm.set_console() - self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") diff --git a/tests/acceptance/x86_cpu_model_versions.py b/tests/acceptance/x86_cpu_model_versions.py index 77ed8597a4..0e9feda62d 100644 --- a/tests/acceptance/x86_cpu_model_versions.py +++ b/tests/acceptance/x86_cpu_model_versions.py @@ -252,10 +252,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ # machine-type only: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') @@ -263,9 +266,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') @@ -273,10 +279,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_set_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # command line must override machine-type if CPU model is not versioned: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,+arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') @@ -284,9 +293,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_unset_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,-arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') @@ -294,10 +306,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v1_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # versioned CPU model overrides machine-type: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') @@ -305,9 +320,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v2_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') @@ -315,10 +333,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v1_set_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # command line must override machine-type and versioned CPU model: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off,+arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') @@ -326,9 +347,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v2_unset_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off,-arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') diff --git a/tests/docker/common.rc b/tests/docker/common.rc index ebc5b97ecf..c5cc33d366 100755 --- a/tests/docker/common.rc +++ b/tests/docker/common.rc @@ -15,14 +15,23 @@ # overriden by TARGET_LIST if the user sets it. DEF_TARGET_LIST=${DEF_TARGET_LIST:-"x86_64-softmmu,aarch64-softmmu"} -requires() +requires_binary() { + found=0 for c in $@; do - if ! echo "$FEATURES" | grep -wq -e "$c"; then - echo "Prerequisite '$c' not present, skip" - exit 0 - fi + for d in /bin /usr/bin /usr/local/bin + do + if test -f "$d/$c" + then + found=1 + fi + done done + if test "$found" != "1" + then + echo "Prerequisite '$c' not present, skip" + exit 0 + fi } configure_qemu() diff --git a/tests/docker/docker.py b/tests/docker/docker.py index 4d9bb7c7ed..78dd13171e 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -228,7 +228,9 @@ class Docker(object): def __init__(self): self._command = _guess_engine_command() - if "docker" in self._command and "TRAVIS" not in os.environ: + if ("docker" in self._command and + "TRAVIS" not in os.environ and + "GITLAB_CI" not in os.environ): os.environ["DOCKER_BUILDKIT"] = "1" self._buildkit = True else: diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 03e0440e03..46398c61ee 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -1,41 +1,111 @@ -FROM centos:8.3.2011 +FROM docker.io/centos:8 RUN dnf -y update ENV PACKAGES \ SDL2-devel \ + alsa-lib-devel \ + bc \ + brlapi-devel \ bzip2 \ bzip2-devel \ + ca-certificates \ + capstone-devel \ + ccache \ + clang \ + ctags \ + cyrus-sasl-devel \ + daxctl-devel \ dbus-daemon \ + device-mapper-multipath-devel \ diffutils \ + findutils \ gcc \ gcc-c++ \ genisoimage \ gettext \ git \ glib2-devel \ + glibc-langpack-en \ + glibc-static \ + glusterfs-api-devel \ + gnutls-devel \ + gtk3-devel \ + hostname \ + jemalloc-devel \ libaio-devel \ + libasan \ + libattr-devel \ libbpf-devel \ + libcacard-devel \ + libcap-ng-devel \ + libcurl-devel \ + libdrm-devel \ libepoxy-devel \ libfdt-devel \ libffi-devel \ libgcrypt-devel \ + libiscsi-devel \ + libjpeg-devel \ + libnfs-devel \ + libpmem-devel \ + libpng-devel \ + librbd-devel \ + libseccomp-devel \ + libslirp-devel \ + libssh-devel \ + libtasn1-devel \ + libubsan \ + libudev-devel \ + libusbx-devel \ + libxml2-devel \ + libzstd-devel \ + llvm \ lzo-devel \ make \ - mesa-libEGL-devel \ - nmap-ncat \ + mesa-libgbm-devel \ + ncurses-devel \ nettle-devel \ ninja-build \ + nmap-ncat \ + numactl-devel \ + openssh-clients \ + pam-devel \ + perl \ perl-Test-Harness \ pixman-devel \ - python36 \ + pkgconfig \ + pulseaudio-libs-devel \ + python3 \ + python3-PyYAML \ + python3-numpy \ + python3-pillow \ + python3-pip \ + python3-setuptools \ + python3-sphinx \ + python3-sphinx_rtd_theme \ + python3-virtualenv \ + python3-wheel \ rdma-core-devel \ - spice-glib-devel \ - spice-server \ + rpm \ + sed \ + snappy-devel \ + spice-protocol \ + spice-server-devel \ + systemd-devel \ systemtap-sdt-devel \ tar \ + texinfo \ + usbredir-devel \ + util-linux \ + virglrenderer-devel \ + vte291-devel \ + which \ + xfsprogs-devel \ zlib-devel RUN dnf install -y dnf-plugins-core && \ dnf config-manager --set-enabled powertools && \ + dnf install -y centos-release-advanced-virtualization && \ + dnf install -y epel-release && \ dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker index ba4148299c..2f11b3b7bc 100644 --- a/tests/docker/dockerfiles/debian-xtensa-cross.docker +++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker @@ -5,7 +5,7 @@ # using a prebuilt toolchains for Xtensa cores from: # https://github.com/foss-xtensa/toolchain/releases # -FROM debian:stretch-slim +FROM docker.io/library/debian:stretch-slim RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker index 4ffe47671e..b414af1b9f 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -7,7 +7,7 @@ # On its own you can't build much but the docker-foo-cross targets # build on top of the base debian image. # -FROM debian:buster-slim +FROM docker.io/library/debian:buster-slim # Duplicate deb line as deb-src RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list @@ -35,5 +35,3 @@ RUN apt update && \ python3-sphinx \ python3-sphinx-rtd-theme \ $(apt-get -s build-dep --arch-only qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) - -ENV FEATURES docs diff --git a/tests/docker/dockerfiles/debian11.docker b/tests/docker/dockerfiles/debian11.docker index 5adfd62d55..febf884f8f 100644 --- a/tests/docker/dockerfiles/debian11.docker +++ b/tests/docker/dockerfiles/debian11.docker @@ -8,7 +8,7 @@ # On its own you can't build much but the docker-foo-cross targets # build on top of the base debian image. # -FROM debian:bullseye-slim +FROM docker.io/library/debian:bullseye-slim # Duplicate deb line as deb-src RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list diff --git a/tests/docker/dockerfiles/fedora-cris-cross.docker b/tests/docker/dockerfiles/fedora-cris-cross.docker index 1dfff6e0b9..91c373fdd3 100644 --- a/tests/docker/dockerfiles/fedora-cris-cross.docker +++ b/tests/docker/dockerfiles/fedora-cris-cross.docker @@ -2,7 +2,7 @@ # Cross compiler for cris system tests # -FROM fedora:33 +FROM registry.fedoraproject.org/fedora:33 ENV PACKAGES gcc-cris-linux-gnu RUN dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker index 8004fd8ee5..dbb8195eb1 100644 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ b/tests/docker/dockerfiles/fedora-i386-cross.docker @@ -1,4 +1,4 @@ -FROM fedora:33 +FROM registry.fedoraproject.org/fedora:33 ENV PACKAGES \ bzip2 \ ccache \ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker index a638afb525..5a03e1af43 100644 --- a/tests/docker/dockerfiles/fedora-win32-cross.docker +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -1,4 +1,4 @@ -FROM fedora:33 +FROM registry.fedoraproject.org/fedora:33 # Please keep this list sorted alphabetically ENV PACKAGES \ @@ -37,7 +37,6 @@ ENV PACKAGES \ RUN dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt -ENV FEATURES mingw # Specify the cross prefix for this image (see tests/docker/common.rc) ENV QEMU_CONFIGURE_OPTS --cross-prefix=i686-w64-mingw32- diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker index f53007ac86..ff706040c4 100644 --- a/tests/docker/dockerfiles/fedora-win64-cross.docker +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -1,4 +1,4 @@ -FROM fedora:33 +FROM registry.fedoraproject.org/fedora:33 # Please keep this list sorted alphabetically ENV PACKAGES \ @@ -33,7 +33,6 @@ ENV PACKAGES \ RUN dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt -ENV FEATURES mingw # Specify the cross prefix for this image (see tests/docker/common.rc) ENV QEMU_CONFIGURE_OPTS --cross-prefix=x86_64-w64-mingw32- --disable-capstone diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 00cac5d61c..eec1add7f6 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -1,92 +1,85 @@ -FROM fedora:33 +FROM registry.fedoraproject.org/fedora:33 # Please keep this list sorted alphabetically ENV PACKAGES \ + SDL2-devel \ + SDL2_image-devel \ + alsa-lib-devel \ bc \ brlapi-devel \ bzip2 \ bzip2-devel \ + ca-certificates \ capstone-devel \ ccache \ clang \ + ctags \ cyrus-sasl-devel \ + daxctl-devel \ dbus-daemon \ device-mapper-multipath-devel \ diffutils \ findutils \ gcc \ gcc-c++ \ + gcovr \ genisoimage \ gettext \ git \ glib2-devel \ + glibc-langpack-en \ + glibc-static \ glusterfs-api-devel \ gnutls-devel \ gtk3-devel \ hostname \ + jemalloc-devel \ libaio-devel \ libasan \ libattr-devel \ - libblockdev-mpath-devel \ + libbpf-devel \ + libcacard-devel \ libcap-ng-devel \ libcurl-devel \ + libdrm-devel \ libepoxy-devel \ libfdt-devel \ - libbpf-devel \ libffi-devel \ + libgcrypt-devel \ libiscsi-devel \ libjpeg-devel \ + libnfs-devel \ libpmem-devel \ libpng-devel \ librbd-devel \ libseccomp-devel \ libslirp-devel \ libssh-devel \ + libtasn1-devel \ libubsan \ libudev-devel \ + liburing-devel \ libusbx-devel \ libxml2-devel \ libzstd-devel \ llvm \ + lttng-ust-devel \ lzo-devel \ make \ + mesa-libgbm-devel \ meson \ - mingw32-bzip2 \ - mingw32-curl \ - mingw32-glib2 \ - mingw32-gmp \ - mingw32-gnutls \ - mingw32-gtk3 \ - mingw32-libjpeg-turbo \ - mingw32-libpng \ - mingw32-libtasn1 \ - mingw32-nettle \ - mingw32-nsis \ - mingw32-pixman \ - mingw32-pkg-config \ - mingw32-SDL2 \ - mingw64-bzip2 \ - mingw64-curl \ - mingw64-glib2 \ - mingw64-gmp \ - mingw64-gnutls \ - mingw64-gtk3 \ - mingw64-libjpeg-turbo \ - mingw64-libpng \ - mingw64-libtasn1 \ - mingw64-nettle \ - mingw64-pixman \ - mingw64-pkg-config \ - mingw64-SDL2 \ - nmap-ncat \ ncurses-devel \ nettle-devel \ ninja-build \ - nss-devel \ + nmap-ncat \ numactl-devel \ - perl \ + openssh-clients \ + pam-devel \ perl-Test-Harness \ + perl-base \ pixman-devel \ + pkgconfig \ + pulseaudio-libs-devel \ python3 \ python3-PyYAML \ python3-numpy \ @@ -97,24 +90,28 @@ ENV PACKAGES \ python3-sphinx_rtd_theme \ python3-virtualenv \ rdma-core-devel \ - SDL2-devel \ + rpm \ + sed \ snappy-devel \ sparse \ + spice-protocol \ spice-server-devel \ systemd-devel \ systemtap-sdt-devel \ tar \ tesseract \ tesseract-langpack-eng \ + texinfo \ usbredir-devel \ + util-linux \ virglrenderer-devel \ vte291-devel \ which \ xen-devel \ + xfsprogs-devel \ zlib-devel ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3 RUN dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt ENV PATH $PATH:/usr/libexec/python3-sphinx/ -ENV FEATURES mingw clang pyyaml asan docs diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index f7e1cbfbe6..5a8bee0289 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -1,54 +1,111 @@ -FROM opensuse/leap:15.2 +FROM registry.opensuse.org/opensuse/leap:15.2 # Please keep this list sorted alphabetically ENV PACKAGES \ + Mesa-devel \ + alsa-lib-devel \ bc \ brlapi-devel \ bzip2 \ + ca-certificates \ ccache \ + clang \ + ctags \ cyrus-sasl-devel \ + dbus-1 \ + diffutils \ + findutils \ gcc \ gcc-c++ \ - mkisofs \ + gcovr \ gettext-runtime \ git \ glib2-devel \ + glibc-locale \ + glibc-static \ glusterfs-devel \ - libgnutls-devel \ gtk3-devel \ + hostname \ + jemalloc-devel \ + libSDL2-devel \ + libSDL2_image-devel \ libaio-devel \ + libasan6 \ libattr-devel \ + libbpf-devel \ + libbz2-devel \ + libcacard-devel \ libcap-ng-devel \ + libcurl-devel \ + libdrm-devel \ libepoxy-devel \ libfdt-devel \ + libffi-devel \ + libgcrypt-devel \ + libgnutls-devel \ libiscsi-devel \ libjpeg8-devel \ + libndctl-devel \ + libnettle-devel \ + libnfs-devel \ + libnuma-devel \ + libpixman-1-0-devel \ libpmem-devel \ libpng16-devel \ + libpulse-devel \ librbd-devel \ libseccomp-devel \ + libspice-server-devel \ libssh-devel \ + libtasn1-devel \ + libubsan1 \ + libudev-devel \ + libusb-1_0-devel \ + libxml2-devel \ + libzstd-devel \ + llvm \ + lttng-ust-devel \ lzo-devel \ make \ - libSDL2_image-devel \ + mkisofs \ + ncat \ ncurses-devel \ ninja \ - libnuma-devel \ - perl \ - libpixman-1-0-devel \ + openssh \ + pam-devel \ + perl-Test-Harness \ + perl-base \ + pkgconfig \ + python3-Pillow \ + python3-PyYAML \ + python3-Sphinx \ python3-base \ + python3-numpy \ + python3-opencv \ + python3-pip \ + python3-setuptools \ + python3-sphinx_rtd_theme \ python3-virtualenv \ + python3-wheel \ rdma-core-devel \ - libSDL2-devel \ + rpm \ + sed \ snappy-devel \ - libspice-server-devel \ + sparse \ + spice-protocol-devel \ systemd-devel \ systemtap-sdt-devel \ tar \ + tesseract-ocr \ + tesseract-ocr-traineddata-english \ + texinfo \ usbredir-devel \ + util-linux \ virglrenderer-devel \ - xen-devel \ vte-devel \ + which \ + xen-devel \ + xfsprogs-devel \ zlib-devel ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3.6 diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker index 24d1647a65..f0e0180d21 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -9,7 +9,7 @@ # system won't pick up that it has changed. # -FROM ubuntu:20.04 +FROM docker.io/library/ubuntu:20.04 ENV PACKAGES \ ccache \ clang \ @@ -40,7 +40,6 @@ ENV PACKAGES \ libncurses5-dev \ libncursesw5-dev \ libnfs-dev \ - libnss3-dev \ libnuma-dev \ libpixman-1-dev \ libpng-dev \ @@ -70,4 +69,3 @@ ENV PACKAGES \ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES RUN dpkg -l $PACKAGES | sort > /packages.txt -ENV FEATURES clang pyyaml sdl2 docs diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker index 2f1ec7c42b..0880bf3e29 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -1,62 +1,116 @@ -FROM ubuntu:18.04 +FROM docker.io/library/ubuntu:18.04 ENV PACKAGES \ + bc \ + bsdmainutils \ + bzip2 \ + ca-certificates \ ccache \ clang \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + g++ \ gcc \ + gcovr \ + genisoimage \ gettext \ git \ glusterfs-common \ + hostname \ libaio-dev \ + libasan5 \ + libasound2-dev \ libattr1-dev \ libbrlapi-dev \ libbz2-dev \ + libc6-dev \ libcacard-dev \ libcap-ng-dev \ + libcapstone-dev \ libcurl4-gnutls-dev \ + libdaxctl-dev \ libdrm-dev \ libepoxy-dev \ libfdt-dev \ libffi-dev \ libgbm-dev \ + libgcrypt20-dev \ + libglib2.0-dev \ + libgnutls28-dev \ libgtk-3-dev \ libibverbs-dev \ libiscsi-dev \ libjemalloc-dev \ libjpeg-turbo8-dev \ + liblttng-ust-dev \ liblzo2-dev \ - libncurses5-dev \ libncursesw5-dev \ libnfs-dev \ - libnss3-dev \ libnuma-dev \ + libpam0g-dev \ libpixman-1-dev \ - librados-dev \ + libpmem-dev \ + libpng-dev \ + libpulse-dev \ librbd-dev \ librdmacm-dev \ libsasl2-dev \ libsdl2-dev \ + libsdl2-image-dev \ libseccomp-dev \ libsnappy-dev \ libspice-protocol-dev \ libspice-server-dev \ libssh-dev \ + libsystemd-dev \ + libtasn1-6-dev \ + libtest-harness-perl \ + libubsan1 \ + libudev-dev \ libusb-1.0-0-dev \ libusbredirhost-dev \ libvdeplug-dev \ + libvirglrenderer-dev \ libvte-2.91-dev \ libxen-dev \ + libxml2-dev \ libzstd-dev \ + llvm \ + locales \ make \ - python3-yaml \ + multipath-tools \ + netcat-openbsd \ + nettle-dev \ + ninja-build \ + openssh-client \ + perl-base \ + pkgconf \ + python3 \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-setuptools \ python3-sphinx \ python3-sphinx-rtd-theme \ - ninja-build \ + python3-venv \ + python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ sparse \ - xfslibs-dev + systemtap-sdt-dev \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ + texinfo \ + xfslibs-dev \ + zlib1g-dev RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES RUN dpkg -l $PACKAGES | sort > /packages.txt -ENV FEATURES clang pyyaml sdl2 docs # https://bugs.launchpad.net/qemu/+bug/1838763 ENV QEMU_CONFIGURE_OPTS --disable-libssh diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index fe993fe2a3..39de63d012 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -1,26 +1,44 @@ -FROM ubuntu:20.04 -ENV PACKAGES flex bison \ +FROM docker.io/library/ubuntu:20.04 +ENV PACKAGES \ + bc \ bsdmainutils \ + bzip2 \ + ca-certificates \ ccache \ - clang-10\ + clang \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + g++ \ gcc \ gcovr \ genisoimage \ gettext \ git \ - glusterfs-common \ + hostname \ libaio-dev \ + libasan5 \ + libasound2-dev \ libattr1-dev \ libbrlapi-dev \ libbz2-dev \ + libc6-dev \ libcacard-dev \ libcap-ng-dev \ + libcapstone-dev \ libcurl4-gnutls-dev \ + libdaxctl-dev \ libdrm-dev \ libepoxy-dev \ libfdt-dev \ libffi-dev \ libgbm-dev \ + libgcrypt20-dev \ + libglib2.0-dev \ + libglusterfs-dev \ + libgnutls28-dev \ libgtk-3-dev \ libibverbs-dev \ libiscsi-dev \ @@ -28,50 +46,72 @@ ENV PACKAGES flex bison \ libjpeg-turbo8-dev \ liblttng-ust-dev \ liblzo2-dev \ - libncurses5-dev \ libncursesw5-dev \ libnfs-dev \ - libnss3-dev \ libnuma-dev \ + libpam0g-dev \ libpixman-1-dev \ - librados-dev \ + libpmem-dev \ + libpng-dev \ + libpulse-dev \ librbd-dev \ librdmacm-dev \ libsasl2-dev \ libsdl2-dev \ + libsdl2-image-dev \ libseccomp-dev \ libslirp-dev \ libsnappy-dev \ libspice-protocol-dev \ libspice-server-dev \ libssh-dev \ + libsystemd-dev \ + libtasn1-6-dev \ + libtest-harness-perl \ + libubsan1 \ + libudev-dev \ libusb-1.0-0-dev \ libusbredirhost-dev \ libvdeplug-dev \ + libvirglrenderer-dev \ libvte-2.91-dev \ libxen-dev \ + libxml2-dev \ libzstd-dev \ + llvm \ + locales \ make \ - netcat-openbsd \ + multipath-tools \ + ncat \ + nettle-dev \ ninja-build \ + openssh-client \ + perl-base \ + pkgconf \ + python3 \ python3-numpy \ python3-opencv \ - python3-pil \ + python3-pillow \ python3-pip \ + python3-setuptools \ python3-sphinx \ python3-sphinx-rtd-theme \ python3-venv \ + python3-wheel \ python3-yaml \ rpm2cpio \ + sed \ sparse \ + systemtap-sdt-dev \ + tar \ tesseract-ocr \ tesseract-ocr-eng \ - xfslibs-dev\ - vim + texinfo \ + xfslibs-dev \ + zlib1g-dev RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES RUN dpkg -l $PACKAGES | sort > /packages.txt -ENV FEATURES clang tsan pyyaml sdl2 # Apply patch https://reviews.llvm.org/D75820 # This is required for TSan in clang-10 to compile with QEMU. diff --git a/tests/docker/run b/tests/docker/run index 8edc7026ee..421393046b 100755 --- a/tests/docker/run +++ b/tests/docker/run @@ -30,9 +30,6 @@ mkdir -p $TEST_DIR/{src,build,install} # Extract the source tarballs tar -C $TEST_DIR/src -xf $BASE/qemu.tar || { echo "Failed to untar source"; exit 2; } -if test -f $TEST_DIR/src/Makefile; then - export FEATURES="$FEATURES dtc" -fi if test -n "$SHOW_ENV"; then if test -f /packages.txt; then diff --git a/tests/docker/test-clang b/tests/docker/test-clang index 8c51ead518..b57e0119d9 100755 --- a/tests/docker/test-clang +++ b/tests/docker/test-clang @@ -13,7 +13,7 @@ . common.rc -requires clang +requires_binary clang cd "$BUILD_DIR" diff --git a/tests/docker/test-debug b/tests/docker/test-debug index c050fa0d93..f52f16328c 100755 --- a/tests/docker/test-debug +++ b/tests/docker/test-debug @@ -14,7 +14,7 @@ . common.rc -requires clang asan +requires_binary clang cd "$BUILD_DIR" diff --git a/tests/docker/test-mingw b/tests/docker/test-mingw index c30eb654eb..0bc6d78872 100755 --- a/tests/docker/test-mingw +++ b/tests/docker/test-mingw @@ -13,7 +13,8 @@ . common.rc -requires mingw dtc +requires_binary x86_64-w64-mingw32-gcc +requires_binary i686-w64-mingw32-gcc cd "$BUILD_DIR" diff --git a/tests/docker/test-misc b/tests/docker/test-misc index cc94a738dd..2a3c2c2e1c 100755 --- a/tests/docker/test-misc +++ b/tests/docker/test-misc @@ -14,7 +14,7 @@ . common.rc -requires docs +requires_binary sphinx-build-3 sphinx-build cd "$BUILD_DIR" diff --git a/tests/docker/test-tsan b/tests/docker/test-tsan index eb40ac45b7..53d90d2f79 100755 --- a/tests/docker/test-tsan +++ b/tests/docker/test-tsan @@ -17,7 +17,7 @@ setup_tsan() { - requires clang tsan + requires_binary clang tsan_log_dir="/tmp/qemu-test/build/tsan" mkdir -p $tsan_log_dir > /dev/null || true EXTRA_CONFIGURE_OPTS="${EXTRA_CONFIGURE_OPTS} --enable-tsan \ diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 0992787d50..050cd61c1a 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -18,15 +18,6 @@ # Hexagon doesn't support gdb, so skip the EXTRA_RUNS EXTRA_RUNS = -# Hexagon has 64K pages, so increase the timeout to keep -# test-mmap from timing out -ifeq ($(CONFIG_DEBUG_TCG),y) -TIMEOUT=800 -else -TIMEOUT=500 -endif - - CFLAGS += -Wno-incompatible-pointer-types -Wno-undefined-internal CFLAGS += -fno-unroll-loops diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index f7efaab918..b0a2128980 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -65,6 +65,9 @@ run-plugin-%-with-libinsn.so: -d plugin -D $*-with-libinsn.so.pout $*, \ "$* (inline) on $(TARGET_NAME)") +run-plugin-signals-with-libinsn.so: + $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups and vdso support") + # Update TESTS I386_TESTS:=$(filter-out $(SKIP_I386_TESTS), $(ALL_X86_TESTS)) TESTS=$(MULTIARCH_TESTS) $(I386_TESTS) diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index d57a115873..85a6fb7a2e 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -37,6 +37,8 @@ signals: LDFLAGS+=-lrt -lpthread run-signals: signals $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups and vdso support") +run-plugin-signals-with-%: + $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups and vdso support") # We define the runner for test-mmap after the individual # architectures have defined their supported pages sizes. If no diff --git a/tests/tcg/multiarch/test-mmap.c b/tests/tcg/multiarch/test-mmap.c index 11d0e777b1..96257f8ebe 100644 --- a/tests/tcg/multiarch/test-mmap.c +++ b/tests/tcg/multiarch/test-mmap.c @@ -49,64 +49,62 @@ size_t test_fsize; void check_aligned_anonymous_unfixed_mmaps(void) { - void *p1; - void *p2; - void *p3; - void *p4; - void *p5; - uintptr_t p; - int i; - - fprintf(stdout, "%s", __func__); - for (i = 0; i < 0x1fff; i++) - { - size_t len; - - len = pagesize + (pagesize * i & 7); - p1 = mmap(NULL, len, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - p2 = mmap(NULL, len, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - p3 = mmap(NULL, len, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - p4 = mmap(NULL, len, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - p5 = mmap(NULL, len, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - - /* Make sure we get pages aligned with the pagesize. The - target expects this. */ - fail_unless (p1 != MAP_FAILED); - fail_unless (p2 != MAP_FAILED); - fail_unless (p3 != MAP_FAILED); - fail_unless (p4 != MAP_FAILED); - fail_unless (p5 != MAP_FAILED); - p = (uintptr_t) p1; - D(printf ("p=%x\n", p)); - fail_unless ((p & pagemask) == 0); - p = (uintptr_t) p2; - fail_unless ((p & pagemask) == 0); - p = (uintptr_t) p3; - fail_unless ((p & pagemask) == 0); - p = (uintptr_t) p4; - fail_unless ((p & pagemask) == 0); - p = (uintptr_t) p5; - fail_unless ((p & pagemask) == 0); - - /* Make sure we can read from the entire area. */ - memcpy (dummybuf, p1, pagesize); - memcpy (dummybuf, p2, pagesize); - memcpy (dummybuf, p3, pagesize); - memcpy (dummybuf, p4, pagesize); - memcpy (dummybuf, p5, pagesize); - - munmap (p1, len); - munmap (p2, len); - munmap (p3, len); - munmap (p4, len); - munmap (p5, len); - } - fprintf(stdout, " passed\n"); + void *p1; + void *p2; + void *p3; + void *p4; + void *p5; + uintptr_t p; + int i; + fprintf(stdout, "%s", __func__); + for (i = 0; i < 8; i++) { + size_t len; + len = pagesize + (pagesize * i); + p1 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p2 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p3 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p4 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p5 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* + * Make sure we get pages aligned with the pagesize. The + * target expects this. + */ + fail_unless(p1 != MAP_FAILED); + fail_unless(p2 != MAP_FAILED); + fail_unless(p3 != MAP_FAILED); + fail_unless(p4 != MAP_FAILED); + fail_unless(p5 != MAP_FAILED); + p = (uintptr_t) p1; + D(printf("p=%x\n", p)); + fail_unless((p & pagemask) == 0); + p = (uintptr_t) p2; + fail_unless((p & pagemask) == 0); + p = (uintptr_t) p3; + fail_unless((p & pagemask) == 0); + p = (uintptr_t) p4; + fail_unless((p & pagemask) == 0); + p = (uintptr_t) p5; + fail_unless((p & pagemask) == 0); + + /* Make sure we can read from the entire area. */ + memcpy(dummybuf, p1, pagesize); + memcpy(dummybuf, p2, pagesize); + memcpy(dummybuf, p3, pagesize); + memcpy(dummybuf, p4, pagesize); + memcpy(dummybuf, p5, pagesize); + munmap(p1, len); + munmap(p2, len); + munmap(p3, len); + munmap(p4, len); + munmap(p5, len); + } + fprintf(stdout, " passed\n"); } void check_large_anonymous_unfixed_mmap(void) @@ -135,52 +133,54 @@ void check_large_anonymous_unfixed_mmap(void) void check_aligned_anonymous_unfixed_colliding_mmaps(void) { - char *p1; - char *p2; - char *p3; - uintptr_t p; - int i; - - fprintf(stdout, "%s", __func__); - for (i = 0; i < 0x2fff; i++) - { - int nlen; - p1 = mmap(NULL, pagesize, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - fail_unless (p1 != MAP_FAILED); - p = (uintptr_t) p1; - fail_unless ((p & pagemask) == 0); - memcpy (dummybuf, p1, pagesize); - - p2 = mmap(NULL, pagesize, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - fail_unless (p2 != MAP_FAILED); - p = (uintptr_t) p2; - fail_unless ((p & pagemask) == 0); - memcpy (dummybuf, p2, pagesize); - - - munmap (p1, pagesize); - nlen = pagesize * 8; - p3 = mmap(NULL, nlen, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - fail_unless (p3 != MAP_FAILED); - - /* Check if the mmaped areas collide. */ - if (p3 < p2 - && (p3 + nlen) > p2) - fail_unless (0); - - memcpy (dummybuf, p3, pagesize); - - /* Make sure we get pages aligned with the pagesize. The - target expects this. */ - p = (uintptr_t) p3; - fail_unless ((p & pagemask) == 0); - munmap (p2, pagesize); - munmap (p3, nlen); - } - fprintf(stdout, " passed\n"); + char *p1; + char *p2; + char *p3; + uintptr_t p; + int i; + + fprintf(stdout, "%s", __func__); + for (i = 0; i < 2; i++) { + int nlen; + p1 = mmap(NULL, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless(p1 != MAP_FAILED); + p = (uintptr_t) p1; + fail_unless((p & pagemask) == 0); + memcpy(dummybuf, p1, pagesize); + + p2 = mmap(NULL, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless(p2 != MAP_FAILED); + p = (uintptr_t) p2; + fail_unless((p & pagemask) == 0); + memcpy(dummybuf, p2, pagesize); + + + munmap(p1, pagesize); + nlen = pagesize * 8; + p3 = mmap(NULL, nlen, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless(p3 != MAP_FAILED); + + /* Check if the mmaped areas collide. */ + if (p3 < p2 + && (p3 + nlen) > p2) { + fail_unless(0); + } + + memcpy(dummybuf, p3, pagesize); + + /* + * Make sure we get pages aligned with the pagesize. The + * target expects this. + */ + p = (uintptr_t) p3; + fail_unless((p & pagemask) == 0); + munmap(p2, pagesize); + munmap(p3, nlen); + } + fprintf(stdout, " passed\n"); } void check_aligned_anonymous_fixed_mmaps(void) diff --git a/tests/vm/netbsd b/tests/vm/netbsd index b9efc269d2..4cc58df130 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -22,8 +22,8 @@ class NetBSDVM(basevm.BaseVM): name = "netbsd" arch = "x86_64" - link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.1/images/NetBSD-9.1-amd64.iso" - csum = "65bddc95945991c3b2021f9c8ded7f34c25f0a7611b7aa15a15fe23399e902307e926ae97fcd01dc1662ac67b5f6e4be643c6a2b581692ddcb616d30125066f9" + link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/images/NetBSD-9.2-amd64.iso" + csum = "5ee0ea101f73386b9b424f5d1041e371db3c42fdd6f4e4518dc79c4a08f31d43091ebe93425c9f0dcaaed2b51131836fe6774f33f89030b58d64709b35fda72f" size = "20G" pkgs = [ # tools diff --git a/tests/vm/openbsd b/tests/vm/openbsd index 4d1399378e..c4c78a80f1 100755 --- a/tests/vm/openbsd +++ b/tests/vm/openbsd @@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM): name = "openbsd" arch = "x86_64" - link = "https://cdn.openbsd.org/pub/OpenBSD/6.8/amd64/install68.iso" - csum = "47e291fcc2d0c1a8ae0b66329f040b33af755b6adbd21739e20bb5ad56f62b6c" + link = "https://cdn.openbsd.org/pub/OpenBSD/6.9/amd64/install69.iso" + csum = "140d26548aec680e34bb5f82295414228e7f61e4f5e7951af066014fda2d6e43" size = "20G" pkgs = [ # tools |